asciiimport.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
3 Copyright (C) 2000 Michael Johnson <mikej@xnet.com>
4 Copyright (C) 2001, 2002, 2004 Nicolas GOUTTE <goutte@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include <config.h>
23
24#ifdef HAVE_UNISTD_H
25#include <unistd.h>
26#endif
27
28#include <tqobject.h>
29#include <tqstring.h>
30// #include <tqregexp.h> // Currently not needed (due to disabled code)
31#include <tqtextcodec.h>
32#include <tqfile.h>
33#include <tqtextstream.h>
34#include <tqdom.h>
35#include <tqfontinfo.h>
36
37#include <kdebug.h>
38#include <tdeglobal.h>
39#include <kgenericfactory.h>
40
41#include <KoGlobal.h>
42#include <KoPageLayout.h>
43#include <KoStore.h>
44#include <KoFilterChain.h>
45#include <KoFilterManager.h>
46
47#include <asciiimport.h>
48#include <asciiimport.moc>
49#include "ImportDialog.h"
50
51class ASCIIImportFactory : KGenericFactory<ASCIIImport, KoFilter>
52{
53public:
54 ASCIIImportFactory(void) : KGenericFactory<ASCIIImport, KoFilter> ("kwordasciiimport")
55 {}
56protected:
57 virtual void setupTranslations( void )
58 {
59 TDEGlobal::locale()->insertCatalogue( "kofficefilters" );
60 }
61};
62
63K_EXPORT_COMPONENT_FACTORY( libasciiimport, ASCIIImportFactory() )
64
65ASCIIImport::ASCIIImport(KoFilter *, const char *, const TQStringList &) :
66 KoFilter() {
67}
68
69void ASCIIImport::prepareDocument(TQDomDocument& mainDocument, TQDomElement& mainFramesetElement)
70{
71 // TODO: other paper formats
72 KoFormat paperFormat=PG_DIN_A4; // ISO A4
73 KoOrientation paperOrientation=PG_PORTRAIT;
74
75 mainDocument.appendChild(
76 mainDocument.createProcessingInstruction(
77 "xml","version=\"1.0\" encoding=\"UTF-8\""));
78
79 TQDomElement elementDoc;
80 elementDoc=mainDocument.createElement("DOC");
81 elementDoc.setAttribute("editor","KWord's Plain Text Import Filter");
82 elementDoc.setAttribute("mime","application/x-kword");
83 // TODO: We claim to be syntax version 2, but we should verify that it is also true.
84 elementDoc.setAttribute("syntaxVersion",2);
85 mainDocument.appendChild(elementDoc);
86
87 TQDomElement element;
88 element=mainDocument.createElement("ATTRIBUTES");
89 element.setAttribute("processing",0);
90 element.setAttribute("standardpage",1);
91 element.setAttribute("hasHeader",0);
92 element.setAttribute("hasFooter",0);
93 //element.setAttribute("unit","mm"); // use KWord default instead
94 elementDoc.appendChild(element);
95
96 TQDomElement elementPaper=mainDocument.createElement("PAPER");
97 elementPaper.setAttribute("format",paperFormat);
98 elementPaper.setAttribute("width" ,KoPageFormat::width (paperFormat,paperOrientation) * 72.0 / 25.4);
99 elementPaper.setAttribute("height",KoPageFormat::height(paperFormat,paperOrientation) * 72.0 / 25.4);
100 elementPaper.setAttribute("orientation",PG_PORTRAIT);
101 elementPaper.setAttribute("columns",1);
102 elementPaper.setAttribute("columnspacing",2);
103 elementPaper.setAttribute("hType",0);
104 elementPaper.setAttribute("fType",0);
105 elementPaper.setAttribute("spHeadBody",9);
106 elementPaper.setAttribute("spFootBody",9);
107 elementPaper.setAttribute("zoom",100);
108 elementDoc.appendChild(elementPaper);
109
110 element=mainDocument.createElement("PAPERBORDERS");
111 element.setAttribute("left",28);
112 element.setAttribute("top",42);
113 element.setAttribute("right",28);
114 element.setAttribute("bottom",42);
115 elementPaper.appendChild(element);
116
117 TQDomElement framesetsPluralElementOut=mainDocument.createElement("FRAMESETS");
118 mainDocument.documentElement().appendChild(framesetsPluralElementOut);
119
120 mainFramesetElement=mainDocument.createElement("FRAMESET");
121 mainFramesetElement.setAttribute("frameType",1);
122 mainFramesetElement.setAttribute("frameInfo",0);
123 mainFramesetElement.setAttribute("autoCreateNewFrame",1);
124 mainFramesetElement.setAttribute("removable",0);
125 // TODO: "name" attribute (needs I18N)
126 framesetsPluralElementOut.appendChild(mainFramesetElement);
127
128 TQDomElement frameElementOut=mainDocument.createElement("FRAME");
129 frameElementOut.setAttribute("left",28);
130 frameElementOut.setAttribute("top",42);
131 frameElementOut.setAttribute("bottom",566);
132 frameElementOut.setAttribute("right",798);
133 frameElementOut.setAttribute("runaround",1);
134 mainFramesetElement.appendChild(frameElementOut);
135
136 TQDomElement elementStylesPlural=mainDocument.createElement("STYLES");
137 elementDoc.appendChild(elementStylesPlural);
138
139 TQDomElement elementStyleStandard=mainDocument.createElement("STYLE");
140 elementStylesPlural.appendChild(elementStyleStandard);
141
142 element=mainDocument.createElement("NAME");
143 element.setAttribute("value","Standard");
144 elementStyleStandard.appendChild(element);
145
146 element=mainDocument.createElement("FOLLOWING");
147 element.setAttribute("name","Standard");
148 elementStyleStandard.appendChild(element);
149
150 TQDomElement elementFormat=mainDocument.createElement("FORMAT");
151 elementStyleStandard.appendChild(elementFormat);
152
153 // Use TQFontInfo, as it does not give back -1 as point size.
154 TQFontInfo defaultFontInfo(KoGlobal::defaultFont());
155
156 element=mainDocument.createElement("FONT");
157 element.setAttribute("name",defaultFontInfo.family());
158 elementFormat.appendChild(element);
159
160 element=mainDocument.createElement("SIZE");
161 element.setAttribute("value",defaultFontInfo.pointSize());
162 elementFormat.appendChild(element);
163
164 element=mainDocument.createElement("ITALIC");
165 element.setAttribute("value",0);
166 elementFormat.appendChild(element);
167
168 element=mainDocument.createElement("WEIGHT");
169 element.setAttribute("value",50);
170 elementFormat.appendChild(element);
171
172 element=mainDocument.createElement("UNDERLINE");
173 element.setAttribute("value",0);
174 elementFormat.appendChild(element);
175
176 element=mainDocument.createElement("STRIKEOUT");
177 element.setAttribute("value",0);
178 elementFormat.appendChild(element);
179
180 element=mainDocument.createElement("VERTALIGN");
181 element.setAttribute("value",0);
182 elementFormat.appendChild(element);
183
184 element=mainDocument.createElement("COLOR");
185 element.setAttribute("red", -1);
186 element.setAttribute("green",1);
187 element.setAttribute("blue", -1);
188 elementFormat.appendChild(element);
189
190 element=mainDocument.createElement("TEXTBACKGROUNDCOLOR");
191 element.setAttribute("red", -1);
192 element.setAttribute("green",-1);
193 element.setAttribute("blue", -1);
194 elementFormat.appendChild(element);
195
196}
197
198KoFilter::ConversionStatus ASCIIImport::convert( const TQCString& from, const TQCString& to )
199{
200 if (to!="application/x-kword" || from!="text/plain")
201 return KoFilter::NotImplemented;
202
203 AsciiImportDialog* dialog = 0;
204 if (!m_chain->manager()->getBatchMode())
205 {
206 dialog = new AsciiImportDialog();
207 if (!dialog)
208 {
209 kdError(30502) << "Dialog has not been created! Aborting!" << endl;
210 return KoFilter::StupidError;
211 }
212 if (!dialog->exec())
213 {
214 kdDebug(30502) << "Dialog was aborted! Aborting filter!" << endl; // this isn't an error!
215 return KoFilter::UserCancelled;
216 }
217 }
218
219 TQTextCodec* codec;
220 int paragraphStrategy;
221 if (dialog)
222 {
223 codec = dialog->getCodec();
224 paragraphStrategy=dialog->getParagraphStrategy();
225 delete dialog;
226 }
227 else
228 {
229 codec = TQTextCodec::codecForName("UTF-8");
230 paragraphStrategy=0;
231 }
232
233 TQFile in(m_chain->inputFile());
234 if(!in.open(IO_ReadOnly)) {
235 kdError(30502) << "Unable to open input file!" << endl;
236 in.close();
237 return KoFilter::FileNotFound;
238 }
239
240 TQString tbl; // string for table XML
241
242 TQDomDocument mainDocument;
243 TQDomElement mainFramesetElement;
244
245 prepareDocument(mainDocument,mainFramesetElement);
246
247 TQTextStream stream(&in);
248
249 if (!codec)
250 {
251 kdError(30502) << "Could not create TQTextCodec! Aborting" << endl;
252 in.close();
253 return KoFilter::StupidError;
254 }
255
256 kdDebug(30502) << "Charset used: " << codec->name() << endl;
257
258 stream.setCodec(codec);
259
260 if (1==paragraphStrategy)
261 sentenceConvert(stream, mainDocument, mainFramesetElement);
262 else if (999==paragraphStrategy)
263 oldWayConvert(stream, mainDocument, mainFramesetElement);
264 else
265 asIsConvert(stream, mainDocument, mainFramesetElement);
266
267
268#if 0
269 kdDebug(30502) << mainDocument.toString() << endl;
270#endif
271
272 KoStoreDevice* out=m_chain->storageFile( "root", KoStore::Write );
273 if(!out) {
274 kdError(30502) << "Unable to open output file!" << endl;
275 in.close();
276 return KoFilter::StorageCreationError;
277 }
278 TQCString cstr=mainDocument.toCString();
279 // WARNING: we cannot use KoStore::write(const TQByteArray&) because it gives an extra NULL character at the end.
280 out->writeBlock(cstr,cstr.length());
281 in.close();
282 return KoFilter::OK;
283}
284
285void ASCIIImport::oldWayConvert(TQTextStream& stream, TQDomDocument& mainDocument,
286 TQDomElement& mainFramesetElement)
287{
288 kdDebug(30502) << "Entering: ASCIIImport::oldWayConvert" << endl;
289 TQStringList paragraph; // lines of the paragraph
290 int linecount = 0; // line counter used to position tables
291 //int table_no = 0; // used for table identifiers
292 int numLines; // Number of lines of the paragraph
293
294 bool lastCharWasCr=false; // Was the previous character a Carriage Return?
295 TQString strLine;
296 while(!stream.atEnd())
297 {
298 paragraph.clear();
299 // Read in paragraph
300 for(int line_no = numLines = 0; line_no < MAXLINES; line_no++, numLines++)
301 {
302 // We need to read a line
303 // NOTE: we cannot use TQStreamText::readLine,
304 // as it does not know anything about Carriage Returns
305 strLine=readLine(stream,lastCharWasCr);
306 if (strLine.isEmpty())
307 {
308 paragraph.append(TQString());
309 break;
310 }
311
312 const int length = strLine.length();
313 if (strLine.at(length-1) == '-')
314 // replace the hard hyphen - at line end by a soft hyphen
315 strLine.at(length-1)=TQChar(173);
316 else
317 strLine += ' '; // add space to end of line
318
319 paragraph.append(strLine);
320 } // for(line_no = 0;
321
322 // process tables
323#if 0
324 if ( Table( &Line[0], &linecount, numLines, table_no, tbl, str))
325 table_no++;
326 else
327#else
328 if (true)
329#endif
330 {
331 // Process bullet and dash lists
332#if 0
333 if(ListItem( &Line[0], numLines, str))
334 linecount += (numLines + 1);
335 else
336 {
337#else
338 if (true)
339 {
340#endif
341 processParagraph(mainDocument,mainFramesetElement,paragraph);
342 linecount += ( numLines + 1); // increment the line count
343 } // else
344 } // else
345 } // while(!eof)
346
347#if 0
348 // Add table info
349 if( table_no > 0) str += tbl;
350#endif
351}
352
353void ASCIIImport::asIsConvert(TQTextStream& stream, TQDomDocument& mainDocument,
354 TQDomElement& mainFramesetElement)
355// Paragraph strategy: one line, one paragraph
356{
357 kdDebug(30502) << "Entering: ASCIIImport::asIsConvert" << endl;
358 bool lastCharWasCr=false; // Was the previous character a Carriage Return?
359 TQString strLine;
360 while(!stream.atEnd())
361 {
362 // Read one line and consider it being a paragraph
363 strLine=readLine(stream,lastCharWasCr);
364 writeOutParagraph(mainDocument,mainFramesetElement, "Standard", strLine,
365 0, 0);
366 }
367}
368
369void ASCIIImport::sentenceConvert(TQTextStream& stream, TQDomDocument& mainDocument,
370 TQDomElement& mainFramesetElement)
371// Strategy:
372// - end a paragraph when a line ends with a point or similar punctuation.
373// - search the punctuation at the end of the line, even if the sentence is quoted or in parentheses.
374// - an empty line also ends the paragraph
375// TODO/FIXME: we have a little problem with empty lines. Perhaps we should not allow empty paragraphs!
376{
377 kdDebug(30502) << "Entering: ASCIIImport::sentenceConvert" << endl;
378 TQStringList paragraph; // lines of the paragraph
379 bool lastCharWasCr=false; // Was the previous character a Carriage Return?
380 TQString strLine;
381 TQString stoppingPunctuation(".!?");
382 TQString skippingQuotes("\"')");
383 while (!stream.atEnd())
384 {
385 paragraph.clear();
386 for(;;)
387 {
388 // We need to read a line
389 // NOTE: we cannot use TQStreamText::readLine,
390 // as it does not know anything about Carriage Returns
391 strLine=readLine(stream,lastCharWasCr);
392 if (strLine.isEmpty())
393 {
394 break;
395 }
396
397 paragraph.append(strLine);
398
399 uint lastPos=strLine.length()-1;
400 TQChar lastChar;
401 // Skip a maximum of 10 quotes (or similar) at the end of the line
402 for (int i=0;i<10;i++)
403 {
404 lastChar=strLine[lastPos];
405 if (lastChar.isNull())
406 break;
407 else if (skippingQuotes.find(lastChar)==-1)
408 break;
409 else
410 lastPos--;
411 }
412
413 lastChar=strLine[lastPos];
414 if (lastChar.isNull())
415 continue;
416 else if (stoppingPunctuation.find(lastChar)!=-1)
417 break;
418 }
419#if 1
420 writeOutParagraph(mainDocument,mainFramesetElement, "Standard",
421 paragraph.join(" ").simplifyWhiteSpace(), 0, 0);
422#else
423 // FIXME/TODO: why is this not working?
424 //processParagraph(mainDocument,mainFramesetElement,paragraph);
425#endif
426 } // while(!eof)
427}
428
429void ASCIIImport::processParagraph(TQDomDocument& mainDocument,
430 TQDomElement& mainFramesetElement, const TQStringList& paragraph)
431{
432 // Paragraph with no tables or lists
433 TQString text;
434 TQStringList::ConstIterator it=paragraph.begin(); // Current line (at start, the first one)
435 TQStringList::ConstIterator previousLine=it; // The previous one (at start, also the first one)
436 int firstindent=Indent(*it);
437
438 // We work with one line in advance (therefore the two it++)
439 for( it++; it!=paragraph.end(); it++)
440 {
441 text += *previousLine; // add previous line to paragraph
442 // check for a short line - if short make it a paragraph
443 if( (*previousLine).length() <= shortline)
444 {
445 if((*it).length() > shortline)
446 // skip if short last line of normal paragraph
447 {
448 const int secondindent = Indent(*previousLine);
449 writeOutParagraph(mainDocument,mainFramesetElement,
450 "Standard", text.simplifyWhiteSpace(), firstindent, secondindent);
451
452 firstindent = Indent(*it);
453 text = TQString(); // reinitialize paragraph text
454 }
455 }
456 previousLine=it;
457 }
458 // write out paragraph begin to end
459 const int secondindent = Indent(*previousLine);
460 writeOutParagraph(mainDocument,mainFramesetElement,
461 "Standard", text.simplifyWhiteSpace(), firstindent, secondindent);
462}
463
464void ASCIIImport::writeOutParagraph(TQDomDocument& mainDocument,
465 TQDomElement& mainFramesetElement, const TQString& name,
466 const TQString& text, const int firstindent, const int secondindent)
467{
468 TQDomElement paragraphElementOut=mainDocument.createElement("PARAGRAPH");
469 mainFramesetElement.appendChild(paragraphElementOut);
470 TQDomElement textElement=mainDocument.createElement("TEXT");
471 paragraphElementOut.appendChild(textElement);
472 //TQDomElement formatsPluralElementOut=mainDocument.createElement("FORMATS");
473 //paragraphElementOut.appendChild(formatsPluralElementOut);
474 TQDomElement layoutElement=mainDocument.createElement("LAYOUT");
475 paragraphElementOut.appendChild(layoutElement);
476
477 TQDomElement element;
478 element=mainDocument.createElement("NAME");
479 element.setAttribute("value",name);
480 layoutElement.appendChild(element);
481
482 double size;
483 element=mainDocument.createElement("INDENTS");
484 size = firstindent-secondindent;
485 size *= ptsperchar; // convert indent spaces to points
486 element.setAttribute("first",TQString::number(size));
487 size = secondindent;
488 size *= ptsperchar; // convert indent spaces to points
489 element.setAttribute("left",TQString::number(size));
490 element.setAttribute("right",0);
491
492 textElement.appendChild(mainDocument.createTextNode(text));
493 textElement.normalize(); // Put text together (not sure if needed)
494
495#if 0
496 // If the paragraph is indented, write out indentation elements.
497 // TODO: why not always write identation?
498 if (firstindent > 0 || secondindent > 0) \
499 WriteOutIndents( firstindent, secondindent, str);
500
501 // If this is a bullet or a dash list, write out a COUNTER element
502 if(type.isEmpty())
503 {
504 str += "<COUNTER type=\"";
505 str += type; // "6" = bullet "7" = dash
506 str += "\" depth=\"0\" start=\"1\" numberingtype=\"0\" lefttext=\"\" righttext=\".\" />\n";
507 }
508
509 str += "<FORMAT>\n";
510 // for now we try with style (TODO: verify that KWord 1.2 works correctly)
511 //str += "<FONT name=\"times\"/>\n";
512 str += "</FORMAT>\n";
513 str += "</LAYOUT>\n";
514 str += "</PARAGRAPH>\n";
515#endif
516} // WriteOutParagraph
517
518 /* The Indent method determines the equivalent number of spaces
519 at the beginning of a line */
520
521int ASCIIImport::Indent(const TQString& line) const
522{
523
524 TQChar c; // for reading string a character at a time
525 int count=0; // amount of white space at the begining of the line
526
527 for( uint i = 0; i < line.length(); i++ )
528 {
529 c = line.at(i);
530 if( c == TQChar(' '))
531 count++;
532 else if( c == TQChar('\t'))
533 count += spacespertab;
534 else
535 break;
536 }
537
538 return count;
539
540} // Indent
541
542 /* The WriteOutTableCell method writes out a single table cell
543 in Kword XML to the output string str. The table is sized according
544 to the spacing in the ascii document.
545 Arguments
546 int table_no - used to keep the group number count
547 int row - row number
548 int col - column number
549 Position *pos - pointer to the table position
550 TQString str - the output string.
551
552 Returns - void
553 */
554
555#if 0
556 void ASCIIImport::WriteOutTableCell( int table_no, int row,
557 int col, Position *pos, TQString &str)
558 {
559
560 str += "<FRAMESET frameType=\"1\" frameInfo=\"0\" grpMgr=\"grpmgr_";
561
562 TQString buf = TQString::number(table_no); // convert int to string
563 str += buf;
564
565 str += "\" row=\"";
566 buf = TQString::number(row); // convert row to string
567 str += buf;
568
569 str += "\" col=\"";
570 buf = TQString::number(col); // convert col to string
571 str += buf;
572
573 str += "\" rows=\"1\" cols=\"1\" removable=\"0\" visible=\"1\" name=\"Cell ";
574 buf = TQString::number(row); // convert row to string
575 str += buf;
576 str += ",";
577 buf = TQString::number(col); // convert col to string
578 str += buf;
579
580 str += "\">\n";
581
582 str += "<FRAME left=\"";
583 buf = TQString::number(pos->left); // convert left coordinate to string
584 str += buf;
585
586 str += "\" top=\"";
587 buf = TQString::number(pos->top); // convert top coordinate to string
588 str += buf;
589
590 str += "\" right=\"";
591 buf = TQString::number(pos->right); // convert right coordinate to string
592 str += buf;
593
594 str += "\" bottom=\"";
595 buf = TQString::number(pos->bottom); // convert bottom coordinate to string
596 str += buf;
597
598 str += "\" runaround=\"0\" autoCreateNewFrame=\"0\" newFrameBehavior=\"1\" />\n";
599
600 return;
601
602 } // WriteOutTableCell
603
604
605
606
607bool ASCIIImport::Table( TQString *Line, int *linecount, int no_lines,
608 int table_no, TQString &tbl, TQString &str )
609{
610 return false; // this method is disabled
611
612 /* This method examines a paragraph for embedded tables.
613 If none are found, it returns. If tables are found then it
614 writes out the paragraph including the tables. It does not
615 check for embedded bullet or dash lists which is a seperate
616 method.
617 Arguments
618 TQString *Line - pointer to the array of text lines in the paragraph.
619 int *linecount - pointer to the line counter used to position tables
620 int no_lines - the number of lines in the paragraph
621 int *table_no - pointer to the table number counter
622 TQString str - the output string
623 Returns - enum value indicating wheterer a table was processed. */
624
625 enum LiType{paragraph, table} linetype[MAXLINES];
626 struct Tabs tabs[MAXLINES]; // array of structures for tables
627 struct Position pos; // struct to pass cell position
628 int width[MAXCOLUMNS]; // array of column widths
629 TQString *currentline; // pointer to the current line
630 TQString *beginline; // pointer to the beginning line
631 TQString text; // text buffer
632 TQString text1; // another text buffer
633 TQString No_indents; // Line with leading white space removed
634 int index, index1, index2, index3; // used to define column positions in a line
635
636 int no_cols; // column counter
637 int firstindent;
638 int secondindent;
639 int i; // counter
640 int j; // counter
641 int k; // counter
642 TQString *firstline;
643 firstline = Line;
644 int begin = 0; // beginning line number
645 int tabcount = 0; // counts tab characters
646
647 // check all lines for tabs
648 for(i = 0; i < no_lines; i++)
649 {
650 no_cols = 0; // inilialize the number of columns
651 index = 0; // initialize the line index
652
653 // check the line for leading tabs and indentation
654 if( (tabs[i].indent = Indent( *Line)) > 0)
655 {
656 // save and remove tabs at beginning of the line
657 text = *Line; // copy
658 Line->remove(TQRegExp("^[\\ \t]*"));
659 }
660
661 // find column positions and record text fields
662 while((index2 = Line->find( TQRegExp("\t"),index)) > index
663 || (index3 = MultSpaces( *Line, index)) > index )
664 {
665 index1 = kMax(index2, index3);
666 if( index2 > index3)
667 index1 = Line->find( TQRegExp("[^\t]"), index1);
668 tabcount++;
669 tabs[i].field[no_cols] = Line->mid(index, (index1 - index -1));
670 tabs[i].width[no_cols] = index1 - index + spacespertab - 1;
671
672 no_cols++;
673 index = index1;
674 } // while( (index1 = ...
675
676 // record last column
677 if( no_cols > 0)
678 {
679 index1 = Line->length() - (index + 1); // +1 for space at line end
680 tabs[i].field[no_cols] = Line->mid(index,index1);
681 tabs[i].width[no_cols] = index1;
682 }
683
684 if(tabs[i].indent > 0) *Line = text; // restore original line
685 Line++; // increment the line pointer
686 tabs[i].columns = no_cols;
687 } // for(i = 0; ...
688 // All lines of the paragraph have been checked for tabs
689
690 // check for a tab in at least one line
691 if( tabcount == 0) return false;
692 tabcount = 0;
693
694 Line = firstline; // reset the line pointer
695
696 for(j = 0; j < MAXCOLUMNS; j++) width[j] = 0;
697 for( i = 0; i <= no_lines; i++)
698 {
699 if(tabs[i].columns == 0 ) // indicates no tabs in line
700 {
701 text += *Line; // add line of text to the paragraph
702 linetype[i] = paragraph;
703 }
704
705 else // this means a tabulated line
706 {
707 linetype[i] = table;
708
709 // calculate the column widths
710 for(j = 0; j <= tabs[i].columns; j++)
711 width[j] = kMax(tabs[i].width[j], width[j] );
712 } // else
713
714 if(i > 0)
715 {
716 if( linetype[i] != linetype[(i - 1)] || i == no_lines) // change of type
717 {
718 if( linetype[(begin)] == paragraph ) // write out a paragraph
719 {
720 text = ""; // initialize a null string for paragraph text
721 currentline = firstline;
722 currentline += begin; //starting line
723 beginline = currentline;
724 firstindent = Indent(*currentline);
725 currentline += 1; // second line
726 if( (i - begin) > 1)
727 secondindent = Indent( *currentline );
728 else secondindent = 0;
729
730 for( j= begin; j < i; j++)
731 {
732 text += *beginline; // form text entry
733 beginline++; // increment pointer
734 }
735 // process the white space to eliminate unwanted spaces
736 TQString text1 = text.simplifyWhiteSpace();
737 WriteOutParagraph( "Standard", "", text1 , firstindent, secondindent, str);
738 *linecount += (i - begin);
739
740 } // if( linetype[(i - 1)]
741
742 else // this implies a table
743 {
744 // Write out a blank line to align text and table
745 WriteOutParagraph( "Standard", "", "" , 0, 0, str);
746 for( j = begin; j < i; j++ )
747 {
748 int row = j - begin;
749 pos.top = (double)((*linecount) + 1) * ptsperline;
750 pos.bottom = pos.top + ptsperline;
751 // initialize position of first col
752 pos.left = leftmargin + (double)tabs[i].indent * ptsperchar;
753
754 // write out a cell for each column
755 for( k = 0; k <= tabs[j].columns; k++)
756 {
757
758 text = tabs[j].field[k];
759 // process the white space to eliminate unwanted spaces
760 text1 = text.simplifyWhiteSpace();
761
762 // calculate position of table cell
763 pos.right = pos.left + (double)width[k] * ptsperchar;
764
765 WriteOutTableCell( table_no, row, k, &pos, tbl);
766 WriteOutParagraph( "Standard", "", text1 , 0, 0, tbl);
767 tbl += "</FRAMESET>\n";
768 pos.left += ptsperchar * (double)width[k];
769 } // for( k = 0; ...
770 (*linecount) += 1;
771 } // for( j = begin; ...
772
773
774 } // else...
775 begin = i;
776 } // if( linetype[i]...
777
778 } // if(i > 0)
779 Line++;
780 } // for( i = 0; ...
781
782 (*linecount) += 1;
783
784 return true;
785 } // end of Table()
786#endif
787
788 // the following method finds the location of multiple spaces in a string
789int ASCIIImport::MultSpaces(const TQString& text, const int index) const
790{
791
792 TQChar c;
793 TQChar lastchar = 'c'; // previous character - initialize non blank
794 bool found = false;
795 // kdDebug(30502) << "length = " << text.length() << endl;
796 for (uint i = index; i < text.length(); i++)
797 {
798 c = text.at(i);
799 // kdDebug(30502) << "i = " << i << " found = " << found << " c = " << c << " lastchar = " << lastchar << endl;
800 if ( (c != ' ') && found)
801 return i;
802 else if (c == ' ' && lastchar == ' ')
803 found = true;
804 lastchar = c;
805 }
806 return -1;
807} // MultSpaces
808
809#if 0
810 bool ASCIIImport::ListItem( TQString *Line, int no_lines,
811 TQString &str )
812 {
813
814 /* This method examines a paragraph for embedded lists.
815 If none are found, it returns. If lists are found then it
816 writes out the paragraph including the lists.
817 Arguments
818 TQString *Line - pointer to the array of text lines in the paragraph.
819 int *linecount - pointer to the line counter used to position tables
820 int no_lines - the number of lines in the paragraph
821 TQString &str - the output string
822 Returns - bool value indicating whether a list item was processed. */
823
824
825 TQString *currentline; // pointer to the current line
826 enum Listtype{none, bullet, dash} listtype[MAXLINES];
827 TQString type; // type of list - bullet or dash
828 TQString *firstline;
829 int i; // counter
830 int firstindent;
831 int secondindent;
832 int begin = 0; // beginning line number
833 int listcount = 0; // counts lines with list items
834 firstline = Line;
835
836 // check all lines for list item indicators - or *
837 for(i = 0; i < no_lines; i++)
838 {
839 listtype[i] = none; // initialize
840
841 // check for a bullet list item
842 if( IsListItem( *Line, TQChar('*')))
843 {
844 listtype[i] = bullet;
845 listcount++;
846 }
847 // check for a dash list item
848 if( IsListItem( *Line, TQChar('-')))
849 {
850 listtype[i] = dash;
851 listcount++;
852 }
853
854 Line++; // increment the line pointer
855 } // for(i = 0; ...
856 // All lines of the paragraph have been checked for list items
857
858 // check for at least one list
859 if( listcount == 0) return false;
860
861 TQString text = ""; // initialize a null string for paragraph text
862 Line = firstline; // reset the line pointer
863
864 for( i = 0; i < no_lines; i++)
865 {
866
867 if(i > 0)
868 {
869 if( listtype[i] != none || Line->isEmpty()) // new list item
870 {
871 if( listtype[begin] == bullet) // write out a bullet list
872 {
873 type = "6";
874 // delete * at beginning of line
875 text.remove( TQRegExp("^[ \t]*\\* ") );
876 }
877 else if( listtype[begin] == dash) // write out a dash list
878 {
879 type = "7";
880 // delete - at beginning of line
881 text.remove( TQRegExp("^[ \t]*\\- ") );
882 }
883 else if( listtype[begin] == none) // write out a paragraph
884 type = "";
885
886 currentline = firstline;
887 currentline += begin; //starting line
888 firstindent = Indent(*currentline);
889 if( (i - begin) > 1)
890 {
891 currentline += 1; // second line
892 secondindent = Indent( *currentline );
893 }
894 else secondindent = 0;
895
896 // process the white space to eliminate unwanted spaces
897 TQString text1 = text.simplifyWhiteSpace();
898 WriteOutParagraph( "Standard", type, text1 , firstindent, secondindent, str);
899
900 begin = i;
901 text = ""; // reset text
902
903
904 } // if( listtype[i] != none
905
906
907 } // if(i > 0)
908
909 text += *Line; // add text to paragraph
910 Line++;
911
912 } // for( i = 0; ...
913
914 // write out the last paragraph
915 if( listtype[begin] == bullet) // write out a bullet list
916 {
917 type = "6";
918 // delete * at beginning of line
919 text.replace( TQRegExp("^[ \t]*\\* "), "");
920 }
921 else if( listtype[begin] == dash) // write out a dash list
922 {
923 type = "7";
924 // delete - at beginning of line
925 text.replace( TQRegExp("^[ \t]*\\- "), "");
926 }
927 else if( listtype[begin] == none) // write out a paragraph
928 type = "";
929
930 currentline = firstline;
931 currentline += begin; //starting line
932 firstindent = Indent(*currentline);
933 if( (i - begin) > 1)
934 {
935 currentline += 1; // second line
936 secondindent = Indent( *currentline );
937 }
938 else secondindent = 0;
939
940 // process the white space to eliminate unwanted spaces
941 TQString text1 = text.simplifyWhiteSpace();
942 WriteOutParagraph( "Standard", type, text1 , firstindent, secondindent, str);
943
944
945
946 return true;
947 } // end of ListItem()
948#endif
949
950/* The IsListItem method checks a paragraph's first line and determines if
951 the text appears to be a list item (bullet or dash).
952
953 Arguments
954 TQString FirstLine the first line of text in a paragraph
955 TQChar mark the mark - or * that indicates a list item
956
957 Return
958 true if the line appears as a list item, false if not. */
959
960bool ASCIIImport::IsListItem( TQString FirstLine, TQChar mark )
961 {
962
963 int i; // counter
964 TQChar c; // to stream into one character at a time
965
966
967
968 int k = FirstLine.find(mark);
969
970 if( k < 0) return false; // list item mark not on line
971
972 // find first non white character on the line
973 for( i=0; IsWhiteSpace( c = FirstLine.at((uint)i) ); i++);
974
975 if(i != k ) return false; // mark is in wrong position
976
977 c = FirstLine.at((uint)++i);
978
979 return IsWhiteSpace(c); // character after the mark must be a white space
980
981 } // IsListItem
982
983
984bool ASCIIImport::IsWhiteSpace(const TQChar& c) const
985{
986 if ( c == TQChar(' ') || c == TQChar('\t') )
987 return true;
988 else
989 return false;
990} // IsWhiteSpace
991
992TQString ASCIIImport::readLine(TQTextStream& textstream, bool& lastCharWasCr)
993{
994 // We need to read a line, character by character
995 // NOTE: we cannot use TQStreamText::readLine,
996 // as it does not know anything about Carriage Returns
997 TQString strLine;
998 TQChar ch;
999 while (!textstream.atEnd())
1000 {
1001 textstream >> ch; // Read one character
1002 if (ch=="\n")
1003 {
1004 if (lastCharWasCr)
1005 {
1006 // We have a line feed following a Carriage Return
1007 // As the Carriage Return has already ended the previous line,
1008 // discard this Line Feed.
1009 lastCharWasCr=false;
1010 }
1011 else
1012 {
1013 // We have a normal Line Feed, therefore we end the line
1014 break;
1015 }
1016 }
1017 else if (ch=="\r")
1018 {
1019 // We have a Carriage Return, therefore we end the line
1020 lastCharWasCr=true;
1021 break;
1022 }
1023 else if (ch==char(12)) // Form Feed
1024 {
1025 // Ignore the form feed
1026 continue;
1027 }
1028 else
1029 {
1030 strLine+=ch;
1031 lastCharWasCr=false;
1032 }
1033 } // while
1034 return strLine;
1035}
This class hold a table.