You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/filters/kword/ascii/asciiimport.cc

1036 lines
34 KiB

/* This file is part of the KDE project
Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
Copyright (C) 2000 Michael Johnson <mikej@xnet.com>
Copyright (C) 2001, 2002, 2004 Nicolas GOUTTE <goutte@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <config.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <tqobject.h>
#include <tqstring.h>
// #include <tqregexp.h> // Currently not needed (due to disabled code)
#include <tqtextcodec.h>
#include <tqfile.h>
#include <tqtextstream.h>
#include <tqdom.h>
#include <tqfontinfo.h>
#include <kdebug.h>
#include <tdeglobal.h>
#include <kgenericfactory.h>
#include <KoGlobal.h>
#include <KoPageLayout.h>
#include <KoStore.h>
#include <KoFilterChain.h>
#include <KoFilterManager.h>
#include <asciiimport.h>
#include <asciiimport.moc>
#include "ImportDialog.h"
class ASCIIImportFactory : KGenericFactory<ASCIIImport, KoFilter>
{
public:
ASCIIImportFactory(void) : KGenericFactory<ASCIIImport, KoFilter> ("kwordasciiimport")
{}
protected:
virtual void setupTranslations( void )
{
TDEGlobal::locale()->insertCatalogue( "kofficefilters" );
}
};
K_EXPORT_COMPONENT_FACTORY( libasciiimport, ASCIIImportFactory() )
ASCIIImport::ASCIIImport(KoFilter *, const char *, const TQStringList &) :
KoFilter() {
}
void ASCIIImport::prepareDocument(TQDomDocument& mainDocument, TQDomElement& mainFramesetElement)
{
// TODO: other paper formats
KoFormat paperFormat=PG_DIN_A4; // ISO A4
KoOrientation paperOrientation=PG_PORTRAIT;
mainDocument.appendChild(
mainDocument.createProcessingInstruction(
"xml","version=\"1.0\" encoding=\"UTF-8\""));
TQDomElement elementDoc;
elementDoc=mainDocument.createElement("DOC");
elementDoc.setAttribute("editor","KWord's Plain Text Import Filter");
elementDoc.setAttribute("mime","application/x-kword");
// TODO: We claim to be syntax version 2, but we should verify that it is also true.
elementDoc.setAttribute("syntaxVersion",2);
mainDocument.appendChild(elementDoc);
TQDomElement element;
element=mainDocument.createElement("ATTRIBUTES");
element.setAttribute("processing",0);
element.setAttribute("standardpage",1);
element.setAttribute("hasHeader",0);
element.setAttribute("hasFooter",0);
//element.setAttribute("unit","mm"); // use KWord default instead
elementDoc.appendChild(element);
TQDomElement elementPaper=mainDocument.createElement("PAPER");
elementPaper.setAttribute("format",paperFormat);
elementPaper.setAttribute("width" ,KoPageFormat::width (paperFormat,paperOrientation) * 72.0 / 25.4);
elementPaper.setAttribute("height",KoPageFormat::height(paperFormat,paperOrientation) * 72.0 / 25.4);
elementPaper.setAttribute("orientation",PG_PORTRAIT);
elementPaper.setAttribute("columns",1);
elementPaper.setAttribute("columnspacing",2);
elementPaper.setAttribute("hType",0);
elementPaper.setAttribute("fType",0);
elementPaper.setAttribute("spHeadBody",9);
elementPaper.setAttribute("spFootBody",9);
elementPaper.setAttribute("zoom",100);
elementDoc.appendChild(elementPaper);
element=mainDocument.createElement("PAPERBORDERS");
element.setAttribute("left",28);
element.setAttribute("top",42);
element.setAttribute("right",28);
element.setAttribute("bottom",42);
elementPaper.appendChild(element);
TQDomElement framesetsPluralElementOut=mainDocument.createElement("FRAMESETS");
mainDocument.documentElement().appendChild(framesetsPluralElementOut);
mainFramesetElement=mainDocument.createElement("FRAMESET");
mainFramesetElement.setAttribute("frameType",1);
mainFramesetElement.setAttribute("frameInfo",0);
mainFramesetElement.setAttribute("autoCreateNewFrame",1);
mainFramesetElement.setAttribute("removable",0);
// TODO: "name" attribute (needs I18N)
framesetsPluralElementOut.appendChild(mainFramesetElement);
TQDomElement frameElementOut=mainDocument.createElement("FRAME");
frameElementOut.setAttribute("left",28);
frameElementOut.setAttribute("top",42);
frameElementOut.setAttribute("bottom",566);
frameElementOut.setAttribute("right",798);
frameElementOut.setAttribute("runaround",1);
mainFramesetElement.appendChild(frameElementOut);
TQDomElement elementStylesPlural=mainDocument.createElement("STYLES");
elementDoc.appendChild(elementStylesPlural);
TQDomElement elementStyleStandard=mainDocument.createElement("STYLE");
elementStylesPlural.appendChild(elementStyleStandard);
element=mainDocument.createElement("NAME");
element.setAttribute("value","Standard");
elementStyleStandard.appendChild(element);
element=mainDocument.createElement("FOLLOWING");
element.setAttribute("name","Standard");
elementStyleStandard.appendChild(element);
TQDomElement elementFormat=mainDocument.createElement("FORMAT");
elementStyleStandard.appendChild(elementFormat);
// Use TQFontInfo, as it does not give back -1 as point size.
TQFontInfo defaultFontInfo(KoGlobal::defaultFont());
element=mainDocument.createElement("FONT");
element.setAttribute("name",defaultFontInfo.family());
elementFormat.appendChild(element);
element=mainDocument.createElement("SIZE");
element.setAttribute("value",defaultFontInfo.pointSize());
elementFormat.appendChild(element);
element=mainDocument.createElement("ITALIC");
element.setAttribute("value",0);
elementFormat.appendChild(element);
element=mainDocument.createElement("WEIGHT");
element.setAttribute("value",50);
elementFormat.appendChild(element);
element=mainDocument.createElement("UNDERLINE");
element.setAttribute("value",0);
elementFormat.appendChild(element);
element=mainDocument.createElement("STRIKEOUT");
element.setAttribute("value",0);
elementFormat.appendChild(element);
element=mainDocument.createElement("VERTALIGN");
element.setAttribute("value",0);
elementFormat.appendChild(element);
element=mainDocument.createElement("COLOR");
element.setAttribute("red", -1);
element.setAttribute("green",1);
element.setAttribute("blue", -1);
elementFormat.appendChild(element);
element=mainDocument.createElement("TEXTBACKGROUNDCOLOR");
element.setAttribute("red", -1);
element.setAttribute("green",-1);
element.setAttribute("blue", -1);
elementFormat.appendChild(element);
}
KoFilter::ConversionStatus ASCIIImport::convert( const TQCString& from, const TQCString& to )
{
if (to!="application/x-kword" || from!="text/plain")
return KoFilter::NotImplemented;
AsciiImportDialog* dialog = 0;
if (!m_chain->manager()->getBatchMode())
{
dialog = new AsciiImportDialog();
if (!dialog)
{
kdError(30502) << "Dialog has not been created! Aborting!" << endl;
return KoFilter::StupidError;
}
if (!dialog->exec())
{
kdDebug(30502) << "Dialog was aborted! Aborting filter!" << endl; // this isn't an error!
return KoFilter::UserCancelled;
}
}
TQTextCodec* codec;
int paragraphStrategy;
if (dialog)
{
codec = dialog->getCodec();
paragraphStrategy=dialog->getParagraphStrategy();
delete dialog;
}
else
{
codec = TQTextCodec::codecForName("UTF-8");
paragraphStrategy=0;
}
TQFile in(m_chain->inputFile());
if(!in.open(IO_ReadOnly)) {
kdError(30502) << "Unable to open input file!" << endl;
in.close();
return KoFilter::FileNotFound;
}
TQString tbl; // string for table XML
TQDomDocument mainDocument;
TQDomElement mainFramesetElement;
prepareDocument(mainDocument,mainFramesetElement);
TQTextStream stream(&in);
if (!codec)
{
kdError(30502) << "Could not create TQTextCodec! Aborting" << endl;
in.close();
return KoFilter::StupidError;
}
kdDebug(30502) << "Charset used: " << codec->name() << endl;
stream.setCodec(codec);
if (1==paragraphStrategy)
sentenceConvert(stream, mainDocument, mainFramesetElement);
else if (999==paragraphStrategy)
oldWayConvert(stream, mainDocument, mainFramesetElement);
else
asIsConvert(stream, mainDocument, mainFramesetElement);
#if 0
kdDebug(30502) << mainDocument.toString() << endl;
#endif
KoStoreDevice* out=m_chain->storageFile( "root", KoStore::Write );
if(!out) {
kdError(30502) << "Unable to open output file!" << endl;
in.close();
return KoFilter::StorageCreationError;
}
TQCString cstr=mainDocument.toCString();
// WARNING: we cannot use KoStore::write(const TQByteArray&) because it gives an extra NULL character at the end.
out->writeBlock(cstr,cstr.length());
in.close();
return KoFilter::OK;
}
void ASCIIImport::oldWayConvert(TQTextStream& stream, TQDomDocument& mainDocument,
TQDomElement& mainFramesetElement)
{
kdDebug(30502) << "Entering: ASCIIImport::oldWayConvert" << endl;
TQStringList paragraph; // lines of the paragraph
int linecount = 0; // line counter used to position tables
//int table_no = 0; // used for table identifiers
int numLines; // Number of lines of the paragraph
bool lastCharWasCr=false; // Was the previous character a Carriage Return?
TQString strLine;
while(!stream.atEnd())
{
paragraph.clear();
// Read in paragraph
for(int line_no = numLines = 0; line_no < MAXLINES; line_no++, numLines++)
{
// We need to read a line
// NOTE: we cannot use TQStreamText::readLine,
// as it does not know anything about Carriage Returns
strLine=readLine(stream,lastCharWasCr);
if (strLine.isEmpty())
{
paragraph.append(TQString());
break;
}
const int length = strLine.length();
if (strLine.at(length-1) == '-')
// replace the hard hyphen - at line end by a soft hyphen
strLine.at(length-1)=TQChar(173);
else
strLine += ' '; // add space to end of line
paragraph.append(strLine);
} // for(line_no = 0;
// process tables
#if 0
if ( Table( &Line[0], &linecount, numLines, table_no, tbl, str))
table_no++;
else
#else
if (true)
#endif
{
// Process bullet and dash lists
#if 0
if(ListItem( &Line[0], numLines, str))
linecount += (numLines + 1);
else
{
#else
if (true)
{
#endif
processParagraph(mainDocument,mainFramesetElement,paragraph);
linecount += ( numLines + 1); // increment the line count
} // else
} // else
} // while(!eof)
#if 0
// Add table info
if( table_no > 0) str += tbl;
#endif
}
void ASCIIImport::asIsConvert(TQTextStream& stream, TQDomDocument& mainDocument,
TQDomElement& mainFramesetElement)
// Paragraph strategy: one line, one paragraph
{
kdDebug(30502) << "Entering: ASCIIImport::asIsConvert" << endl;
bool lastCharWasCr=false; // Was the previous character a Carriage Return?
TQString strLine;
while(!stream.atEnd())
{
// Read one line and consider it being a paragraph
strLine=readLine(stream,lastCharWasCr);
writeOutParagraph(mainDocument,mainFramesetElement, "Standard", strLine,
0, 0);
}
}
void ASCIIImport::sentenceConvert(TQTextStream& stream, TQDomDocument& mainDocument,
TQDomElement& mainFramesetElement)
// Strategy:
// - end a paragraph when a line ends with a point or similar punctuation.
// - search the punctuation at the end of the line, even if the sentence is quoted or in parentheses.
// - an empty line also ends the paragraph
// TODO/FIXME: we have a little problem with empty lines. Perhaps we should not allow empty paragraphs!
{
kdDebug(30502) << "Entering: ASCIIImport::sentenceConvert" << endl;
TQStringList paragraph; // lines of the paragraph
bool lastCharWasCr=false; // Was the previous character a Carriage Return?
TQString strLine;
TQString stoppingPunctuation(".!?");
TQString skippingQuotes("\"')");
while (!stream.atEnd())
{
paragraph.clear();
for(;;)
{
// We need to read a line
// NOTE: we cannot use TQStreamText::readLine,
// as it does not know anything about Carriage Returns
strLine=readLine(stream,lastCharWasCr);
if (strLine.isEmpty())
{
break;
}
paragraph.append(strLine);
uint lastPos=strLine.length()-1;
TQChar lastChar;
// Skip a maximum of 10 quotes (or similar) at the end of the line
for (int i=0;i<10;i++)
{
lastChar=strLine[lastPos];
if (lastChar.isNull())
break;
else if (skippingQuotes.find(lastChar)==-1)
break;
else
lastPos--;
}
lastChar=strLine[lastPos];
if (lastChar.isNull())
continue;
else if (stoppingPunctuation.find(lastChar)!=-1)
break;
}
#if 1
writeOutParagraph(mainDocument,mainFramesetElement, "Standard",
paragraph.join(" ").simplifyWhiteSpace(), 0, 0);
#else
// FIXME/TODO: why is this not working?
//processParagraph(mainDocument,mainFramesetElement,paragraph);
#endif
} // while(!eof)
}
void ASCIIImport::processParagraph(TQDomDocument& mainDocument,
TQDomElement& mainFramesetElement, const TQStringList& paragraph)
{
// Paragraph with no tables or lists
TQString text;
TQStringList::ConstIterator it=paragraph.begin(); // Current line (at start, the first one)
TQStringList::ConstIterator previousLine=it; // The previous one (at start, also the first one)
int firstindent=Indent(*it);
// We work with one line in advance (therefore the two it++)
for( it++; it!=paragraph.end(); it++)
{
text += *previousLine; // add previous line to paragraph
// check for a short line - if short make it a paragraph
if( (*previousLine).length() <= shortline)
{
if((*it).length() > shortline)
// skip if short last line of normal paragraph
{
const int secondindent = Indent(*previousLine);
writeOutParagraph(mainDocument,mainFramesetElement,
"Standard", text.simplifyWhiteSpace(), firstindent, secondindent);
firstindent = Indent(*it);
text = TQString(); // reinitialize paragraph text
}
}
previousLine=it;
}
// write out paragraph begin to end
const int secondindent = Indent(*previousLine);
writeOutParagraph(mainDocument,mainFramesetElement,
"Standard", text.simplifyWhiteSpace(), firstindent, secondindent);
}
void ASCIIImport::writeOutParagraph(TQDomDocument& mainDocument,
TQDomElement& mainFramesetElement, const TQString& name,
const TQString& text, const int firstindent, const int secondindent)
{
TQDomElement paragraphElementOut=mainDocument.createElement("PARAGRAPH");
mainFramesetElement.appendChild(paragraphElementOut);
TQDomElement textElement=mainDocument.createElement("TEXT");
paragraphElementOut.appendChild(textElement);
//TQDomElement formatsPluralElementOut=mainDocument.createElement("FORMATS");
//paragraphElementOut.appendChild(formatsPluralElementOut);
TQDomElement layoutElement=mainDocument.createElement("LAYOUT");
paragraphElementOut.appendChild(layoutElement);
TQDomElement element;
element=mainDocument.createElement("NAME");
element.setAttribute("value",name);
layoutElement.appendChild(element);
double size;
element=mainDocument.createElement("INDENTS");
size = firstindent-secondindent;
size *= ptsperchar; // convert indent spaces to points
element.setAttribute("first",TQString::number(size));
size = secondindent;
size *= ptsperchar; // convert indent spaces to points
element.setAttribute("left",TQString::number(size));
element.setAttribute("right",0);
textElement.appendChild(mainDocument.createTextNode(text));
textElement.normalize(); // Put text together (not sure if needed)
#if 0
// If the paragraph is indented, write out indentation elements.
// TODO: why not always write identation?
if (firstindent > 0 || secondindent > 0) \
WriteOutIndents( firstindent, secondindent, str);
// If this is a bullet or a dash list, write out a COUNTER element
if(type.isEmpty())
{
str += "<COUNTER type=\"";
str += type; // "6" = bullet "7" = dash
str += "\" depth=\"0\" start=\"1\" numberingtype=\"0\" lefttext=\"\" righttext=\".\" />\n";
}
str += "<FORMAT>\n";
// for now we try with style (TODO: verify that KWord 1.2 works correctly)
//str += "<FONT name=\"times\"/>\n";
str += "</FORMAT>\n";
str += "</LAYOUT>\n";
str += "</PARAGRAPH>\n";
#endif
} // WriteOutParagraph
/* The Indent method determines the equivalent number of spaces
at the beginning of a line */
int ASCIIImport::Indent(const TQString& line) const
{
TQChar c; // for reading string a character at a time
int count=0; // amount of white space at the begining of the line
for( uint i = 0; i < line.length(); i++ )
{
c = line.at(i);
if( c == TQChar(' '))
count++;
else if( c == TQChar('\t'))
count += spacespertab;
else
break;
}
return count;
} // Indent
/* The WriteOutTableCell method writes out a single table cell
in Kword XML to the output string str. The table is sized according
to the spacing in the ascii document.
Arguments
int table_no - used to keep the group number count
int row - row number
int col - column number
Position *pos - pointer to the table position
TQString str - the output string.
Returns - void
*/
#if 0
void ASCIIImport::WriteOutTableCell( int table_no, int row,
int col, Position *pos, TQString &str)
{
str += "<FRAMESET frameType=\"1\" frameInfo=\"0\" grpMgr=\"grpmgr_";
TQString buf = TQString::number(table_no); // convert int to string
str += buf;
str += "\" row=\"";
buf = TQString::number(row); // convert row to string
str += buf;
str += "\" col=\"";
buf = TQString::number(col); // convert col to string
str += buf;
str += "\" rows=\"1\" cols=\"1\" removable=\"0\" visible=\"1\" name=\"Cell ";
buf = TQString::number(row); // convert row to string
str += buf;
str += ",";
buf = TQString::number(col); // convert col to string
str += buf;
str += "\">\n";
str += "<FRAME left=\"";
buf = TQString::number(pos->left); // convert left coordinate to string
str += buf;
str += "\" top=\"";
buf = TQString::number(pos->top); // convert top coordinate to string
str += buf;
str += "\" right=\"";
buf = TQString::number(pos->right); // convert right coordinate to string
str += buf;
str += "\" bottom=\"";
buf = TQString::number(pos->bottom); // convert bottom coordinate to string
str += buf;
str += "\" runaround=\"0\" autoCreateNewFrame=\"0\" newFrameBehavior=\"1\" />\n";
return;
} // WriteOutTableCell
bool ASCIIImport::Table( TQString *Line, int *linecount, int no_lines,
int table_no, TQString &tbl, TQString &str )
{
return false; // this method is disabled
/* This method examines a paragraph for embedded tables.
If none are found, it returns. If tables are found then it
writes out the paragraph including the tables. It does not
check for embedded bullet or dash lists which is a seperate
method.
Arguments
TQString *Line - pointer to the array of text lines in the paragraph.
int *linecount - pointer to the line counter used to position tables
int no_lines - the number of lines in the paragraph
int *table_no - pointer to the table number counter
TQString str - the output string
Returns - enum value indicating wheterer a table was processed. */
enum LiType{paragraph, table} linetype[MAXLINES];
struct Tabs tabs[MAXLINES]; // array of structures for tables
struct Position pos; // struct to pass cell position
int width[MAXCOLUMNS]; // array of column widths
TQString *currentline; // pointer to the current line
TQString *beginline; // pointer to the beginning line
TQString text; // text buffer
TQString text1; // another text buffer
TQString No_indents; // Line with leading white space removed
int index, index1, index2, index3; // used to define column positions in a line
int no_cols; // column counter
int firstindent;
int secondindent;
int i; // counter
int j; // counter
int k; // counter
TQString *firstline;
firstline = Line;
int begin = 0; // beginning line number
int tabcount = 0; // counts tab characters
// check all lines for tabs
for(i = 0; i < no_lines; i++)
{
no_cols = 0; // inilialize the number of columns
index = 0; // initialize the line index
// check the line for leading tabs and indentation
if( (tabs[i].indent = Indent( *Line)) > 0)
{
// save and remove tabs at beginning of the line
text = *Line; // copy
Line->remove(TQRegExp("^[\\ \t]*"));
}
// find column positions and record text fields
while((index2 = Line->find( TQRegExp("\t"),index)) > index
|| (index3 = MultSpaces( *Line, index)) > index )
{
index1 = kMax(index2, index3);
if( index2 > index3)
index1 = Line->find( TQRegExp("[^\t]"), index1);
tabcount++;
tabs[i].field[no_cols] = Line->mid(index, (index1 - index -1));
tabs[i].width[no_cols] = index1 - index + spacespertab - 1;
no_cols++;
index = index1;
} // while( (index1 = ...
// record last column
if( no_cols > 0)
{
index1 = Line->length() - (index + 1); // +1 for space at line end
tabs[i].field[no_cols] = Line->mid(index,index1);
tabs[i].width[no_cols] = index1;
}
if(tabs[i].indent > 0) *Line = text; // restore original line
Line++; // increment the line pointer
tabs[i].columns = no_cols;
} // for(i = 0; ...
// All lines of the paragraph have been checked for tabs
// check for a tab in at least one line
if( tabcount == 0) return false;
tabcount = 0;
Line = firstline; // reset the line pointer
for(j = 0; j < MAXCOLUMNS; j++) width[j] = 0;
for( i = 0; i <= no_lines; i++)
{
if(tabs[i].columns == 0 ) // indicates no tabs in line
{
text += *Line; // add line of text to the paragraph
linetype[i] = paragraph;
}
else // this means a tabulated line
{
linetype[i] = table;
// calculate the column widths
for(j = 0; j <= tabs[i].columns; j++)
width[j] = kMax(tabs[i].width[j], width[j] );
} // else
if(i > 0)
{
if( linetype[i] != linetype[(i - 1)] || i == no_lines) // change of type
{
if( linetype[(begin)] == paragraph ) // write out a paragraph
{
text = ""; // initialize a null string for paragraph text
currentline = firstline;
currentline += begin; //starting line
beginline = currentline;
firstindent = Indent(*currentline);
currentline += 1; // second line
if( (i - begin) > 1)
secondindent = Indent( *currentline );
else secondindent = 0;
for( j= begin; j < i; j++)
{
text += *beginline; // form text entry
beginline++; // increment pointer
}
// process the white space to eliminate unwanted spaces
TQString text1 = text.simplifyWhiteSpace();
WriteOutParagraph( "Standard", "", text1 , firstindent, secondindent, str);
*linecount += (i - begin);
} // if( linetype[(i - 1)]
else // this implies a table
{
// Write out a blank line to align text and table
WriteOutParagraph( "Standard", "", "" , 0, 0, str);
for( j = begin; j < i; j++ )
{
int row = j - begin;
pos.top = (double)((*linecount) + 1) * ptsperline;
pos.bottom = pos.top + ptsperline;
// initialize position of first col
pos.left = leftmargin + (double)tabs[i].indent * ptsperchar;
// write out a cell for each column
for( k = 0; k <= tabs[j].columns; k++)
{
text = tabs[j].field[k];
// process the white space to eliminate unwanted spaces
text1 = text.simplifyWhiteSpace();
// calculate position of table cell
pos.right = pos.left + (double)width[k] * ptsperchar;
WriteOutTableCell( table_no, row, k, &pos, tbl);
WriteOutParagraph( "Standard", "", text1 , 0, 0, tbl);
tbl += "</FRAMESET>\n";
pos.left += ptsperchar * (double)width[k];
} // for( k = 0; ...
(*linecount) += 1;
} // for( j = begin; ...
} // else...
begin = i;
} // if( linetype[i]...
} // if(i > 0)
Line++;
} // for( i = 0; ...
(*linecount) += 1;
return true;
} // end of Table()
#endif
// the following method finds the location of multiple spaces in a string
int ASCIIImport::MultSpaces(const TQString& text, const int index) const
{
TQChar c;
TQChar lastchar = 'c'; // previous character - initialize non blank
bool found = false;
// kdDebug(30502) << "length = " << text.length() << endl;
for (uint i = index; i < text.length(); i++)
{
c = text.at(i);
// kdDebug(30502) << "i = " << i << " found = " << found << " c = " << c << " lastchar = " << lastchar << endl;
if ( (c != ' ') && found)
return i;
else if (c == ' ' && lastchar == ' ')
found = true;
lastchar = c;
}
return -1;
} // MultSpaces
#if 0
bool ASCIIImport::ListItem( TQString *Line, int no_lines,
TQString &str )
{
/* This method examines a paragraph for embedded lists.
If none are found, it returns. If lists are found then it
writes out the paragraph including the lists.
Arguments
TQString *Line - pointer to the array of text lines in the paragraph.
int *linecount - pointer to the line counter used to position tables
int no_lines - the number of lines in the paragraph
TQString &str - the output string
Returns - bool value indicating whether a list item was processed. */
TQString *currentline; // pointer to the current line
enum Listtype{none, bullet, dash} listtype[MAXLINES];
TQString type; // type of list - bullet or dash
TQString *firstline;
int i; // counter
int firstindent;
int secondindent;
int begin = 0; // beginning line number
int listcount = 0; // counts lines with list items
firstline = Line;
// check all lines for list item indicators - or *
for(i = 0; i < no_lines; i++)
{
listtype[i] = none; // initialize
// check for a bullet list item
if( IsListItem( *Line, TQChar('*')))
{
listtype[i] = bullet;
listcount++;
}
// check for a dash list item
if( IsListItem( *Line, TQChar('-')))
{
listtype[i] = dash;
listcount++;
}
Line++; // increment the line pointer
} // for(i = 0; ...
// All lines of the paragraph have been checked for list items
// check for at least one list
if( listcount == 0) return false;
TQString text = ""; // initialize a null string for paragraph text
Line = firstline; // reset the line pointer
for( i = 0; i < no_lines; i++)
{
if(i > 0)
{
if( listtype[i] != none || Line->isEmpty()) // new list item
{
if( listtype[begin] == bullet) // write out a bullet list
{
type = "6";
// delete * at beginning of line
text.remove( TQRegExp("^[ \t]*\\* ") );
}
else if( listtype[begin] == dash) // write out a dash list
{
type = "7";
// delete - at beginning of line
text.remove( TQRegExp("^[ \t]*\\- ") );
}
else if( listtype[begin] == none) // write out a paragraph
type = "";
currentline = firstline;
currentline += begin; //starting line
firstindent = Indent(*currentline);
if( (i - begin) > 1)
{
currentline += 1; // second line
secondindent = Indent( *currentline );
}
else secondindent = 0;
// process the white space to eliminate unwanted spaces
TQString text1 = text.simplifyWhiteSpace();
WriteOutParagraph( "Standard", type, text1 , firstindent, secondindent, str);
begin = i;
text = ""; // reset text
} // if( listtype[i] != none
} // if(i > 0)
text += *Line; // add text to paragraph
Line++;
} // for( i = 0; ...
// write out the last paragraph
if( listtype[begin] == bullet) // write out a bullet list
{
type = "6";
// delete * at beginning of line
text.replace( TQRegExp("^[ \t]*\\* "), "");
}
else if( listtype[begin] == dash) // write out a dash list
{
type = "7";
// delete - at beginning of line
text.replace( TQRegExp("^[ \t]*\\- "), "");
}
else if( listtype[begin] == none) // write out a paragraph
type = "";
currentline = firstline;
currentline += begin; //starting line
firstindent = Indent(*currentline);
if( (i - begin) > 1)
{
currentline += 1; // second line
secondindent = Indent( *currentline );
}
else secondindent = 0;
// process the white space to eliminate unwanted spaces
TQString text1 = text.simplifyWhiteSpace();
WriteOutParagraph( "Standard", type, text1 , firstindent, secondindent, str);
return true;
} // end of ListItem()
#endif
/* The IsListItem method checks a paragraph's first line and determines if
the text appears to be a list item (bullet or dash).
Arguments
TQString FirstLine the first line of text in a paragraph
TQChar mark the mark - or * that indicates a list item
Return
true if the line appears as a list item, false if not. */
bool ASCIIImport::IsListItem( TQString FirstLine, TQChar mark )
{
int i; // counter
TQChar c; // to stream into one character at a time
int k = FirstLine.find(mark);
if( k < 0) return false; // list item mark not on line
// find first non white character on the line
for( i=0; IsWhiteSpace( c = FirstLine.at((uint)i) ); i++);
if(i != k ) return false; // mark is in wrong position
c = FirstLine.at((uint)++i);
return IsWhiteSpace(c); // character after the mark must be a white space
} // IsListItem
bool ASCIIImport::IsWhiteSpace(const TQChar& c) const
{
if ( c == TQChar(' ') || c == TQChar('\t') )
return true;
else
return false;
} // IsWhiteSpace
TQString ASCIIImport::readLine(TQTextStream& textstream, bool& lastCharWasCr)
{
// We need to read a line, character by character
// NOTE: we cannot use TQStreamText::readLine,
// as it does not know anything about Carriage Returns
TQString strLine;
TQChar ch;
while (!textstream.atEnd())
{
textstream >> ch; // Read one character
if (ch=="\n")
{
if (lastCharWasCr)
{
// We have a line feed following a Carriage Return
// As the Carriage Return has already ended the previous line,
// discard this Line Feed.
lastCharWasCr=false;
}
else
{
// We have a normal Line Feed, therefore we end the line
break;
}
}
else if (ch=="\r")
{
// We have a Carriage Return, therefore we end the line
lastCharWasCr=true;
break;
}
else if (ch==char(12)) // Form Feed
{
// Ignore the form feed
continue;
}
else
{
strLine+=ch;
lastCharWasCr=false;
}
} // while
return strLine;
}