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