filters

para.cc

00001 /*
00002 ** A program to convert the XML rendered by KWord into LATEX.
00003 **
00004 ** Copyright (C) 2000, 2001, 2002 Robert JACOLIN
00005 **
00006 ** This library is free software; you can redistribute it and/or
00007 ** modify it under the terms of the GNU Library General Public
00008 ** License as published by the Free Software Foundation; either
00009 ** version 2 of the License, or (at your option) any later version.
00010 **
00011 ** This library is distributed in the hope that it will be useful,
00012 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** Library General Public License for more details.
00015 **
00016 ** To receive a copy of the GNU Library General Public License, write to the
00017 ** Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 **
00020 */
00021 
00022 #include <stdlib.h>     /* for atoi function    */
00023 #include <kdebug.h>     /* for kdDebug() stream */
00024 #include "para.h"
00025 #include "textFrame.h"      /* father class.        */
00026 #include "format.h"     /* children classes.    */
00027 //#include "picturezone.h"
00028 #include "fileheader.h"
00029 #include "textzone.h"
00030 #include "variablezone.h"
00031 #include "footnote.h"
00032 #include "anchor.h"
00033 
00034 /* static data */
00035 QPtrStack<EType> Para::_historicList;
00036 int Para::_tabulation = 0;
00037 
00038 /*******************************************/
00039 /* Constructor                             */
00040 /*******************************************/
00041 Para::Para(TextFrame* textFrame)
00042 {
00043     _element    = textFrame;
00044     _lines      = 0;
00045     _name       = 0;
00046     _info       = EP_NONE;  /* the parag is not a footnote */
00047     //_hardbrk   = EP_FLOW; /* and it's not a new page */
00048     _currentPos = 0;        /* At the beginning of the paragraph */
00049     _tabulation = 0;
00050     _text = "";
00051 }
00052 
00053 /*******************************************/
00054 /* Destructor                              */
00055 /*******************************************/
00056 Para::~Para()
00057 {
00058     kdDebug(30522) << "Destruction of a parag." << endl;
00059     if(_lines != 0)
00060         delete _lines;
00061 }
00062 
00063 /*******************************************/
00064 /* GetFrameType                            */
00065 /*******************************************/
00066 /* To know if it's the text or it's a      */
00067 /* header or a footer.                     */
00068 /*******************************************/
00069 SSect Para::getFrameType() const
00070 {
00071     return _element->getSection();
00072 }
00073 
00074 /*******************************************/
00075 /* getTypeFormat                           */
00076 /*******************************************/
00077 /* To know if the zone is a textzone, a    */
00078 /* footnote, a picture, a variable.        */
00079 /*******************************************/
00080 EFormat Para::getTypeFormat(const QDomNode balise) const
00081 {
00082     //<FORMAT id="1" ...>
00083 
00084     return (EFormat) getAttr(balise, "id").toInt();
00085 }
00086 
00087 /*******************************************/
00088 /* getNbCharPara                           */
00089 /*******************************************/
00090 /* To know the size of a paragraph.        */
00091 /*******************************************/
00092 int Para::getNbCharPara() const
00093 {
00094     int nb = 0;
00095     Format* zone = 0;
00096 
00097     if(_lines != 0)
00098     {
00099         kdDebug(30522) << "  NB ZONE : " << _lines->count() << endl;
00100 
00101         for(zone = _lines->first(); zone != 0; zone = _lines->next())
00102         {
00103             switch(zone->getId())
00104             {
00105                 case EF_TEXTZONE:
00106                         nb = nb + ((TextZone*) zone)->getSize();
00107                     break;
00108                 case EF_PICTURE:
00109                     break;
00110                 case EF_TABULATOR:
00111                     break;
00112                 case EF_VARIABLE:
00113                     break;
00114                 case EF_FOOTNOTE:
00115                     break;
00116                 case EF_ANCHOR:
00117                     break;
00118                 case EF_ERROR:
00119                     break;
00120             }
00121         }
00122     }
00123     return nb;
00124 }
00125 
00126 /*******************************************/
00127 /* Analyse                                 */
00128 /*******************************************/
00129 void Para::analyse(const QDomNode balise)
00130 {
00131     /* MARKUP TYPE :  PARAGRAPH */
00132 
00133     kdDebug(30522) << "**** PARAGRAPH ****" << endl;
00134 
00135     /* Analyse of the children markups */
00136     for(int index = 0; index < getNbChild(balise); index++)
00137     {
00138         if(getChildName(balise, index).compare("TEXT")== 0)
00139         {
00140             _text =  getData(balise, index);
00141             kdDebug(30522) << "TEXT : " << _text << endl;
00142         }
00143         else if(getChildName(balise, index).compare("NAME")== 0)
00144         {
00145             analyseName(getChild(balise, index));
00146         }
00147         else if(getChildName(balise, index).compare("INFO")== 0)
00148         {
00149             analyseInfo(getChild(balise, index));
00150         }
00151         /*else if(getChildName(balise, index).compare("HARDBRK")== 0)
00152         {
00153             analyseBrk(getChild(balise, index));
00154         }*/
00155         else if(getChildName(balise, index).compare("FORMATS")== 0)
00156         {
00157             // IMPORTANT ==> police + style
00158             kdDebug(30522) << "FORMATS" << endl;
00159             analyseFormats(getChild(balise, index));
00160 
00161         }
00162         else if(getChildName(balise, index).compare("LAYOUT")== 0)
00163         {
00164             kdDebug(30522) << "LAYOUT" << endl;
00165             analyseLayoutPara(getChild(balise, index));
00166         }
00167     }
00168     kdDebug(30522) << " **** END PARAGRAPH ****" << endl;
00169 }
00170 
00171 /*******************************************/
00172 /* AnalyseName                             */
00173 /*******************************************/
00174 /* If a footnote have a name : it's a      */
00175 /* footnote/endnote.                       */
00176 /*******************************************/
00177 void Para::analyseName(const QDomNode balise)
00178 {
00179     /* <NAME name="Footnote/Endnote_1"> */
00180 
00181     _name = new QString(getAttr(balise, "NAME"));
00182 }
00183 
00184 /*******************************************/
00185 /* AnalyseInfo                             */
00186 /*******************************************/
00187 /* Type of the parag. : if info is 1, it's */
00188 /* a footnote/endnote (so it have a name). */
00189 /*******************************************/
00190 void Para::analyseInfo(const QDomNode balise)
00191 {
00192     /* <INFO info="1"> */
00193 
00194     _info = (EP_INFO) getAttr(balise, "INFO").toInt();
00195 }
00196 
00197 /*******************************************/
00198 /* AnalyseBrk                              */
00199 /*******************************************/
00200 /* There is a new page before this         */
00201 /* paragraph.                              */
00202 /*******************************************/
00203 /*void Para::analyseBrk(const QDomNode balise)
00204 {
00205     //<NAME name="Footnote/Endnote_1">
00206 
00207     _hardbrk = (EP_HARDBRK) getAttr(balise, "FRAME").toInt();
00208 }*/
00209 
00210 /*******************************************/
00211 /* AnalyseLayoutPara                       */
00212 /*******************************************/
00213 /* Analyse the layout of a para.           */
00214 /* For each format, keep the type (picture,*/
00215 /* text, variable, footnote) and put the   */
00216 /* zone in a list.                         */
00217 /*******************************************/
00218 void Para::analyseLayoutPara(const QDomNode balise)
00219 {
00220     Format* zone = 0;
00221 
00222     analyseLayout(balise);
00223     for(int index= 0; index < getNbChild(balise); index++)
00224     {
00225         if(getChildName(balise, index).compare("FORMAT")== 0)
00226         {
00227             //analyseFormat(balise);
00228             /* No more format : verify if all the text zone has been formated */
00229             if(_currentPos != _text.length())
00230             {
00231                 zone = new TextZone(_text, this);
00232                 ((TextZone*) zone)->setPos(_currentPos);
00233                 ((TextZone*) zone)->setLength(_currentPos - _text.length());
00234                 ((TextZone*) zone)->analyse();
00235                 if(_lines == 0)
00236                     _lines = new QPtrList<Format>;
00237                 /* add the text */
00238                 _lines->append(zone);
00239                 _currentPos = _currentPos + ((TextZone*) zone)->getLength();
00240 
00241             }
00242         }
00243         /*else
00244             kdDebug(30522) << " FORMAT FIELD UNKNOWN" << endl;*/
00245     }
00246 }
00247 
00248 /*******************************************/
00249 /* AnalyseFormats                          */
00250 /*******************************************/
00251 /* Analyse several formats.                */
00252 /*  keep the type (picture, text, variable,*/
00253 /* footnote) and put the zone in a list.   */
00254 /*******************************************/
00255 void Para::analyseFormats(const QDomNode balise)
00256 {
00257     for(int index= 0; index < getNbChild(balise, "FORMAT"); index++)
00258     {
00259         if(getChildName(balise, index).compare("FORMAT")== 0)
00260         {
00261             kdDebug(30522) << "A FORMAT !!!" << endl;
00262             analyseFormat(getChild(balise, index));
00263         }
00264         else
00265             kdDebug(30522) << " FORMAT UNUSEFULL HERE" << endl;
00266     }
00267 }
00268 
00269 /*******************************************/
00270 /* AnalyseFormat                           */
00271 /*******************************************/
00272 /* Analyse one format.                     */
00273 /*  keep the type (picture, text, variable,*/
00274 /* footnote) and put the zone in a list.   */
00275 /*******************************************/
00276 void Para::analyseFormat(const QDomNode balise)
00277 {
00278     Format *zone      = 0;
00279     Format *zoneFirst = 0;
00280 
00281     kdDebug(30522) << "ANALYSE FORMAT BODY" << endl;
00282     switch(getTypeFormat(balise))
00283     {
00284         case EF_ERROR: kdDebug(30522) << "Id format error" << endl;
00285             break;
00286         case EF_TEXTZONE: /* It's a text line (1) */
00287                 zone = new TextZone(_text, this);
00288                 if(_currentPos != _text.length())
00289                 {
00290                     zone->analyse(balise);
00291                     if(zone->getPos() != _currentPos)
00292                     {
00293                         if(_lines == 0)
00294                             _lines = new QPtrList<Format>;
00295                             /* Create first a default format */
00296                         zoneFirst = new TextZone(_text, this);
00297                         zoneFirst->setPos(_currentPos);
00298                         zoneFirst->setLength(zone->getPos() - _currentPos);
00299                         ((TextZone*) zoneFirst)->analyse();
00300 
00301                         /* Add the text without format */
00302                         _lines->append(zoneFirst);
00303                         _currentPos = _currentPos + ((TextZone*) zoneFirst)->getLength();
00304                     }
00305                 }
00306             break;
00307         case EF_PICTURE: /* It's a picture (2) */
00308                 /*zone = new PictureZone(this);
00309                 zone->analyse(balise);*/
00310             break;
00311         case EF_VARIABLE: /* It's a variable (4) */
00312                 zone = new VariableZone(this);
00313                 zone->analyse(balise);
00314             break;
00315         case EF_FOOTNOTE: /* It's a footnote (5) */
00316                 zone = new Footnote(this);
00317                 zone->analyse(balise);
00318             break;
00319         case EF_ANCHOR: /* It's an anchor (6) */
00320                 zone = new Anchor(this);
00321                 zone->analyse(balise);
00322             break;
00323         default: /* Unknown */
00324                 kdDebug(30522) << "Format not yet supported" << endl;
00325     }
00326 
00327     if(zone->getPos() != _currentPos)
00328     {
00329         if(_lines == 0)
00330             _lines = new QPtrList<Format>;
00331             /* Create first a default format */
00332         zoneFirst = new TextZone(_text, this);
00333         zoneFirst->setPos(_currentPos);
00334         zoneFirst->setLength(zone->getPos() - _currentPos);
00335         ((TextZone*) zoneFirst)->analyse();
00336         kdDebug(30522) << "pos courante : " << _currentPos << endl;
00337         /* Add the text without format */
00338         _lines->append(zoneFirst);
00339         _currentPos = _currentPos + zoneFirst->getLength();
00340     }
00341 
00342     if(zone != 0)
00343     {
00344         if(_lines == 0)
00345             _lines = new QPtrList<Format>;
00346 
00347         /* add the text */
00348         _lines->append(zone);
00349         _currentPos = _currentPos + zone->getLength();
00350     }
00351 }
00352 
00353 /*******************************************/
00354 /* Generate                                */
00355 /*******************************************/
00356 /* Generate each text zone with the parag. */
00357 /* markup.                                 */
00358 /*******************************************/
00359 void Para::generate(QTextStream &out)
00360 {
00361 
00362     kdDebug(30522) << "  GENERATION PARA" << endl;
00363 
00364     if(getInfo() != EP_FOOTNOTE && getFrameType() != SS_HEADERS &&
00365        getFrameType() != SS_FOOTERS)
00366     {
00367         /* We generate center, itemize tag and new page only for
00368          * parag not for footnote
00369          * If a parag. have a special format (begining)
00370          */
00371         if(isHardBreak())
00372             out << "\\newpage" << endl;
00373         generateDebut(out);
00374     }
00375 
00376     /* If text is a \n, then it's a break line. */
00377     if(_text == "\n")
00378         out << "\\\\" << endl;
00379     else if(_lines != 0)
00380     {
00381         Format* zone = 0;
00382         kdDebug(30522) << "  NB ZONE : " << _lines->count() << endl;
00383 
00384         for(zone = _lines->first(); zone != 0; zone = _lines->next())
00385         {
00386             zone->generate(out);
00387         }
00388         /* To separate the text zones. */
00389     }
00390 
00391     if(getInfo() != EP_FOOTNOTE && getFrameType() != SS_HEADERS &&
00392        getFrameType() != SS_FOOTERS)
00393     {
00394         /* id than above : a parag. have a special format. (end)
00395          * only it's not a header, nor a footer nor a footnote/endnote
00396          */
00397         generateFin(out);
00398         if(isHardBreakAfter())
00399             out << "\\newpage" << endl;
00400     }
00401     kdDebug(30522) << "PARA GENERATED" << endl;
00402 }
00403 
00404 /*******************************************/
00405 /* GenerateDebut                           */
00406 /*******************************************/
00407 /* Generate the begining paragraph markup. */
00408 /*******************************************/
00409 void Para::generateDebut(QTextStream &out)
00410 {
00411     /* Be careful we are in a table !
00412      * You can't use directly environment, ...
00413      */
00414     if(getFrameType() == SS_TABLE)
00415     {
00416         //int sizeCell = 5;
00417         /* first number depends with the cell size (next number}
00418          * and with the number of characters in the para.
00419          * It can be 20 char. / 5 cm  = 4 char / cm so */
00420         /* nbLines = nb_char_para / (4 * cell size) + 1 */
00421         //sizeCell = (_element->getRight() - _element->getLeft()) / 27;
00422         //kdDebug(30522) << "SIZE OF CELL : " << sizeCell << endl;
00423         // TODO : arrondir au superieur avec tgmath.h ??
00424         //_nbLines = ((_element->getBottom() - _element->getTop()) / 27) + 1;
00425         //kdDebug(30522) << "NB OF LINES : " << _nbLines << endl;
00426         /* 2 at least, 1 for the line, 1 for the space line */
00427         /*if(_nbLines < 2)
00428             _nbLines = 2;
00429         out << "\\multirow{" << _nbLines << "}{"<< sizeCell << "cm}{" << endl;*/
00430     }
00431     /* if it's a chapter */
00432     if(isChapter())
00433     {
00434         /* switch the type, the depth do */
00435         generateTitle(out);
00436         Config::instance()->indent();
00437     }
00438     else if(isEnum())
00439     {
00440         Config::instance()->writeIndent(out);
00441         out << "\\item ";
00442     }
00443     else
00444         Config::instance()->writeIndent(out);
00445 }
00446 
00447 void Para::generateBeginEnv(QTextStream &out)
00448 {
00449     kdDebug(30522) << "Begin new Env : " << getEnv() << endl;
00450 
00451     Config::instance()->writeIndent(out);
00452 
00453     switch(getEnv())
00454     {
00455         case ENV_LEFT: out << "\\begin{flushleft}" << endl;
00456             break;
00457         case ENV_RIGHT: out << "\\begin{flushright}" << endl;
00458             break;
00459         case ENV_CENTER: out << "\\begin{center}" << endl;
00460             break;
00461         case ENV_JUSTIFY: out << endl;
00462             break;
00463         case ENV_NONE:
00464             break;
00465     }
00466     
00467     Config::instance()->indent();
00468 }
00469 
00470 /*******************************************/
00471 /* openList                                */
00472 /*******************************************/
00473 /* Generate the markup to begin a list and */
00474 /* push the type in the historic stack.    */
00475 /*******************************************/
00476 void Para::openList(QTextStream &out)
00477 {
00478     EType *type_temp = 0;
00479 
00480     Config::instance()->writeIndent(out);
00481 
00482     switch(getCounterType())
00483     {
00484         case TL_NONE:
00485             break;
00486         case TL_ARABIC:
00487             out << "\\begin{enumerate}" << endl;
00488             break;
00489         case TL_LLETTER:    /* a, b, ... */
00490             out << "\\begin{enumerate}[a]" << endl;
00491             break;
00492         case TL_CLETTER:    /* A, B, ... */
00493             out << "\\begin{enumerate}[A]" << endl;
00494             break;
00495         case TL_LLNUMBER:   /* i, ii, ... */
00496             out << "\\begin{enumerate}[i]" << endl;
00497             break;
00498         case TL_CLNUMBER:   /* I, II, ... */
00499             out << "\\begin{enumerate}[I]" << endl;
00500             break;
00501         case TL_CUSTOM_SIMPLE: /* - */
00502             out << "\\begin{enumerate}[" << convertSpecialChar(getCounterBullet()) << "]" << endl;
00503             break;
00504         case TL_CUSTOM_COMPLEX: /* - */
00505             out << "\\begin{enumerate}[" << convertSpecialChar(getCounterBullet()) << "]" << endl;
00506             break;
00507         case TL_CIRCLE_BULLET:
00508             out << "\\begin{itemize}" << endl;
00509             break;
00510         case TL_SQUARE_BULLET:
00511             out << "\\begin{itemize}" << endl;
00512             break;
00513         case TL_DISC_BULLET:
00514             out << "\\begin{itemize}" << endl;
00515             break;
00516         default:
00517             out << "\\begin{itemize}[SPECIAL]" << endl;
00518     }
00519 
00520     Config::instance()->indent();
00521 
00522     /* Keep the list type */
00523     type_temp = new EType(getCounterType());
00524     kdDebug(30522) << " type list to open : " << *type_temp << endl;
00525     _historicList.push(type_temp);
00526 }
00527 
00528 /*******************************************/
00529 /* GenerateFin                             */
00530 /*******************************************/
00531 /* Generate the closing paragraph markup.  */
00532 /*******************************************/
00533 void Para::generateFin(QTextStream &out)
00534 {
00535     /* Close a title of chapter */
00536     if(isChapter())
00537         out << "}";
00538 }
00539 
00540 /*******************************************/
00541 /* GenerateEndEnv                          */
00542 /*******************************************/
00543 /* Generate the closing environment markup.*/
00544 /*******************************************/
00545 void Para::generateEndEnv(QTextStream &out)
00546 {
00547     kdDebug(30522) << "end of an environment : " << getEnv() << endl;
00548     
00549     Config::instance()->desindent();
00550     
00551     switch(getEnv())
00552     {
00553         case ENV_LEFT:
00554                 out << endl;
00555                 Config::instance()->writeIndent(out);
00556                 out << "\\end{flushleft}";
00557             break;
00558         case ENV_RIGHT:
00559                 out << endl;
00560                 Config::instance()->writeIndent(out);
00561                 out << "\\end{flushright}";
00562             break;
00563         case ENV_CENTER:
00564                 out << endl;
00565                 Config::instance()->writeIndent(out);
00566                 out << "\\end{center}";
00567             break;
00568         case ENV_JUSTIFY:
00569             break;
00570         case ENV_NONE:
00571             break;
00572     }
00573 
00574     Config::instance()->desindent();
00575 }
00576 
00577 /*******************************************/
00578 /* closeList                               */
00579 /*******************************************/
00580 /* Generate the closing list markup for a  */
00581 /* list type (letter, custom, ...) and     */
00582 /* remove the last list saved.             */
00583 /*******************************************/
00584 void Para::closeList(QTextStream &out, Para* next)
00585 {
00586     closeList(getCounterType(), out);
00587 
00588     if(((getCounterDepth() - 1) >= 0) && ((next!= 0 && !next->isEnum()) || next == 0))
00589     {
00590         /* We must close all the lists since
00591          * after this paragraph it's a normal paragraph.
00592          */
00593         kdDebug(30522) << "lists to close" << endl;
00594         while(!_historicList.isEmpty())
00595         {
00596             EType *type_temp = 0;
00597             type_temp = _historicList.pop();
00598             if(type_temp != 0)
00599                 closeList(*type_temp, out);
00600         }
00601     }
00602 }
00603 
00604 /*******************************************/
00605 /* closeList                               */
00606 /*******************************************/
00607 /* Generate the closing list markup for a  */
00608 /* list type (letter, custom, ...) and     */
00609 /* remove the last list saved.             */
00610 /*******************************************/
00611 void Para::closeList(EType type, QTextStream &out)
00612 {
00613     //out << endl;
00614     kdDebug(30522) << " type list to close : " << type << endl;
00615 
00616     /* Because of a new markup, we need a new line. */
00617     out << endl;
00618 
00619     Config::instance()->desindent();
00620     Config::instance()->writeIndent(out);
00621     
00622     /* but the next parag is not a same list */
00623     switch(type)
00624     {
00625         case TL_NONE: //out << endl;
00626             break;
00627         case TL_ARABIC:
00628         case TL_LLETTER:  /* a, b, ... */
00629         case TL_CLETTER:  /* A, B, ... P. 250*/
00630         case TL_LLNUMBER: /* i, ii, ... */
00631         case TL_CLNUMBER: /* I, II, ... */
00632         case TL_CUSTOM_SIMPLE: /* - */
00633         case TL_CUSTOM_COMPLEX: /* - */
00634                    out << "\\end{enumerate}" << endl;
00635             break;
00636         case TL_CIRCLE_BULLET:
00637                 out << "\\end{itemize}" << endl;
00638             break;
00639         case TL_SQUARE_BULLET:
00640         case TL_DISC_BULLET:
00641                 out << "\\end{itemize}" << endl;
00642             break;
00643         default:
00644                 out << "no suported" << endl;
00645     }
00646 
00647     Config::instance()->writeIndent(out);
00648 
00649     /* Pop the list which has been closed */
00650     _historicList.remove();
00651     kdDebug(30522) << "removed" << endl;
00652 }
00653 
00654 /*******************************************/
00655 /* GenerateTitle                           */
00656 /*******************************************/
00657 void Para::generateTitle(QTextStream &out)
00658 {
00659     switch(getCounterDepth())
00660     {
00661         case 0:
00662             out << "\\section{";
00663             break;
00664         case 1:
00665             out << "\\subsection{";
00666             break;
00667         case 2:
00668             out << "\\subsubsection{";
00669             break;
00670         case 3:
00671             out << "\\paragraph{";
00672             break;
00673         case 4:
00674             out << "\\subparagraph{";
00675             break;
00676         case 5:
00677             out << "% section too deep" << endl;
00678             out << "\\textbf{";
00679     }
00680 }
KDE Home | KDE Accessibility Home | Description of Access Keys