1 /******************************************************************************
2 *******************************************************************************
3 *******************************************************************************
4
5 Copyright (C) 2013 Ben Martin
6 Copyright 2014-2015, the FontForge Project Developers.
7
8 This file is part of FontForge.
9
10 FontForge is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation,either version 3 of the License, or
13 (at your option) any later version.
14
15 FontForge is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with FontForge. If not, see <http://www.gnu.org/licenses/>.
22
23 For more details see the COPYING.gplv3 file in the root directory of this
24 distribution.
25
26 *******************************************************************************
27 *******************************************************************************
28 ******************************************************************************/
29
30 #include <fontforge-config.h>
31
32 #include "fvfonts.h"
33 #include "ggadget.h"
34 #include "gwidget.h"
35 #include "uiinterface.h"
36 #include "ustring.h"
37 #include "wordlistparser.h"
38
39 #include <ctype.h>
40 #include <string.h>
41
dump_ustr(char * msg,unichar_t * u)42 static void dump_ustr( char* msg, unichar_t* u )
43 {
44 char u8buf[1001];
45 char* pt = u8buf;
46 memset( u8buf, 0, 1000 );
47 printf("%s\n", msg );
48 unichar_t* p = u;
49 unichar_t* e = u + u_strlen( u );
50 for( ; p!=e; ++p )
51 {
52 unichar_t buf[5];
53 buf[0] = *p;
54 buf[1] = '\0';
55 printf("walk %d %s\n", *p, u_to_c(buf));
56
57 pt = utf8_idpb( pt, *p, 0);
58 }
59 printf("%s u8str:%s\n", msg, u8buf );
60 }
61
62
Wordlist_getSCName(SplineChar * sc)63 const char* Wordlist_getSCName( SplineChar* sc )
64 {
65 /* printf("Wordlist_getSCName() sc->name:%s\n", sc->name ); */
66 /* printf("Wordlist_getSCName() sc->len :%zd\n", strlen(sc->name) ); */
67 /* printf("Wordlist_getSCName() is three:%d\n", strcmp( sc->name, "three" ) ); */
68
69 static char ret[ 1024 ];
70 int simple = false;
71 /* If the glyph is unencoded, we need to keep a slash before the name because
72 it doesn't correspond to the codepoint. */
73 if( sc->unicodeenc != -1 ) {
74 if( strlen( sc->name ) == 1 )
75 {
76 char ch = sc->name[0];
77
78 if( ch >= 'a' && ch <= 'z' )
79 simple = true;
80 else if( ch >= '0' && ch <= '9' )
81 simple = true;
82 if( ch >= 'A' && ch <= 'Z' )
83 simple = true;
84
85 if( simple )
86 {
87 strcpy( ret, sc->name );
88 return ret;
89 }
90 }
91
92 if( !strcmp( sc->name, "zero" ))
93 return "0";
94 if( !strcmp( sc->name, "one" ))
95 return "1";
96 if( !strcmp( sc->name, "two" ))
97 return "2";
98 if( !strcmp( sc->name, "three" ))
99 return "3";
100 if( !strcmp( sc->name, "four" ))
101 return "4";
102 if( !strcmp( sc->name, "five" ))
103 return "5";
104 if( !strcmp( sc->name, "six" ))
105 return "6";
106 if( !strcmp( sc->name, "seven" ))
107 return "7";
108 if( !strcmp( sc->name, "eight" ))
109 return "8";
110 if( !strcmp( sc->name, "nine" ))
111 return "9";
112 }
113
114 snprintf( ret, 1024, "/%s", sc->name );
115 return ret;
116 }
117
118
119
120 static SplineChar*
WordlistEscapedInputStringToRealString_readGlyphName(SplineFont * sf,char * in,char * in_end,char ** updated_in,char * glyphname)121 WordlistEscapedInputStringToRealString_readGlyphName(
122 SplineFont *sf, char* in, char* in_end,
123 char** updated_in, char* glyphname )
124 {
125 // printf("WordlistEscapedInputStringToRealString_readGlyphName(top)\n");
126
127 int startedWithBackSlash = (*in == '\\');
128 if( *in != '/' && *in != '\\' )
129 return 0;
130 // move over the delimiter that we know we are on
131 in++;
132 char* startpos = in;
133
134 // Get the largest possible 'glyphname' from the input stream.
135 memset( glyphname, '\0', PATH_MAX );
136 char* outname = glyphname;
137 while( *in != '/' && *in != ' ' && *in != ']' && in != in_end )
138 {
139 *outname = *in;
140 ++outname;
141 in++;
142 }
143 bool FullMatchEndsOnSpace = 0;
144 char* maxpos = in;
145 char* endpos = maxpos-1;
146 // printf("WordlistEscapedInputStringToRealString_readGlyphName(x1) -->:%s:<--\n", glyphname);
147 // printf("WordlistEscapedInputStringToRealString_readGlyphName(x2) %c %p %p\n",*in,startpos,endpos);
148
149 int loopCounter = 0;
150 int firstLookup = 1;
151 for( ; endpos >= startpos; endpos--, loopCounter++ )
152 {
153 // printf("WordlistEscapedInputStringToRealString_readGlyphName(trim loop top) gn:%s\n", glyphname );
154 SplineChar* sc = 0;
155 if( startedWithBackSlash )
156 {
157 if( glyphname[0] == 'u' )
158 glyphname++;
159
160 char* endptr = 0;
161 long unicodepoint = strtoul( glyphname+1, &endptr, 16 );
162 TRACE("AAA glyphname:%s\n", glyphname+1 );
163 TRACE("AAA unicodepoint:%ld\n", unicodepoint );
164 sc = SFGetChar( sf, unicodepoint, 0 );
165 if( sc && endptr )
166 {
167 char* endofglyphname = glyphname + strlen(glyphname);
168 for( ; endptr < endofglyphname; endptr++ )
169 --endpos;
170 }
171 if( !sc )
172 {
173 // printf("WordlistEscapedInputStringToRealString_readGlyphName() no char found for backslashed unicodepoint:%ld\n", unicodepoint );
174 strcpy(glyphname,"backslash");
175 sc = SFGetChar( sf, -1, glyphname );
176 endpos = startpos;
177 }
178 }
179 else
180 {
181 if( firstLookup && glyphname[0] == '#' )
182 {
183 char* endptr = 0;
184 long unicodepoint = strtoul( glyphname+1, &endptr, 16 );
185 // printf("WordlistEscapedInputStringToRealString_readGlyphName() unicodepoint:%ld\n", unicodepoint );
186 sc = SFGetChar( sf, unicodepoint, 0 );
187 if( sc && endptr )
188 {
189 char* endofglyphname = glyphname + strlen(glyphname);
190 // printf("endptr:%p endofglyphname:%p\n", endptr, endofglyphname );
191 for( ; endptr < endofglyphname; endptr++ )
192 --endpos;
193 }
194 }
195 if( !sc )
196 {
197 // printf("WordlistEscapedInputStringToRealString_readGlyphName(getchar) gn:%s\n", glyphname );
198 sc = SFGetChar( sf, -1, glyphname );
199 }
200 }
201
202 if( sc )
203 {
204 // printf("WordlistEscapedInputStringToRealString_readGlyphName(found!) gn:%s start:%p end:%p\n", glyphname, startpos, endpos );
205 if( !loopCounter && FullMatchEndsOnSpace )
206 {
207 endpos++;
208 }
209 *updated_in = endpos;
210 return sc;
211 }
212 if( glyphname[0] != '\0' )
213 glyphname[ strlen(glyphname)-1 ] = '\0';
214 }
215
216
217 *updated_in = endpos;
218
219 // printf("WordlistEscapedInputStringToRealString_readGlyphName(end) gn:%s\n", glyphname );
220 return 0;
221 }
222
223
224 static SplineChar*
u_WordlistEscapedInputStringToRealString_readGlyphName(SplineFont * sf,unichar_t * in,unichar_t * in_end,unichar_t ** updated_in,unichar_t * glyphname)225 u_WordlistEscapedInputStringToRealString_readGlyphName(
226 SplineFont *sf, unichar_t* in, unichar_t* in_end,
227 unichar_t** updated_in, unichar_t* glyphname )
228 {
229 int startedWithBackSlash = (*in == '\\');
230 if( *in != '/' && *in != '\\' )
231 return 0;
232 bool startsWithBackSlash = *in == '\\';
233 // move over the delimiter that we know we are on
234 in++;
235 unichar_t* startpos = in;
236
237 // Get the largest possible 'glyphname' from the input stream.
238 memset( glyphname, '\0', PATH_MAX );
239 unichar_t* outname = glyphname;
240 while( *in != '/'
241 && ( !startsWithBackSlash || *in != '\\' )
242 && *in != ' ' && *in != ']' && in != in_end )
243 {
244 *outname = *in;
245 ++outname;
246 in++;
247 }
248 bool FullMatchEndsOnSpace = 0;
249 unichar_t* maxpos = in;
250 unichar_t* endpos = maxpos-1;
251 TRACE("WordlistEscapedInputStringToRealString_readGlyphName(x1) -->:%s:<--\n", u_to_c(glyphname));
252
253 int loopCounter = 0;
254 int firstLookup = 1;
255 for( ; endpos >= startpos; endpos--, loopCounter++ )
256 {
257 // printf("WordlistEscapedInputStringToRealString_readGlyphName(trim loop top) gn:%s\n", u_to_c(glyphname) );
258 SplineChar* sc = 0;
259
260 if( startedWithBackSlash )
261 {
262 if( glyphname[0] == 'u' )
263 glyphname++;
264
265 unichar_t* endptr = 0;
266 long unicodepoint = u_strtoul( glyphname+1, &endptr, 16 );
267 TRACE("AAA glyphname:%s\n", u_to_c(glyphname+1) );
268 TRACE("AAA unicodepoint:%ld\n", unicodepoint );
269 sc = SFGetChar( sf, unicodepoint, 0 );
270 if( sc && endptr )
271 {
272 unichar_t* endofglyphname = glyphname + u_strlen(glyphname);
273 /* printf("glyphname:%p\n", glyphname ); */
274 /* printf("endptr:%p endofglyphname:%p\n", endptr, endofglyphname ); */
275 for( ; endptr < endofglyphname; endptr++ )
276 --endpos;
277 }
278 if( !sc )
279 {
280 // printf("WordlistEscapedInputStringToRealString_readGlyphName() no char found for backslashed unicodepoint:%ld\n", unicodepoint );
281 uc_strcpy(glyphname,"backslash");
282 sc = SFGetChar( sf, -1, u_to_c(glyphname) );
283 endpos = startpos;
284 }
285 }
286 else
287 {
288 if( uc_startswith( glyphname, "uni"))
289 {
290 unichar_t* endptr = 0, *tmp_gn;
291 int gn_len;
292 long unicodepoint = u_strtoul( glyphname+3, &endptr, 16 );
293 char c;
294 SplineChar* tmp = 0;
295 TRACE("uni prefix, codepoint: %ld\n", unicodepoint );
296 sc = SFGetChar( sf, unicodepoint, 0 );
297
298 /* When text is added after a glyphname with a period (such as "uni1234.alt"
299 * the other search heuristics will tend to interpret the period as a glyph
300 * and split the string. Here we search for the glyphname trimming off
301 * characters at the end in order to find the glyph
302 */
303 gn_len = u_strlen(glyphname);
304 tmp_gn = malloc((gn_len+1)*sizeof(unichar_t));
305 u_strncpy(tmp_gn, glyphname, gn_len);
306 for (int i = gn_len; i>0; i--) {
307 tmp_gn[i] = 0;
308 tmp = SFGetChar( sf, -1, u_to_c(tmp_gn) );
309 TRACE("looking for subst. char: %s\n", u_to_c(tmp_gn));
310 if (tmp != NULL) {
311 TRACE("have subst. char: %s\n", tmp->name ); break;
312 }
313 }
314 free(tmp_gn);
315
316 if (tmp != NULL){
317 sc = tmp;
318 } else {
319 if( sc && endptr )
320 {
321 unichar_t* endofglyphname = glyphname + u_strlen(glyphname);
322 //printf("endptr:%p endofglyphname:%p\n", endptr, endofglyphname );
323 for( ; endptr < endofglyphname; endptr++ ) --endpos;
324 }
325 }
326 }
327
328 if( firstLookup && glyphname[0] == '#' )
329 {
330 unichar_t* endptr = 0;
331 long unicodepoint = u_strtoul( glyphname+1, &endptr, 16 );
332 // printf("WordlistEscapedInputStringToRealString_readGlyphName() unicodepoint:%ld\n", unicodepoint );
333 sc = SFGetChar( sf, unicodepoint, 0 );
334 if( sc && endptr )
335 {
336 unichar_t* endofglyphname = glyphname + u_strlen(glyphname);
337 // printf("endptr:%p endofglyphname:%p\n", endptr, endofglyphname );
338 for( ; endptr < endofglyphname; endptr++ )
339 --endpos;
340 }
341 }
342 if( !sc )
343 {
344 // printf("WordlistEscapedInputStringToRealString_readGlyphName(getchar) gn:%s\n", glyphname );
345 sc = SFGetChar( sf, -1, u_to_c(glyphname) );
346 }
347 }
348
349 if( sc )
350 {
351 // printf("WordlistEscapedInputStringToRealString_readGlyphName(found!) gn:%s start:%p end:%p\n", glyphname, startpos, endpos );
352 if( !loopCounter && FullMatchEndsOnSpace )
353 {
354 endpos++;
355 }
356 *updated_in = endpos;
357 return sc;
358 }
359 if( glyphname[0] != '\0' )
360 glyphname[ u_strlen(glyphname)-1 ] = '\0';
361 }
362
363
364 *updated_in = endpos;
365
366 // printf("WordlistEscapedInputStringToRealString_readGlyphName(end) gn:%s\n", glyphname );
367 return 0;
368 }
369
370
WordlistEscapedInputStringToRealString_getFakeUnicodeAsScUnicodeEnc(SplineChar * sc,void * udata)371 int WordlistEscapedInputStringToRealString_getFakeUnicodeAsScUnicodeEnc( SplineChar *sc, void* udata )
372 {
373 return( sc->unicodeenc );
374 }
375
376
377 //
378 // If there is only one trailing slash, then remove it.
379 //
WordlistTrimTrailingSingleSlash(unichar_t * txt)380 void WordlistTrimTrailingSingleSlash( unichar_t* txt )
381 {
382 int len = u_strlen(txt);
383 // printf("text changed, len :%d -1:%c -2:%c\n", len, txt[ len-1 ], txt[ len-2 ] );
384 if( len >= 1 )
385 {
386 if( len >= 2 && txt[ len-1 ]=='/' && txt[ len-2 ]=='/' )
387 {
388 // nothing
389 }
390 else
391 {
392 if( txt[ len-1 ]=='/' )
393 txt[ len-1 ] = '\0';
394 }
395 }
396 }
397
398
399
400 /************************************************************/
401 /************************************************************/
402 /************************************************************/
403
WordListLine_countSelected(WordListLine wll)404 int WordListLine_countSelected( WordListLine wll )
405 {
406 int ret = 0;
407 for( ; wll->sc; wll++ ) {
408 ret += wll->isSelected;
409 }
410 return ret;
411 }
412
WordListLine_end(WordListLine wll)413 WordListLine WordListLine_end( WordListLine wll )
414 {
415 for( ; wll->sc; wll++ ) {
416 }
417 return wll;
418 }
419
WordListLine_size(WordListLine wll)420 int WordListLine_size( WordListLine wll )
421 {
422 int ret = 0;
423 for( ; wll->sc; wll++ ) {
424 ++ret;
425 }
426 return ret;
427 }
428
429
WordlistEscapedInputStringToParsedDataComplex(SplineFont * sf,const unichar_t * input_const,WordlistEscapedInputStringToRealString_getFakeUnicodeOfScFunc getUnicodeFunc,void * udata)430 WordListLine WordlistEscapedInputStringToParsedDataComplex(
431 SplineFont* sf,
432 const unichar_t* input_const,
433 WordlistEscapedInputStringToRealString_getFakeUnicodeOfScFunc getUnicodeFunc,
434 void* udata )
435 {
436 unichar_t* input = u_copy( input_const );
437 int input_len = u_strlen(input);
438 WordListChar* ret = calloc( input_len+1, sizeof(WordListChar));
439 WordListChar* out = ret;
440 unichar_t* in = input;
441 unichar_t* in_end = input + input_len;
442 // trim comment and beyond from input
443 {
444 unichar_t* p = input;
445 while( p && p < in_end )
446 {
447 p = u_strchr( p, '#' );
448 if( p > input && *(p-1) == '/' )
449 {
450 p++;
451 continue;
452 }
453 if( p )
454 *p = '\0';
455 break;
456 }
457 }
458 in_end = input + u_strlen(input);
459
460 int addingGlyphsToSelected = 0;
461 int currentGlyphIndex = -1;
462 for ( ; in < in_end; in++ )
463 {
464 unichar_t ch = *in;
465 TRACE("in:%p end:%p got char %d %c\n", in, in_end, ch, ch );
466 if( ch == '[' )
467 {
468 addingGlyphsToSelected = 1;
469 continue;
470 }
471 if( ch == ']' )
472 {
473 addingGlyphsToSelected = 0;
474 continue;
475 }
476 int isSelected = addingGlyphsToSelected;
477 currentGlyphIndex++;
478
479 if( ch == '/' || ch == '\\' )
480 {
481 // start of a glyph name
482 unichar_t glyphname[ PATH_MAX+1 ];
483 unichar_t* updated_in = 0;
484 SplineChar* sc = u_WordlistEscapedInputStringToRealString_readGlyphName( sf, in, in_end, &updated_in, glyphname );
485 if( sc )
486 {
487 in = updated_in;
488 int n = getUnicodeFunc( sc, udata );
489 if( n == -1 )
490 {
491 /*
492 * Okay, this probably means we've got an unencoded glyph (generally
493 * used for OpenType substitutions).
494 * Redeem the value from the SplineFont datamap instead of fetching from
495 * the Unicode identifier.
496 */
497 n = sf->map->backmap[sc->orig_pos];
498
499 /*
500 * Unencoded glyphs have special mappings in the SplineFont that
501 * start from 65536 (values beyond Unicode, 65535 being the reserved
502 * "frontier" value).
503 */
504 if ( (sf->map->enc->is_unicodebmp || sf->map->enc->is_unicodefull) && n < 65536 ) {
505 TRACE("ToRealString: backmapped position does not match Unicode encoding\n");
506 TRACE("orig_pos: %d, backmap: %d, attached unicode enc: %d\n", sc->orig_pos, n, sc->unicodeenc );
507 TRACE("ToRealString: INVALID CHAR POSITION, name: %s\n", sc->name );
508 }
509 }
510
511 out->sc = sc;
512 out->isSelected = isSelected;
513 out->currentGlyphIndex = currentGlyphIndex;
514 out->n = n;
515 out++;
516 /* out = utf8_idpb( out, n, 0 ); */
517 /* if( !out ) */
518 /* printf("ToRealString error on out\n"); */
519 continue;
520 }
521 }
522
523 /* If we reach this point, we're looking based on codepoint. */
524 SplineChar* sc = SFGetOrMakeChar( sf, (int)ch, 0 );
525 out->sc = sc;
526 out->isSelected = isSelected;
527 out->currentGlyphIndex = currentGlyphIndex;
528 out++;
529 }
530
531 free(input);
532 return(ret);
533 }
534
WordlistEscapedInputStringToParsedData(SplineFont * sf,unichar_t * input_const)535 WordListLine WordlistEscapedInputStringToParsedData(
536 SplineFont* sf,
537 unichar_t* input_const )
538 {
539 WordListLine ret = WordlistEscapedInputStringToParsedDataComplex(
540 sf, input_const,
541 WordlistEscapedInputStringToRealString_getFakeUnicodeAsScUnicodeEnc, 0 );
542 return ret;
543 }
544
545
546
547
548 /************************************************************/
549 /************************************************************/
550 /************************************************************/
551
WordlistLoadFileToGTextInfo_IsLineBreak(char ch)552 static bool WordlistLoadFileToGTextInfo_IsLineBreak( char ch )
553 {
554 return ch == '\n' || ch == '\r';
555 }
WordlistLoadFileToGTextInfo_isLineAllWhiteSpace(char * buffer)556 static bool WordlistLoadFileToGTextInfo_isLineAllWhiteSpace( char* buffer )
557 {
558 char* p = buffer;
559 for( ; *p; ++p )
560 {
561 if( !isspace( *p ))
562 return false;
563 }
564
565 return true;
566 }
567
568
569
WordlistLoadFileToGTextInfoBasic(int words_max)570 GTextInfo** WordlistLoadFileToGTextInfoBasic( int words_max )
571 {
572 return WordlistLoadFileToGTextInfo( -1, words_max );
573 }
574
575
WordlistLoadFileToGTextInfo(int type,int words_max)576 GTextInfo** WordlistLoadFileToGTextInfo( int type, int words_max )
577 {
578 GTextInfo **words = 0;
579 int cnt;
580 char buffer[PATH_MAX];
581 char *filename, *temp;
582
583 filename = gwwv_open_filename(type==-1 ? "File of Kerning Words":"File of glyphname lists",NULL,"*.txt",NULL);
584 if ( !filename )
585 {
586 return 0;
587 }
588 temp = utf82def_copy(filename);
589 GIOChannel* file = g_io_channel_new_file( temp, "r", 0 );
590 free(temp);
591 if ( !file )
592 {
593 ff_post_error("Could not open", "Could not open %s", filename );
594 return 0;
595 }
596 free(filename);
597
598 words = malloc( words_max * sizeof(GTextInfo *));
599
600 cnt = 0;
601 if ( type==-1 )
602 {
603 // Kerning words
604 while( true )
605 {
606 gsize len = 0;
607 gchar* buffer = 0;
608 GIOStatus status = g_io_channel_read_line( file, &buffer, &len, 0, 0 );
609
610 // printf("getline status:%d \n", status );
611 if( status != G_IO_STATUS_NORMAL )
612 break;
613
614 chomp(buffer);
615 if ( buffer[0]=='\0'
616 || WordlistLoadFileToGTextInfo_IsLineBreak(buffer[0])
617 || WordlistLoadFileToGTextInfo_isLineAllWhiteSpace( buffer ))
618 {
619 free(buffer);
620 continue;
621 }
622
623 words[cnt] = calloc(1,sizeof(GTextInfo));
624 words[cnt]->fg = words[cnt]->bg = COLOR_DEFAULT;
625 words[cnt]->text = (unichar_t *) utf82def_copy( buffer );
626 words[cnt++]->text_is_1byte = true;
627 free(buffer);
628 if( cnt >= words_max )
629 break;
630 }
631 }
632 else
633 {
634 // glyphname lists
635 strcpy(buffer,""); /* Zero width space: 0x200b, I use as a flag */
636 gsize bytes_read = 0;
637 while( G_IO_STATUS_NORMAL == g_io_channel_read_chars( file,
638 buffer+3,
639 sizeof(buffer)-3,
640 &bytes_read,
641 0 ))
642 {
643 if ( buffer[3]=='\n' || buffer[3]=='#' )
644 continue;
645 if ( cnt>1000-3 )
646 break;
647 if ( buffer[strlen(buffer)-1]=='\n' )
648 buffer[strlen(buffer)-1] = '\0';
649 words[cnt] = calloc(1,sizeof(GTextInfo));
650 words[cnt]->fg = words[cnt]->bg = COLOR_DEFAULT;
651 words[cnt]->text = (unichar_t *) copy( buffer );
652 words[cnt++]->text_is_1byte = true;
653 }
654 }
655
656 g_io_channel_shutdown( file, 1, 0 );
657 g_io_channel_unref( file );
658 if ( cnt!=0 )
659 {
660 words[cnt] = calloc(1,sizeof(GTextInfo));
661 words[cnt]->fg = words[cnt]->bg = COLOR_DEFAULT;
662 words[cnt++]->line = true;
663 words[cnt] = calloc(1,sizeof(GTextInfo));
664 words[cnt]->fg = words[cnt]->bg = COLOR_DEFAULT;
665 words[cnt]->text = (unichar_t *) copy( _("Load Word List...") );
666 words[cnt]->text_is_1byte = true;
667 words[cnt++]->userdata = (void *) -1;
668 words[cnt] = calloc(1,sizeof(GTextInfo));
669 words[cnt]->fg = words[cnt]->bg = COLOR_DEFAULT;
670 words[cnt]->text = (unichar_t *) copy( _("Load Glyph Name List...") );
671 words[cnt]->text_is_1byte = true;
672 words[cnt++]->userdata = (void *) -2;
673 words[cnt] = calloc(1,sizeof(GTextInfo));
674 }
675 else
676 {
677 free(words);
678 words = 0;
679 }
680 return words;
681 }
682
683
Wordlist_MoveByOffset(GGadget * g,int * idx,int offset)684 void Wordlist_MoveByOffset( GGadget* g, int* idx, int offset )
685 {
686 int cidx = *idx;
687 if ( cidx!=-1 )
688 {
689 int32 len;
690 GTextInfo **ti = GGadgetGetList(g,&len);
691 /* We subtract 3 because: There are two lines saying "load * list" */
692 /* and then a line with a rule on it which we don't want access to */
693 if ( cidx+offset >=0 && cidx+offset<len-3 )
694 {
695 cidx += offset;
696 *idx = cidx;
697 GGadgetSelectOneListItem( g, cidx );
698 ti = NULL;
699 }
700 Wordlist_touch( g );
701 }
702 }
703
Wordlist_touch(GGadget * g)704 void Wordlist_touch( GGadget* g )
705 {
706 // Force any extra chars to be setup and drawn
707 GEvent e;
708 e.type=et_controlevent;
709 e.u.control.subtype = et_textchanged;
710 e.u.control.u.tf_changed.from_pulldown = GGadgetGetFirstListSelectedItem(g);
711 GGadgetDispatchEvent( g, &e );
712 }
713
714
WordlistLoadToGTextInfo(GGadget * g,int * idx)715 void WordlistLoadToGTextInfo( GGadget* g, int* idx )
716 {
717 int words_max = 1024*128;
718 GTextInfo** words = WordlistLoadFileToGTextInfoBasic( words_max );
719 if( !words )
720 {
721 GGadgetSetTitle8(g,"");
722 return;
723 }
724
725 if( words[0] )
726 {
727 GGadgetSetList(g,words,true);
728 GGadgetSetTitle8(g,(char *) (words[0]->text));
729 GTextInfoArrayFree(words);
730 *idx = 0;
731 GGadgetSelectOneListItem( g, *idx );
732 Wordlist_touch( g );
733 return;
734 }
735 return;
736 }
737
738
Wordlist_selectedToBitmapArray(GArray * a)739 static GArray* Wordlist_selectedToBitmapArray( GArray* a )
740 {
741 GArray* ret = g_array_new( 1, 1, sizeof(gint) );
742 ret = g_array_set_size( ret, PATH_MAX+1 );
743
744 int i = 0;
745 for (i = 0; i < a->len; i++)
746 {
747 int v = g_array_index (a, gint, i);
748 int one = 1;
749 g_array_insert_val( ret, v, one );
750 }
751 return ret;
752 }
753
754
Wordlist_selectionClear(SplineFont * sf,EncMap * map,unichar_t * txtu)755 unichar_t* Wordlist_selectionClear( SplineFont* sf, EncMap *map, unichar_t* txtu )
756 {
757 static unichar_t ret[ PATH_MAX ];
758 int limit = PATH_MAX;
759 memset( ret, 0, sizeof(unichar_t) * PATH_MAX );
760
761 unichar_t *dst = ret;
762 const unichar_t *src_end = 0;
763 const unichar_t *src = 0;
764 src_end=txtu+u_strlen(txtu);
765 for ( src=txtu; src < src_end; ++src )
766 {
767 if( *src != '[' && *src != ']' )
768 {
769 *dst = *src;
770 dst++;
771 }
772 }
773
774 return ret;
775 }
776
Wordlist_selectionAdd(SplineFont * sf,EncMap * map,unichar_t * txtu,int offset)777 unichar_t* Wordlist_selectionAdd( SplineFont* sf, EncMap *map, unichar_t* txtu, int offset )
778 {
779 int i = 0;
780 static unichar_t ret[ PATH_MAX ];
781 memset( ret, 0, sizeof(unichar_t) * PATH_MAX );
782
783 WordlistTrimTrailingSingleSlash( txtu );
784 WordListLine wll = WordlistEscapedInputStringToParsedData( sf, txtu );
785
786 for( i = 0; wll->sc; wll++, i++ )
787 {
788 SplineChar* sc = wll->sc;
789 int element_selected = wll->isSelected;
790
791 if( i == offset )
792 element_selected = 1;
793
794 if( element_selected )
795 {
796 int pos = map->backmap[ sc->orig_pos ];
797 TRACE("pos1:%d\n", pos );
798 TRACE("map:%d\n", map->map[ pos ] );
799 int gid = pos < 0 || pos >= map->enccount ? -2 : map->map[pos];
800 if( gid == -2 )
801 continue;
802 if( gid==-1 || !sf->glyphs[gid] )
803 sc = SFMakeChar( sf, map, pos );
804 else
805 sc = sf->glyphs[gid];
806 }
807
808
809 if( element_selected )
810 uc_strcat( ret, "[" );
811
812 /* uc_strcat( ret, "/" ); */
813 /* uc_strcat( ret, scarray[i]->name ); */
814 uc_strcat( ret, Wordlist_getSCName( sc ));
815
816 if( element_selected )
817 uc_strcat( ret, "]" );
818 }
819
820 return ret;
821 }
822
823
Wordlist_advanceSelectedCharsBy(SplineFont * sf,EncMap * map,unichar_t * txtu,int offset)824 unichar_t* Wordlist_advanceSelectedCharsBy( SplineFont* sf, EncMap *map, unichar_t* txtu, int offset )
825 {
826 unichar_t original_data[ PATH_MAX ];
827 static unichar_t ret[ PATH_MAX ];
828 int i = 0;
829
830 u_strcpy( original_data, txtu );
831 TRACE("Wordlist_advanceSelectedCharsBy(1) %s\n", u_to_c( txtu ));
832 WordlistTrimTrailingSingleSlash( txtu );
833 WordListLine wll = WordlistEscapedInputStringToParsedData( sf, txtu );
834
835 int selectedCount = WordListLine_countSelected( wll );
836 if( !selectedCount )
837 wll->isSelected = 1;
838
839 memset( ret, 0, sizeof(unichar_t) * PATH_MAX );
840 for( i = 0; wll->sc; wll++, i++ )
841 {
842 SplineChar* sc = wll->sc;
843 int element_selected = wll->isSelected;
844
845 if( element_selected )
846 {
847 int pos = map->backmap[ sc->orig_pos ];
848 pos += offset;
849 int gid = pos < 0 || pos >= map->enccount ? -2 : map->map[pos];
850 if( gid == -2 )
851 {
852 // we can't find a glyph at the desired position.
853 // so instead of dropping it we just do not perform the operation
854 // on this char.
855 pos -= offset;
856 gid = pos < 0 || pos >= map->enccount ? -2 : map->map[pos];
857 if( gid == -2 )
858 {
859 // we can't go back manually!
860 u_strcpy( ret, original_data );
861 return ret;
862 }
863 }
864 if( gid==-1 || !sf->glyphs[gid] )
865 sc = SFMakeChar( sf, map, pos );
866 else
867 sc = sf->glyphs[gid];
868 }
869
870
871 if( element_selected )
872 uc_strcat( ret, "[" );
873
874 /* uc_strcat( ret, "/" ); */
875 /* uc_strcat( ret, scarray[i]->name ); */
876 uc_strcat( ret, Wordlist_getSCName( sc ));
877
878 if( element_selected )
879 uc_strcat( ret, "]" );
880 }
881
882 return ret;
883 }
884
885
886
887 /**
888 * haveSelection is set to true iff there is 1+ selections i txtu
889 */
Wordlist_selectionStringOnly(unichar_t * txtu,int * haveSelection)890 static unichar_t* Wordlist_selectionStringOnly( unichar_t* txtu, int* haveSelection )
891 {
892 static unichar_t ret[ PATH_MAX ];
893 int limit = PATH_MAX;
894 memset( ret, 0, sizeof(unichar_t) * PATH_MAX );
895 *haveSelection = 0;
896
897 int inSelection = 0;
898 unichar_t *dst = ret;
899 const unichar_t *src_end = 0;
900 const unichar_t *src = 0;
901 src_end=txtu+u_strlen(txtu);
902 for ( src=txtu; src < src_end; ++src )
903 {
904 if( *src == '[' )
905 {
906 inSelection = 1;
907 *haveSelection = 1;
908 continue;
909 }
910 if( *src == ']' )
911 {
912 inSelection = 0;
913 continue;
914 }
915
916 if( inSelection )
917 {
918 *dst = *src;
919 dst++;
920 }
921 }
922
923 return ret;
924 }
925
926
Wordlist_selectionsEqual(unichar_t * s1,unichar_t * s2)927 bool Wordlist_selectionsEqual( unichar_t* s1, unichar_t* s2 )
928 {
929 static unichar_t s1stripped[ PATH_MAX ];
930 static unichar_t s2stripped[ PATH_MAX ];
931 int s1HasSelection = 0;
932 int s2HasSelection = 0;
933
934 u_strcpy( s1stripped, Wordlist_selectionStringOnly( s1, &s1HasSelection ));
935 u_strcpy( s2stripped, Wordlist_selectionStringOnly( s2, &s2HasSelection ));
936
937 if( s1HasSelection && !s2HasSelection )
938 return false;
939 if( !s1HasSelection && s2HasSelection )
940 return false;
941
942 return !u_strcmp( s1stripped, s2stripped );
943 }
944
945
WordListLine_toustr(WordListLine wll)946 unichar_t* WordListLine_toustr( WordListLine wll )
947 {
948 unichar_t* ret = calloc( WordListLine_size(wll)+1, sizeof(unichar_t));
949 unichar_t* p = ret;
950 for( ; wll->sc; wll++, p++ ) {
951 *p = wll->sc->unicodeenc;
952 if (*p == -1) *p = wll->n;
953 }
954 return ret;
955 }
956
957
958
959
960
961