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