Back to index

scribus-ng  1.3.4.dfsg+svn20071115
pageitem_textframe.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008                           pageitem.cpp  -  description
00009                              -------------------
00010     begin                : Sat Apr 7 2001
00011     copyright            : (C) 2001 by Franz Schmid
00012     email                : Franz.Schmid@altmuehlnet.de
00013  ***************************************************************************/
00014 
00015 /***************************************************************************
00016  *                                                                         *
00017  *   This program is free software; you can redistribute it and/or modify  *
00018  *   it under the terms of the GNU General Public License as published by  *
00019  *   the Free Software Foundation; either version 2 of the License, or     *
00020  *   (at your option) any later version.                                   *
00021  *                                                                         *
00022  ***************************************************************************/
00023 
00024 #include "pageitem_textframe.h"
00025 #include "pageitem_textframe.moc"
00026 #include <qpainter.h>
00027 #include <qpen.h>
00028 #include <qfont.h>
00029 #include <qregion.h>
00030 #include <qpoint.h>
00031 #include <qfileinfo.h>
00032 #include <qdrawutil.h>
00033 #include <qbitmap.h>
00034 #include <qregexp.h>
00035 #include <qmessagebox.h>
00036 #include <cmath>
00037 #include <cassert>
00038 
00039 #include "hyphenator.h"
00040 #include "mpalette.h"
00041 #include "page.h"
00042 #include "pageitem.h"
00043 #include "prefsmanager.h"
00044 #include "scpaths.h"
00045 #include "scribus.h"
00046 #include "scribusstructs.h"
00047 #include "scribusdoc.h"
00048 #include "selection.h"
00049 #include "undomanager.h"
00050 #include "undostate.h"
00051 #include "scconfig.h"
00052 #include "commonstrings.h"
00053 #include "guidemanager.h"
00054 
00055 #include "util.h"
00056 #include "text/nlsconfig.h"
00057 #ifdef HAVE_CAIRO
00058 #include <cairo.h>
00059 #endif
00060 
00061 using namespace std;
00062 
00063 PageItem_TextFrame::PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, QString fill, QString outline)
00064        : PageItem(pa, PageItem::TextFrame, x, y, w, h, w2, fill, outline)
00065 {
00066        cursorBiasBackward = false;  // not used yet - av
00067        unicodeTextEditMode = false;
00068        unicodeInputCount = 0;
00069        unicodeInputString = "";
00070 }
00071 
00072 
00073 static QRegion itemShape(PageItem* docItem, ScribusView* view, double xOffset, double yOffset)
00074 {
00075        QRegion res;
00076        QPainter pp;
00077        pp.begin(view->viewport());
00078        pp.translate(docItem->xPos() - xOffset, docItem->yPos() - yOffset);
00079        pp.rotate(docItem->rotation());
00080        if (docItem->textFlowUsesBoundingBox())
00081        {
00082               QPointArray tcli(4);
00083               tcli.setPoint(0, QPoint(0,0));
00084               tcli.setPoint(1, QPoint(qRound(docItem->width()), 0));
00085               tcli.setPoint(2, QPoint(qRound(docItem->width()), qRound(docItem->height())));
00086               tcli.setPoint(3, QPoint(0, qRound(docItem->height())));
00087               res = QRegion(pp.xForm(tcli));
00088        }
00089        else if ((docItem->textFlowUsesImageClipping()) && (docItem->imageClip.size() != 0))
00090        {
00091               QValueList<uint> Segs;
00092               QPointArray Clip2 = FlattenPath(docItem->imageClip, Segs);
00093               res = QRegion(pp.xForm(Clip2)).intersect(QRegion(pp.xForm(docItem->Clip)));
00094        }
00095        else if ((docItem->textFlowUsesContourLine()) && (docItem->ContourLine.size() != 0))
00096        {
00097               QValueList<uint> Segs;
00098               QPointArray Clip2 = FlattenPath(docItem->ContourLine, Segs);
00099               res = QRegion(pp.xForm(Clip2));
00100        }
00101        else
00102               res = QRegion(pp.xForm(docItem->Clip));
00103        pp.end();
00104        return  res;
00105 }
00106 
00107 QRegion PageItem_TextFrame::availableRegion(QRegion clip)
00108 {
00109        QRegion result(clip);
00110        if (!isEmbedded)
00111        {
00112               int LayerLev = m_Doc->layerLevelFromNumber(LayerNr);
00113               uint docItemsCount=m_Doc->Items->count();
00114               Page* Mp=0;
00115               Page* Dp=0;
00116               PageItem* docItem=0;
00117               int LayerLevItem;
00118               if (!OnMasterPage.isEmpty())
00119               {
00120                      if ((savedOwnPage == -1) || (savedOwnPage >= signed(m_Doc->Pages->count())))
00121                             return result;
00122                      Mp = m_Doc->MasterPages.at(m_Doc->MasterNames[OnMasterPage]);
00123                      Dp = m_Doc->Pages->at(savedOwnPage);
00124                      for (uint a = 0; a < m_Doc->MasterItems.count(); ++a)
00125                      {
00126                             docItem = m_Doc->MasterItems.at(a);
00127                             LayerLevItem = m_Doc->layerLevelFromNumber(docItem->LayerNr);
00128                             if (((docItem->ItemNr > ItemNr) && (docItem->LayerNr == LayerNr)) || (LayerLevItem > LayerLev) && (m_Doc->layerFlow(docItem->LayerNr)))
00129                             {
00130                                    if (docItem->textFlowAroundObject())
00131                                    {
00132                                           result = result.subtract(itemShape(docItem, m_Doc->view(),  Mp->xOffset() - Dp->xOffset(), Mp->yOffset() - Dp->yOffset()));
00133                                    }
00134                             }
00135                      } // for all masterItems
00136                      if (!m_Doc->masterPageMode())
00137                      {
00138                             for (uint a = 0; a < docItemsCount; ++a)
00139                             {
00140                                    docItem = m_Doc->Items->at(a);
00141                                    Mp = m_Doc->MasterPages.at(m_Doc->MasterNames[OnMasterPage]);
00142                                    Dp = m_Doc->Pages->at(OwnPage);
00143                                    if ((docItem->textFlowAroundObject()) && (docItem->OwnPage == OwnPage))
00144                                    {
00145                                           result = result.subtract(itemShape(docItem, m_Doc->view(), Mp->xOffset() - Dp->xOffset(), Mp->yOffset() - Dp->yOffset()));
00146                                    }
00147                             } // for all docItems
00148                      } // if (! masterPageMode)
00149               } // if (!OnMasterPage.isEmpty())
00150               else
00151               {
00152                      for (uint a = 0; a < docItemsCount; ++a)
00153                      {
00154                             docItem = m_Doc->Items->at(a);
00155                             LayerLevItem = m_Doc->layerLevelFromNumber(docItem->LayerNr);
00156                             if (((docItem->ItemNr > ItemNr) && (docItem->LayerNr == LayerNr)) || (LayerLevItem > LayerLev) && (m_Doc->layerFlow(docItem->LayerNr)))
00157                             {
00158                                     if (docItem->textFlowAroundObject())
00159                                           result = result.subtract(itemShape(docItem, m_Doc->view(), 0, 0));
00160                             }
00161                      } // for all docItems
00162                      } // if(OnMasterPage.isEmpty()            
00163        } // if(!Embedded)
00164        return result;
00165 }
00166 
00167 
00168 void PageItem_TextFrame::setShadow()
00169 {
00170        if (OnMasterPage.isEmpty())
00171               return;
00172        
00173        QString newShadow = m_Doc->masterPageMode() ? OnMasterPage : QString::number(OwnPage);
00174        if (newShadow != currentShadow) {
00175               if (currentShadow == OnMasterPage) {
00176                      // masterpage was edited, clear all shadows
00177                      shadows.clear();
00178               }
00179               if (!shadows.contains(newShadow)) {
00180                      if (!shadows.contains(OnMasterPage)) {
00181                             shadows[OnMasterPage] = itemText;
00182 //                          const ParagraphStyle& pstyle(shadows[OnMasterPage].paragraphStyle(0));
00183 //                          qDebug(QString("Pageitem_Textframe: style of master: %1 align=%2").arg(pstyle.parent()).arg(pstyle.alignment()));
00184 //                          qDebug(QString("Pageitem_Textframe: shadow itemText->%1").arg(OnMasterPage));
00185                      }
00186                      if (newShadow != OnMasterPage) {
00187                             shadows[newShadow] = shadows[OnMasterPage].copy();
00188 //                          const ParagraphStyle& pstyle(shadows[newShadow].paragraphStyle(0));
00189 //                          qDebug(QString("Pageitem_Textframe: style of shadow copy: %1 align=%2").arg(pstyle.parent()).arg(pstyle.alignment()));
00190                      }
00191 //                   qDebug(QString("Pageitem_Textframe: shadow %1<-%2").arg(newShadow).arg(OnMasterPage));
00192               }
00193               itemText = shadows[newShadow];
00194 //            const ParagraphStyle& pstyle(itemText.paragraphStyle(0));
00195 //            qDebug(QString("Pageitem_Textframe: style of shadow: %1 align=%2").arg(pstyle.parent()).arg(pstyle.alignment()));
00196               invalid = true;
00197               currentShadow = newShadow;
00198        }
00199 }
00200               
00201 #ifdef NLS_PROTO
00202 #include "text/pageitem_textframe.cpp"
00203 #else
00204 
00205 static void dumpIt(const ParagraphStyle& pstyle, QString indent = QString("->"))
00206 {
00207        qDebug(QString("%6%1/%2 @ %3: %4--%5 linespa%6: %7 align%8")
00208                  .arg(pstyle.name())
00209                  .arg(pstyle.parent())
00210                  .arg( (unsigned long int) &pstyle)
00211                  .arg(pstyle.leftMargin())
00212                  .arg(pstyle.rightMargin())
00213                  .arg(indent)
00214                  .arg(pstyle.lineSpacingMode())
00215                  .arg(pstyle.lineSpacing())
00216                  .arg(pstyle.alignment()));
00217        static QString more("  ");
00218        if (pstyle.hasParent())
00219               dumpIt(*dynamic_cast<const ParagraphStyle*>(pstyle.parentStyle()), more + indent);
00220 }
00221 
00222 
00223 static const bool legacy = true;
00224 
00225 
00226 /*static void layoutDropCap(GlyphLayout layout, double curX, double curY, double offsetX, double offsetY, double dropCapDrop) 
00227 {      
00228 }
00229 */
00230 
00234 static void fillInTabLeaders(StoryText & itemText, LineSpec & curLine)
00235 {
00236        // fill in tab leaders
00237        double xPos = curLine.x;
00238        for (int ti= curLine.firstItem; ti < curLine.lastItem; ++ti)
00239        {
00240               ScText * hl = itemText.item(ti);
00241               if (hl->ch[0] == SpecialChars::TAB) 
00242               {
00243                      GlyphLayout * tglyph = hl->glyph.more;
00244                      
00245                      if (!tglyph)
00246                             continue;
00247                      
00248                      const CharStyle & charStyle(itemText.charStyle(ti));
00249                      double wt   = charStyle.font().glyphWidth(tglyph->glyph, charStyle.fontSize() * tglyph->scaleV / 10.0);
00250                      double len  = hl->glyph.xadvance;
00251                      int count   = static_cast<int>(len / wt);
00252                      double sPos = -len;
00253                      tglyph->xoffset = sPos;
00254 //                   qDebug(QString("tab leaders: %1 %2 width=%3 count=%4").arg(sPos).arg(curLine.y).arg(wt).arg(count));
00255                      for (int cx = 1; cx < count; ++cx)
00256                      {
00257                             // clone fillchar
00258                             tglyph->grow();
00259                             *(tglyph->more) = *tglyph;
00260                             tglyph->more->more = NULL;
00261                             tglyph = tglyph->more;
00262                             tglyph->xoffset =  sPos + wt * cx;
00263                      }
00264               }
00265               xPos += hl->glyph.wide();
00266        }
00267 }
00268 
00269 
00270 
00271 enum TabStatus {
00272        TabNONE    = 0,
00273        TabLEFT    = TabNONE,
00274        TabRIGHT   = 1,
00275        TabPOINT   = 2,
00276        TabCOMMA   = 3,
00277        TabCENTER  = 4
00278 };
00279 
00280 
00284 struct TabControl {
00285        bool   active;
00286        int    status;
00287        int    charIndex;
00288        double xPos;
00289        QChar  fillChar;
00290 };
00291 
00295 struct LineControl {
00296        LineSpec line;
00297        int      itemsInLine;
00298        int      hyphenCount;
00299        double   colWidth;
00300        double   colGap;
00301        double   colLeft;
00302        double   colRight;
00303        int      column;
00304        bool     startOfCol;
00305        double   ascend;
00306        double   descend;
00307        double   width;
00308        double   xPos;
00309        double   yPos;
00310        int      breakIndex;
00311        double   breakXPos;
00312        double   maxShrink;
00313        double   maxStretch;
00314        
00316        void init(double w, double h, const MarginStruct& extra, double lCorr)
00317        {
00318               insets = extra;
00319               lineCorr = lCorr;
00320               frameWidth = w;
00321               frameHeight = h;
00322        }
00323        
00325        void initColumns(double width, double gap)
00326        {
00327               column = 0;
00328               colWidth = width;
00329               colGap = gap;
00330        }
00331        
00333        void nextColumn(double asce)
00334        {
00335               startOfCol = true;
00336               colLeft = (colWidth + colGap) * column + insets.Left + lineCorr;
00337               colRight = colLeft + colWidth;
00338               if (legacy)
00339                      colRight += insets.Right + lineCorr; //???
00340               xPos = colLeft;
00341               yPos = asce + insets.Top + lineCorr + 1;
00342        }
00343        
00344        bool isEndOfCol(double morespace = 0)
00345        {
00346               return yPos + morespace + insets.Bottom + lineCorr > frameHeight;
00347        }
00348        
00352        void startLine(int first)
00353        {             
00354               itemsInLine = 0;
00355               line.x = xPos;
00356               line.y = yPos;
00357               line.firstItem = first;
00358               line.ascent = 10;
00359               line.descent = 0;
00360               line.width = 0;
00361               line.naturalWidth = 0;
00362               breakIndex = -1;
00363               breakXPos = 0;
00364               maxShrink = 0;
00365               maxStretch = 0;
00366        }
00367        
00368        
00370        void rememberShrinkStretch(QChar ch, double wide, const ParagraphStyle& style)
00371        {
00372               if (SpecialChars::isExpandingSpace(ch))
00373                      maxShrink += (1 - style.minWordTracking()) * wide;
00374               else
00375               {
00376                      maxShrink += (1 - style.minGlyphExtension()) * wide;
00377               }
00378               maxStretch += (style.maxGlyphExtension() - 1) * wide;
00379        }
00380        
00381        
00383        void rememberBreak(int index, double pos)
00384        {
00385               if (pos > colRight)
00386               {
00387                      // only look for the first break behind the right edge
00388                      maxShrink = 0;
00389               
00390                      // check if we already have a better break
00391                      if (breakIndex >= 0)
00392                      {
00393                             double oldLooseness = QABS(colRight - breakXPos);
00394                             double newLooseness = pos - colRight;
00395                             if (newLooseness >= oldLooseness)
00396                                    return;
00397                      }
00398                      breakXPos = colRight;
00399               }
00400               else
00401               {
00402                      breakXPos = pos;
00403               }
00404               breakIndex = index;
00405        }
00406        
00408        void breakLine(const StoryText& itemText, int last)
00409        {
00410               breakIndex = last;
00411               breakXPos  = line.x;
00412               for (int j = line.firstItem; j <= last; ++j)
00413                      if ( (itemText.item(j)->effects() & ScStyle_SuppressSpace) == 0)
00414                             breakXPos += itemText.item(j)->glyph.wide();            
00415        }
00416        
00418        void finishLine(double endX)
00419        {
00420               line.lastItem = breakIndex;
00421               line.naturalWidth = breakXPos - line.x;
00422               line.width = endX - line.x;
00423               maxShrink = maxStretch = 0;
00424 //            qDebug(QString("finishLine ..%1: %2___%3 %4->%5").arg(breakIndex).arg(line.x).arg(endX).arg(line.naturalWidth).arg(line.width));
00425        }
00426        
00427        
00428        bool isEndOfLine(double moreSpace = 0)
00429        {
00430               if (legacy)
00431                      return xPos + insets.Right + lineCorr + moreSpace - maxShrink >= colRight;
00432               else
00433                      return xPos + moreSpace - maxShrink >= colRight;
00434        }
00435        
00437        double startOfLine(const QRegion& shape, const QPainter& pf2, double ascent, double descent, double morespace)
00438        {
00439               QPoint pt1, pt2;
00440               double tmpX = xPos;
00441               pt1 = QPoint(static_cast<int>(ceil(tmpX)), static_cast<int>(yPos + descent));
00442               pt2 = QPoint(static_cast<int>(ceil(tmpX)), static_cast<int>(ceil(yPos - ascent)));
00443               // increase pt1/pt2 until i-beam reaches end of line
00444               while ((!shape.contains(pf2.xForm(pt1))) || (!shape.contains(pf2.xForm(pt2))))
00445               {
00446                      tmpX++;
00447                      if (xPos + (legacy? lineCorr + insets.Right : 0) + lineCorr + morespace >= colRight)
00448                      {
00449                             return tmpX;
00450                      }
00451                      pt1 = QPoint(static_cast<int>(ceil(tmpX)), static_cast<int>(yPos + descent));
00452                      pt2 = QPoint(static_cast<int>(ceil(tmpX)), static_cast<int>(ceil(yPos - ascent)));
00453               }
00454               return tmpX;
00455        }
00456        
00458        double endOfLine(const QRegion& shape, const QPainter& pf2, double ascent, double descent, double morespace = 0)
00459        {
00460               double EndX = floor(QMAX(line.x, QMIN(colRight,breakXPos) - 1));
00461               QPoint pt1, pt2;
00462               //     qDebug(QString("endx start=%1, hl is '%2'").arg(EndX).arg(hl->ch));
00463               do {
00464                      EndX += 0.125;
00465                      pt1 = QPoint(qRound(ceil(EndX + insets.Right)), static_cast<int>(yPos+descent));
00466                      pt2 = QPoint(qRound(ceil(EndX + insets.Right)), static_cast<int>(ceil(yPos-ascent)));
00467               } while 
00468                      (   (EndX + (legacy? lineCorr + insets.Right : 0) < colRight - morespace)
00469                        && shape.contains(pf2.xForm(pt1))
00470                        && shape.contains(pf2.xForm(pt2)) 
00471                        );
00472               
00473               return EndX;
00474        }
00475        
00476        
00477        double getLineAscent(const StoryText& itemText)
00478        {
00479               double result = 0;
00480               if ((itemText.text(line.firstItem) == SpecialChars::PARSEP) || (itemText.text(line.firstItem) == SpecialChars::LINEBREAK))
00481                      result = itemText.charStyle(line.firstItem).font().ascent(itemText.charStyle(line.firstItem).fontSize() / 10.0);
00482               else if (itemText.object(line.firstItem) != 0)
00483                      result = QMAX(result, (itemText.object(line.firstItem)->gHeight + itemText.object(line.firstItem)->lineWidth()) * (itemText.charStyle(line.firstItem).scaleV() / 1000.0));
00484               else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
00485                      result = itemText.charStyle(line.firstItem).font().realCharAscent(itemText.text(line.firstItem), itemText.charStyle(line.firstItem).fontSize() / 10.0);
00486               for (int zc = 0; zc < itemsInLine; ++zc)
00487               {
00488                      QChar ch = itemText.text(line.firstItem + zc);
00489                      if (ch == SpecialChars::PAGENUMBER)
00490                             ch = '8'; // should have highest ascender even in oldstyle
00491                      const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc));
00492                      if ((ch == SpecialChars::TAB) || (ch == QChar(10))
00493                             || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
00494                             || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::LINEBREAK)
00495                             || (ch == SpecialChars::FRAMEBREAK) || (ch.isSpace()))
00496                             continue;
00497                      double asce;
00498                      if (itemText.object(line.firstItem + zc) != 0)
00499                             asce = itemText.object(line.firstItem + zc)->gHeight + itemText.object(line.firstItem + zc)->lineWidth() * (cStyle.scaleV() / 1000.0);
00500                      else //if (itemText.charStyle(current.line.firstItem + zc).effects() & ScStyle_DropCap == 0)
00501                             asce = cStyle.font().realCharAscent(ch, cStyle.fontSize() / 10.0);
00502 //                   qDebug(QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result));
00503                      result = QMAX(result, asce);
00504               }
00505               return result;
00506        }
00507        
00508        double getLineHeight(const StoryText& itemText)
00509        {
00510               double result = 0;
00511               if (itemText.object(line.firstItem) != 0)
00512                      result = QMAX(result, (itemText.object(line.firstItem)->gHeight + itemText.object(line.firstItem)->lineWidth()) * (itemText.charStyle(line.firstItem).scaleV() / 1000.0));
00513               else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
00514                      result = itemText.charStyle(line.firstItem).font().height(itemText.charStyle(line.firstItem).fontSize() / 10.0);
00515               for (int zc = 0; zc < itemsInLine; ++zc)
00516               {
00517                      QChar ch = itemText.text(line.firstItem+zc);
00518                      if ((ch == SpecialChars::TAB) || (ch == QChar(10))
00519                             || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
00520                             || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::FRAMEBREAK)
00521                             || (ch == SpecialChars::LINEBREAK) || (ch.isSpace()))
00522                             continue;
00523                      double asce;
00524                      if (itemText.object(line.firstItem+zc) != 0)
00525                             asce = (itemText.object(line.firstItem+zc)->gHeight + itemText.object(line.firstItem+zc)->lineWidth()) * (itemText.charStyle(line.firstItem+zc).scaleV() / 1000.0);
00526                      else //if (itemText.charStyle(current.line.firstItem+zc).effects() & ScStyle_DropCap == 0)
00527                             asce = itemText.charStyle(line.firstItem+zc).font().height(itemText.charStyle(line.firstItem+zc).fontSize() / 10.0);
00528                      //                                 qDebug(QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result));
00529                      result = QMAX(result, asce);
00530               }
00531               return result;
00532        }
00533        
00534        
00535 private:
00536        double frameWidth;
00537        double frameHeight;
00538        MarginStruct insets;
00539        double lineCorr;
00540 };
00541 
00542 
00543 
00545 static void justifyLine(StoryText& itemText, LineSpec& line)
00546 {
00547        double glyphNatural = 0;
00548        double spaceNatural = 0;
00549        double glyphExtension;
00550        double spaceExtension;
00551        
00552        const ParagraphStyle& style(itemText.paragraphStyle(line.firstItem));
00553        
00554        // measure natural widths for glyphs and spaces
00555        for (int sof = line.firstItem; sof <= line.lastItem; ++sof)
00556        {
00557               if (!SpecialChars::isExpandingSpace(itemText.text(sof)))
00558               {
00559                      glyphNatural += itemText.item(sof)->glyph.wide();
00560               }
00561               else if ((itemText.item(sof)->effects() & ScStyle_SuppressSpace) == 0)
00562               {
00563                      spaceNatural += itemText.item(sof)->glyph.wide();
00564               }
00565        }
00566        
00567        // decision: prio 1: stretch glyph;  prio 2: stretch spaces
00568        
00569        if (line.width < spaceNatural + glyphNatural * style.minGlyphExtension() && spaceNatural > 0)
00570        {
00571               glyphExtension = style.minGlyphExtension() - 1;
00572               spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural  - 1;
00573        }
00574        else if (line.width < spaceNatural + glyphNatural * style.maxGlyphExtension() && glyphNatural > 0)
00575        {
00576               spaceExtension = 0;
00577               glyphExtension = (line.width - spaceNatural) / glyphNatural  - 1;
00578        }
00579        else
00580        {
00581               glyphExtension = style.maxGlyphExtension() - 1;
00582               if (spaceNatural > 0)
00583                      spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural  - 1;
00584               else
00585                      spaceExtension = 0;
00586        }
00587        
00588        double glyphScale = 1 + glyphExtension;
00589        
00590 /*
00591        qDebug(QString("justify: line = %7 natural = %1 + %2 = %3 (%4); spaces + %5%%; min=%8; glyphs + %6%%; min=%9")
00592                  .arg(spaceNatural).arg(glyphNatural).arg(spaceNatural+glyphNatural).arg(line.naturalWidth)
00593                  .arg(spaceExtension).arg(glyphExtension).arg(line.width)
00594                  .arg(style.minWordTracking()).arg(style.minGlyphExtension()));
00595        */
00596        
00597        // distribute whitespace on spaces and glyphs
00598        for (int yof = line.firstItem; yof <= line.lastItem; ++yof)
00599        {
00600               double wide = itemText.item(yof)->glyph.wide();
00601               if (!SpecialChars::isExpandingSpace(itemText.text(yof)))
00602               {
00603                      itemText.item(yof)->glyph.last()->xadvance += wide * glyphExtension;
00604                      GlyphLayout* glyph = &(itemText.item(yof)->glyph);
00605                      while (glyph)
00606                      {
00607                             glyph->xoffset *= glyphScale;
00608                             glyph->scaleH *= glyphScale;
00609                             glyph = glyph->more;
00610                      }
00611               }
00612               else if ((itemText.item(yof)->effects() & ScStyle_SuppressSpace) == 0)
00613               {
00614                      itemText.item(yof)->glyph.last()->xadvance += wide * spaceExtension;
00615               }
00616        }
00617 }
00618 
00619 
00621 static void indentLine(StoryText& itemText, LineSpec& line, double leftIndent)
00622 {
00623        if (line.naturalWidth > line.width)
00624        {
00625               justifyLine(itemText, line);
00626        }
00627        if (leftIndent > 0)
00628        {
00629               line.x += leftIndent;
00630               line.width -= leftIndent;
00631        }
00632 }
00633 
00635 static double opticalLeftMargin(const StoryText& itemText, const LineSpec& line)
00636 {
00637        int b = line.firstItem;
00638        while (b < line.lastItem && (itemText.item(b)->effects() & ScStyle_SuppressSpace))
00639                  ++b;
00640        
00641        double chs = itemText.charStyle(b).fontSize() * (itemText.charStyle(b).scaleH() / 1000.0);
00642        QChar chr = itemText.text(b);
00643        double leftCorr = itemText.charStyle(b).font().realCharWidth(chr, chs / 10.0);
00644        if (QString("'´`").find(chr) >= 0
00645               || chr == QChar(0x2018) // quote 6
00646               || chr == QChar(0x2019) // quote 9
00647               || chr == QChar(0x201a) // lower quote 9
00648               || chr == QChar(0x201b) // upper reversed 9 6
00649               || chr == QChar(0x2039) // single guillemet <
00650               || chr == QChar(0x203a) // single guillemet >
00651               )
00652               leftCorr *= -0.7;
00653        else if (QString("\"").find(chr) >= 0
00654                       || chr == QChar(0x00ab) // guillemet <<
00655                       || chr == QChar(0x00bb) // guillemet >>
00656                       || chr == QChar(0x201c) // quote 66
00657                       || chr == QChar(0x201d) // quote 99
00658                       || chr == QChar(0x201e) // lower quote 99
00659                       || chr == QChar(0x201f) // upper reversed 99
00660                       ) 
00661               leftCorr *= -0.5;
00662        else {
00663               leftCorr = itemText.charStyle(b).font().charWidth(QChar(' '), chs / 10.0, chr);
00664               leftCorr -= itemText.charStyle(b).font().charWidth(QChar(' '), chs / 10.0);
00665 //                          double leftCorr2 = itemText.charStyle(a).font().charWidth(QChar('K'), chs / 10.0, chr);
00666 //                          leftCorr2 -= itemText.charStyle(a).font().charWidth(QChar('K'), chs / 10.0);
00667 //                          leftCorr = QMIN(leftCorr, leftCorr2);
00668        }
00669        return leftCorr;
00670 }
00671 
00672 
00673 
00675 static double opticalRightMargin(const StoryText& itemText, const LineSpec& line)
00676 {
00677        int b = line.lastItem;
00678        while (b > line.firstItem && 
00679                  (SpecialChars::isBreakingSpace(itemText.text(b)) || SpecialChars::isBreak(itemText.text(b)))
00680                  )
00681               --b;
00682        if (b >= line.firstItem) 
00683        {
00684               double chs = itemText.charStyle(b).fontSize() * (itemText.charStyle(b).scaleH() / 1000.0);
00685               QChar chr = (itemText.item(b)->effects() & ScStyle_SmartHyphenVisible) ? 
00686                      QChar('-') : itemText.text(b);
00687               double rightCorr = itemText.charStyle(b).font().realCharWidth(chr, chs / 10.0);
00688               if (QString("-,.`´'~").find(chr) >= 0
00689                      || chr == QChar(0x2018)
00690                      || chr == QChar(0x2019)
00691                      || chr == QChar(0x201a)
00692                      || chr == QChar(0x201b)
00693                      || chr == QChar(0x2039)
00694                      || chr == QChar(0x203a)
00695                      || chr == QChar(0x2032) // PRIME
00696                      )
00697                      rightCorr *= 0.7;
00698               else if (QString(";:\"").find(chr) >= 0
00699                              || chr == QChar(0x00ab)
00700                              || chr == QChar(0x00bb)
00701                              || chr == QChar(0x201c)
00702                              || chr == QChar(0x201d)
00703                              || chr == QChar(0x201e)
00704                              || chr == QChar(0x201f)
00705                              || chr == QChar(0x2013) // EN DASH
00706                              || chr == QChar(0x2033) // double prime
00707                              )
00708                      rightCorr *= 0.5;
00709               else {
00710                      rightCorr = itemText.charStyle(b).font().charWidth(chr, chs / 10.0);
00711                      rightCorr -= itemText.charStyle(b).font().charWidth(chr, chs / 10.0, QChar('.'));
00712               }
00713               return rightCorr;
00714        }
00715        return 0.0;
00716 }
00717 
00718 
00719 
00720 
00721 
00722 void PageItem_TextFrame::layout() 
00723 {
00724        
00725        if (BackBox != NULL && BackBox->invalid) {
00726 //            qDebug("textframe: len=%d, going back", itemText.length());
00727               invalid = false;
00728               PageItem_TextFrame* prevInChain = dynamic_cast<PageItem_TextFrame*>(BackBox);
00729               if (!prevInChain)
00730                      qDebug(QString("layout(): backBox=%1 is no textframe!!").arg((ulong)BackBox));
00731               else 
00732                      BackBox->layout();
00733               return;
00734        }
00735        else if (!invalid && OnMasterPage.isEmpty()) {
00736 //            qDebug(QString("textframe: len=%1, invalid=%2 OnMasterPage=%3: no relayout").arg(itemText.length()).arg(invalid).arg(OnMasterPage));
00737               return;
00738        }
00739        if (invalid && BackBox == NULL)
00740               firstChar = 0;
00741        
00742 //     qDebug(QString("textframe(%1,%2): len=%3, start relayout at %4").arg(Xpos).arg(Ypos).arg(itemText.length()).arg(firstInFrame()));
00743        ScribusView* view = m_Doc->view();
00744        QPainter pf2;
00745        QPoint pt1, pt2;
00746        QRegion cm;
00747        double chs, chsd = 0;
00748        double oldCurY, EndX, OFs, wide, kernVal;
00749        QString chstr;
00750        ScText *hl;
00751        ParagraphStyle style;
00752        int /*ParagraphStyle::OpticalMarginType*/ opticalMargins = ParagraphStyle::OM_None;
00753        
00754        bool outs = false;
00755        bool fBorder = false;
00756        bool goNoRoom = false;
00757        bool goNextColumn = false;
00758        
00759        TabControl tabs;
00760        tabs.active    = false;     // RTab
00761        tabs.status    = TabNONE;   // TabCode
00762        tabs.charIndex = -1;        // StartRT
00763        tabs.xPos      = 0;         // RTabX
00764 
00765        QValueList<ParagraphStyle::TabRecord> tTabValues;
00766        tTabValues.clear();
00767        
00768        bool DropCmode = false;
00769        bool AbsHasDrop = false;
00770        double desc=0, asce=0, maxDY=0, desc2=0, maxDX=0;
00771        int DropLines = 0;
00772        double DropCapDrop = 0;
00773        
00774        itemText.clearLines();
00775 
00776        double lineCorr = 0;
00777        if (lineColor() != CommonStrings::None)
00778               lineCorr = m_lineWidth / 2.0;
00779        
00780        // TODO: refactor this into PageItem
00781        MarginStruct extra;
00782        extra.Top = TExtra;
00783        extra.Left = Extra;
00784        extra.Right = RExtra;
00785        extra.Bottom = BExtra;
00786 
00787        LineControl current;
00788        current.init(Width, Height, extra, lineCorr);
00789        current.initColumns(columnWidth(), ColGap);
00790        current.hyphenCount = 0;
00791                              
00792        // dump styles
00793 /*     
00794        for (int i=0; i < itemText.nrOfParagraphs(); ++i) {
00795               const ParagraphStyle& pstyle(itemText.paragraphStyle(itemText.endOfParagraph(i)));
00796               qDebug(QString("par %1:").arg(i));
00797               dumpIt(pstyle);
00798        }
00799        qDebug(QString("default:"));
00800        dumpIt(itemText.defaultStyle());
00801 */     
00802        
00803        pf2.begin(view->viewport());
00804        pf2.translate(Xpos, Ypos);
00805        pf2.rotate(Rot);
00806        
00807        setShadow();
00808        if ((itemText.length() != 0)) // || (NextBox != 0))
00809        {
00810               // determine layout area
00811               QRegion cl = availableRegion(QRegion(pf2.xForm(Clip)));
00812               
00813               if (imageFlippedH())
00814               {
00815                      pf2.translate(Width, 0);
00816                      pf2.scale(-1, 1);
00817               }
00818               if (imageFlippedV())
00819               {
00820                      pf2.translate(0, Height);
00821                      pf2.scale(1, -1);
00822               }
00823               
00824               current.nextColumn(0);
00825 
00826               // find start of first line
00827               if (firstInFrame() < itemText.length())
00828               {
00829                      hl = itemText.item(firstInFrame());
00830                      style = itemText.paragraphStyle(firstInFrame());
00831                      if (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing)
00832                      {
00833                             style.setLineSpacing(style.charStyle().font().height(style.charStyle().fontSize() / 10.0));
00834 //                          qDebug(QString("auto linespacing: %1").arg(style.lineSpacing()));
00835                      }
00836 
00837 //                   qDebug(QString("style @0: %1 -- %2, %4/%5 char: %3").arg(style.leftMargin()).arg(style.rightMargin())
00838 //                             .arg(style.charStyle().asString()).arg(style.name()).arg(style.parent()?style.parent()->name():""));
00839                      if (style.hasDropCap())
00840                      {
00841                             if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
00842                                    chs = qRound(m_Doc->typographicSettings.valueBaseGrid  * style.dropCapLines() * 10);
00843                             else
00844                                    chs = qRound(style.lineSpacing() * style.dropCapLines() * 10);
00845                      }
00846                      else 
00847                             chs = hl->fontSize();
00848                      desc2 = -hl->font().descent(chs / 10.0);
00849                      current.yPos = extra.Top + lineCorr;
00850 //                   qDebug(QString("first line at y=%1").arg(current.yPos));
00851               }
00852               else // empty itemText:
00853               {
00854                      desc2 = -itemText.defaultStyle().charStyle().font().descent(itemText.defaultStyle().charStyle().fontSize() / 10.0);
00855                      current.yPos = itemText.defaultStyle().lineSpacing() + extra.Top+lineCorr-desc2;
00856               }
00857               current.startLine(firstInFrame());
00858               outs = false;
00859               OFs = 0;
00860               MaxChars = 0;
00861               for (int a = firstInFrame(); a < itemText.length(); ++a)
00862               {
00863                      hl = itemText.item(a);
00864                      if (a > 0 && itemText.text(a-1) == SpecialChars::PARSEP)
00865                             style = itemText.paragraphStyle(a);
00866                      if (current.itemsInLine == 0)
00867                             opticalMargins = style.opticalMargins();
00868                      
00869 //                   qDebug(QString("style pos %1: %2 (%3)").arg(a).arg(style.alignment()).arg(style.parent()));
00870                      const CharStyle& charStyle =  (chstr[0] != SpecialChars::PARSEP? itemText.charStyle(a) : itemText.paragraphStyle(a).charStyle());
00871                      if (!charStyle.parent().isEmpty())
00872                      {
00873 //                          qDebug(QString("charstyle pos %1: %2 (%3 %4 %5 %6 %7 %8 %9)").arg(a).arg(charStyle.parent())
00874 //                                    .arg((uint)charStyle.parentStyle()).arg(charStyle.font().scName()).arg(charStyle.fontSize())
00875 //                                    .arg(charStyle.fillColor()).arg(charStyle.strokeColor()).arg(charStyle.parentStyle()->name()).arg((uint)charStyle.parentStyle()->parentStyle()));
00876                      }                           
00877 //                   qDebug(QString("charstyle pos %1: %2 (%3)").arg(a).arg(charStyle.asString()).arg(charStyle.fontSize()));
00878 //                   qDebug(QString("style @%6: %1 -- %2, %4/%5 char: %3").arg(style.leftMargin()).arg(style.rightMargin())
00879 //                             .arg(style.charStyle().asString()).arg(style.name()).arg(style.parent())
00880 //                             .arg(a));
00881 
00882                      chstr = ExpandToken(a);
00883 //                   qDebug(QString("expanded token: '%1'").arg(chstr));
00884                      if (chstr.isEmpty())
00885                             chstr = SpecialChars::ZWNBSPACE;
00886                      if (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing)
00887                      {
00888                             style.setLineSpacing(style.charStyle().font().height(style.charStyle().fontSize() / 10.0));
00889                      }
00890                      // find out about par gap and dropcap
00891                      if (a == firstInFrame())
00892                      {
00893                             if (a == 0 || itemText.text(a-1) == SpecialChars::PARSEP)
00894                             {
00895 //                                 qDebug(QString("gap before: y=%1+%2").arg(current.yPos).arg(style.gapBefore()));
00896 
00897                                    current.yPos += style.gapBefore();
00898                                    if (chstr[0] != SpecialChars::PARSEP)
00899                                    {
00900                                           DropCmode = style.hasDropCap();
00901                                           if (DropCmode)
00902                                                  DropLines = style.dropCapLines();
00903                                    }
00904                                    else
00905                                           DropCmode = false;
00906                             }
00907                      }
00908 
00909                      {  // local block for 'fl'
00910                             StyleFlag fl = hl->effects();
00911                             fl &= ~ScStyle_DropCap;
00912                             fl &= ~ScStyle_SmartHyphenVisible;
00913                             hl->setEffects(fl);
00914                      }
00915                      
00916                      // No space at begin of line, 
00917                      if (legacy)
00918                      {
00919                             // unless at begin of par (eeks)
00920                             if ( (current.itemsInLine == 0) && (SpecialChars::isBreakingSpace(hl->ch[0]))
00921                                     && (a > 0 && ! SpecialChars::isBreak(itemText.text(a-1)))
00922                                     && ! (a > 0 && SpecialChars::isBreakingSpace(itemText.text(a-1)) 
00923                                              && (itemText.charStyle(a-1).effects() & ScStyle_SuppressSpace) != ScStyle_SuppressSpace))
00924                             {
00925                                    hl->setEffects(hl->effects() | ScStyle_SuppressSpace);
00926                                    hl->glyph.xadvance = 0;
00927                                    continue;
00928                             }
00929                             else
00930                                    hl->setEffects(hl->effects() & ~ScStyle_SuppressSpace);
00931                      }
00932                      else // from 134 on use NBSPACE for this effect
00933                      {
00934                             if ( current.itemsInLine == 0 && SpecialChars::isBreakingSpace(hl->ch[0]))
00935                             {
00936                                    hl->setEffects(hl->effects() | ScStyle_SuppressSpace);
00937                                    hl->glyph.xadvance = 0;
00938                                    continue;
00939                             }
00940                             else
00941                                    hl->setEffects(hl->effects() & ~ScStyle_SuppressSpace);
00942                      }
00943                      //                   qDebug(QString("textframe(%1,%2): len=%3, fontsize=%4, ascent=%5").arg(Xpos).arg(Ypos).arg(itemText.length())
00944 //                                    .arg(charStyle.fontSize()).arg(charStyle.font().ascent()));                      
00945                      if (current.itemsInLine == 0)
00946                      {
00947                             // more about par gap and dropcaps
00948                             if (((a > firstInFrame()) && (itemText.text(a-1) == SpecialChars::PARSEP)) || ((a == 0) && (BackBox == 0)) && (!current.startOfCol)) // after || always evaluates to false? FIXME
00949                             {
00950 //                                 qDebug(QString("gap before2: y=%1+%2").arg(current.yPos).arg(style.gapBefore()));
00951                                    current.yPos += style.gapBefore();
00952                                    DropCapDrop = 0;
00953                                    if (chstr[0] != SpecialChars::PARSEP)
00954                                           DropCmode = style.hasDropCap();
00955                                    else
00956                                           DropCmode = false;
00957                                    if (DropCmode)
00958                                    {
00959                                           DropLines = style.dropCapLines();
00960                                           if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
00961                                                  DropCapDrop = m_Doc->typographicSettings.valueBaseGrid * (DropLines-1);
00962                                           else
00963                                           {
00964                                                  if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
00965                                                         DropCapDrop = style.lineSpacing() * (DropLines-1);
00966                                                  else
00967                                                         DropCapDrop = charStyle.font().height(style.charStyle().fontSize() / 10.0) * (DropLines-1);
00968                                           }
00969 //                                        qDebug(QString("dropcapdrop: y=%1+%2").arg(current.yPos).arg(DropCapDrop));
00970                                           current.yPos += DropCapDrop;
00971                                    }
00972                             }
00973                      }
00974                      // find charsize & y pos
00975                      if (DropCmode)
00976                      {
00977                             // dropcap active?
00978                             if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
00979                                    DropCapDrop = m_Doc->typographicSettings.valueBaseGrid * (DropLines-1);
00980                             else
00981                             {
00982                                    if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
00983                                           DropCapDrop = style.lineSpacing() * (DropLines-1);
00984                                    else
00985                                           DropCapDrop = charStyle.font().height(style.charStyle().fontSize() / 10.0) * (DropLines-1);
00986                             }
00987 
00988                             if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
00989                             {
00990                                    chsd = (10 * ((m_Doc->typographicSettings.valueBaseGrid * (DropLines-1)+(charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / (charStyle.font().realCharHeight(chstr[0], 1))));
00991                                    chs = (10 * ((m_Doc->typographicSettings.valueBaseGrid * (DropLines-1)+(charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / charStyle.font().realCharAscent(chstr[0], 1)));
00992                             }
00993                             else
00994                             {
00995                                    if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
00996                                    {
00997                                           chsd = (10 * ((style.lineSpacing() * (DropLines-1)+(charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / (charStyle.font().realCharHeight(chstr[0], 1))));
00998                                           chs = (10 * ((style.lineSpacing() * (DropLines-1)+(charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / charStyle.font().realCharAscent(chstr[0], 1)));
00999                                    }
01000                                    else
01001                                    {
01002                                           double currasce = charStyle.font().height(style.charStyle().fontSize() / 10.0);
01003                                           chsd = (10 * ((currasce * (DropLines-1)+(charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / (charStyle.font().realCharHeight(chstr[0], 1))));
01004                                           chs = (10 * ((currasce * (DropLines-1)+(charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / charStyle.font().realCharAscent(chstr[0], 1)));
01005                                    }
01006                             }
01007                             hl->setEffects(hl->effects() | ScStyle_DropCap);
01008                             hl->glyph.yoffset -= DropCapDrop;
01009                      }
01010                      else // ! dropCapMode
01011                      {
01012                             if ((hl->ch[0] == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
01013                                    chs = qRound((hl->embedded.getItem()->gHeight + hl->embedded.getItem()->lineWidth()) * 10);
01014                             else
01015                                    chs = charStyle.fontSize();
01016                      }
01017                      // find tracking
01018                      if (current.itemsInLine == 0)
01019                      {
01020                             itemText.item(a)->setEffects(itemText.item(a)->effects() | ScStyle_StartOfLine);
01021                             kernVal = 0;
01022                      }
01023                      else
01024                      {
01025                             kernVal = 0; // chs * charStyle.tracking() / 10000.0;
01026                             itemText.item(a)->setEffects(itemText.item(a)->effects() & ~ScStyle_StartOfLine);
01027                      }
01028                      hl->glyph.yadvance = 0;
01029                      oldCurY = layoutGlyphs(*hl, chstr, hl->glyph);
01030                      // find out width of char
01031                      if ((hl->ch[0] == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
01032                             wide = hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth();
01033                      else
01034                      {
01035                             wide = hl->glyph.wide();
01036                             // apply kerning
01037                             if (a+1 < itemText.length())
01038                             {
01039                                    uint glyph2 = charStyle.font().char2CMap(itemText.text(a+1));
01040                                    double kern= charStyle.font().glyphKerning(hl->glyph.glyph, glyph2, chs / 10.0) * hl->glyph.scaleH;
01041                                    wide += kern;
01042                                    hl->glyph.xadvance += kern;
01043                             }
01044                      }
01045                      if (DropCmode)
01046                      {
01047                             // drop caps are wider...
01048                             if ((hl->ch[0] == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
01049                             {
01050                                    wide = hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth();
01051                                    if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01052                                           asce = m_Doc->typographicSettings.valueBaseGrid * DropLines;
01053                                    else
01054                                    {
01055                                           if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
01056                                                  asce = style.lineSpacing() * DropLines;
01057                                           else
01058                                                  asce = charStyle.font().height(style.charStyle().fontSize() / 10.0) * DropLines;
01059                                    }
01060                                    hl->glyph.scaleH /= hl->glyph.scaleV;
01061                                    hl->glyph.scaleV = (asce / (hl->embedded.getItem()->gHeight + hl->embedded.getItem()->lineWidth()));
01062                                    hl->glyph.scaleH *= hl->glyph.scaleV;
01063                             }
01064                             else
01065                             {
01066                                    wide = charStyle.font().realCharWidth(chstr[0], chsd / 10.0);
01067                                    asce = charStyle.font().realCharHeight(chstr[0], chsd / 10.0);
01068 //                                 qDebug(QString("dropcaps pre: chsd=%1 realCharHeight = %2 chstr=%3").arg(chsd).arg(asce).arg(chstr2[0]));
01069                                    hl->glyph.scaleH /= hl->glyph.scaleV;
01070                                    hl->glyph.scaleV = (asce / charStyle.font().realCharHeight(chstr[0], charStyle.fontSize() / 10.0));
01071                                    hl->glyph.scaleH *= hl->glyph.scaleV;
01072                             }
01073                             hl->glyph.xadvance = wide;
01074                             desc2 = 0;
01075                             desc = 0;
01076                      }
01077                      else // !DropCMode
01078                      {
01079 //                          qDebug(QString("textframe ascent/descent: fontsize=%1, ascent=%2, descent=%3")
01080 //                                    .arg(charStyle.fontSize()).arg(charStyle.font().ascent()).arg(charStyle.font().descent()));                         
01081 
01082                             if (SpecialChars::isExpandingSpace(hl->ch[0]))
01083                             {
01084                                    double wordtracking = charStyle.wordTracking();
01085                                    hl->glyph.xadvance *= wordtracking;
01086                                    wide *= wordtracking;
01087                             }
01088                             
01089                             // find ascent / descent
01090                             double hlcsize10=charStyle.fontSize() / 10.0;
01091                             if ((hl->ch[0] == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
01092                             {
01093                                    desc = desc2 = 0;
01094                             }
01095                             else
01096                             {
01097                                    desc = desc2 = -charStyle.font().descent(hlcsize10);
01098                                    current.rememberShrinkStretch(hl->ch[0], wide, style);                              
01099                             }
01100                             asce = charStyle.font().ascent(hlcsize10);
01101 //                          wide = wide * hl->glyph.scaleH;
01102                      }
01103                      fBorder = false;
01104                      // end of col reached?
01105 //                   qDebug(QString("eocol? %1 + %2 + %3 > %4 -- asce=%5").arg(current.yPos).arg(extra.Bottom).arg(lineCorr).arg(Height).arg(asce));
01106                      if (current.isEndOfCol())
01107                      {
01108                             current.column++;
01109                             if (current.column < Cols)
01110                             {
01111                                    // start next col
01112                                    current.nextColumn(asce);
01113                                    if (((a > firstInFrame()) && (itemText.text(a-1) == SpecialChars::PARSEP)) 
01114                                           || ((a == firstInFrame()) && (BackBox == 0)))
01115                                    {
01116                                           if (chstr[0] != SpecialChars::PARSEP)
01117                                                  DropCmode = style.hasDropCap();
01118                                           else
01119                                                  DropCmode = false;
01120                                           if (DropCmode)
01121                                           {
01122                                                  if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01123                                                         desc2 = -charStyle.font().descent() * m_Doc->typographicSettings.valueBaseGrid * style.dropCapLines();
01124                                                  else
01125                                                         desc2 = -charStyle.font().descent() * style.lineSpacing() * style.dropCapLines();
01126                                           }
01127                                           if (DropCmode)
01128                                                  DropLines = style.dropCapLines();
01129                                    }
01130 //                                 qDebug(QString("layout: nextcol grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid));
01131                                    if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01132                                    {
01133                                           double by = Ypos;
01134                                           if (OwnPage != -1)
01135                                                  by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
01136                                           int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
01137                                           int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
01138 //                                        qDebug(QString("baseline adjust: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by));
01139 
01140                                           current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
01141                                    }
01142                             }
01143                             else
01144                             {
01145                                    MaxChars = a;
01146 //                                 qDebug(QString("no room A: %1").arg(a));
01147                                    goto NoRoom;
01148                             }
01149                      }
01150                      // ok, there's more room in col
01151                      if (current.itemsInLine == 0)
01152                      {
01153 //                          qDebug(QString("newline: '%1' %2 %3").arg(a).arg(current.yPos).arg(asce));
01154                             // start a new line
01155                             double TopOffset = asce;
01156                             double BotOffset = desc2;
01157                             goNoRoom = false;
01158                             if (current.startOfCol)
01159                             {
01160 //                                 qDebug(QString("current.startOfCol: %1 + %2 + %3 + 1 =%4").arg(asce).arg(extra.Top).arg(lineCorr).arg(asce + extra.Top + lineCorr + 1));
01161                                    current.yPos = asce + extra.Top + lineCorr + 1;
01162 //                                               if (((a > 0) && (itemText.at(a-1)->ch == QChar(13))) || ((a == 0) && (BackBox == 0)))
01163 //                                                      current.yPos += m_Doc->docParagraphStyles[hl->cab].gapBefore;
01164                             }
01165 //                          qDebug(QString("layout: nextline grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid));
01166                             if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01167                             {
01168                                    double by = Ypos;
01169                                    if (OwnPage != -1)
01170                                           by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
01171                                    int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
01172                                    int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
01173 //                                 qDebug(QString("useBaselIneGrid: %1 * %2 + %3 - %4").arg(ol2 / 10000.0).arg(m_Doc->typographicSettings.valueBaseGrid).arg(m_Doc->typographicSettings.offsetBaseGrid).arg(by));
01174 //                                 qDebug(QString("baseline adjust: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by));
01175                                    current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
01176                             }
01177                             /* this causes different spacing for first line:
01178                             if (current.yPos-TopOffset < 0.0)
01179                             {
01180                                    qDebug(QString("current.yPos - Ascender < 0 (%1 - %2 < 0)").arg(current.yPos).arg(TopOffset));
01181                                    current.yPos = TopOffset+1;
01182                             }
01183                              */
01184                             // find linelength:
01185                             pt1 = QPoint(static_cast<int>(ceil(current.xPos)), static_cast<int>(current.yPos+BotOffset));
01186                             pt2 = QPoint(static_cast<int>(ceil(current.xPos)), static_cast<int>(ceil(current.yPos-TopOffset)));
01187                             // increase pt1/pt2 until i-beam reaches end of line
01188 //                          qDebug(QString("linestart: %1 + %2 + %3 < %4").arg(current.xPos).arg(wide).arg(style.rightMargin()).arg(current.colRight));
01189                             double leftIndent = 0;
01190                             double xStep = legacy? 1 : 0.125;
01191                             while (!cl.contains(pf2.xForm(pt1)) || !cl.contains(pf2.xForm(pt2)) || current.isEndOfLine(wide + leftIndent + style.rightMargin()))
01192                             {
01193                                    fBorder = true;
01194                                    current.xPos += xStep;
01195                                    if (current.isEndOfLine(wide + leftIndent + style.rightMargin()))
01196                                    {
01197 //                                        qDebug(QString("eocol %5? %1 + %2 + %3 + %4").arg(current.yPos).arg(current.startOfCol).arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(style.lineSpacing()).arg(current.column));
01198                                           // new line
01199                                           fBorder = false;
01200                                           current.xPos = current.colLeft;
01201 
01202                                           leftIndent = style.leftMargin();
01203                                           if (a > 0 && itemText.text(a-1) == SpecialChars::PARSEP)
01204                                                  leftIndent += style.firstIndent();
01205 
01206                                           if (current.startOfCol)
01207                                           {
01208 //                                               qDebug(QString("startofcol adjust: y=%1->%2").arg(current.yPos).arg(current.yPos+1));
01209 
01210                                                  current.yPos++;
01211                                           }
01212                                           else
01213                                           {
01214                                                  current.yPos += style.lineSpacing();
01215 //                                               qDebug(QString("next line: y=%1").arg(current.yPos));
01216                                           }
01217 //                                        qDebug(QString("layout: next lower line grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid));
01218                                           if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01219                                           {
01220                                                  double by = Ypos;
01221                                                  if (OwnPage != -1)
01222                                                         by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
01223                                                  int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
01224                                                  int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
01225 //                                               qDebug(QString("baseline adjust: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by));
01226                                                  current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
01227                                           }
01228                                           if (current.isEndOfCol())
01229                                           {
01230                                                  fBorder = false;
01231                                                  current.column++;
01232                                                  if (current.column < Cols)
01233                                                  {
01234                                                         current.nextColumn(asce);
01235                                                         if (((a > firstInFrame()) && (itemText.text(a-1) == SpecialChars::PARSEP)) || ((a == firstInFrame()) && (BackBox == 0)))
01236                                                         {
01237                                                                if (chstr[0] != SpecialChars::PARSEP)
01238                                                                       DropCmode = style.hasDropCap();
01239                                                                else
01240                                                                       DropCmode = false;
01241                                                                if (DropCmode)
01242                                                                {
01243                                                                       if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01244                                                                              desc2 = -charStyle.font().descent() * m_Doc->typographicSettings.valueBaseGrid * style.dropCapLines();
01245                                                                       else
01246                                                                              desc2 = -charStyle.font().descent() * style.lineSpacing() * style.dropCapLines();
01247                                                                }
01248                                                                if (DropCmode)
01249                                                                       DropLines = style.dropCapLines();
01250                                                         }
01251 //                                                      qDebug(QString("layout: nextcol2 grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid));
01252                                                         if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01253                                                         {
01254                                                                double by = Ypos;
01255                                                                if (OwnPage != -1)
01256                                                                       by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
01257                                                                int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
01258                                                                int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
01259 //                                                             qDebug(QString("baseline adjust: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by));
01260                                                                current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
01261                                                         }
01262                                                  }
01263                                                  else
01264                                                  {
01265                                                         MaxChars = a;
01266 //                                                      qDebug(QString("no room B: %1").arg(a));
01267                                                         goto NoRoom;
01268                                                  }
01269                                           }
01270                                    }
01271                                    pt1 = QPoint(static_cast<int>(ceil(current.xPos)), static_cast<int>(current.yPos+BotOffset));
01272                                    pt2 = QPoint(static_cast<int>(ceil(current.xPos)), static_cast<int>(ceil(current.yPos-TopOffset)));
01273                             }
01274 
01275                             if (((fBorder)) && (!AbsHasDrop))
01276                                    current.xPos += extra.Left;
01277                             // indent first line of par
01278                             if (a > 0)
01279                             {
01280                                    if (itemText.text(a-1) == SpecialChars::PARSEP)
01281                                           current.xPos += style.firstIndent();
01282                             }
01283                             else
01284                             {
01285                                    if (legacy)
01286                                           current.xPos += style.firstIndent();
01287                             }
01288                             // add left margin
01289                             if (!AbsHasDrop)
01290                                    current.xPos += style.leftMargin();
01291                             if (opticalMargins & ParagraphStyle::OM_LeftHangingPunct) {
01292                                    current.xPos += opticalLeftMargin(itemText, current.line);
01293                             }
01294 //                          qDebug(QString("store line: (%1,%2)").arg(current.xPos).arg(current.yPos));
01295                             current.line.x = current.xPos;
01296                             current.line.y = current.yPos;
01297                             fBorder = false;
01298                      }
01299                      else {
01300 //                          qDebug(QString("cont.' line: '%1'").arg(a));
01301                      }
01302                      // right tab stuff
01303                      if (tabs.active)
01304                      {
01305                             if (((hl->ch[0] == '.') && (tabs.status == TabPOINT)) || ((hl->ch[0] == ',') && (tabs.status == TabCOMMA)) || (hl->ch[0] == SpecialChars::TAB))
01306                             {
01307                                    tabs.active = false;
01308                                    tabs.status = TabNONE;
01309                             }
01310                      }
01311                      // tab positioning
01312                      if (hl->ch[0] == SpecialChars::TAB)
01313                      {
01314                             wide = 1;
01315                             if (tabs.active)
01316                                    tabs.active = false;
01317                             else // ???
01318                             {
01319                                    tabs.xPos = current.xPos;
01320                                    tTabValues = style.tabValues();
01321                                    if (tTabValues.isEmpty())
01322                                    {
01323                                           if ((current.xPos - current.colLeft) != 0)
01324                                           {
01325                                                  if (current.xPos == current.colLeft + ceil((current.xPos-current.colLeft) / m_Doc->toolSettings.dTabWidth) * m_Doc->toolSettings.dTabWidth)
01326                                                         current.xPos += m_Doc->toolSettings.dTabWidth;
01327                                                  else
01328                                                         current.xPos = current.colLeft + ceil((current.xPos-current.colLeft) / m_Doc->toolSettings.dTabWidth) * m_Doc->toolSettings.dTabWidth;
01329                                           }
01330                                           else
01331                                                  current.xPos = current.colLeft + m_Doc->toolSettings.dTabWidth;
01332                                           tabs.status = TabNONE;
01333                                           tabs.active = false;
01334                                    }
01335                                    else
01336                                    {
01337                                           double tCurX = current.xPos - current.colLeft;
01338                                           double oCurX = tCurX + wide;
01339                                           for (int yg = static_cast<int>(tTabValues.count()-1); yg > -1; yg--)
01340                                           {
01341                                                  if (oCurX < tTabValues[yg].tabPosition)
01342                                                  {
01343                                                         tabs.status = static_cast<int>(tTabValues[yg].tabType);
01344                                                         tCurX = tTabValues[yg].tabPosition;
01345                                                         tabs.fillChar    = tTabValues[yg].tabFillChar;
01346                                                  }
01347                                           }
01348                                           tabs.active = (tabs.status != TabLEFT);
01349                                           if (tCurX == oCurX-wide)
01350                                                  current.xPos = current.colLeft + ceil((current.xPos-current.colLeft) / m_Doc->toolSettings.dTabWidth) * m_Doc->toolSettings.dTabWidth;
01351                                           else
01352                                                  current.xPos = current.colLeft + tCurX;
01353                                           
01354                                           // remember fill char
01355 //                                        qDebug(QString("tab: %1 '%2'").arg(tCurX).arg(tabs.fillChar));
01356                                           if (!tabs.fillChar.isNull()) {
01357                                                  hl->glyph.grow();
01358                                                  GlyphLayout * tglyph = hl->glyph.more;
01359                                                  tglyph->glyph = charStyle.font().char2CMap(tabs.fillChar);
01360                                                  tglyph->yoffset = hl->glyph.yoffset;
01361                                                  tglyph->scaleV = tglyph->scaleH = chs / charStyle.fontSize();
01362                                                  tglyph->xadvance = 0;
01363                                           }
01364                                    }
01365                                    hl->glyph.xadvance = current.xPos - tabs.xPos;
01366 //                                 wide = current.xPos - RTabX;
01367                                    tabs.charIndex = a;
01368                             }
01369                      }
01370                      
01371                      // remember y pos
01372                      if (DropCmode)
01373                             hl->glyph.yoffset -= charStyle.font().realCharHeight(chstr[0], chsd / 10.0) - charStyle.font().realCharAscent(chstr[0], chsd / 10.0);
01374 
01375                      
01376                      // remember x pos
01377                      double breakPos = current.xPos;
01378                      
01379                      if (!tabs.active) // normal case
01380                      {
01381                             current.xPos += wide+kernVal;
01382                      }
01383                      else if (tabs.active && tabs.status == TabCENTER)       // center tab
01384                      {
01385                             current.xPos += (wide+kernVal) / 2;
01386                             current.xPos = QMAX(current.xPos, current.colLeft);
01387                      }
01388                      else // other tabs.active                 
01389                      {
01390                             current.xPos = QMAX(current.xPos, current.colLeft);
01391                      }
01392                      
01393                      
01394                      //FIXME: asce / desc set correctly?
01395                      if (legacy && 
01396                             ((hl->ch[0] == '-' || (hl->effects() & ScStyle_HyphenationPossible)) && (current.hyphenCount < m_Doc->HyCount || m_Doc->HyCount == 0))  
01397                             || hl->ch[0] == SpecialChars::SHYPHEN)
01398                      {
01399                             if (hl->effects() & ScStyle_HyphenationPossible || hl->ch[0] == SpecialChars::SHYPHEN)
01400                             {
01401                                    pt1 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink + charStyle.font().charWidth('-', charStyle.fontSize() / 10.0) * (charStyle.scaleH() / 1000.0))), qRound(current.yPos+desc));
01402                                    pt2 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink + charStyle.font().charWidth('-', charStyle.fontSize() / 10.0) * (charStyle.scaleH() / 1000.0))), qRound(ceil(current.yPos-asce)));
01403                             }
01404                             else
01405                             {
01406                                    pt1 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink )), qRound(current.yPos+desc));
01407                                    pt2 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink )), qRound(ceil(current.yPos-asce)));
01408                             }
01409                      }
01410                      else if (!legacy && SpecialChars::isBreakingSpace(hl->ch[0]))
01411                      {
01412                             pt1 = QPoint(qRound(ceil(breakPos + extra.Right - current.maxShrink )), qRound(current.yPos+desc));
01413                             pt2 = QPoint(qRound(ceil(breakPos + extra.Right - current.maxShrink )), qRound(ceil(current.yPos-asce)));
01414                      }
01415                      else
01416                      {
01417                             pt1 = QPoint(qRound(ceil(current.xPos + extra.Right - current.maxShrink )), qRound(current.yPos+desc));
01418                             pt2 = QPoint(qRound(ceil(current.xPos + extra.Right - current.maxShrink )), qRound(ceil(current.yPos-asce)));
01419                      }
01420                      
01421                      // test if end of line reached
01422                      if ((!cl.contains(pf2.xForm(pt1))) || (!cl.contains(pf2.xForm(pt2))) || (legacy && current.isEndOfLine(style.rightMargin())))
01423                             outs = true;
01424                      if (current.isEndOfCol())
01425                             outs = true;
01426                      if ((hl->ch[0] == SpecialChars::FRAMEBREAK) && (a < itemText.length()-1))
01427                             goNoRoom = true;
01428                      if ((hl->ch[0] == SpecialChars::COLBREAK) && (Cols > 1))
01429                             goNextColumn = true;
01430 
01431 
01432                      // remember possible break
01433                      if ( (SpecialChars::isBreakingSpace(hl->ch[0]) || hl->ch[0] == SpecialChars::TAB) && !outs)
01434                      {
01435                             if ( a == firstInFrame() || !SpecialChars::isBreakingSpace(itemText.text(a-1)) )
01436                             {
01437                                    current.rememberBreak(a, breakPos);
01438                             }
01439                      }
01440                      
01441 
01442                      // hyphenation
01443                      if (((hl->effects() & ScStyle_HyphenationPossible) || (hl->ch[0] == '-') || hl->ch[0] == SpecialChars::SHYPHEN) && (!outs) && !itemText.text(a-1).isSpace() )
01444                      {
01445                             breakPos = current.xPos;
01446                             if (hl->ch[0] != '-')
01447                             {
01448                                    breakPos += charStyle.font().charWidth('-', charStyle.fontSize() / 10.0) * (charStyle.scaleH() / 1000.0);
01449                             }
01450                             
01451                             double rightHang = 0;
01452                             if (opticalMargins & ParagraphStyle::OM_RightHangingPunct) {
01453                                    rightHang = 0.7 * charStyle.font().realCharWidth('-', (charStyle.fontSize() / 10.0) * (charStyle.scaleH() / 1000.0));
01454                             }
01455                             
01456                             if (legacy || (breakPos - rightHang < current.colRight - style.rightMargin()))
01457                             {
01458                                    if ((current.hyphenCount < m_Doc->HyCount) || (m_Doc->HyCount == 0) || hl->ch[0] == SpecialChars::SHYPHEN)
01459                                    {
01460                                           current.rememberBreak(a, breakPos);
01461                                    }
01462                             }
01463                      }
01464                      
01465                                           
01466                      ++current.itemsInLine;
01467                      
01468                      if (tabs.active)
01469                      {
01470                             double cen = 1;
01471                             if (tabs.status == TabCENTER)
01472                                    cen = 2;
01473                             
01474                             double newTabAdvance = itemText.item(tabs.charIndex)->glyph.xadvance - (wide+kernVal) / cen;
01475                             
01476                             if (newTabAdvance >= 0) {
01477                                    itemText.item(tabs.charIndex)->glyph.xadvance = newTabAdvance;
01478                             }
01479                             else {
01480                                    tabs.active = false;
01481                                    tabs.status = TabNONE;
01482                             }
01483                      }
01484                      
01485                      if (DropCmode)
01486                      {
01487                             DropCmode = false;
01488                             AbsHasDrop = true;
01489                             maxDY = current.yPos;
01490                             current.xPos += style.dropCapOffset();
01491                             hl->glyph.xadvance += style.dropCapOffset();
01492 //                          qDebug(QString("dropcapoffset: %1 -> %2").arg(current.xPos-style.dropCapOffset()).arg(current.xPos));
01493                             current.xPos = QMAX(current.xPos, current.colLeft);
01494                             maxDX = current.xPos;
01495                             QPointArray tcli(4);
01496                             if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01497                             {
01498                                    current.yPos -= m_Doc->typographicSettings.valueBaseGrid * (DropLines-1);
01499                                    double by = Ypos;
01500                                    if (OwnPage != -1)
01501                                           by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
01502                                    int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
01503                                    int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
01504 //                                 qDebug(QString("baseline adjust after dropcaps: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by));
01505                                    current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
01506                                    //FIXME: use current.colLeft instead of xOffset?
01507                                    tcli.setPoint(0, QPoint(qRound(hl->glyph.xoffset), qRound(maxDY-DropLines*m_Doc->typographicSettings.valueBaseGrid)));
01508                                    tcli.setPoint(1, QPoint(qRound(maxDX), qRound(maxDY-DropLines*m_Doc->typographicSettings.valueBaseGrid)));
01509                             }
01510                             else
01511                             {
01512                                    if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
01513                                    {
01514                                           current.yPos -= style.lineSpacing() * (DropLines-1);
01515 //                                        qDebug(QString("after dropcaps: y=%1").arg(current.yPos));
01516                                           tcli.setPoint(0, QPoint(qRound(hl->glyph.xoffset), qRound(maxDY - DropLines * style.lineSpacing())));
01517                                           tcli.setPoint(1, QPoint(qRound(maxDX), qRound(maxDY-DropLines*style.lineSpacing())));
01518                                    }
01519                                    else
01520                                    {
01521                                           double currasce = charStyle.font().height(style.charStyle().fontSize() / 10.0);
01522                                           current.yPos -= currasce * (DropLines-1);
01523 //                                        qDebug(QString("after dropcaps: y=%1").arg(current.yPos));
01524                                           tcli.setPoint(0, QPoint(qRound(hl->glyph.xoffset), qRound(maxDY-DropLines*currasce)));
01525                                           tcli.setPoint(1, QPoint(qRound(maxDX), qRound(maxDY-DropLines*currasce)));
01526                                    }
01527                             }
01528                             tcli.setPoint(2, QPoint(qRound(maxDX), qRound(maxDY)));
01529                             tcli.setPoint(3, QPoint(qRound(hl->glyph.xoffset), qRound(maxDY)));
01530                             cm = QRegion(pf2.xForm(tcli));
01531                             cl = cl.subtract(cm);
01532 //                          current.yPos = maxDY;
01533                      }
01534                      // end of line
01535                      if ( SpecialChars::isBreak(hl->ch[0], Cols > 1) || (outs))
01536                      {
01537                             tabs.active = false;
01538                             tabs.status = TabNONE;
01539                             if (SpecialChars::isBreak(hl->ch[0], Cols > 1))
01540                             {
01541                                    // find end of line
01542                                    current.breakLine(itemText, a);
01543                                    EndX = current.endOfLine(cl, pf2, asce, desc, style.rightMargin());
01544                                    current.finishLine(EndX);
01545                                    
01546 //                                 if (style.alignment() != 0)
01547                                    {
01548                                           if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
01549                                                  current.line.width += opticalRightMargin(itemText, current.line);
01550 
01551                                           OFs = 0;
01552                                           if (style.alignment() == 2)
01553                                                  OFs = current.line.width - current.line.naturalWidth;
01554                                           if (style.alignment() == 1)
01555                                                  OFs = (current.line.width - current.line.naturalWidth) / 2;
01556                                           if (style.alignment() == 3)
01557                                                  OFs = 0;
01558                                           
01559                                           if (style.alignment() == 4
01560                                                  || (style.alignment() == 3 
01561                                                         &&  (hl->ch[0] == SpecialChars::LINEBREAK ||
01562                                                                 hl->ch[0] == SpecialChars::FRAMEBREAK ||
01563                                                                 hl->ch[0] == SpecialChars::COLBREAK)
01564                                                         &&  !itemText.text(current.line.lastItem - 1).isSpace()))
01565                                           {
01566                                                  justifyLine(itemText, current.line); 
01567                                           }
01568                                           else
01569                                           {
01570                                                  if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
01571                                                         current.line.naturalWidth += opticalRightMargin(itemText, current.line);
01572                                                  double optiWidth = current.colRight - style.lineSpacing()/2.0 - current.line.x;
01573                                                  if (current.line.naturalWidth > optiWidth)
01574                                                         current.line.width = QMAX(current.line.width - current.maxShrink, optiWidth);
01575                                                  // simple offset
01576                                                  indentLine(itemText, current.line, OFs);
01577                                           }
01578                                           current.xPos = current.colRight;
01579                                    }
01580                             }
01581                             else // outs -- last char went outside the columns (or into flow-around shape)
01582                             {
01583                                    if (current.breakIndex >= 0)            // Hier koenen auch andere Trennungen eingebaut werden
01584                                    {
01585                                           // go back to last break position
01586 //                                        qDebug(QString("new break pos a=%1 BuPos=%2 current.breakIndex=%3").arg(a).arg(BuPos).arg(current.breakIndex));
01587                                           a = current.breakIndex;
01588                                           assert( a >= 0 );
01589                                           assert( a < itemText.length() );
01590                                           hl = itemText.item(a);
01591                                           style = itemText.paragraphStyle(a);
01592                                           if (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing)
01593                                           {
01594                                                  style.setLineSpacing(style.charStyle().font().height(style.charStyle().fontSize() / 10.0));
01595 //                                               qDebug(QString("auto linespacing: %1").arg(style.lineSpacing()));
01596                                           }
01597                                           current.itemsInLine = a - current.line.firstItem + 1;
01598 //                                        qDebug(QString("style outs pos %1: %2 (%3)").arg(a).arg(style.alignment()).arg(style.parent()));
01599 //                                        qDebug(QString("style <@%6: %1 -- %2, %4/%5 char: %3").arg(style.leftMargin()).arg(style.rightMargin())
01600 //                                                  .arg(style.charStyle().asString()).arg(style.name()).arg(style.parent()?style.parent()->name():"")
01601 //                                                  .arg(a));
01602 
01603                                           if (hl->ch[0] == ' ') {
01604                                                  hl->setEffects(hl->effects() | ScStyle_SuppressSpace);
01605                                                  hl->glyph.xadvance = 0;
01606                                           }
01607                                           
01608 //                                        current.breakXPos = current.line.x;
01609 //                                        for (int j=current.line.firstItem; j <= a; ++j)
01610 //                                               current.breakXPos += itemText.item(j)->glyph.wide();
01611                                           
01612                                           EndX = current.endOfLine(cl, pf2, asce, desc, style.rightMargin());
01613                                           current.finishLine(EndX);
01614                                           
01615                                           if ((hl->effects() & ScStyle_HyphenationPossible) || hl->ch[0] == SpecialChars::SHYPHEN)
01616                                           {
01617                                                  // insert hyphen
01618                                                  current.hyphenCount++;
01619                                                  hl->setEffects(hl->effects() | ScStyle_SmartHyphenVisible);
01620                                                  hl->glyph.grow();
01621                                                  hl->glyph.more->glyph = charStyle.font().char2CMap(QChar('-'));
01622                                                  hl->glyph.more->xadvance = charStyle.font().charWidth('-', itemText.charStyle(a).fontSize() / 10.0) * (itemText.charStyle(a).scaleH() / 1000.0);
01623                                           }
01624                                           else 
01625                                           {
01626                                                  if (hl->ch[0] != '-')
01627                                                         current.hyphenCount = 0;
01628                                                  hl->setEffects(hl->effects() & ~ScStyle_SmartHyphenVisible);
01629                                                  hl->glyph.shrink();
01630                                           }
01631                                           
01632                                           // Justification
01633 //                                        if (style.alignment() != 0)
01634                                           {
01635                                                  if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
01636                                                         current.line.width += opticalRightMargin(itemText, current.line);
01637 
01638                                                  OFs = 0;
01639                                                  if (style.alignment() == 2)
01640                                                         OFs = current.line.width - current.line.naturalWidth;
01641                                                  if (style.alignment() == 1)
01642                                                         OFs = (current.line.width - current.line.naturalWidth) / 2;
01643                                                  
01644                                                  if ((style.alignment() == 3) 
01645                                                         || (style.alignment() == 4))
01646                                                  {
01647                                                         justifyLine(itemText, current.line);
01648                                                  }
01649                                                  else
01650                                                  {
01651                                                         if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
01652                                                                current.line.naturalWidth += opticalRightMargin(itemText, current.line);
01653                                                         indentLine(itemText, current.line, OFs);
01654                                                  }
01655 //                                               qDebug(QString("line: endx=%1 next pos=(%2,%3)").arg(EndX).arg(current.line.x + current.line.width).arg(current.yPos));
01656                                                  current.xPos = current.line.x + current.line.width;
01657                                           }
01658                                    }
01659                                    else  // no break position
01660                                    {
01661                                           if (a >= current.line.firstItem)
01662                                           {
01663                                                  --a;
01664                                                  --current.itemsInLine;
01665                                           }
01666                                           if (a >= 0)
01667                                           {
01668                                                  hl = itemText.item(a);
01669                                                  style = itemText.paragraphStyle(a);
01670                                                  if (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing)
01671                                                  {
01672                                                         style.setLineSpacing(style.charStyle().font().height(style.charStyle().fontSize() / 10.0));
01673 //                                                      qDebug(QString("auto linespacing: %1").arg(style.lineSpacing()));
01674                                                  }
01675                                           }
01676                                           current.breakLine(itemText, a);
01677 //                                        qDebug(QString("style no break pos %1: %2 (%3)").arg(a).arg(style.alignment()).arg(style.parent()));
01678 //                                        qDebug(QString("style nb @%6: %1 -- %2, %4/%5 char: %3").arg(style.leftMargin()).arg(style.rightMargin())
01679 //                                                  .arg(style.charStyle().asString()).arg(style.name()).arg(style.parent())
01680 //                                                  .arg(a));
01681                                           EndX = current.endOfLine(cl, pf2, asce, desc, style.rightMargin());
01682                                           current.finishLine(EndX);
01683 //                                        qDebug(QString("no break pos: %1-%2 @ %3 wid %4 nat %5 endX %6")
01684 //                                                  .arg(current.line.firstItem).arg(current.line.firstItem)
01685 //                                                  .arg(current.line.x).arg(current.line.width).arg(current.line.naturalWidth).arg(EndX));
01686                                           indentLine(itemText, current.line, 0);
01687                                    }
01688                             }
01689                             if ( outs || SpecialChars::isBreak(hl->ch[0], (Cols > 1)) )
01690                             {
01691                                    if (outs && !current.isEndOfLine(hl->glyph.wide() + style.rightMargin()))
01692                                    {
01693                                           if (( hl->ch[0] == SpecialChars::PARSEP || hl->ch[0] == SpecialChars::LINEBREAK) 
01694                                                  && AbsHasDrop)
01695                                           {
01696                                                  AbsHasDrop = false;
01697                                                  if (current.yPos < maxDY)
01698                                                         current.yPos = maxDY;
01699 //                                               qDebug(QString("after dropcaps: y=%1 maxDY=%2").arg(current.yPos).arg(maxDY));
01700                                           }
01701                                           bool fromOut = true;
01702                                           double BotOffset = desc+extra.Bottom+lineCorr;
01703 //                                        pt1 = QPoint(qRound(current.xPos+extra.Right), static_cast<int>(current.yPos+BotOffset));
01704 //                                        pt2 = QPoint(qRound(current.xPos+extra.Right), static_cast<int>(ceil(current.yPos-asce)));
01705                                           while (!current.isEndOfLine(style.rightMargin()))
01706                                           {
01707                                                  current.xPos++;
01708                                                  if (current.isEndOfLine(style.rightMargin()))
01709                                                  {
01710                                                         fromOut = false;
01711 //                                                      qDebug(QString("layout: next lower2 grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid));
01712 //                                                      qDebug(QString("nextline: y=%1+%2").arg(current.yPos).arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing? m_Doc->typographicSettings.valueBaseGrid : style.lineSpacing()));
01713 
01714                                                         if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01715                                                                current.yPos += m_Doc->typographicSettings.valueBaseGrid;
01716                                                         else
01717                                                                current.yPos += style.lineSpacing();
01718                                                         if (current.isEndOfCol(desc) && (current.column+1 == Cols))
01719                                                         {
01720                                                                goNoRoom = true;
01721 //                                                             qDebug(QString("go no room 1: %1").arg(a));
01722                                                                break;
01723                                                         }
01724                                                         if (AbsHasDrop)
01725                                                         {
01726                                                                if ((current.yPos > maxDY) && (current.yPos - asce > maxDY))
01727                                                                {
01728                                                                       AbsHasDrop = false;
01729                                                                       current.xPos = current.colLeft;
01730                                                                }
01731                                                                else
01732                                                                       current.xPos = maxDX;
01733                                                         }
01734                                                         else
01735                                                                current.xPos = current.colLeft;
01736                                                         if (SpecialChars::isBreak(hl->ch[0]))
01737                                                         {
01738                                                                if (hl->ch[0] == SpecialChars::PARSEP)
01739                                                                {
01740 //                                                                    qDebug(QString("gap after: y=%1+%2").arg(current.yPos).arg(style.gapAfter()));
01741                                                                       current.yPos += style.gapAfter();
01742                                                                }
01743                                                                current.hyphenCount = 0;
01744                                                         }
01745                                                         break;
01746                                                  }
01747                                                  pt1 = QPoint(qRound(current.xPos + extra.Right), static_cast<int>(current.yPos+BotOffset));
01748                                                  pt2 = QPoint(qRound(current.xPos + extra.Right), static_cast<int>(ceil(current.yPos-asce)));
01749                                                  if (cl.contains(pf2.xForm(pt1)) && cl.contains(pf2.xForm(pt2)))
01750                                                         break;
01751 //                                               else
01752 //                                                      qDebug(QString("looking for start of line at %1,%2").arg(current.xPos).arg(current.yPos));
01753                                           }
01754                                           if (fromOut)
01755                                           {
01756                                                  if (current.isEndOfCol(desc) && (current.column+1 == Cols))
01757                                                  {
01758                                                         goNoRoom = true;
01759 //                                                      qDebug(QString("go no room 2: %1").arg(a));
01760                                                         break;
01761                                                  }
01762                                                  current.xPos--;
01763                                                  current.xPos = QMAX(current.xPos, current.colLeft);
01764                                           }
01765                                    }
01766                                    else
01767                                    {
01768                                           if (( hl->ch[0] == SpecialChars::PARSEP || hl->ch[0] == SpecialChars::LINEBREAK ) 
01769                                                  && AbsHasDrop)
01770                                           {
01771                                                  AbsHasDrop = false;
01772                                                  if (current.yPos < maxDY)
01773                                                         current.yPos = maxDY;
01774 //                                               qDebug(QString("after dropcap2: y=%1+%2").arg(current.yPos).arg(maxDY));
01775                                           }
01776 //                                        qDebug(QString("layout: next lower3 grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid));
01777 
01778 
01779                                           if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
01780                                           {
01781 //                                               qDebug(QString("next line (grid): y=%1+%2").arg(current.yPos).arg(m_Doc->typographicSettings.valueBaseGrid));
01782 
01783                                                  current.yPos += m_Doc->typographicSettings.valueBaseGrid;
01784                                           }
01785                                           else if (a < lastInFrame() && style.lineSpacingMode() != ParagraphStyle::AutomaticLineSpacing)
01786                                           {
01787 //                                               qDebug(QString("next line (fixed): y=%1+%2").arg(current.yPos).arg(itemText.paragraphStyle(a+1).lineSpacing()));
01788                                                  current.yPos += itemText.paragraphStyle(a+1).lineSpacing();
01789                                           }
01790                                           else
01791                                           {
01792 //                                               qDebug(QString("next line (auto): y=%1+%2").arg(current.yPos).arg(style.lineSpacing()));
01793                                                  current.yPos += style.lineSpacing();
01794                                           }
01795                                           if (AbsHasDrop)
01796                                           {
01797                                                  if ((current.yPos > maxDY) && (current.yPos - asce > maxDY))
01798                                                  {
01799                                                         AbsHasDrop = false;
01800                                                         current.xPos = current.colLeft;
01801                                                  }
01802                                                  else
01803                                                         current.xPos = maxDX;
01804                                           }
01805                                           else
01806                                                  current.xPos = current.colLeft;
01807                                           if ( SpecialChars::isBreak(hl->ch[0]) )
01808                                           {
01809                                                  if (hl->ch[0] == SpecialChars::PARSEP)
01810                                                  {
01811 //                                                      qDebug(QString("gap after: y=%1+%2").arg(current.yPos).arg(style.gapAfter()));
01812                                                         current.yPos += style.gapAfter();
01813                                                  }
01814                                                  current.hyphenCount = 0;
01815                                           }
01816                                    }
01817                             }
01818                             
01819 
01820                             // calc. needed vertical space
01821                             if (current.itemsInLine != 0)
01822                             {
01823                                    if ((!AbsHasDrop) && (current.startOfCol) && (style.lineSpacingMode() != ParagraphStyle::BaselineGridLineSpacing))
01824                                    {
01825                                           //FIXME: use glyphs, not chars
01826                                           double firstasce = itemText.charStyle(current.line.firstItem).font().ascent(itemText.charStyle(current.line.firstItem).fontSize() / 10.0);
01827                                           double currasce = current.getLineAscent(itemText);
01828                                                  /*0;
01829                                           if ((itemText.text(current.line.firstItem) == SpecialChars::PARSEP) || (itemText.text(current.line.firstItem) == SpecialChars::LINEBREAK))
01830                                                  currasce = itemText.charStyle(current.line.firstItem).font().ascent(itemText.charStyle(current.line.firstItem).fontSize() / 10.0);
01831                                           else if (itemText.object(current.line.firstItem) != 0)
01832                                                  currasce = QMAX(currasce, (itemText.object(current.line.firstItem)->gHeight + itemText.object(current.line.firstItem)->lineWidth()) * (itemText.charStyle(current.line.firstItem).scaleV() / 1000.0));
01833                                           else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
01834                                                  currasce = itemText.charStyle(current.line.firstItem).font().realCharAscent(itemText.text(current.line.firstItem), itemText.charStyle(current.line.firstItem).fontSize() / 10.0);
01835                                           for (int zc = 0; zc < current.itemsInLine; ++zc)
01836                                           {
01837                                                  QChar ch = itemText.text(current.line.firstItem + zc);
01838                                                  if (ch == SpecialChars::PAGENUMBER)
01839                                                         ch = '8'; // should have highest ascender even in oldstyle
01840                                                  const CharStyle& cStyle(itemText.charStyle(current.line.firstItem + zc));
01841                                                  if ((ch == SpecialChars::TAB) || (ch == QChar(10))
01842                                                         || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
01843                                                         || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::LINEBREAK)
01844                                                         || (ch == SpecialChars::FRAMEBREAK) || (ch.isSpace()))
01845                                                         continue;
01846                                                  double asce;
01847                                                  if (itemText.object(current.line.firstItem + zc) != 0)
01848                                                         asce = itemText.object(current.line.firstItem + zc)->gHeight + itemText.object(current.line.firstItem + zc)->lineWidth() * (cStyle.scaleV() / 1000.0);
01849                                                  else //if (itemText.charStyle(current.line.firstItem + zc).effects() & ScStyle_DropCap == 0)
01850                                                         asce = cStyle.font().realCharAscent(ch, cStyle.fontSize() / 10.0);
01851 //                                               qDebug(QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(currasce));
01852                                                  currasce = QMAX(currasce, asce);
01853                                           }*/
01854                                           double adj = firstasce - currasce;
01855 //                                        qDebug(QString("move1 line %1.. down by %2").arg(current.line.firstItem).arg(-adj));
01856                                           current.line.ascent = currasce;
01857                                           current.line.y -= adj;
01858                                           current.yPos -= adj;
01859                                    }
01860                                    else if ((!current.startOfCol) && (style.lineSpacingMode() != ParagraphStyle::BaselineGridLineSpacing) && (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing))
01861                                    {
01862                                           QChar ch = itemText.text(current.line.firstItem);
01863                                           double firstasce = style.lineSpacing();
01864                                           double currasce = current.getLineHeight(itemText);
01865                                           /*0;
01866                                           if (itemText.object(current.line.firstItem) != 0)
01867                                                  currasce = QMAX(currasce, (itemText.object(current.line.firstItem)->gHeight + itemText.object(current.line.firstItem)->lineWidth()) * (itemText.charStyle(current.line.firstItem).scaleV() / 1000.0));
01868                                           else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
01869                                                  currasce = itemText.charStyle(current.line.firstItem).font().height(itemText.charStyle(current.line.firstItem).fontSize() / 10.0);
01870                                           for (int zc = 0; zc < current.itemsInLine; ++zc)
01871                                           {
01872                                                  QChar ch = itemText.text(current.line.firstItem + zc);
01873                                                  if ((ch == SpecialChars::TAB) || (ch == QChar(10))
01874                                                         || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
01875                                                         || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::FRAMEBREAK)
01876                                                         || (ch == SpecialChars::LINEBREAK) || (ch.isSpace()))
01877                                                         continue;
01878                                                  double asce;
01879                                                  if (itemText.object(current.line.firstItem + zc) != 0)
01880                                                         asce = itemText.object(current.line.firstItem + zc)->gHeight + itemText.object(current.line.firstItem + zc)->lineWidth() * (itemText.charStyle(current.line.firstItem + zc).scaleV() / 1000.0);
01881                                                  else //if (itemText.charStyle(current.line.firstItem + zc).effects() & ScStyle_DropCap == 0)
01882                                                         asce = itemText.charStyle(current.line.firstItem + zc).font().height(itemText.charStyle(current.line.firstItem + zc).fontSize() / 10.0);
01883 //                                               qDebug(QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(currasce));
01884                                                  currasce = QMAX(currasce, asce);
01885                                           }
01886                                           */                                               
01887                                           double adj = firstasce - currasce;
01888 //                                        qDebug(QString("move2 line %1.. down by %2").arg(current.line.firstItem).arg(-adj));
01889                                           current.line.ascent = currasce;
01890                                           current.line.y -= adj;
01891                                           current.yPos -= adj;
01892                                    }
01893                                    if ( itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap)
01894                                    {
01895                                           // put line back to top
01896                                           current.line.y -= DropCapDrop;
01897                                           itemText.item(current.line.firstItem)->glyph.yoffset += DropCapDrop;
01898                                    }
01899                             }
01900                             
01901                             fillInTabLeaders(itemText, current.line);
01902 
01903                             current.startOfCol = false;
01904 /* has no effect except setting wide, asce and desc
01905                             uint loopC = BuPos3;
01906                             if (m_Doc->guidesSettings.showControls)
01907                                    loopC++;  // ??? AV
01908                             for (int zc = 0; zc < loopC; ++zc)
01909                             {
01910                                    if ( zc >= current.itemsInLine) {
01911                                           qDebug("layout: zc too large %d / %d", zc, current.itemsInLine);
01912                                           continue;
01913                                    }
01914                                    if ( startLin + zc >= itemText.length()) {
01915                                           qDebug("layout: startLin+zc too large %d+%d / %d", startLin, zc, itemText.length());
01916                                           continue;
01917                                    }
01918 //                                 else
01919 //                                        qDebug("layout: startLin, zc ok. %d, %d, %d", startLin, zc, LiList.count());
01920                                    double wide2 = 0;
01921                                    double xcoZli = itemText.item(current.line.firstItem + zc)->glyph.xoffset;
01922 //                                 itemText.item(startLin+zc)->glyph.xoffset = Zli2->xco;
01924                                    tTabValues = itemText.paragraphStyle(startLin+zc).tabValues();
01925                                    desc = - itemText.charStyle(startLin+zc).font().descent(itemText.charStyle(startLin+zc).fontSize() / 10.0);
01926                                    asce = itemText.charStyle(startLin+zc).font().ascent(itemText.charStyle(startLin+zc).fontSize() / 10.0);
01927                                    bool Sele = itemText.selected(startLin+zc);
01928                                    if (((Sele && (Select)) || (((NextBox != 0) || (BackBox != 0)) && Sele)) && (m_Doc->appMode == modeEdit))
01929                                    {
01930                                           wide = itemText.item(startLin+zc)->glyph.xadvance;
01931                                           if ((zc > 0) && (itemText.text(startLin+zc) == SpecialChars::TAB))
01932                                           {
01933                                                  wide2 = itemText.item(startLin+zc-1)->glyph.xadvance;
01934                                                  xcoZli = itemText.item(startLin+zc-1)->glyph.xoffset + wide2;
01935                                                  wide = itemText.item(startLin+zc)->glyph.xoffset - xcoZli + itemText.item(startLin+zc)->glyph.xadvance;
01936                                           }
01937                                    }
01938                             }
01939                             */
01940 //                          qDebug(QString("layout: line %1 - %2 @ (%3,%4) wd %5/%6").arg(current.line.firstItem).arg(current.line.lastItem)
01941 //                                    .arg(current.line.x).arg(current.line.y).arg(current.line.naturalWidth).arg(current.line.width));
01942                             if (current.line.firstItem > current.line.lastItem)
01943                                    ; //qDebug(QString("layout: empty line %1 - %2").arg(current.line.firstItem).arg(current.line.lastItem));
01944                             else if (current.itemsInLine > 0)
01945                                    itemText.appendLine(current.line);
01946                             current.startLine(a+1);
01947                             outs = false;
01948                             if (goNoRoom)
01949                             {
01950                                    goNoRoom = false;
01951                                    MaxChars = a+1;
01952 //                                 qDebug(QString("no room C: %1").arg(a+1));
01953                                    goto NoRoom;
01954                             }
01955                             if (goNextColumn)
01956                             {
01957                                    goNextColumn = false;
01958                                    current.column++;
01959                                    if (current.column < Cols)
01960                                    {
01961                                           current.nextColumn(asce);
01962                                    }
01963                                    else
01964                                    {
01965                                           MaxChars = a;
01966 //                                        qDebug(QString("no room D: %1").arg(a));
01967                                           goto NoRoom;
01968                                    }
01969                             }
01970                      }
01971               }
01972 // end of itemText
01973               int a = itemText.length()-1;
01974               hl = a >=0 ? itemText.item(a) : NULL;
01975               current.breakLine(itemText, a);
01976               EndX = current.endOfLine(cl, pf2, asce, desc, style.rightMargin());
01977               current.finishLine(EndX);
01978 
01979 //            if (style.alignment() != 0)
01980               {
01981                      if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
01982                      {
01983                             current.line.width += opticalRightMargin(itemText, current.line);
01984                      }
01985                      
01986                      OFs = 0;
01987                      if (style.alignment() == 2)
01988                             OFs = current.line.width - current.line.naturalWidth;
01989                      if (style.alignment() == 1)
01990                             OFs = (current.line.width - current.line.naturalWidth) / 2;
01991                      if (style.alignment() == 3)
01992                             OFs = 0;
01993                      if (style.alignment() == 4
01994                             || (style.alignment() == 3 
01995                                    &&  (hl->ch[0] == SpecialChars::LINEBREAK ||
01996                                            hl->ch[0] == SpecialChars::FRAMEBREAK ||
01997                                            hl->ch[0] == SpecialChars::COLBREAK)
01998                                    &&  !itemText.text(current.line.firstItem + current.itemsInLine-1).isSpace()))
01999                      {
02000                             justifyLine(itemText, current.line);
02001                      }
02002                      else
02003                      {
02004                             if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
02005                                    current.line.naturalWidth += opticalRightMargin(itemText, current.line);
02006                             indentLine(itemText, current.line, OFs);
02007                      }
02008               }
02009 
02010               if (current.itemsInLine != 0)
02011               {
02012                      if ((!AbsHasDrop) && (current.startOfCol) && (style.lineSpacingMode() != ParagraphStyle::BaselineGridLineSpacing))
02013                      {
02014                             double firstasce = itemText.charStyle(current.line.firstItem).font().ascent(itemText.charStyle(current.line.firstItem).fontSize() / 10.0);
02015                             double currasce = current.getLineAscent(itemText);
02016                                    /*0; 
02017                             double asce;
02018                             if ((itemText.text(current.line.firstItem) == SpecialChars::PARSEP) || (itemText.text(current.line.firstItem) == SpecialChars::LINEBREAK))
02019                                    asce = itemText.charStyle(current.line.firstItem).font().ascent(itemText.charStyle(current.line.firstItem).fontSize() / 10.0);
02020                             else if (itemText.object(current.line.firstItem) != 0)
02021                                    asce = QMAX(currasce, (itemText.object(current.line.firstItem)->gHeight + itemText.object(current.line.firstItem)->lineWidth()) * (itemText.charStyle(current.line.firstItem).scaleV() / 1000.0));
02022                             else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
02023                                    asce = itemText.charStyle(current.line.firstItem).font().realCharAscent(itemText.text(current.line.firstItem), itemText.charStyle(current.line.firstItem).fontSize() / 10.0);
02024 //                          qDebug(QString("starting with ascender %1 (firstasce=%2)").arg(asce).arg(firstasce));
02025                             currasce = asce;
02026                             for (int zc = 0; zc < current.itemsInLine; ++zc)
02027                             {
02028                                    QChar ch = itemText.text(current.line.firstItem+zc);
02029                                    if (ch == SpecialChars::PAGENUMBER)
02030                                           ch = '8'; // should have highest ascender even in oldstyle
02031                                    if ((ch == SpecialChars::TAB) || (ch == QChar(10))
02032                                           || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
02033                                           || (ch == SpecialChars::FRAMEBREAK) || (ch == SpecialChars::COLBREAK)
02034                                           || (ch == SpecialChars::LINEBREAK) || (ch.isSpace()))
02035                                           continue;
02036                                    if (itemText.object(current.line.firstItem+zc) != 0)
02037                                           asce = (itemText.object(current.line.firstItem+zc)->gHeight + itemText.object(current.line.firstItem+zc)->lineWidth()) * itemText.charStyle(current.line.firstItem+zc).scaleV() / 1000.0;
02038                                    else //if (itemText.charStyle(current.line.firstItem+zc).effects() & ScStyle_DropCap == 0)
02039                                           asce = itemText.charStyle(current.line.firstItem+zc).font().realCharAscent(ch, itemText.charStyle(current.line.firstItem+zc).fontSize() / 10.0);
02040 //                                 qDebug(QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(currasce));
02041                                    currasce = QMAX(currasce, asce);
02042                             }
02043                             */
02044                             double adj = firstasce - currasce;
02045 //                          qDebug(QString("move3 line %1.. down by %2 current ascender=%3").arg(current.line.firstItem).arg(-adj).arg(currasce));
02046 
02047                             current.line.ascent = currasce;
02048                             current.line.y -= adj;
02049                             current.yPos -= adj;
02050                      }
02051                      else if ((!current.startOfCol) && (style.lineSpacingMode() != ParagraphStyle::BaselineGridLineSpacing) && (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing))
02052                      {
02053                             double firstasce = style.lineSpacing();
02054                             double currasce = current.getLineHeight(itemText);
02055                             /*0;
02056                             if (itemText.object(current.line.firstItem) != 0)
02057                                    currasce = QMAX(currasce, (itemText.object(current.line.firstItem)->gHeight + itemText.object(current.line.firstItem)->lineWidth()) * (itemText.charStyle(current.line.firstItem).scaleV() / 1000.0));
02058                             else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
02059                                    currasce = itemText.charStyle(current.line.firstItem).font().height(itemText.charStyle(current.line.firstItem).fontSize() / 10.0);
02060                             for (int zc = 0; zc < current.itemsInLine; ++zc)
02061                             {
02062                                    QChar ch = itemText.text(current.line.firstItem+zc);
02063                                    if (ch == SpecialChars::PAGENUMBER)
02064                                           ch = '8'; // should have highest ascender even in oldstyle
02065                                    if ((ch == SpecialChars::TAB) || (itemText.text(current.line.firstItem+zc) == QChar(10))
02066                                           || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
02067                                           || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::FRAMEBREAK)
02068                                           || (ch == SpecialChars::LINEBREAK) || (ch.isSpace()))
02069                                           continue;
02070                                    double asce;
02071                                    if (itemText.object(current.line.firstItem+zc) != 0)
02072                                           asce = (itemText.object(current.line.firstItem+zc)->gHeight + itemText.object(current.line.firstItem+zc)->lineWidth()) * (itemText.charStyle(current.line.firstItem+zc).scaleV() / 1000.0);
02073                                    else //if (itemText.charStyle(current.line.firstItem+zc).effects() & ScStyle_DropCap == 0)
02074                                           asce = itemText.charStyle(current.line.firstItem+zc).font().height(itemText.charStyle(current.line.firstItem+zc).fontSize() / 10.0);
02075 //                                 qDebug(QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(currasce));
02076                                    currasce = QMAX(currasce, asce);
02077                             }
02078                             */
02079                             double adj = firstasce - currasce;
02080 //                          qDebug(QString("move4 line %1.. down by %2").arg(current.line.firstItem).arg(-adj));
02081 
02082                             current.line.ascent = currasce;
02083                             current.line.y -= adj;
02084                             current.yPos -= adj;
02085                      }
02086                      if ( itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap )
02087                      {
02088                             // put line back to top
02089                             current.line.y -= DropCapDrop;
02090                             itemText.item(current.line.firstItem)->glyph.yoffset += DropCapDrop;
02091                      }
02092               }
02093               fillInTabLeaders(itemText, current.line);
02094               current.startOfCol = false;
02095               goNextColumn = false;
02096 
02097 //            qDebug(QString("layout: last line %1 - %2 @ (%3,%4) wd %5/%6").arg(current.line.firstItem).arg(current.line.lastItem)
02098 //                      .arg(current.line.x).arg(current.line.y).arg(current.line.naturalWidth).arg(current.line.width));
02099               
02100               if (current.itemsInLine > 0) {
02101                      itemText.appendLine(current.line);
02102               }
02103        }
02104        MaxChars = itemText.length();
02105        invalid = false;
02106        pf2.end();
02107        if (NextBox != NULL) {
02108               NextBox->invalid = true;
02109               dynamic_cast<PageItem_TextFrame*>(NextBox)->firstChar = MaxChars;
02110        }
02111 //     qDebug("textframe: len=%d, done relayout", itemText.length());
02112        return;
02113                      
02114 NoRoom:     
02115        pf2.end();
02116        invalid = false;
02117        PageItem_TextFrame * next = dynamic_cast<PageItem_TextFrame*>(NextBox);
02118        if (next != 0)
02119        {
02120               next->invalid = true;
02121               next->firstChar = MaxChars;
02122               if (CPos > signed(MaxChars))
02123               {
02124                      int nCP = CPos;
02125 //                   CPos = MaxChars;
02126                      if (m_Doc->appMode == modeEdit)
02127                      {
02128                             //                                               OwnPage->Deselect(true);
02129                             next->CPos = QMAX(nCP, signed(MaxChars));
02130                             //                                               Doc->currentPage = NextBox->OwnPage;
02131                             //                                               NextBox->OwnPage->SelectItemNr(NextBox->ItemNr);
02132 //                          qDebug("textframe: len=%d, leaving relayout in editmode && Tinput", itemText.length());
02133                             return;
02134                      }
02135               }
02136               // relayout next frame
02137 //            qDebug("textframe: len=%d, going to next at %d", itemText.length(), MaxChars);
02138               next->layout();
02139        }
02140 //     qDebug("textframe: len=%d, done relayout (no room %d)", itemText.length(), MaxChars);
02141 }
02142 
02143 
02144 void PageItem_TextFrame::DrawObj_Item(ScPainter *p, QRect e, double sc)
02145 {
02146        layout();
02147        if (invalid)
02148               return;
02149        QWMatrix pf2;
02150        QPoint pt1, pt2;
02151        QRegion cm;
02152        double wide, lineCorr;
02153        QChar chstr0;
02154        ScText *hl;
02155        QString cachedStroke = "";
02156        QString cachedFill = "";
02157        int cachedFillShade = -1;
02158        int cachedStrokeShade = -1;
02159        QString actStroke = "";
02160        QString actFill = "";
02161        int actFillShade = -1;
02162        int actStrokeShade = -1;
02163        QColor cachedFillQ;
02164        QColor cachedStrokeQ;
02165 //     QValueList<ParagraphStyle::TabRecord> tTabValues;
02166        double desc, asce, tabDist;
02167 //     tTabValues.clear();
02168        p->save();
02169        QRect e2;
02170        if (isEmbedded)
02171               e2 = e;
02172        else
02173        {
02174               e2 = QRect(qRound(e.x()  / sc + m_Doc->minCanvasCoordinate.x()), qRound(e.y()  / sc + m_Doc->minCanvasCoordinate.y()), qRound(e.width() / sc), qRound(e.height() / sc));
02175               pf2.translate(Xpos, Ypos);
02176        }
02177        pf2.rotate(Rot);
02178        if (!m_Doc->layerOutline(LayerNr))
02179        {
02180               if ((fillColor() != CommonStrings::None) || (GrType != 0))
02181               {
02182                      p->setupPolygon(&PoLine);
02183                      p->fillPath();
02184               }
02185        }
02186        if (lineColor() != CommonStrings::None)
02187               lineCorr = m_lineWidth / 2.0;
02188        else
02189               lineCorr = 0;
02190        if ((isAnnotation()) && (annotation().Type() == 2) && (!Pfile.isEmpty()) && (PicAvail) && (PicArt) && (annotation().UseIcons()))
02191        {
02192               p->save();
02193               p->setupPolygon(&PoLine);
02194               p->setClipPath();
02195               p->scale(LocalScX, LocalScY);
02196               p->translate(static_cast<int>(LocalX*LocalScX), static_cast<int>(LocalY*LocalScY));
02197               if (pixm.width() > 0 && pixm.height() > 0)
02198               {
02199                      QImage img(pixm.qImage());
02200                      p->drawImage(&img);
02201               }
02202               p->restore();
02203        }
02204        if (itemText.length() != 0)
02205        {
02206 //            qDebug("drawing textframe: len=%d", itemText.length());
02207 #ifdef HAVE_CAIRO
02208               if (imageFlippedH())
02209               {
02210                      p->translate(Width, 0);
02211                      p->scale(-1, 1);
02212                      pf2.translate(Width, 0);
02213                      pf2.scale(-1, 1);
02214               }
02215               if (imageFlippedV())
02216               {
02217                      p->translate(0, Height);
02218                      p->scale(1, -1);
02219                      pf2.translate(0, Height);
02220                      pf2.scale(1, -1);
02221               }
02222 #else
02223               if (imageFlippedH())
02224               {
02225                      p->translate(Width * sc, 0);
02226                      p->scale(-1, 1);
02227                      pf2.translate(Width, 0);
02228                      pf2.scale(-1, 1);
02229               }
02230               if (imageFlippedV())
02231               {
02232                      p->translate(0, Height * sc);
02233                      p->scale(1, -1);
02234                      pf2.translate(0, Height);
02235                      pf2.scale(1, -1);
02236               }
02237 #endif
02238               uint tabCc = 0;
02239               assert( firstInFrame() >= 0 );
02240               assert( lastInFrame() < itemText.length() );
02241               LineSpec ls;
02242               for (uint ll=0; ll < itemText.lines(); ++ll) {
02243                      ls = itemText.line(ll);
02244                      tabDist = ls.x;
02245                      double CurX = ls.x;
02246 //                   p->setLineWidth(0);
02247 //                   p->setBrush(Qt::yellow);
02248 //                   p->drawRect(ls.x, ls.y-ls.ascent, ls.width, ls.ascent);
02249 //                   p->setBrush(Qt::red);
02250 //                   p->drawRect(ls.x, ls.y, ls.width, ls.descent);
02251                      
02252                      QColor tmp;
02253                      for (int a = ls.firstItem; a <= ls.lastItem; ++a)
02254                      {
02255                             hl = itemText.item(a);
02256                             const CharStyle& charStyle(itemText.charStyle(a));
02257                             double chs = charStyle.fontSize() * hl->glyph.scaleV;
02258                             bool selected = itemText.selected(a);
02259                             if (charStyle.effects() & ScStyle_StartOfLine)
02260                                    tabCc = 0;
02261                             chstr0 = hl->ch[0];
02262                             actFill = charStyle.fillColor();
02263                             actFillShade = charStyle.fillShade();
02264                             if (actFill != CommonStrings::None)
02265                             {
02266                                    if ((cachedFillShade != actFillShade) || (cachedFill != actFill))
02267                                    {
02268                                           SetFarbe(&tmp, actFill, actFillShade);
02269                                           p->setBrush(tmp);
02270                                           cachedFillQ = tmp;
02271                                           cachedFill = actFill;
02272                                           cachedFillShade = actFillShade;
02273                                    }
02274                                    else
02275                                           p->setBrush(cachedFillQ);
02276                             }
02277                             if (charStyle.effects() & ScStyle_DropCap)
02278                             {
02279                                    const ParagraphStyle& style(itemText.paragraphStyle(a));
02280                                    if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
02281                                           chs = qRound(10 * ((m_Doc->typographicSettings.valueBaseGrid * (style.dropCapLines()-1) + (charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / charStyle.font().realCharHeight(chstr0, 10)));
02282                                    else
02283                                    {
02284                                           if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
02285                                                  chs = qRound(10 * ((style.lineSpacing() * (style.dropCapLines()-1)+(charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / charStyle.font().realCharHeight(chstr0, 10)));
02286                                           else
02287                                           {
02288                                                  double currasce = charStyle.font().height(style.charStyle().fontSize() / 10.0);
02289                                                  chs = qRound(10 * ((currasce * (style.dropCapLines()-1)+(charStyle.font().ascent(style.charStyle().fontSize() / 10.0))) / charStyle.font().realCharHeight(chstr0, 10)));
02290                                           }
02291                                    }
02292                             }
02293                             if (chstr0 == SpecialChars::TAB)
02294                                    tabCc++;
02295                             // paint selection
02296                             if (!m_Doc->RePos)
02297                             {
02298                                    double xcoZli = CurX + hl->glyph.xoffset;
02299                                    desc = - charStyle.font().descent(charStyle.fontSize() / 10.0);
02300                                    asce = charStyle.font().ascent(charStyle.fontSize() / 10.0);
02301                                    if (((selected && Select) || ((NextBox != 0 || BackBox != 0) && selected)) && (m_Doc->appMode == modeEdit))
02302                                    {
02303                                           wide = hl->glyph.xadvance;
02304                                           p->setFillMode(1);
02305                                           p->setBrush(qApp->palette().color(QPalette::Active, QColorGroup::Highlight));
02306                                           p->setLineWidth(0);
02307 //                                        if ((a > 0) && (QChar(hl->glyph.glyph) == SpecialChars::TAB))
02308 //                                        {
02309 //                                               xcoZli = CurX + itemText.item(a-1)->glyph.xoffset + itemText.charStyle(a-1).font().charWidth(itemText.text(a-1), itemText.charStyle(a-1).fontSize() / 10.0);
02310 //                                               wide = CurX + hl->glyph.xoffset - xcoZli + hl->glyph.xadvance;
02311 //                                        }
02312                                           if (!m_Doc->RePos)
02313                                                  p->drawRect(xcoZli, qRound(ls.y + hl->glyph.yoffset - asce * hl->glyph.scaleV), wide+1, qRound((asce+desc) * (hl->glyph.scaleV)));
02314                                           p->setBrush(qApp->palette().color(QPalette::Active, QColorGroup::HighlightedText));
02315                                    }
02316                                    actStroke = charStyle.strokeColor();
02317                                    actStrokeShade = charStyle.strokeShade();
02318                                    if (actStroke != CommonStrings::None)
02319                                    {
02320                                           if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke))
02321                                           {
02322                                                  SetFarbe(&tmp, actStroke, actStrokeShade);
02323                                                  p->setPen(tmp, 1, SolidLine, FlatCap, MiterJoin);
02324                                                  cachedStrokeQ = tmp;
02325                                                  cachedStroke = actStroke;
02326                                                  cachedStrokeShade = actStrokeShade;
02327                                           }
02328                                           else
02329                                                  p->setPen(cachedStrokeQ, 1, SolidLine, FlatCap, MiterJoin);
02330                                    }
02331                                    // paint glyphs
02332                                    if (e2.intersects(pf2.mapRect(QRect(qRound(CurX + hl->glyph.xoffset),qRound(ls.y + hl->glyph.yoffset-asce), qRound(hl->glyph.xadvance+1), qRound(asce+desc)))))
02333                                    {
02334                                           p->save();
02335 #ifdef HAVE_CAIRO
02336                                           p->translate(CurX, ls.y);
02337 #else
02338                                           p->translate(CurX * p->zoomFactor(), ls.y * p->zoomFactor());
02339 #endif
02340                                           if (hl->ch[0] == SpecialChars::OBJECT)
02341                                                  DrawObj_Embedded(p, e, charStyle, hl->embedded.getItem());
02342                                           else
02343                                                  drawGlyphs(p, charStyle, hl->glyph);
02344                                           p->restore();
02345                                    }
02346                                    if (hl->ch[0] == SpecialChars::OBJECT)
02347 #ifdef HAVE_CAIRO
02348                                           CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth());
02349 #else
02350                                           CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) ;
02351 #endif
02352                                    else
02353                                           CurX += hl->glyph.wide();
02354                             }
02355                             tabDist = CurX;
02356                      }
02357               }
02358        }
02359        else {
02360 //            qDebug("skipping textframe: len=%d", itemText.count());
02361        }
02362 
02363 //     pf2.end();
02364        p->restore();
02365 }
02366 
02367 
02368 void PageItem_TextFrame::DrawObj_Post(ScPainter *p)
02369 {
02370        ScribusView* view = m_Doc->view();
02371        if (m_Doc->layerOutline(LayerNr))
02372        {
02373               p->setPen(m_Doc->layerMarker(LayerNr), 1, SolidLine, FlatCap, MiterJoin);
02374               p->setFillMode(ScPainter::None);
02375               p->setBrushOpacity(1.0);
02376               p->setPenOpacity(1.0);
02377               p->setupPolygon(&PoLine);
02378               p->strokePath();
02379        }
02380        else
02381        {
02382 #ifdef HAVE_CAIRO
02383 //#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 1, 6)
02384               if (fillBlendmode() != 0)
02385                      p->endLayer();
02386 //#endif
02387 #endif
02388               if (!m_Doc->RePos)
02389               {
02390 #ifdef HAVE_CAIRO
02391 //#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 1, 6)
02392                      if (lineBlendmode() != 0)
02393                             p->beginLayer(1.0 - lineTransparency(), lineBlendmode());
02394 //#endif
02395 #endif
02396                      if (lineColor() != CommonStrings::None)
02397                      {
02398                             p->setPen(strokeQColor, m_lineWidth, PLineArt, PLineEnd, PLineJoin);
02399                             if (DashValues.count() != 0)
02400                                    p->setDash(DashValues, DashOffset);
02401                      }
02402                      else
02403                             p->setLineWidth(0);
02404                      if (!isTableItem)
02405                      {
02406                             p->setupPolygon(&PoLine);
02407                             if (NamedLStyle.isEmpty())
02408                                    p->strokePath();
02409                             else
02410                             {
02411                                    multiLine ml = m_Doc->MLineStyles[NamedLStyle];
02412                                    QColor tmp;
02413                                    for (int it = ml.size()-1; it > -1; it--)
02414                                    {
02415                                           SetFarbe(&tmp, ml[it].Color, ml[it].Shade);
02416                                           p->setPen(tmp, ml[it].Width,
02417                                                         static_cast<PenStyle>(ml[it].Dash),
02418                                                         static_cast<PenCapStyle>(ml[it].LineEnd),
02419                                                         static_cast<PenJoinStyle>(ml[it].LineJoin));
02420                                           p->strokePath();
02421                                    }
02422                             }
02423                      }
02424 #ifdef HAVE_CAIRO
02425 //#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 1, 6)
02426                      if (lineBlendmode() != 0)
02427                             p->endLayer();
02428 //#endif
02429 #endif
02430               }
02431        }
02432        if ((!isEmbedded) && (!m_Doc->RePos))
02433        {
02434               double scpInv = 1.0 / (QMAX(view->scale(), 1));
02435               if ((Frame) && (m_Doc->guidesSettings.framesShown) && ((itemType() == ImageFrame) || (itemType() == TextFrame) || (itemType() == PathText)))
02436               {
02437                      p->setPen(PrefsManager::instance()->appPrefs.DFrameNormColor, scpInv, DotLine, FlatCap, MiterJoin);
02438                      if ((isBookmark) || (m_isAnnotation))
02439                             p->setPen(PrefsManager::instance()->appPrefs.DFrameAnnotationColor, scpInv, DotLine, FlatCap, MiterJoin);
02440                      if ((BackBox != 0) || (NextBox != 0))
02441                             p->setPen(PrefsManager::instance()->appPrefs.DFrameLinkColor, scpInv, SolidLine, FlatCap, MiterJoin);
02442                      if (m_Locked)
02443                             p->setPen(PrefsManager::instance()->appPrefs.DFrameLockColor, scpInv, SolidLine, FlatCap, MiterJoin);
02444 
02445                      p->setFillMode(0);
02446                      if (itemType()==PathText)
02447                      {
02448                             if (Clip.count() != 0)
02449                             {
02450                                    FPointArray tclip;
02451                                    FPoint np = FPoint(Clip.point(0));
02452                                    tclip.resize(2);
02453                                    tclip.setPoint(0, np);
02454                                    tclip.setPoint(1, np);
02455                                    for (uint a = 1; a < Clip.size(); ++a)
02456                                    {
02457                                           np = FPoint(Clip.point(a));
02458                                           tclip.putPoints(tclip.size(), 4, np.x(), np.y(), np.x(), np.y(), np.x(), np.y(), np.x(), np.y());
02459                                    }
02460                                    np = FPoint(Clip.point(0));
02461                                    tclip.putPoints(tclip.size(), 2, np.x(), np.y(), np.x(), np.y());
02462                                    p->setupPolygon(&tclip);
02463                             }
02464                      }
02465                      else
02466                             p->setupPolygon(&PoLine);
02467                      p->strokePath();
02468               }
02469               if ((m_Doc->guidesSettings.framesShown) && textFlowUsesContourLine() && (ContourLine.size() != 0))
02470               {
02471                      p->setPen(lightGray, scpInv, DotLine, FlatCap, MiterJoin);
02472                      p->setupPolygon(&ContourLine);
02473                      p->strokePath();
02474               }
02475 
02476               //Draw the overflow icon
02477               if (frameOverflows())
02478               {//CB && added here for jghali prior to commit access
02479                      if ((!view->previewMode) && (!view->viewAsPreview))
02480                             drawOverflowMarker(p);
02481               }
02482               if ((m_Doc->guidesSettings.colBordersShown) && ((!view->previewMode) && (!view->viewAsPreview)))
02483                      drawColumnBorders(p);
02484               if ((m_Doc->guidesSettings.layerMarkersShown) && (m_Doc->layerCount() > 1) && (!m_Doc->layerOutline(LayerNr)))
02485               {
02486                      p->setPen(black, 0.5/ m_Doc->view()->scale(), SolidLine, FlatCap, MiterJoin);
02487                      p->setPenOpacity(1.0);
02488                      p->setBrush(m_Doc->layerMarker(LayerNr));
02489                      p->setBrushOpacity(1.0);
02490                      p->setFillMode(ScPainter::Solid);
02491                      double ofwh = 10;
02492                      double ofx = Width - ofwh/2;
02493                      double ofy = Height - ofwh*3;
02494                      p->drawRect(ofx, ofy, ofwh, ofwh);
02495               }
02496               //if (m_Doc->selection->findItem(this)!=-1)
02497               //     drawLockedMarker(p);
02498        }
02499 //     Tinput = false;
02500        FrameOnly = false;
02501        p->restore();
02502 }
02503 
02504 
02505 void PageItem_TextFrame::clearContents()
02506 {
02507        PageItem *nextItem = this;
02508        while (nextItem != 0)
02509        {
02510               if (nextItem->prevInChain() != 0)
02511                      nextItem = nextItem->prevInChain();
02512               else
02513                      break;
02514        }
02515        ParagraphStyle defaultStyle = nextItem->itemText.defaultStyle();
02516        nextItem->itemText.clear();
02517        nextItem->itemText.setDefaultStyle(defaultStyle);
02518 
02519        while (nextItem != 0)
02520        {
02521               nextItem->CPos = 0;
02522               nextItem->invalid = true;
02523               nextItem = nextItem->nextInChain();
02524        }
02525 }
02526 
02527 void PageItem_TextFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat)
02528 {
02529        int oldPos = CPos; // 15-mar-2004 jjsa for cursor movement with Shift + Arrow key
02530        int kk = k->key();
02531        int as = k->ascii();
02532        QString uc = k->text();
02533        QString cr, Tcha, Twort;
02534        uint Tcoun;
02535        int len, pos;
02536        int KeyMod;
02537        ScribusView* view = m_Doc->view();
02538        ButtonState buttonState = k->state();
02539        switch (buttonState)
02540        {
02541        case ShiftButton:
02542               KeyMod = SHIFT;
02543               break;
02544        case AltButton:
02545               KeyMod = ALT;
02546               break;
02547        case ControlButton:
02548               KeyMod = CTRL;
02549               break;
02550        default:
02551               KeyMod = 0;
02552               break;
02553        }
02554 
02555        view->slotDoCurs(false);
02556        switch (kk)
02557        {
02558        case Key_Prior:
02559        case Key_Next:
02560        case Key_End:
02561        case Key_Home:
02562        case Key_Right:
02563        case Key_Left:
02564        case Key_Up:
02565        case Key_Down:
02566               if ( (buttonState & ShiftButton) == 0 )
02567                      deselectAll();
02568        }
02569        //<< ISO 14755
02570        //if ((buttonState & ControlButton) && (buttonState & ShiftButton))
02571        //{
02572        //     if (!unicodeTextEditMode)
02573        //     {
02574        //            unicodeTextEditMode=true;
02575        //            unicodeInputCount = 0;
02576        //            unicodeInputString = "";
02577        //            keyrep = false;
02578        //     }
02579        //     qDebug(QString("%1 %2 %3 %4 %5").arg("uni").arg("c+s").arg(uc).arg(kk).arg(as));
02580        //}
02581        //>>
02582        if (unicodeTextEditMode)
02583        {
02584               int conv = 0;
02585               bool ok = false;
02586               unicodeInputString += uc;
02587               conv = unicodeInputString.toInt(&ok, 16);
02588               if (!ok)
02589               {
02590                      unicodeTextEditMode = false;
02591                      unicodeInputCount = 0;
02592                      unicodeInputString = "";
02593                      keyRepeat = false;
02594                      return;
02595               }
02596               unicodeInputCount++;
02597               if (unicodeInputCount == 4)
02598               {
02599                      unicodeTextEditMode = false;
02600                      unicodeInputCount = 0;
02601                      unicodeInputString = "";
02602                      if (ok)
02603                      {
02604                             if (itemText.lengthOfSelection() > 0)
02605                                    deleteSelectedTextFromFrame();
02606                             if (conv < 31)
02607                                    conv = 32;
02608                             itemText.insertChars(CPos, QString(QChar(conv)), true);
02609                             CPos += 1;
02610 //                          Tinput = true;
02611                             m_Doc->scMW()->setTBvals(this);
02612                             view->RefreshItem(this);
02613                             keyRepeat = false;
02614                             return;
02615                      }
02616               }
02617               else
02618               {
02619                      keyRepeat = false;
02620                      return;
02621               }
02622        }
02623        switch (kk)
02624        {
02625        case Key_F12:
02626               unicodeTextEditMode = true;
02627               unicodeInputCount = 0;
02628               unicodeInputString = "";
02629               keyRepeat = false;
02630               return;
02631               break;
02632        case Key_Home:
02633               // go to begin of line
02634               if ( (pos = CPos) == firstInFrame() )
02635                      break; // at begin of frame
02636               len = lastInFrame();
02637               if ( pos >= len )
02638                      pos = len-1;
02639               if ( (buttonState & ControlButton) == 0 )
02640               {
02641                      pos = itemText.startOfLine(pos);
02642               }
02643               else
02644               {
02645                      //Control Home for start of frame text
02646                      pos = itemText.startOfFrame(pos);
02647               }
02648               CPos = pos;
02649               if ( buttonState & ShiftButton )
02650                      ExpandSel(-1, oldPos);
02651               if ( this->itemText.lengthOfSelection() > 0 )
02652                      view->RefreshItem(this);
02653               m_Doc->scMW()->setTBvals(this);
02654               break;
02655        case Key_End:
02656               // go to end of line
02657               len = lastInFrame();
02658               if ( CPos >= len )
02659                      break; // at end of frame
02660               if ( (buttonState & ControlButton) == 0 )
02661               {
02662                      CPos = itemText.endOfLine(CPos);
02663               }
02664               else
02665               {
02666                      //Control End for end of frame text
02667                      CPos = itemText.endOfFrame(CPos);
02668               }
02669               if ( buttonState & ShiftButton )
02670                      ExpandSel(1, oldPos);
02671               if ( this->itemText.lengthOfSelection() > 0 )
02672                      view->RefreshItem(this);
02673               m_Doc->scMW()->setTBvals(this);
02674               break;
02675        case Key_Down:
02676               if (buttonState & ControlButton)
02677               {
02678                      // go to end of paragraph
02679                      len = itemText.length();
02680                      CPos = itemText.nextParagraph(CPos);
02681                      if ( buttonState & ShiftButton )
02682                             ExpandSel(1, oldPos);
02683               }
02684               else
02685               {
02686                      if (CPos <= lastInFrame())
02687                      {
02688                             CPos = itemText.nextLine(CPos);
02689                             if ( buttonState & ShiftButton )
02690                             {
02691                                    if ( buttonState & AltButton )
02692                                           CPos = lastInFrame()+1;
02693                                    ExpandSel(1, oldPos);
02694                             }
02695                             else 
02696                                    if (CPos > lastInFrame() && NextBox != 0)
02697                                    {
02698                                           if (NextBox->frameDisplays(CPos))
02699                                           {
02700                                                  view->Deselect(true);
02701                                                  NextBox->CPos = CPos;
02702                                                  view->SelectItemNr(NextBox->ItemNr);
02703                                           }
02704                                    }
02705                      }
02706                      else
02707                      {
02708                             if (NextBox != 0)
02709                             {
02710                                    if (NextBox->frameDisplays(lastInFrame()+1))
02711                                    {
02712                                           view->Deselect(true);
02713                                           NextBox->CPos = lastInFrame()+1;
02714                                           view->SelectItemNr(NextBox->ItemNr);
02715                                    }
02716                             }
02717                      }
02718               }
02719               if ( this->itemText.lengthOfSelection() > 0 )
02720                      view->RefreshItem(this);
02721               m_Doc->scMW()->setTBvals(this);
02722               break;
02723        case Key_Up:
02724               if (buttonState & ControlButton)
02725               {
02726                      if ( (pos = CPos) == firstInFrame() )
02727                             break; // at begin of frame
02728                      len = itemText.length();
02729                      CPos = itemText.prevParagraph(CPos);
02730                      if ( buttonState & ShiftButton )
02731                             ExpandSel(-1, oldPos);
02732               }
02733               else
02734               {
02735                      if (CPos > firstInFrame())
02736                      {
02737                             if (CPos > lastInFrame() || CPos >= itemText.length())
02738                                    CPos = lastInFrame();
02739                             CPos = itemText.prevLine(CPos);
02740                             if ( buttonState & ShiftButton )
02741                             {
02742                                    if ( buttonState & AltButton )
02743                                           CPos = firstInFrame();
02744                                    ExpandSel(-1, oldPos);
02745                             }
02746                             else
02747                                    if (CPos == firstInFrame() && BackBox != 0)
02748                                    {
02749                                           view->Deselect(true);
02750                                           BackBox->CPos = BackBox->lastInFrame();
02751                                           view->SelectItemNr(BackBox->ItemNr);
02752                                    }
02753                      }
02754                      else
02755                      {
02756                             CPos = firstInFrame();
02757                             if (BackBox != 0)
02758                             {
02759                                    view->Deselect(true);
02760                                    BackBox->CPos = BackBox->lastInFrame();
02761                                    view->SelectItemNr(BackBox->ItemNr);
02762                             }
02763                      }
02764               }
02765               if ( this->itemText.lengthOfSelection() > 0 )
02766                      view->RefreshItem(this);
02767               m_Doc->scMW()->setTBvals(this);
02768               break;
02769        case Key_Prior:
02770               CPos = itemText.startOfFrame(CPos);
02771               if ( buttonState & ShiftButton )
02772                      ExpandSel(-1, oldPos);
02773               m_Doc->scMW()->setTBvals(this);
02774               break;
02775        case Key_Next:
02776               CPos = itemText.endOfFrame(CPos);
02777               if ( buttonState & ShiftButton )
02778                      ExpandSel(1, oldPos);
02779               m_Doc->scMW()->setTBvals(this);
02780               break;
02781        case Key_Left:
02782               if ( buttonState & ControlButton )
02783               {
02784                      setNewPos(oldPos, itemText.length(), -1);
02785                      if ( buttonState & ShiftButton )
02786                             ExpandSel(-1, oldPos);
02787               }
02788               else if ( buttonState & ShiftButton )
02789               {
02790                      --CPos;
02791                      if ( CPos < 0 )
02792                             CPos = 0;
02793                      else
02794                             ExpandSel(-1, oldPos);
02795               }
02796               else
02797               {
02798                      --CPos;
02799                      if (CPos < firstInFrame())
02800                      {
02801                             CPos = firstInFrame();
02802                             if (BackBox != 0)
02803                             {
02804                                    view->Deselect(true);
02805                                    BackBox->CPos = BackBox->lastInFrame();
02806                                    view->SelectItemNr(BackBox->ItemNr);
02807                                    //currItem = currItem->BackBox;
02808                             }
02809                      }
02810               }
02811               if ((CPos > 0) && (CPos >= lastInFrame()))
02812               {
02813                      CPos = lastInFrame();
02814                      if (itemText.charStyle(CPos-1).effects() & ScStyle_SuppressSpace)
02815                      {
02816                             --CPos;
02817                             while ((CPos > 0) && (itemText.charStyle(CPos).effects() & ScStyle_SuppressSpace))
02818                             {
02819                                    --CPos;
02820                                    if (CPos == 0)
02821                                           break;
02822                             }
02823                      }
02824               }
02825               else
02826               {
02827                      while ((CPos > 0) && (itemText.charStyle(CPos).effects() & ScStyle_SuppressSpace))
02828                      {
02829                             --CPos;
02830                             if (CPos == 0)
02831                                    break;
02832                      }
02833               }
02834               if ( itemText.lengthOfSelection() > 0 )
02835                      view->RefreshItem(this);
02836               m_Doc->scMW()->setTBvals(this);
02837               break;
02838        case Key_Right:
02839               if ( buttonState & ControlButton )
02840               {
02841                      setNewPos(oldPos, itemText.length(), 1);
02842                      if ( buttonState & ShiftButton )
02843                             ExpandSel(1, oldPos);
02844               }
02845               else if ( buttonState & ShiftButton )
02846               {
02847                      ++CPos;
02848                      if ( CPos > itemText.length() )
02849                             --CPos;
02850                      else
02851                             ExpandSel(1, oldPos);
02852               }
02853               else
02854               {
02855                      ++CPos; // new position within text ?
02856                      if (CPos > lastInFrame())
02857                      {
02858 //                          --CPos;
02859                             CPos = lastInFrame() + 1;
02860                             if (NextBox != 0)
02861                             {
02862                                    if (NextBox->frameDisplays(CPos))
02863                                    {
02864                                           view->Deselect(true);
02865                                           NextBox->CPos = CPos;
02866                                           view->SelectItemNr(NextBox->ItemNr);
02867                                           //currItem = currItem->NextBox;
02868                                    }
02869                             }
02870                      }
02871               }
02872               if ( itemText.lengthOfSelection() > 0 )
02873                      view->RefreshItem(this);
02874               m_Doc->scMW()->setTBvals(this);
02875               break;
02876        case Key_Delete:
02877               if (CPos == itemText.length())
02878               {
02879                      if (itemText.lengthOfSelection() > 0)
02880                      {
02881                             deleteSelectedTextFromFrame();
02882                             m_Doc->scMW()->setTBvals(this);
02883                             view->RefreshItem(this);
02884                      }
02885                      keyRepeat = false;
02886                      return;
02887               }
02888               if (itemText.length() == 0)
02889               {
02890                      keyRepeat = false;
02891                      return;
02892               }
02893               cr = itemText.text(CPos,1);
02894               if (itemText.lengthOfSelection() == 0)
02895                      itemText.select(CPos, 1, true);
02896               deleteSelectedTextFromFrame();
02897 //            Tinput = false;
02898               if ((cr == QChar(13)) && (itemText.length() != 0))
02899               {
02900 //                   m_Doc->chAbStyle(this, findParagraphStyle(m_Doc, itemText.paragraphStyle(QMAX(CPos-1,0))));
02901 //                   Tinput = false;
02902               }
02903               m_Doc->scMW()->setTBvals(this);
02904               view->RefreshItem(this);
02905               break;
02906        case Key_Backspace:
02907               if (CPos == 0)
02908               {
02909                      if (itemText.lengthOfSelection() > 0)
02910                      {
02911                             deleteSelectedTextFromFrame();
02912                             m_Doc->scMW()->setTBvals(this);
02913                             view->RefreshItem(this);
02914                      }
02915                      break;
02916               }
02917               if (itemText.length() == 0)
02918                      break;
02919               cr = itemText.text(QMAX(CPos-1,0),1);
02920               if (itemText.lengthOfSelection() == 0)
02921               {
02922                      --CPos;
02923                      itemText.select(CPos, 1, true);
02924               }
02925               deleteSelectedTextFromFrame();
02926 //            Tinput = false;
02927               if ((cr == QChar(13)) && (itemText.length() != 0))
02928               {
02929 //                   m_Doc->chAbStyle(this, findParagraphStyle(m_Doc, itemText.paragraphStyle(QMAX(CPos-1,0))));
02930 //                   Tinput = false;
02931               }
02932               m_Doc->scMW()->setTBvals(this);
02933               view->RefreshItem(this);
02934               break;
02935        default:
02936               if ((itemText.lengthOfSelection() > 0) && (kk < 0x1000))
02937                      deleteSelectedTextFromFrame();
02938               //if ((kk == Key_Tab) || ((kk == Key_Return) && (buttonState & ShiftButton)))
02939               if (kk == Key_Tab)
02940               {
02941                      itemText.insertChars(CPos, QString(SpecialChars::TAB), true);
02942                      CPos += 1;
02943 //                   Tinput = true;
02944                      view->RefreshItem(this);
02945                      break;
02946               }
02947               if ((uc[0] > QChar(31) && m_Doc->currentStyle.charStyle().font().canRender(uc[0])) || (as == 13) || (as == 30))
02948               {
02949                      itemText.insertChars(CPos, uc, true);
02950                      CPos += 1;
02951                      if ((m_Doc->docHyphenator->AutoCheck) && (CPos > 1))
02952                      {
02953                             Twort = "";
02954                             Tcoun = 0;
02955                             for (int hych = CPos-1; hych > -1; hych--)
02956                             {
02957                                    Tcha = itemText.text(hych,1);
02958                                    if (Tcha[0] == ' ')
02959                                    {
02960                                           Tcoun = hych+1;
02961                                           break;
02962                                    }
02963                                    Twort.prepend(Tcha);
02964                             }
02965                             if (!Twort.isEmpty())
02966                             {
02967                                    m_Doc->docHyphenator->slotHyphenateWord(this, Twort, Tcoun);
02968                             }
02969                      }
02970 //                   Tinput = true;
02971                      view->RefreshItem(this);
02972               }
02973               break;
02974        }
02975        view->slotDoCurs(true);
02976        if ((kk == Key_Left) || (kk == Key_Right) || (kk == Key_Up) || (kk == Key_Down))
02977        {
02978               keyRepeat = false;
02979               return;
02980        }
02981 }
02982 
02983 void PageItem_TextFrame::deleteSelectedTextFromFrame()
02984 {
02985        if (itemText.lengthOfSelection() > 0) {
02986               CPos = itemText.startOfSelection();
02987               itemText.removeSelection();
02988               HasSel = false;
02989        }
02990 //     m_Doc->updateFrameItems();
02991        m_Doc->scMW()->DisableTxEdit();
02992 }
02993 
02994 
02995 //CB Rewrote JJSA code, March 06
02996 // jjsa added on 15-mar-2004
02997 // calculate the end position while ctrl + arrow pressed
02998 
02999 void PageItem_TextFrame::setNewPos(int oldPos, int len, int dir)
03000 {
03001        
03002        bool isSpace, wasSpace;
03003        if ( dir > 0 && oldPos < len )
03004        {
03005               wasSpace = itemText.text(oldPos).isSpace();
03006               CPos=oldPos+1;
03007               while (CPos<len)
03008               {
03009                      isSpace = itemText.text(CPos).isSpace();
03010                      if (wasSpace && !isSpace)
03011                             break;
03012                      ++CPos;
03013                      wasSpace=isSpace;
03014                      
03015               }
03016               /*
03017               isSpace = itemText.at(oldPos)->ch.at(0).isSpace();
03018               CPos = oldPos +1;
03019               for (int i=oldPos+1; i < len; i++)
03020               {
03021                      if ( itemText.at(i)->ch.at(0).isSpace() != isSpace )
03022                             break;
03023                      CPos++;
03024               }
03025               */
03026        }
03027        else if ( dir < 0 && oldPos > 0 )
03028        {
03029               CPos=oldPos-1;
03030               wasSpace = itemText.text(CPos).isSpace();
03031               while (CPos>0)
03032               {
03033                      isSpace = itemText.text(CPos).isSpace();
03034                      if (!wasSpace && isSpace)
03035                      {
03036                             ++CPos;
03037                             break;
03038                      }
03039                      --CPos;
03040                      wasSpace=isSpace;
03041                      
03042               }
03043               /*
03044               oldPos--;
03045               isSpace = itemText.at(oldPos)->ch.at(0).isSpace();
03046               for (int i=oldPos; i >= 0; i--)
03047               {
03048                      if (  itemText.at(i)->ch.at(0).isSpace() != isSpace )
03049                             break;
03050                      CPos--;
03051               }
03052               */
03053        }
03054        cursorBiasBackward = (dir < 0);
03055 }
03056 
03057 
03058 
03059 // jjsa added on 15-mar-2004 expand / decrease selection
03060 
03061 // jjsa added on 14-mar-2004 text selection with pressed
03062 // shift button and <-, -> cursor keys
03063 // Parameters
03064 //   PageItem *currItem text item to be processed
03065 //   inc < 0 for left key > 0 for right key
03066 //  if value is +/-1 work on slection
03067 //  if value is +/-2 refresh if text under cursor is selected
03068 
03069 void PageItem_TextFrame::ExpandSel(int dir, int oldPos)
03070 {
03071        int len = itemText.length();
03072        ScribusView* view = m_Doc->view();
03073        bool rightSel = false; // assume left right and actual char not selected
03074        bool leftSel  = false;
03075        bool actSel   = false;
03076        bool selMode  = false;
03077 
03078        if ( dir == -1 || dir == 1 )
03079               selMode = true;
03080        else
03081        {
03082               if ( dir > 0 )
03083                      dir = 1;
03084               else
03085                      dir = -1;
03086        }
03087    // show for selection of previous, actual and next character
03088        if ( itemText.lengthOfSelection() > 0 ) /* selection already present */
03089        {
03090               if (dir > 0 && oldPos < len) // -> key
03091               {
03092                      if ( oldPos == 0 )
03093                             leftSel = false;
03094                      else
03095                             leftSel = itemText.selected(oldPos-1);
03096                      actSel = itemText.selected(oldPos);
03097                      rightSel = false; // not relevant
03098               }
03099               else if ( dir > 0 && oldPos == len) // -> key
03100               {
03101                      return;
03102               }
03103               else if ( dir < 0 && oldPos > 0 ) // <- key
03104               {
03105                      actSel = itemText.selected(oldPos-1);
03106                      leftSel = false; // not relevant
03107                      if ( oldPos < len  )
03108                             rightSel = itemText.selected(oldPos);
03109                      else
03110                             rightSel = false;
03111               }
03112               else if ( dir < 0 && oldPos == 0 ) // <- key
03113               {
03114          return;
03115               }
03116               if ( selMode && !(leftSel||actSel||rightSel) )
03117               {
03118          // selected outside from concerned range
03119                      itemText.deselectAll();
03120                      HasSel = false;
03121                      //CB Replace with direct call for now //emit HasNoTextSel();
03122                      m_Doc->scMW()->DisableTxEdit();
03123               }
03124               else if ( !selMode )
03125               {
03126                      if (leftSel||actSel||rightSel)
03127                             view->RefreshItem(this);
03128               }
03129        }
03130        if ( !selMode )
03131               return;
03132    // no selection
03133        if ( !HasSel )
03134        {
03135               HasSel = true;
03136               //CB Replace with direct call for now //emit HasTextSel();
03137               m_Doc->scMW()->EnableTxEdit();
03138               leftSel = true;
03139               rightSel = true;
03140        }
03141        int start;
03142        int end;
03143        int sel;
03144        if (dir == 1) // ->  key
03145        {
03146               start = oldPos;
03147               end   = CPos;
03148               sel = leftSel == true;
03149        }
03150        else
03151        {
03152               start = CPos;
03153               end   = oldPos;
03154               sel = rightSel == true;
03155        }
03156        itemText.select(start, end-start, sel);
03157        if ( ! sel )
03158               //CB Replace with direct call for now //emit  HasNoTextSel();
03159               m_Doc->scMW()->DisableTxEdit();
03160 
03161        cursorBiasBackward = (dir < 0);
03162 
03163        view->RefreshItem(this);
03164 }
03165 
03166 void PageItem_TextFrame::deselectAll()
03167 {
03168        PageItem *item = this;
03169        while( item->prevInChain() )
03170               item=item->prevInChain();
03171 
03172        while ( item )
03173        {
03174               if ( item->itemText.lengthOfSelection() > 0 )
03175               {
03176                      item->itemText.deselectAll();
03177                      m_Doc->view()->RefreshItem(this);
03178                      item->HasSel = false;
03179               }
03180               item = item->nextInChain();
03181        }
03182        //CB Replace with direct call for now //emit HasNoTextSel();
03183        m_Doc->scMW()->DisableTxEdit();
03184 }
03185 
03186 double PageItem_TextFrame::columnWidth()
03187 {
03188        double lineCorr;
03189        if (lineColor() != CommonStrings::None)
03190               lineCorr = m_lineWidth;
03191        else
03192               lineCorr = 0;
03193        return (Width - (ColGap * (Cols - 1)) - Extra - RExtra - 2 * lineCorr) / Cols;
03194 //     return (Width - (ColGap * (Cols - 1)) - Extra - RExtra - lineCorr) / Cols;
03195 }
03196 
03197 void PageItem_TextFrame::drawOverflowMarker(ScPainter *p)
03198 {
03199        /*CB Old large corner indicator.
03200        double scp1 = 1.0/QMAX(ScMW->view->getScale(), 1);
03201        double scp16 = 16.0*scp1;
03202        double scp14 = 14.0*scp1;
03203        double scp3 = 3.0*scp1;
03204        double scm_lineWidth16 = Width - scp16;
03205        double scpheight16 = Height - scp16;
03206        double scm_lineWidth3 = Width - scp3;
03207        double scpheight3 = Height - scp3;
03208        p->setPen(black, scp1, SolidLine, FlatCap, MiterJoin);
03209        p->setBrush(white);
03210        p->drawRect(scm_lineWidth16, scpheight16, scp14, scp14);
03211        p->drawLine(FPoint(scm_lineWidth16, scpheight16), FPoint(scm_lineWidth3, scpheight3));
03212        p->drawLine(FPoint(scm_lineWidth16, scpheight3), FPoint(scm_lineWidth3, scpheight16));
03213        */
03214        //TODO: CB clean
03215        ScribusView* view = m_Doc->view();
03216        double scp1 = 1 ;// / ScMW->view->scale();
03217        double ofwh = 8 * scp1;
03218        //CB moved down while locked marker disabled
03219        //double ofx = Width - ofwh/2;
03220        //double ofy = Height - ofwh*3.0;
03221        double ofx = Width - ofwh/2;
03222        double ofy = Height - ofwh*1.5;
03223        double lx1= ofx;
03224        double ly1= ofy;
03225        double lx2= ofx+ofwh;
03226        double ly2= ofy+ofwh;
03227        p->setPen(black, 0.5/ view->scale(), SolidLine, FlatCap, MiterJoin);
03228        p->setPenOpacity(1.0);
03229        p->setBrush(Qt::white);
03230        p->setBrushOpacity(1.0);
03231        p->setFillMode(ScPainter::Solid);
03232        p->drawRect(ofx, ofy, ofwh, ofwh);
03233        p->drawLine(FPoint(lx1, ly1), FPoint(lx2, ly2));
03234        p->drawLine(FPoint(lx1, ly2), FPoint(lx2, ly1));
03235 }
03236 
03237 void PageItem_TextFrame::drawColumnBorders(ScPainter *p)
03238 {
03239        ScribusView* view = m_Doc->view();
03240        p->setPen(black, 0.5/ view->scale(), SolidLine, FlatCap, MiterJoin);
03241        p->setPenOpacity(1.0);
03242        p->setBrush(Qt::white);
03243        p->setBrushOpacity(1.0);
03244        p->setFillMode(ScPainter::Solid);
03245 #ifdef HAVE_CAIRO
03246        p->setupPolygon(&PoLine);
03247        p->setClipPath();
03248 #endif
03249        double colWidth = columnWidth();
03250        double colLeft=0;
03251        int curCol=0;
03252        double lineCorr=0;
03253        if (lineColor() != CommonStrings::None)
03254               lineCorr = m_lineWidth / 2.0;
03255        if (TExtra + lineCorr!=0.0)
03256               p->drawLine(FPoint(0, TExtra + lineCorr), FPoint(Width, TExtra + lineCorr));
03257        if (BExtra + lineCorr!=0.0)
03258               p->drawLine(FPoint(0, Height - BExtra - lineCorr), FPoint(Width, Height - BExtra - lineCorr));
03259        double oldColRightX = Extra + lineCorr;
03260        while(curCol < Cols)
03261        {
03262               colLeft=(colWidth + ColGap) * curCol + Extra + lineCorr;
03263               if (colLeft != 0.0)
03264                      p->drawLine(FPoint(colLeft, 0), FPoint(colLeft, 0+Height));
03265               if (colLeft + colWidth != Width)
03266                      p->drawLine(FPoint(colLeft+colWidth, 0), FPoint(colLeft+colWidth, 0+Height));
03267               oldColRightX=colLeft+colWidth;
03268               ++curCol;
03269        }
03270        
03271 }
03272 
03273 #endif  //NLS_PROTO