1 /* 2 For general Scribus (>=1.3.2) copyright and licensing information please refer 3 to the COPYING file provided with the program. Following this notice may exist 4 a copyright and/or license notice that predates the release of Scribus 1.3.2 5 for which a new license (GPL+exception) is in place. 6 */ 7 /*************************************************************************** 8 pageitem.cpp - description 9 ------------------- 10 begin : Sat Apr 7 2001 11 copyright : (C) 2001 by Franz Schmid 12 email : Franz.Schmid@altmuehlnet.de 13 ***************************************************************************/ 14 15 /*************************************************************************** 16 * * 17 * This program is free software; you can redistribute it and/or modify * 18 * it under the terms of the GNU General Public License as published by * 19 * the Free Software Foundation; either version 2 of the License, or * 20 * (at your option) any later version. * 21 * * 22 ***************************************************************************/ 23 24 25 #ifndef STORYTEXT_H_ 26 #define STORYTEXT_H_ 27 28 #include <cassert> 29 #include <QObject> 30 #include <QString> 31 #include <QList> 32 #include <unicode/uversion.h> 33 34 #include "itextsource.h" 35 #include "marks.h" 36 #include "text/frect.h" 37 #include "text/specialchars.h" 38 #include "sctextstruct.h" 39 #include "style.h" 40 #include "styles/charstyle.h" 41 #include "styles/paragraphstyle.h" 42 #include "desaxe/saxio.h" 43 44 class CharStyle; 45 class ParagraphStyle; 46 class PageItem; 47 class ScribusDoc; 48 class ScText_Shared; 49 class ResourceCollection; 50 class ShapedTextCache; 51 52 U_NAMESPACE_BEGIN 53 class BreakIterator; 54 U_NAMESPACE_END 55 56 /** 57 * This class holds the text of a Scribus textframe and pointers to its 58 * styles and embedded objects. 59 * 60 * The logical view of the text consists of a sequence of Unicode chars. 61 * Partition objects keep track of the positions of style changes, 62 * paragraph ends and embedded objects. 63 * 64 * The physical view consists of a sequence of ScriptItems. Each ScriptItem 65 * corresponds to a subsequence of Unicode chars in the original sequence 66 * and associates this with an array of glyph indices. Metrics information 67 * give the physical position of the ScriptItem in the textframe and its 68 * bounding box. For each glyph there's also its advance and the relative 69 * offsets to its basepoint. Other information in the ScriptItem is only 70 * used by the layouter. 71 */ 72 class SCRIBUS_API StoryText : public QObject, public SaxIO, public ITextSource 73 { 74 Q_OBJECT 75 76 public: 77 StoryText(ScribusDoc *doc); 78 StoryText(); 79 StoryText(const StoryText & other); 80 StoryText& operator= (const StoryText & other); 81 virtual ~StoryText(); 82 83 bool hasBulletOrNum() const; 84 bool hasTextMarks() const; 85 bool marksCountChanged() const; 86 void resetMarksCountChanged(); 87 88 void setDoc(ScribusDoc *docin); doc()89 ScribusDoc* doc() const { return m_doc; } 90 91 static const Xml_string saxxDefaultElem; 92 static void desaxeRules(const Xml_string& prefixPattern, desaxe::Digester& ruleset, Xml_string elemtag = saxxDefaultElem); 93 94 virtual void saxx(SaxHandler& handler, const Xml_string& elemtag) const; saxx(SaxHandler & handler)95 virtual void saxx(SaxHandler& handler) const { saxx(handler, saxxDefaultElem); } 96 97 int cursorPosition() const; 98 void setCursorPosition(int pos, bool relative = false); 99 void normalizeCursorPosition(); 100 int normalizedCursorPosition(); 101 102 void moveCursorForward(); 103 void moveCursorBackward(); 104 void moveCursorLeft(); 105 void moveCursorRight(); 106 107 void moveCursorWordLeft(); 108 void moveCursorWordRight(); 109 110 void clear(); 111 StoryText copy() const; 112 113 // Find text in story 114 int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive, int* pLen = 0) const; 115 int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; 116 117 // Add, change, replace 118 // Insert chars from another StoryText object at current cursor position 119 void insert(const StoryText& other, bool onlySelection = false); 120 // Insert chars from another StoryText object at specific position 121 void insert(int pos, const StoryText& other, bool onlySelection = false); 122 // Append chars from another StoryText object append(const StoryText & other)123 void append(const StoryText& other) { insert(length(), other, false); } 124 // Remove len chars at specific position 125 void removeChars(int pos, uint len); 126 // Removes trailing empty paragraphs 127 void trim(); 128 // Insert chars at current cursor position 129 void insertChars(const QString& txt, bool applyNeighbourStyle = false); 130 // Insert chars ar specific position 131 void insertChars(int pos, const QString& txt, bool applyNeighbourStyle = false); 132 // Insert inline object at current cursor position 133 void insertObject(int obj); 134 // Insert object at specific position 135 void insertObject(int pos, int obj); 136 // Insert mark at cursor or specific position 137 void insertMark(Mark* mark, int pos = -1); 138 // Replace a character 139 void replaceChar(int pos, QChar ch); 140 // Replace current selection with specified text 141 void replaceSelection(const QString& newText); 142 // Replaced a word, and return the difference in length between old and new 143 int replaceWord(int pos, QString newWord); 144 void replaceObject(int pos, int obj); 145 146 void hyphenateWord(int pos, uint len, const char* hyphens); 147 148 // Retrieve length of story text 149 int length() const; 150 151 // Get content at specific position as plain text 152 // Internal paragraph separator are converted to 153 // unix new lines for better compatibility with 154 // text editors 155 QString plainText() const; 156 157 // TextSource methods 158 159 virtual bool isBlockStart(int pos) const; 160 virtual int nextBlockStart(int pos) const; 161 virtual InlineFrame object(int pos) const; 162 virtual bool hasExpansionPoint(int pos) const; 163 virtual ExpansionPoint expansionPoint(int pos) const; 164 165 // Get char at current cursor position 166 // QChar text() const; 167 // Get char at specific position 168 QChar text(int pos) const; 169 // Get text with len chars at specific position 170 QString text(int pos, uint len) const; 171 // Get sentence at any position within it 172 QString sentence(int pos, int &posn); 173 // Get word starting at position 174 QString word(int pos); 175 176 bool hasObject(int pos) const; 177 PageItem* getItem(int pos) const; // deprecated 178 int findMark(const Mark* mrk, int startPos = 0) const; 179 bool hasMark(int pos, const Mark* mrk = nullptr) const; 180 Mark *mark(int pos) const; 181 void replaceMark(int pos, Mark* mrk); 182 void applyMarkCharstyle(Mark* mrk, CharStyle& currStyle) const; 183 184 bool isHighSurrogate(int pos) const; 185 bool isLowSurrogate(int pos) const; 186 187 // Get charstyle at current cursor position 188 const CharStyle& charStyle() const; 189 // Get charstyle at specific position 190 const CharStyle& charStyle(int pos) const; 191 // Get paragraph style at current cursor position 192 const ParagraphStyle& paragraphStyle() const; 193 // Get paragraph style at specific position 194 const ParagraphStyle& paragraphStyle(int pos) const; 195 const ParagraphStyle& defaultStyle() const; 196 void setDefaultStyle(const ParagraphStyle& style); 197 void setCharStyle(int pos, uint len, const CharStyle& style); 198 void setStyle(int pos, const ParagraphStyle& style); 199 void applyCharStyle(int pos, uint len, const CharStyle& style); 200 void applyStyle(int pos, const ParagraphStyle& style, bool rmDirectFormatting = false); 201 void eraseCharStyle(int pos, uint len, const CharStyle& style); 202 void eraseStyle(int pos, const ParagraphStyle& style); 203 void replaceStyles(const QMap<QString,QString>& newNameForOld); 204 void replaceCharStyles(QMap<QString,QString> newNameForOld); 205 206 // Cleanup legacy formatting for whole story, ie remove direct 207 // formatting for parameters already set at paragraph level 208 void fixLegacyFormatting(); 209 210 // Cleanup legacy formatting for paragraph at position pos 211 void fixLegacyFormatting(int pos); 212 213 void getNamedResources(ResourceCollection& lists) const; 214 void replaceNamedResources(ResourceCollection& newNames); 215 216 uint nrOfParagraphs() const; 217 int startOfParagraph() const; 218 int startOfParagraph(uint index) const; 219 int endOfParagraph() const; 220 int endOfParagraph(uint index) const; 221 uint nrOfParagraph() const; 222 uint nrOfParagraph(int pos) const; 223 224 uint nrOfRuns() const; 225 int startOfRun(uint index) const; 226 int endOfRun(uint index) const; 227 228 // positioning 229 int nextChar(int pos); 230 int prevChar(int pos); 231 int firstWord(); 232 int nextWord(int pos); 233 int prevWord(int pos); 234 int endOfWord(int pos) const; 235 int nextSentence(int pos); 236 int prevSentence(int pos); 237 int endOfSentence(int pos) const; 238 int nextParagraph(int pos); 239 int prevParagraph(int pos); 240 241 // these need valid layout: 242 243 // int startOfLine(int pos); 244 // int endOfLine(int pos); 245 // int prevLine(int pos); 246 // int nextLine(int pos); 247 // int startOfFrame(int pos); 248 // int endOfFrame(int pos); 249 250 // selection 251 252 void selectAll(); 253 void deselectAll(); 254 void removeSelection(); 255 void extendSelection(int oldPos, int newPos); 256 int selectWord(int pos); 257 void select(int pos, int len, bool on = true); 258 QString selectedText() const; 259 bool selected(int pos) const; 260 int startOfSelection() const; 261 int endOfSelection() const; 262 int selectionLength() const; 263 bool hasSelection() const; 264 265 // break iterators 266 static icu::BreakIterator* getGraphemeIterator(); 267 static icu::BreakIterator* getWordIterator(); 268 static icu::BreakIterator* getSentenceIterator(); 269 static icu::BreakIterator* getLineIterator(); 270 271 // layout helpers 272 shapedTextCache()273 ShapedTextCache* shapedTextCache() { return m_shapedTextCache; } 274 275 LayoutFlags flags(int pos) const; 276 bool hasFlag(int pos, LayoutFlags flag) const; 277 void setFlag(int pos, LayoutFlags flag); 278 void clearFlag(int pos, LayoutFlags flag); 279 280 // when physical view doesn't match logical view any more: 281 282 /// call this if the shape of an embedded object changes (redos layout) 283 void invalidateObject(const PageItem* embedded); 284 /// call this if the shape of the paragraph changes (redos layout) 285 void invalidateLayout(); 286 287 public slots: 288 /// call this if some logical style changes (redos shaping and layout) 289 void invalidateAll(); 290 291 signals: 292 void changed(int firstItem, int endItem); 293 294 private: 295 ScText * item(int index); 296 const ScText * item(int index) const; 297 void fixSurrogateSelection(); 298 299 private: 300 ScribusDoc * m_doc; 301 ShapedTextCache* m_shapedTextCache; 302 static icu::BreakIterator* m_graphemeIterator; 303 static icu::BreakIterator* m_wordIterator; 304 static icu::BreakIterator* m_sentenceIterator; 305 static icu::BreakIterator* m_lineIterator; 306 307 QString textWithSoftHyphens (int pos, uint len) const; 308 void insertCharsWithSoftHyphens(int pos, const QString& txt, bool applyNeighbourStyle = false); 309 310 /// mark these runs as invalid, ie. need itemize and shaping 311 void invalidate(int firstRun, int lastRun); 312 void removeParSep(int pos); 313 void insertParSep(int pos); 314 315 // int splitRun(int pos); 316 317 /** bring physical view in sync with logical one. 318 * This gets called automatically from all physical view methods 319 */ 320 // void validate(); 321 /// private data structure 322 ScText_Shared * d; 323 /// gives the physical view which was last given to the layouter 324 // uint layouterVersion; 325 /// is true after layout() has been exercised 326 // bool layouterValid; 327 }; 328 329 330 #endif /*STORYTEXT_H_*/ 331