1 /***************************************************************************
2 hebString.cxx - Hebrew string handling
3 -------------------
4 begin : Thu Mar 1 13:15:18 IST 2001
5 copyright : (C) 2001 by Arie Tal
6 email : tal_arie@yahoo.com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include "hebString.h"
23 #include <string.h>
24 #include <iostream>
25 #include <assert.h>
26
27
~hebString()28 hebString::~hebString()
29 {
30 // discard old representation 18/4/97 (to handle memory leakage)
31 for (int j=0; j < last_representation.get_size() ; j++)
32 delete last_representation[j] ;
33
34 last_representation.clear() ;
35 }
36
37 //void
38 //hebString::printLocations()
39 //{
40 // for (int i =0 ; i<last_representation.get_size() ;i++) {
41 // Locations *locs = last_representation[i]->getLocations() ;
42 // locs->print() ;
43 // }
44 //}
45
46 int
line_count(int line_length)47 hebString::line_count(int line_length)
48 {
49 if (line_length != last_line_length) modified = 1 ;
50
51 check_recompile(line_length) ;
52
53 return last_representation.get_size() ;
54 }
55
56 char *
represent(int line_length,int line_offset)57 hebString::represent(int line_length, int line_offset)
58 {
59 if (line_offset >= line_count(line_length)) // also recompiles if needed
60 return (char *)0 ;
61
62 return (char *)(const char *)(*last_representation[line_offset]) ;
63 }
64
65
check_recompile(int line_width,int line_offset)66 void hebString::check_recompile(int line_width, int line_offset)
67 {
68 if (!modified) return ;
69 int margin = 0 , from=0, len = 0 , comment = -1 ;
70
71 const char *txt = (const char *)(aString &)(*this) ;
72 if (*txt)
73 if (txt[strlen(txt)-1] != ' ')
74 (aString &)(*this) += " " ;
75
76 // added this 19/04/97
77 if (line_offset > 0) line_offset-- ;
78
79 if (line_offset > 0) {
80 margin = last_representation[line_offset-1]->getMargin() ;
81 comment = last_representation[line_offset-1]->getComment() ;
82 from = last_representation[line_offset-1]->getMaxLocation() ;
83 }
84 modeStack stack ;
85 stack.copy(last_representation[line_offset]->getLastModeStack()) ;
86 int count = 0 ;
87 do {
88 recompile_line(line_offset, line_width, from, margin, comment, stack) ;
89 hebSegment *seg = last_representation[line_offset++] ;
90 len = seg->length() ;
91 margin = seg->getMargin() ;
92 comment = seg->getComment() ;
93 from=seg->getMaxLocation() ;
94 count++ ;
95 //assert(count == 1) ;
96 } while ((line_offset < last_representation.get_size()) );// &&
97 // !last_representation[line_offset]->noNeedToRecompile(from,margin, line_width, stack)) ;
98 // NOTICE THAT LINES MAY BE DELETED FROM last_representation UPON DELETING CHARACTERS FROM
99 // THE STRING
100 // in case new lines were added
101 if (line_offset >= last_representation.get_size()) {
102 const char *text = (const char *)(aString &)(*this) ;
103 hebStringMode mode = stack.majorMode() ;
104 int len = ((aString *)this)->length() ;
105 int length = 0 ;
106 int count = last_representation.get_size() ;
107 if (count > 0)
108 length = last_representation[count-1]->getMaxLocation() ;
109 while (length < len) {
110 hebSegment *segment = new
111 hebSegment(he, text, length, startHebrew, screen, margin, comment, line_width, stack, show_line_end_marks, activeSpelling) ;
112 length += segment->length() ;
113 margin = segment->getMargin() ;
114 comment = segment->getComment() ;
115 last_representation.append(segment) ;
116 if (segment->getModeChanged())
117 mode = segment->getModeChange() ;
118 }
119 if (mode != stack.majorMode()) { // Major mode was changed here
120 stack.clear() ;
121 stack.push(mode, "", 0) ;
122 }
123 last_stack_depth = stack.depth() ;
124 }
125 modified = 0 ;
126 last_line_length= line_width ;
127 last_str_mode = stack.majorMode() ;
128 }
129
130
recompile_line(int line,int line_width,int from,int margin,int comment,modeStack & stack)131 void hebString::recompile_line(int line, int line_width, int from, int margin, int comment, modeStack& stack)
132 {
133 const char *txt = (const char *)(aString &)(*this) ;
134 if (*txt)
135 if (txt[strlen(txt)-1] != ' ')
136 (aString &)(*this) += " " ;
137 const char *text = (const char *)(aString &)(*this) ;
138 // int len = ((aString *)this)->length() ;
139 hebSegment *seg = last_representation[line] ;
140 int length = from ;
141 delete seg ;
142 hebSegment *segment = new
143 hebSegment(he, text, length, startHebrew, screen, margin, comment, line_width, stack,
144 show_line_end_marks, activeSpelling) ;
145 last_representation[line] = segment ;
146 }
147
148
149
recompile(int line_width,modeStack & activeStack)150 void hebString::recompile(int line_width, modeStack &activeStack)
151 {
152 const char *txt = (const char *)(aString &)(*this) ;
153
154 // use compiled flag to note that the stack is valid
155 compiled = 1 ;
156
157 if (*txt)
158 if (txt[strlen(txt)-1] != ' ')
159 (aString &)(*this) += " " ;
160 const char *text = (const char *)(aString &)(*this) ;
161 int len = ((aString *)this)->length() ;
162 int length = 0 ;
163 last_mode_stack.copy(activeStack) ;
164 hebStringMode mode = activeStack.majorMode() ;
165 int margin = 0, comment = -1 ;
166
167 // discard old representation 18/4/97 (to handle memory leakage)
168 for (int j=0; j < last_representation.get_size() ; j++)
169 delete last_representation[j] ;
170
171 last_representation.clear() ;
172 // handle the special case where a line is empty!
173 if (len == 0) {
174 hebSegment *segment = new
175 hebSegment(he, " ", length, startHebrew, screen, margin, comment, line_width,
176 activeStack, show_line_end_marks,activeSpelling) ;
177 length += segment->length() ;
178 margin = segment->getMargin() ;
179 comment = segment->getComment() ;
180 last_representation.append(segment) ;
181 if (segment->getModeChanged())
182 mode = segment->getModeChange() ;
183 }
184 while (length < len) {
185 hebSegment *segment = new
186 hebSegment(he, text, length, startHebrew, screen, margin, comment, line_width,
187 activeStack, show_line_end_marks,activeSpelling) ;
188 length += segment->length() ;
189 margin = segment->getMargin() ;
190 comment = segment->getComment() ;
191 last_representation.append(segment) ;
192 if (segment->getModeChanged())
193 mode = segment->getModeChange() ;
194 }
195 if (mode != activeStack.majorMode()) { // Major mode was changed here
196 activeStack.clear() ;
197 activeStack.push(mode, "", 0) ;
198 }
199 modified = 0 ;
200 last_line_length= line_width ;
201 last_str_mode = activeStack.majorMode() ;
202 last_stack_depth = activeStack.depth() ;
203 }
204
205
respell(int line_width,modeStack & activeStack)206 void hebString::respell(int line_width, modeStack &activeStack)
207 {
208 const char *txt = (const char *)(aString &)(*this) ;
209
210 // use compiled flag to note that the stack is valid
211 compiled = 1 ;
212
213 if (*txt)
214 if (txt[strlen(txt)-1] != ' ')
215 (aString &)(*this) += " " ;
216 const char *text = (const char *)(aString &)(*this) ;
217 int len = ((aString *)this)->length() ;
218 int length = 0 ;
219 last_mode_stack.copy(activeStack) ;
220 hebStringMode mode = activeStack.majorMode() ;
221 int margin = 0, comment = -1 ;
222
223 // discard old representation 18/4/97 (to handle memory leakage)
224 int need_to_recompile = 0 ;
225
226 for (int j=0; j < last_representation.get_size() ; j++)
227 need_to_recompile += last_representation[j]->getWrongSpelling() ;
228
229 if (!need_to_recompile)
230 return ;
231
232 for (int j=0; j < last_representation.get_size() ; j++)
233 delete last_representation[j] ;
234
235 last_representation.clear() ;
236 // handle the special case where a line is empty!
237 if (len == 0) {
238 hebSegment *segment = new
239 hebSegment(he, " ", length, startHebrew, screen, margin, comment, line_width,
240 activeStack, show_line_end_marks,activeSpelling) ;
241 length += segment->length() ;
242 margin = segment->getMargin() ;
243 comment = segment->getComment() ;
244 last_representation.append(segment) ;
245 if (segment->getModeChanged())
246 mode = segment->getModeChange() ;
247 }
248 while (length < len) {
249 hebSegment *segment = new
250 hebSegment(he, text, length, startHebrew, screen, margin, comment, line_width,
251 activeStack, show_line_end_marks,activeSpelling) ;
252 length += segment->length() ;
253 margin = segment->getMargin() ;
254 comment = segment->getComment() ;
255 last_representation.append(segment) ;
256 if (segment->getModeChanged())
257 mode = segment->getModeChange() ;
258 }
259 if (mode != activeStack.majorMode()) { // Major mode was changed here
260 activeStack.clear() ;
261 activeStack.push(mode, "", 0) ;
262 }
263 modified = 0 ;
264 last_line_length= line_width ;
265 last_str_mode = activeStack.majorMode() ;
266 last_stack_depth = activeStack.depth() ;
267 }
268
269 int
getCurrentXlocation(int line_offset,int x_pos)270 hebString::getCurrentXlocation(int line_offset, int x_pos)
271 {
272 if (line_offset >= last_representation.get_size())
273 return SPLIT_VALUE ; // just a safety guard
274 if (line_offset < 0)
275 return SPLIT_VALUE ;
276 if (x_pos < 0) return SPLIT_VALUE ;
277
278 Locations *locs = last_representation[line_offset]->getLocations() ;
279
280 int pos = (*locs)[ x_pos] ;
281 if (pos > 0)
282 return pos ;
283 return -pos ;
284 }
285
286 int
getCurrentXcode(int line_offset,int x_pos)287 hebString::getCurrentXcode(int line_offset, int x_pos)
288 {
289 if (line_offset >= last_representation.get_size())
290 return SPLIT_VALUE ; // just a safety guard
291 if (line_offset < 0)
292 return SPLIT_VALUE ;
293 if (x_pos < 0) return SPLIT_VALUE ;
294
295 Locations *locs = last_representation[line_offset]->getLocations() ;
296
297 return (*locs)[x_pos].getCode() ;
298 }
299
300 hebStringMode
getCurrentXlang(int line_offset,int x_pos)301 hebString::getCurrentXlang(int line_offset, int x_pos)
302 {
303 if (line_offset >= last_representation.get_size())
304 return StrEnglish ; // just a safety guard
305 if (line_offset < 0)
306 return StrEnglish ;
307 if (x_pos < 0) return StrEnglish ;
308
309 Locations *locs = last_representation[line_offset]->getLocations() ;
310
311 int pos = (*locs)[x_pos] ;
312 if (pos > 0)
313 return StrEnglish ;
314 return StrHebrew ;
315 }
316
317 /*
318 void
319 hebString::delete_ch(int at,int line_length)
320 {
321 Array<int> locations ;
322 aString tmp = (const char *)(aString &)(*this) ;
323 int count = line_count(line_length) ;
324
325 tmp += replicate(' ',count*line_length - length()) ;
326 calculate_locations(tmp, locations) ;
327 if ((at >=0) && (at < locations.get_size()))
328 _delete_ch(locations[at]) ;
329 locations.clear() ;
330 }
331 */
332 void
_delete_ch(int at,int line_offset)333 hebString::_delete_ch(int at, int line_offset)
334 {
335 modified = 1 ;
336 aString &tmp = (aString &)(*this) ;
337 // aString tmp2 = "" ;
338 at-- ; // assume at > 0
339
340 if (at >= tmp.length())
341 return ;
342
343 // if (at > 0)
344 // tmp2 = tmp.at(0,at) ;
345
346 // tmp2 += at+1+(const char *)tmp ;
347 // tmp = tmp2 ;
348 tmp.delete_ch(at) ;
349 for (int i=line_offset+1; i < last_representation.get_size() ; i++)
350 last_representation[i]->updateMinLocation(-1) ;
351 // decrease by one because we deleted a character
352 check_recompile(last_line_length, line_offset) ;
353 }
354
355
356 int
_insert_ch(int at,int line_offset,unsigned char ch,int x_pos)357 hebString::_insert_ch(int at, int line_offset, unsigned char ch, int x_pos)
358 {
359 modified = 1 ;
360 aString &tmp = (aString &)(*this) ;
361 // char before = ' ';
362 // char before2 = ' ' ;
363 at-- ; // asume at > 0
364
365 int move = 1 ;
366
367 if (at > tmp.length()) {
368 tmp += ch ;
369 check_recompile(last_line_length, line_offset) ;
370 return move;
371 }
372
373 // if (at > 0) {
374 // tmp2 = tmp.at(0,at) ;
375 // before = *((const char *)tmp+at-1) ;
376 // if (at > 1) before2 = *((const char *)tmp + at - 2) ;
377 // }
378 // if (((ch == '}') || (ch == '{')) && (before != '\\')) {
379 // if (((before == 'R') || (before == 'L')) && (before2 == '\\'))
380 // tmp2 += "{" ;
381 // else tmp2 += ch ; }
382 // tmp2+=ch ;
383
384 // tmp2 += at+(const char *)tmp ;
385 tmp.insert_ch(at,ch) ;
386 for (int i=line_offset+1; i < last_representation.get_size() ; i++)
387 last_representation[i]->updateMinLocation(1) ; // increase by one because we inserted a character
388 // returned the following command
389 check_recompile(last_line_length, line_offset) ;
390 return move ;
391 }
392 /*
393 void
394 hebString::insert_ch(int at, unsigned char ch)
395 {
396 }
397
398 void
399 hebString::_replace_ch(int at, unsigned char ch)
400 {
401 }
402
403 void
404 hebString::replace_ch(int at, unsigned char ch)
405 {
406 }
407 */
408 char *
split(int at)409 hebString::split(int at)
410 {
411 modified = 1 ;
412 aString &tmp = (aString &)(*this) ;
413 aString tmp2 = "" ;
414
415 if (at >0) at-- ; // since curx is now handled from 1 and above
416 if (at > tmp.length())
417 return 0;
418
419 if (at > 0)
420 tmp2 = tmp.at(0,at) ;
421
422 work_area = at+(const char *)tmp ;
423 tmp = tmp2 ;
424
425 return (char *)(const char *)work_area ;
426 }
427
428