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 /* This is the Scribus Short Words plugin main mechanism.
8
9 This code is based on the Scribus-Vlna plug in rewritten for
10 international use.
11
12 2004 Petr Vanek <petr@yarpen.cz>
13 with contributors.
14
15 This program is free software - see LICENSE file in the distribution
16 or documentation
17 */
18
19 #include <QProgressBar>
20 #include <QRegExp>
21
22 #include "parse.h"
23
24 #include "configuration.h"
25 #include "langmgr.h"
26 #include "pageitem.h"
27 #include "scpage.h"
28 #include "scribus.h"
29 #include "scribusdoc.h"
30 #include "scribusview.h"
31 #include "selection.h"
32 #include "shortwords.h"
33 #include "version.h"
34
35
SWParse()36 SWParse::SWParse()
37 {
38 modify = 0;
39 }
40
parseItem(PageItem * aFrame)41 void SWParse::parseItem(PageItem *aFrame)
42 {
43 // the content of the frame - text itself
44 QString content;
45 int changes = 0;
46 // list of the short words
47 QStringList shorts;
48 // text with special space
49 QString unbreak;
50 // the regexp
51 QRegExp rx(" ");
52 // cfg
53 SWConfig *cfg = new SWConfig();
54
55 // just textframes processed
56 if (!aFrame->isTextFrame())
57 return;
58
59 // an ugly hack to get the language code from the item language property
60 if (lang.isEmpty())
61 {
62 lang = aFrame->itemText.charStyle(0).language();
63 if (lang.isEmpty())
64 qDebug("SWParse::parseItem - variable lang is still empty. No changes are made.");
65 }
66
67 // apply spaces after shorts
68 shorts = cfg->getShortWords(lang);
69 if (shorts.count()==0)
70 return; // no changes
71
72 // get text from frame
73 int i;
74 for (i=0; i < aFrame->itemText.length() && ! aFrame->frameDisplays(i); ++i)
75 ;
76 for (; i < aFrame->itemText.length() && aFrame->frameDisplays(i); ++i)
77 content += aFrame->itemText.text(i,1);
78 changes = content.count(SpecialChars::NBSPACE);
79
80 // for every config string, replace its spaces by nbsp's.
81 for (QStringList::Iterator it = shorts.begin(); it != shorts.end(); ++it)
82 {
83 unbreak = (*it);
84 // replace ' ' from cfg with '~' in the replacement string
85 unbreak = unbreak.replace(SPACE, SpecialChars::NBSPACE);
86 /*
87 Regexp used to find the config string (*it) in content.
88 Cheat sheet:
89 - \b is a "word boundary"; it matches at a *position*
90 not a *character*
91 - \W is a "non-word character"; it matches every character
92 that is neither a letter, nor a number, nor '_';
93 for example, it matches all kind of whitespace
94 (including carriage return) and punctuation
95 Example occurrences when (*it) == "Mr ":
96 - "Mr Bla etc." : there's one of the word boundaries
97 of the word "Mr" before the pattern, and one of the
98 word boundaries of the word "Bla" after.
99 Example occurrences when (*it) == " !":
100 - "ugly hack ! No." : there's a word boundary before,
101 and a whitespace is matched by \W after.
102 - "» !" : '«' is matched by \W before, newline is
103 matched by \W after.
104 */
105 rx.setPattern("(\\b|\\W)" + rx.escape(*it) + "(\\b|\\W)");
106 /*
107 QString::replace works on the whole string in one pass.
108 On every occurrence of our regexp, \1 and \2 are replaced
109 by what has been matched (captured characters) in,
110 respectively, the first and second capturing parentheses.
111 */
112 content.replace(rx, "\\1" + unbreak + "\\2");
113 }
114 // return text into frame
115 for (i=0; i < aFrame->itemText.length() && ! aFrame->frameDisplays(i); ++i)
116 ;
117 for (; i < aFrame->itemText.length() && aFrame->frameDisplays(i); ++i)
118 aFrame->itemText.replaceChar(i, content.at(i));
119 if (content.count(SpecialChars::NBSPACE) > changes)
120 ++modify;
121
122 delete(cfg);
123 } // end of method
124
parseSelection(ScribusDoc * doc)125 void SWParse::parseSelection(ScribusDoc* doc)
126 {
127 uint docSelectionCount = doc->m_Selection->count();
128 if (docSelectionCount == 0)
129 return;
130 doc->scMW()->mainWindowProgressBar->setMaximum(docSelectionCount);
131 for (uint i=0; i < docSelectionCount; ++i)
132 {
133 doc->scMW()->mainWindowProgressBar->setValue(i);
134 parseItem(doc->m_Selection->itemAt(i));
135 } // for items
136 doc->scMW()->mainWindowProgressBar->setValue(docSelectionCount);
137 }
138
139
parsePage(ScribusDoc * doc)140 void SWParse::parsePage(ScribusDoc* doc)
141 {
142 parsePage(doc, doc->currentPageNumber());
143 }
144
parsePage(ScribusDoc * doc,int page)145 void SWParse::parsePage(ScribusDoc* doc, int page)
146 {
147 uint count = 0;
148 uint docItemsCount=doc->Items->count();
149 if (docItemsCount == 0)
150 return;
151
152 for (uint i = 0; i < docItemsCount; ++i)
153 {
154 PageItem* pi = doc->Items->at(i);
155 if (pi->OwnPage == page)
156 ++count;
157 }
158 doc->scMW()->mainWindowProgressBar->setMaximum(count);
159 doc->view()->GotoPage(page);
160 uint j = 0;
161 for (uint i = 0; i < docItemsCount; ++i)
162 {
163 PageItem* pi = doc->Items->at(i);
164 if (pi->OwnPage == page)
165 {
166 doc->scMW()->mainWindowProgressBar->setValue(++j);
167 parseItem(pi);
168 }
169 }
170 doc->scMW()->mainWindowProgressBar->setValue(count);
171 }
172
parseAll(ScribusDoc * doc)173 void SWParse::parseAll(ScribusDoc* doc)
174 {
175 for (int i=0; i < doc->Pages->count(); ++i)
176 parsePage(doc, i);
177 }
178