00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "options.h"
00031 #include "DOC-converter.moc"
00032
00033 #include <qdir.h>
00034 #include <qfileinfo.h>
00035 #include <qregexp.h>
00036 #include <qsortedlist.h>
00037
00038 #include <pilotDatabase.h>
00039 #include <pilotLocalDatabase.h>
00040 #include <pilotSerialDatabase.h>
00041
00042 #include "pilotDOCHead.h"
00043 #include "pilotDOCEntry.h"
00044 #include "pilotDOCBookmark.h"
00045
00046
00047
00048
00049
00050 const char *doc_converter_id = "$Id: DOC-converter.cc,v 1.13 2003/08/12 18:11:51 mueller Exp $";
00051
00052 #define min(a,b) (a<b)?(a):(b)
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 bool docBookmark::compare_pos=true;
00064
00065 bool operator< ( const docBookmark &s1, const docBookmark &s2)
00066 {
00067 if (docBookmark::compare_pos) { return s1.position<s2.position;}
00068 else {return s2.bmkName<s2.bmkName;}
00069 }
00070
00071 bool operator== ( const docBookmark &s1, const docBookmark &s2)
00072 {
00073 return (s1.position==s2.position) && (s1.bmkName==s2.bmkName);
00074 }
00075
00076
00077 int docMatchBookmark::findMatches(QString doctext, bmkList &fBookmarks) {
00078 FUNCTIONSETUP;
00079
00080 int pos = 0, nr=0, found=0;
00081 DEBUGCONDUIT<<"Finding matches of "<<pattern<<endl;
00082
00083 while (pos >= 0 && found<to) {
00084 pos = doctext.find(pattern, pos);
00085 DEBUGCONDUIT<<"Result of search: pos="<<pos<<endl;
00086 if (pos >= 0)
00087 {
00088 found++;
00089 if (found>=from && found<=to) {
00090 fBookmarks.append(new docBookmark(pattern, pos));
00091 nr++;
00092
00093 }
00094 pos++;
00095 }
00096 }
00097 return nr;
00098 }
00099
00100
00101
00102 int docRegExpBookmark::findMatches(QString doctext, bmkList &fBookmarks) {
00103
00104 QRegExp rx(pattern);
00105 int pos = 0, nr=0, found=0;
00106
00107 while (pos>=0 && found<=to) {
00108 DEBUGCONDUIT<<"Searching for bookmark "<<pattern<<endl;
00109 pos=rx.search(doctext, pos);
00110 if (pos > -1) {
00111 found++;
00112 if (found>=from && found<to) {
00113 if (capSubexpression>=0) {
00114 fBookmarks.append(new docBookmark(rx.cap(capSubexpression), pos));
00115 } else {
00116
00117 QString bmkText(bmkName);
00118 for (int i=0; i<=rx.numCaptures(); i++) {
00119 bmkText.replace(QString("$%1").arg(i), rx.cap(i));
00120 bmkText.replace(QString("\\%1").arg(i), rx.cap(i));
00121 }
00122 fBookmarks.append(new docBookmark(bmkText.left(16), pos));
00123 }
00124 nr++;
00125 }
00126 pos++;
00127 }
00128 }
00129 return nr;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 DOCConverter::DOCConverter(QObject *parent, const char *name):QObject(parent,name) {
00145 FUNCTIONSETUP;
00146 docdb=0L;
00147 eSortBookmarks=eSortNone;
00148 fBookmarks.setAutoDelete( TRUE );
00149 (void) doc_converter_id;
00150 }
00151
00152
00153
00154 DOCConverter::~DOCConverter() {
00155 FUNCTIONSETUP;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 void DOCConverter::setTXTpath(QString path, QString file) {
00169 QDir dr(path);
00170 QFileInfo pth(dr, file);
00171 if (!file.isEmpty())
00172 txtfilename = pth.absFilePath();
00173 }
00174
00175
00176
00177 void DOCConverter::setTXTpath(QString filename) {
00178 if (!filename.isEmpty()) txtfilename = filename;
00179 }
00180
00181
00182
00183 void DOCConverter::setPDB(PilotDatabase * dbi) {
00184 if (dbi) docdb = dbi;
00185 }
00186
00187
00188
00189 QString DOCConverter::readText() {
00190 FUNCTIONSETUP;
00191 if (txtfilename.isEmpty()) return QString();
00192 QFile docfile(txtfilename);
00193 if (!docfile.open(IO_ReadOnly))
00194 {
00195 emit logError(i18n("Unable to open text file %1 for reading.").arg(txtfilename));
00196 return QString();
00197 }
00198
00199 QTextStream docstream(&docfile);
00200
00201 QString doc = docstream.read();
00202 docfile.close();
00203 return doc;
00204 }
00205
00206
00207
00208 int DOCConverter::findBmkEndtags(QString &text, bmkList&fBmks) {
00209 FUNCTIONSETUP;
00210
00211 int pos = text.length() - 1, nr=0;
00212 bool doSearch=true;
00213 while (pos >= 0) {
00214 DEBUGCONDUIT<<"Current character is \'"<<text[pos].latin1()<<"\'"<<endl;
00215
00216 while (text[pos].isSpace() && pos >= 0) {
00217 DEBUGCONDUIT<<"Skipping whitespaces at the end of the file"<<endl;
00218 pos--;
00219 }
00220
00221 if (pos < 0 || text[pos] != '>') {
00222 DEBUGCONDUIT<<"Current character \'"<<text[pos].latin1()<<"\' at position "<<pos<<" is not and ending >. Finish searching for bookmarks."<<endl;
00223
00224 pos=-1;
00225 break;
00226 } else {
00227 int endpos = pos;
00228 doSearch=true;
00229 DEBUGCONDUIT<<"Found the ending >, now looking for the opening <"<<endl;
00230
00231
00232 while (doSearch && pos > 0) {
00233
00234 pos--;
00235 if (text[pos] == '\n') {
00236 DEBUGCONDUIT<<"Found carriage return at position "<<pos<<" inside the bookmark text, assuming this is not a bookmark, and the text ends in a >"<<endl;
00237 doSearch = false;
00238 pos = -1;
00239 break;
00240 }
00241 if (text[pos] == '<') {
00242 fBmks.append(new docMatchBookmark(text.mid(pos + 1, endpos - pos - 1)));
00243 nr++;
00244 DEBUGCONDUIT<<"Found opening < at position "<<pos<<", bookmarktext ="<<text.mid(pos+1, endpos-pos-1)<<endl;
00245 text.remove(pos, text.length());
00246 pos--;
00247 doSearch = false;
00248 }
00249 }
00250 }
00251 DEBUGCONDUIT<<"Finished processing the next bookmark, current position: "<<pos<<endl;
00252 }
00253 return nr;
00254 }
00255
00256 int DOCConverter::findBmkInline(QString &text, bmkList &fBmks) {
00257 FUNCTIONSETUP;
00258
00259 int nr=0;
00260 QRegExp rx(CSL1("<\\*(.*)\\*>"));
00261
00262 rx.setMinimal(TRUE);
00263 int pos = 0;
00264 while (pos >= 0) {
00265 pos = rx.search(text, pos);
00266 if (pos >= 0) {
00267 fBmks.append(new docBookmark(rx.cap(1), pos+1));
00268 nr++;
00269 text = text.remove(pos, rx.matchedLength());
00270 }
00271 }
00272 return nr;
00273 }
00274
00275 int DOCConverter::findBmkFile(QString &, bmkList &fBmks) {
00276 FUNCTIONSETUP;
00277 int nr=0;
00278
00279 QString bmkfilename = txtfilename;
00280 if (bmkfilename.endsWith(CSL1(".txt"))){
00281 bmkfilename.remove(bmkfilename.length()-4, 4);
00282 }
00283 QString oldbmkfilename=bmkfilename;
00284 bmkfilename+=CSL1(BMK_SUFFIX);
00285 QFile bmkfile(bmkfilename);
00286 if (!bmkfile.open(IO_ReadOnly)) {
00287 bmkfilename=oldbmkfilename+CSL1(PDBBMK_SUFFIX);
00288 bmkfile.setName(bmkfilename);
00289 if (!bmkfile.open(IO_ReadOnly)) {
00290 DEBUGCONDUIT<<"Unable to open bookmarks file "<<bmkfilename<<" for reading the bookmarks of "<<docdb ->dbPathName()<<endl;
00291 return 0;
00292 }
00293 }
00294
00295 DEBUGCONDUIT<<"Bookmark file: "<<bmkfilename<<endl;
00296
00297 QTextStream bmkstream(&bmkfile);
00298 QString line;
00299 while ( !(line=bmkstream.readLine()).isEmpty() ) {
00300 if (!line.isEmpty() && !line.startsWith(CSL1("#")) ) {
00301 QStringList bmkinfo=QStringList::split(CSL1(","), line);
00302 int fieldnr=bmkinfo.count();
00303
00304
00305
00306 if (fieldnr>0){
00307 DEBUGCONDUIT<<"Working on bookmark \""<<line<<"\""<<endl;
00308 docMatchBookmark*bmk=0L;
00309 QString bookmark=bmkinfo[0];
00310 bool ok;
00311 int pos=bookmark.toInt(&ok);
00312 if (ok) {
00313 if (fieldnr>1) {
00314 QString name(bmkinfo[1]);
00315 DEBUGCONDUIT<<"Bookmark \""<<name<<"\" set at position "<<pos<<endl;
00316 fBmks.append(new docBookmark(name, pos));
00317 }
00318 } else if (bookmark==CSL1("-") || bookmark==CSL1("+")) {
00319 if (fieldnr>1) {
00320 QString patt(bmkinfo[1]);
00321 QString name(patt);
00322 if (fieldnr>2) {
00323 int cap=bmkinfo[2].toInt(&ok);
00324 if (ok) {
00325 bmk=new docRegExpBookmark(patt, cap);
00326 } else {
00327 name=bmkinfo[2];
00328 bmk=new docRegExpBookmark(patt, name);
00329 }
00330 } else{
00331 bmk=new docRegExpBookmark(patt, name);
00332 }
00333
00334 DEBUGCONDUIT<<"RegExp Bookmark, pattern="<<patt<<", name="<<name<<endl;
00335 if (bmk) {
00336 if (bookmark==CSL1("-")) {
00337 bmk->from=1;
00338 bmk->to=1;
00339 } else {
00340 if (fieldnr>3) {
00341 bool ok;
00342 int tmp=bmkinfo[3].toInt(&ok);
00343 if (ok) bmk->from=tmp;
00344 if (fieldnr>4) {
00345 tmp=bmkinfo[4].toInt(&ok);
00346 if (ok) bmk->to=tmp;
00347 }
00348 }
00349 }
00350 fBmks.append(bmk);
00351 bmk=0L;
00352 } else {
00353 DEBUGCONDUIT<<"Could not allocate bookmark "<<name<<endl;
00354 }
00355 } else {
00356 DEBUGCONDUIT<<"RegExp bookmark found with no other information (no bookmark pattern nor name)"<<endl;
00357 }
00358 } else {
00359 QString pattern(bookmark);
00360 if (fieldnr>1) pattern=bmkinfo[1];
00361 if (fieldnr>2) bookmark=bmkinfo[2];
00362 DEBUGCONDUIT<<"RegExp Bookmark, pattern="<<pattern<<", name="<<bookmark<<endl;
00363 bmk=new docRegExpBookmark(pattern, bookmark);
00364 if (bmk) {
00365 bmk->from=1;
00366 bmk->to=1;
00367 fBmks.append(bmk);
00368 }
00369 }
00370 }
00371 }
00372 }
00373 return nr;
00374 }
00375
00376 bool DOCConverter::convertTXTtoPDB() {
00377 FUNCTIONSETUP;
00378
00379 if (!docdb) {
00380 emit logError(i18n("Unable to open Database for writing"));
00381 return false;
00382 }
00383
00384 QString text = readText();
00385
00386 if (fBmkTypes & eBmkEndtags) {
00387 findBmkEndtags(text, fBookmarks);
00388 }
00389
00390
00391
00392 if (fBmkTypes & eBmkInline) {
00393 findBmkInline(text, fBookmarks);
00394 }
00395
00396
00397
00398 if (fBmkTypes & eBmkFile)
00399 {
00400 findBmkFile(text, fBookmarks);
00401 }
00402
00403
00404 bmkSortedList pdbBookmarks;
00405 pdbBookmarks.setAutoDelete(TRUE);
00406 docBookmark*bmk;
00407 for (bmk = fBookmarks.first(); bmk; bmk = fBookmarks.next())
00408 {
00409 bmk->findMatches(text, pdbBookmarks);
00410 }
00411
00412 switch (eSortBookmarks)
00413 {
00414 case eSortName:
00415 docBookmark::compare_pos=false;
00416
00417 pdbBookmarks.sort();
00418 break;
00419 case eSortPos:
00420 docBookmark::compare_pos=true;
00421 pdbBookmarks.sort();
00422 break;
00423 case eSortNone:
00424 default:
00425 break;
00426 }
00427
00428 #ifdef DEBUG
00429 DEBUGCONDUIT << "Bookmarks: "<<endl;
00430 for (bmk = pdbBookmarks.first(); bmk; bmk = pdbBookmarks.next())
00431 {
00432 DEBUGCONDUIT<<bmk->bmkName.left(20)<<" at position "<<bmk->position<<endl;
00433 }
00434 #endif
00435
00436 if (!docdb->isDBOpen()) {
00437 emit logError(i18n("Unable to open palm doc database %1").arg(docdb->dbPathName()) );
00438 return false;
00439 }
00440
00441
00442 docdb->deleteRecord(0, true);
00443
00444
00445 PilotDOCHead docHead;
00446 docHead.position=0;
00447 docHead.recordSize=4096;
00448 docHead.spare=0;
00449 docHead.storyLen=text.length();
00450 docHead.version=compress?DOC_COMPRESSED:DOC_UNCOMPRESSED;
00451 docHead.numRecords=(int)( (text.length()-1)/docHead.recordSize)+1;
00452 PilotRecord*rec=docHead.pack();
00453 docdb->writeRecord(rec);
00454 KPILOT_DELETE(rec);
00455
00456 DEBUGCONDUIT << "Write header record: length="<<text.length()<<", compress="<<compress<<endl;
00457
00458
00459 int len=text.length();
00460 int start=0,reclen=0;
00461 int recnum=0;
00462 while (start<len)
00463 {
00464 reclen=min(len-start, PilotDOCEntry::TEXT_SIZE);
00465 DEBUGCONDUIT << "Record #"<<recnum<<", reclen="<<reclen<<", compress="<<compress<<endl;
00466
00467 PilotDOCEntry recText;
00468
00469 recText.setText(text.mid(start, reclen));
00470
00471 recText.setCompress(compress);
00472 PilotRecord*textRec=recText.pack();
00473 docdb->writeRecord(textRec);
00474 recnum++;
00475 start+=reclen;
00476 KPILOT_DELETE(textRec);
00477 }
00478
00479 recnum=0;
00480
00481 for (bmk = pdbBookmarks.first(); bmk; bmk = pdbBookmarks.next())
00482
00483 {
00484 recnum++;
00485 DEBUGCONDUIT << "Bookmark #"<<recnum<<", Name="<<bmk->bmkName.left(20)<<", Position="<<bmk->position<<endl;
00486
00487 PilotDOCBookmark bmkEntry;
00488 bmkEntry.pos=bmk->position;
00489 strncpy(&bmkEntry.bookmarkName[0], bmk->bmkName.latin1(), 16);
00490 PilotRecord*bmkRecord=bmkEntry.pack();
00491 docdb->writeRecord(bmkRecord);
00492 KPILOT_DELETE(bmkRecord);
00493 }
00494
00495 pdbBookmarks.clear();
00496 fBookmarks.clear();
00497
00498 return true;
00499 }
00500
00501
00502
00503 bool DOCConverter::convertPDBtoTXT()
00504 {
00505 FUNCTIONSETUP;
00506 if (txtfilename.isEmpty()) {
00507 emit logError(i18n("No filename set for the conversion"));
00508 return false;
00509 }
00510
00511 if (!docdb) {
00512 emit logError(i18n("Unable to open Database for reading"));
00513 return false;
00514 }
00515
00516
00517 PilotRecord*headerRec = docdb->readRecordByIndex(0);
00518 if (!headerRec)
00519 {
00520 emit logError(i18n("Unable to read database header for database %1.").arg(docdb->dbPathName()));
00521 KPILOT_DELETE(docdb);
00522 return false;
00523 }
00524 PilotDOCHead header(headerRec);
00525 KPILOT_DELETE(headerRec);
00526
00527 DEBUGCONDUIT<<"Database "<<docdb->dbPathName()<<" has "<<header.numRecords<<" text records, "<<endl
00528 <<" total number of records: "<<docdb->recordCount()<<endl
00529 <<" position="<<header.position<<endl
00530 <<" recordSize="<<header.recordSize<<endl
00531 <<" spare="<<header.spare<<endl
00532 <<" storyLen="<<header.storyLen<<endl
00533
00534 <<" version="<<header.version<<endl;
00535
00536
00537 QFile docfile(txtfilename);
00538 if (!docfile.open(IO_WriteOnly))
00539 {
00540 emit logError(i18n("Unable to open output file %1.").arg(txtfilename));
00541 KPILOT_DELETE(docdb);
00542 return false;
00543 }
00544 QString doctext;
00545 for (int i=1; i<header.numRecords+1; i++)
00546 {
00547 PilotRecord*rec=docdb->readRecordByIndex(i);
00548 if (rec)
00549 {
00550 PilotDOCEntry recText(rec, header.version==DOC_COMPRESSED);
00551 doctext.append(recText.getText());
00552 DEBUGCONDUIT<<"Record "<<i<<endl;
00553 KPILOT_DELETE(rec);
00554 } else {
00555 emit logMessage(i18n("Could not read text record #%1 from Database %2").arg(i).arg(docdb->dbPathName()));
00556 }
00557 }
00558
00559
00560
00561 int upperBmkRec=docdb->recordCount();
00562 bmkSortedList bmks;
00563 bmks.setAutoDelete(TRUE);
00564 for (int i=header.numRecords+1; i<upperBmkRec; i++)
00565 {
00566 PilotRecord*rec=docdb->readRecordByIndex(i);
00567 if (rec)
00568 {
00569 PilotDOCBookmark bookie(rec);
00570 docBookmark*bmk=new docBookmark(bookie.bookmarkName, bookie.pos);
00571 bmks.append(bmk);
00572 KPILOT_DELETE(rec);
00573 } else {
00574 emit logMessage(i18n("Could not read bookmark record #%1 from Database %2").arg(i).arg(docdb->dbPathName()));
00575 }
00576 }
00577
00578 docBookmark::compare_pos=true;
00579 bmks.sort();
00580
00581 if ((fBmkTypes & eBmkFile) && (bmks.count()>0))
00582 {
00583 QString bmkfilename = docfile.name();
00584 if (bmkfilename.endsWith(CSL1(".txt"))){
00585 bmkfilename.remove(bmkfilename.length()-4, 4);
00586 }
00587 bmkfilename+=CSL1(PDBBMK_SUFFIX);
00588 QFile bmkfile(bmkfilename);
00589 if (!bmkfile.open(IO_WriteOnly))
00590 {
00591 emit logError(i18n("Unable to open file %1 for the bookmarks of %2.")
00592 .arg(bmkfilename).arg(docdb ->dbPathName()));
00593 }
00594 else
00595 {
00596 DEBUGCONDUIT<<"Writing "<<upperBmkRec-header.numRecords<<
00597 "("<<upperBmkRec<<") bookmarks to file "<<bmkfilename<<endl;
00598 QTextStream bmkstream(&bmkfile);
00599 for (docBookmark*bmk=bmks.first(); bmk; bmk=bmks.next())
00600 {
00601 bmkstream<<bmk->position<<", "<<bmk->bmkName<<endl;
00602 }
00603
00604 bmkfile.close();
00605 }
00606 }
00607 if (fBmkTypes & eBmkInline)
00608 {
00609 for (docBookmark*bmk=bmks.last(); bmk; bmk=bmks.prev())
00610 {
00611 doctext.insert(bmk->position, QString(CSL1("<*") +
00612 bmk->bmkName +
00613 CSL1("*>")));
00614 }
00615 }
00616
00617
00618 QTextStream docstream(&docfile);
00619 docstream<<doctext;
00620
00621 docfile.close();
00622 docdb->cleanup();
00623
00624 docdb->resetSyncFlags();
00625 return true;
00626 }
00627
00628