Line data Source code
1 : /* Copyright (C) 2005-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include "fontforgeui.h"
28 : #include "fvfonts.h"
29 : #include "groups.h"
30 : #include "namelist.h"
31 : #include "splineutil.h"
32 : #include <unistd.h>
33 : #include <ustring.h>
34 : #include <utype.h>
35 : #include <gkeysym.h>
36 : #include <math.h>
37 :
38 :
39 :
40 : /******************************************************************************/
41 : /******************************** Group Widget ********************************/
42 : /******************************************************************************/
43 :
44 : #define COLOR_CHOOSE (-10)
45 : static GTextInfo std_colors[] = {
46 : { (unichar_t *) N_("Select by Color"), NULL, 0, 0, (void *) COLOR_DEFAULT, NULL, 0, 1, 0, 0, 0, 0, 1, 0, 0, '\0' },
47 : { (unichar_t *) N_("Color|Choose..."), NULL, 0, 0, (void *) COLOR_CHOOSE, NULL, 0, 1, 0, 0, 0, 0, 1, 0, 0, '\0' },
48 : { (unichar_t *) N_("Color|Default"), &def_image, 0, 0, (void *) COLOR_DEFAULT, NULL, 0, 1, 0, 0, 0, 0, 1, 0, 0, '\0' },
49 : { NULL, &white_image, 0, 0, (void *) 0xffffff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' },
50 : { NULL, &red_image, 0, 0, (void *) 0xff0000, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' },
51 : { NULL, &green_image, 0, 0, (void *) 0x00ff00, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' },
52 : { NULL, &blue_image, 0, 0, (void *) 0x0000ff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' },
53 : { NULL, &yellow_image, 0, 0, (void *) 0xffff00, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' },
54 : { NULL, &cyan_image, 0, 0, (void *) 0x00ffff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' },
55 : { NULL, &magenta_image, 0, 0, (void *) 0xff00ff, NULL, 0, 1, 0, 0, 0, 0, 0, 0, 0, '\0' },
56 : GTEXTINFO_EMPTY
57 : };
58 :
59 : struct groupdlg {
60 : unsigned int oked: 1;
61 : unsigned int done: 1;
62 : unsigned int select_many: 1;
63 : /* define groups can only select one group at a time, select/restrict */
64 : /* to groups can select multiple things */
65 : unsigned int select_kids_too: 1;
66 : /* When we select a parent group do we want to select all the kids? */
67 : Group *root;
68 : Group *oldsel;
69 : int open_cnt, lines_page, off_top, off_left, page_width, bmargin;
70 : int maxl;
71 : GWindow gw,v;
72 : GGadget *vsb, *hsb, *cancel, *ok, *compact;
73 : GGadget *newsub, *delete, *line1, *gpnamelab, *gpname, *glyphslab, *glyphs;
74 : GGadget *idlab, *idname, *iduni, *set, *select, *unique, *colour, *line2;
75 : int fh, as;
76 : GFont *font;
77 : FontView *fv;
78 : void (*select_callback)(struct groupdlg *);
79 : GTimer *showchange;
80 : };
81 :
82 : extern int _GScrollBar_Width;
83 :
84 0 : static Group *GroupFindLPos(Group *group,int lpos,int *depth) {
85 : int i;
86 :
87 : for (;;) {
88 0 : if ( group->lpos==lpos )
89 0 : return( group );
90 0 : if ( !group->open )
91 0 : return( NULL );
92 0 : for ( i=0; i<group->kid_cnt-1; ++i ) {
93 0 : if ( lpos<group->kids[i+1]->lpos )
94 0 : break;
95 : }
96 0 : group = group->kids[i];
97 0 : ++*depth;
98 0 : }
99 : }
100 :
101 0 : static int GroupPosInParent(Group *group) {
102 0 : Group *parent = group->parent;
103 : int i;
104 :
105 0 : if ( parent==NULL )
106 0 : return( 0 );
107 0 : for ( i=0; i<parent->kid_cnt; ++i )
108 0 : if ( parent->kids[i]==group )
109 0 : return( i );
110 :
111 0 : return( -1 );
112 : }
113 :
114 0 : static Group *GroupNext(Group *group,int *depth) {
115 0 : if ( group->open && group->kids ) {
116 0 : ++*depth;
117 0 : return( group->kids[0] );
118 : }
119 : for (;;) {
120 : int pos;
121 0 : if ( group->parent==NULL )
122 0 : return( NULL );
123 0 : pos = GroupPosInParent(group);
124 0 : if ( pos+1<group->parent->kid_cnt )
125 0 : return( group->parent->kids[pos+1] );
126 0 : group = group->parent;
127 0 : --*depth;
128 0 : }
129 : }
130 :
131 0 : static Group *GroupPrev(struct groupdlg *grp, Group *group,int *depth) {
132 : int pos;
133 :
134 0 : while ( group->parent!=NULL && group==group->parent->kids[0] ) {
135 0 : group = group->parent;
136 0 : --*depth;
137 : }
138 0 : if ( group->parent==NULL )
139 0 : return( NULL );
140 0 : pos = GroupPosInParent(group);
141 0 : group = group->parent->kids[pos-1];
142 0 : while ( group->open ) {
143 0 : group = group->kids[group->kid_cnt-1];
144 0 : ++*depth;
145 : }
146 0 : return( group );
147 : }
148 :
149 0 : static int _GroupSBSizes(struct groupdlg *grp, Group *group, int lpos, int depth) {
150 : int i, len;
151 :
152 0 : group->lpos = lpos++;
153 :
154 0 : len = 5+8*depth+ grp->as + 5 + GDrawGetText8Width(grp->v,group->name,-1);
155 0 : if ( group->glyphs!=NULL )
156 0 : len += 5 + GDrawGetText8Width(grp->v,group->glyphs,-1);
157 0 : if ( len > grp->maxl )
158 0 : grp->maxl = len;
159 :
160 0 : if ( group->open ) {
161 0 : for ( i=0; i< group->kid_cnt; ++i )
162 0 : lpos = _GroupSBSizes(grp,group->kids[i],lpos,depth+1);
163 : }
164 0 : return( lpos );
165 : }
166 :
167 0 : static int GroupSBSizes(struct groupdlg *grp) {
168 : int lpos;
169 :
170 0 : grp->maxl = 0;
171 0 : GDrawSetFont(grp->v,grp->font);
172 0 : lpos = _GroupSBSizes(grp,grp->root,0,0);
173 0 : grp->maxl += 5; /* margin */
174 :
175 0 : GScrollBarSetBounds(grp->vsb,0,lpos,grp->lines_page);
176 0 : GScrollBarSetBounds(grp->hsb,0,grp->maxl,grp->page_width);
177 0 : grp->open_cnt = lpos;
178 0 : return( lpos );
179 : }
180 :
181 0 : static void GroupSelectKids(Group *group,int sel) {
182 : int i;
183 :
184 0 : group->selected = sel;
185 0 : for ( i=0; i<group->kid_cnt; ++i )
186 0 : GroupSelectKids(group->kids[i],sel);
187 0 : }
188 :
189 0 : static void GroupDeselectAllBut(Group *root,Group *group) {
190 : int i;
191 :
192 0 : if ( root!=group )
193 0 : root->selected = false;
194 0 : for ( i=0; i<root->kid_cnt; ++i )
195 0 : GroupDeselectAllBut(root->kids[i],group);
196 0 : }
197 :
198 0 : static Group *_GroupCurrentlySelected(Group *group) {
199 : int i;
200 : Group *sel;
201 :
202 0 : if ( group->selected )
203 0 : return( group );
204 0 : for ( i=0; i<group->kid_cnt; ++i ) {
205 0 : sel = _GroupCurrentlySelected(group->kids[i]);
206 0 : if ( sel!=NULL )
207 0 : return( sel );
208 : }
209 0 : return( NULL );
210 : }
211 :
212 0 : static Group *GroupCurrentlySelected(struct groupdlg *grp) {
213 :
214 0 : if ( grp->select_many )
215 0 : return( NULL );
216 0 : return( _GroupCurrentlySelected(grp->root));
217 : }
218 :
219 0 : static void GroupWExpose(struct groupdlg *grp,GWindow pixmap,GRect *rect) {
220 : int depth, y, len;
221 : Group *group;
222 : GRect r;
223 : Color fg;
224 :
225 0 : GDrawFillRect(pixmap,rect,GDrawGetDefaultBackground(NULL));
226 0 : GDrawSetLineWidth(pixmap,0);
227 :
228 0 : r.height = r.width = grp->as;
229 0 : y = (rect->y/grp->fh) * grp->fh + grp->as;
230 0 : depth=0;
231 0 : group = GroupFindLPos(grp->root,rect->y/grp->fh+grp->off_top,&depth);
232 0 : GDrawSetFont(pixmap,grp->font);
233 0 : while ( group!=NULL ) {
234 0 : r.y = y-grp->as+1;
235 0 : r.x = 5+8*depth - grp->off_left;
236 0 : fg = group->selected ? 0xff0000 : 0x000000;
237 0 : if ( group->glyphs==NULL ) {
238 0 : GDrawDrawRect(pixmap,&r,fg);
239 0 : GDrawDrawLine(pixmap,r.x+2,r.y+grp->as/2,r.x+grp->as-2,r.y+grp->as/2,
240 : fg);
241 0 : if ( !group->open )
242 0 : GDrawDrawLine(pixmap,r.x+grp->as/2,r.y+2,r.x+grp->as/2,r.y+grp->as-2,
243 : fg);
244 : }
245 0 : len = GDrawDrawText8(pixmap,r.x+r.width+5,y,group->name,-1,fg);
246 0 : if ( group->glyphs )
247 0 : GDrawDrawText8(pixmap,r.x+r.width+5+len+5,y,group->glyphs,-1,fg);
248 0 : group = GroupNext(group,&depth);
249 0 : y += grp->fh;
250 0 : if ( y-grp->fh>rect->y+rect->height )
251 0 : break;
252 : }
253 0 : }
254 :
255 0 : static void GroupWMouse(struct groupdlg *grp,GEvent *event) {
256 : int x;
257 0 : int depth=0;
258 : Group *group;
259 :
260 0 : group = GroupFindLPos(grp->root,event->u.mouse.y/grp->fh+grp->off_top,&depth);
261 0 : if ( group==NULL )
262 0 : return;
263 :
264 0 : x = 5+8*depth - grp->off_left;
265 0 : if ( event->u.mouse.x<x )
266 0 : return;
267 0 : if ( event->u.mouse.x<=x+grp->as ) {
268 0 : if ( group->glyphs != NULL )
269 0 : return;
270 0 : group->open = !group->open;
271 0 : GroupSBSizes(grp);
272 : } else {
273 0 : group->selected = !group->selected;
274 0 : if ( grp->select_kids_too )
275 0 : GroupSelectKids(group,group->selected);
276 0 : else if ( group->selected && !grp->select_many )
277 0 : GroupDeselectAllBut(grp->root,group);
278 0 : if ( grp->select_callback!=NULL )
279 0 : (grp->select_callback)(grp);
280 : }
281 0 : GDrawRequestExpose(grp->v,NULL,false);
282 : }
283 :
284 0 : static void GroupScroll(struct groupdlg *grp,struct sbevent *sb) {
285 0 : int newpos = grp->off_top;
286 :
287 0 : switch( sb->type ) {
288 : case et_sb_top:
289 0 : newpos = 0;
290 0 : break;
291 : case et_sb_uppage:
292 0 : newpos -= grp->lines_page;
293 0 : break;
294 : case et_sb_up:
295 0 : --newpos;
296 0 : break;
297 : case et_sb_down:
298 0 : ++newpos;
299 0 : break;
300 : case et_sb_downpage:
301 0 : newpos += grp->lines_page;
302 0 : break;
303 : case et_sb_bottom:
304 0 : newpos = grp->open_cnt-grp->lines_page;
305 0 : break;
306 : case et_sb_thumb:
307 : case et_sb_thumbrelease:
308 0 : newpos = sb->pos;
309 0 : break;
310 : }
311 0 : if ( newpos>grp->open_cnt-grp->lines_page )
312 0 : newpos = grp->open_cnt-grp->lines_page;
313 0 : if ( newpos<0 ) newpos =0;
314 0 : if ( newpos!=grp->off_top ) {
315 0 : int diff = newpos-grp->off_top;
316 0 : grp->off_top = newpos;
317 0 : GScrollBarSetPos(grp->vsb,grp->off_top);
318 0 : GDrawScroll(grp->v,NULL,0,diff*grp->fh);
319 : }
320 0 : }
321 :
322 :
323 0 : static void GroupHScroll(struct groupdlg *grp,struct sbevent *sb) {
324 0 : int newpos = grp->off_left;
325 :
326 0 : switch( sb->type ) {
327 : case et_sb_top:
328 0 : newpos = 0;
329 0 : break;
330 : case et_sb_uppage:
331 0 : newpos -= grp->page_width;
332 0 : break;
333 : case et_sb_up:
334 0 : --newpos;
335 0 : break;
336 : case et_sb_down:
337 0 : ++newpos;
338 0 : break;
339 : case et_sb_downpage:
340 0 : newpos += grp->page_width;
341 0 : break;
342 : case et_sb_bottom:
343 0 : newpos = grp->maxl-grp->page_width;
344 0 : break;
345 : case et_sb_thumb:
346 : case et_sb_thumbrelease:
347 0 : newpos = sb->pos;
348 0 : break;
349 : }
350 0 : if ( newpos>grp->maxl-grp->page_width )
351 0 : newpos = grp->maxl-grp->page_width;
352 0 : if ( newpos<0 ) newpos =0;
353 0 : if ( newpos!=grp->off_left ) {
354 0 : int diff = newpos-grp->off_left;
355 0 : grp->off_left = newpos;
356 0 : GScrollBarSetPos(grp->hsb,grp->off_left);
357 0 : GDrawScroll(grp->v,NULL,-diff,0);
358 : }
359 0 : }
360 :
361 0 : static void GroupResize(struct groupdlg *grp,GEvent *event) {
362 : GRect size, wsize;
363 : int lcnt, offy;
364 0 : int sbsize = GDrawPointsToPixels(grp->gw,_GScrollBar_Width);
365 :
366 0 : GDrawGetSize(grp->gw,&size);
367 0 : lcnt = (size.height-grp->bmargin)/grp->fh;
368 0 : GGadgetResize(grp->vsb,sbsize,lcnt*grp->fh);
369 0 : GGadgetMove(grp->vsb,size.width-sbsize,0);
370 0 : GGadgetResize(grp->hsb,size.width-sbsize,sbsize);
371 0 : GGadgetMove(grp->hsb,0,lcnt*grp->fh);
372 0 : GDrawResize(grp->v,size.width-sbsize,lcnt*grp->fh);
373 0 : grp->page_width = size.width-sbsize;
374 0 : grp->lines_page = lcnt;
375 0 : GScrollBarSetBounds(grp->vsb,0,grp->open_cnt,grp->lines_page);
376 0 : GScrollBarSetBounds(grp->hsb,0,grp->maxl,grp->page_width);
377 :
378 0 : GGadgetGetSize(grp->cancel,&wsize);
379 0 : offy = size.height-wsize.height-6 - wsize.y;
380 0 : GGadgetMove(grp->cancel,size.width-wsize.width-30, wsize.y+offy);
381 0 : GGadgetMove(grp->ok , 30-3,wsize.y+offy-3);
382 0 : if ( grp->newsub!=NULL ) {
383 0 : GGadgetGetSize(grp->newsub,&wsize);
384 0 : GGadgetMove(grp->newsub,wsize.x,wsize.y+offy);
385 0 : GGadgetGetSize(grp->delete,&wsize);
386 0 : GGadgetMove(grp->delete,wsize.x,wsize.y+offy);
387 0 : GGadgetGetSize(grp->line1,&wsize);
388 0 : GGadgetMove(grp->line1,wsize.x,wsize.y+offy);
389 0 : GGadgetGetSize(grp->gpnamelab,&wsize);
390 0 : GGadgetMove(grp->gpnamelab,wsize.x,wsize.y+offy);
391 0 : GGadgetGetSize(grp->gpname,&wsize);
392 0 : GGadgetMove(grp->gpname,wsize.x,wsize.y+offy);
393 0 : GGadgetGetSize(grp->glyphslab,&wsize);
394 0 : GGadgetMove(grp->glyphslab,wsize.x,wsize.y+offy);
395 0 : GGadgetGetSize(grp->glyphs,&wsize);
396 0 : GGadgetMove(grp->glyphs,wsize.x,wsize.y+offy);
397 0 : GGadgetGetSize(grp->idlab,&wsize);
398 0 : GGadgetMove(grp->idlab,wsize.x,wsize.y+offy);
399 0 : GGadgetGetSize(grp->idname,&wsize);
400 0 : GGadgetMove(grp->idname,wsize.x,wsize.y+offy);
401 0 : GGadgetGetSize(grp->iduni,&wsize);
402 0 : GGadgetMove(grp->iduni,wsize.x,wsize.y+offy);
403 0 : GGadgetGetSize(grp->set,&wsize);
404 0 : GGadgetMove(grp->set,wsize.x,wsize.y+offy);
405 0 : GGadgetGetSize(grp->select,&wsize);
406 0 : GGadgetMove(grp->select,wsize.x,wsize.y+offy);
407 0 : GGadgetGetSize(grp->unique,&wsize);
408 0 : GGadgetMove(grp->unique,wsize.x,wsize.y+offy);
409 0 : GGadgetGetSize(grp->colour,&wsize);
410 0 : GGadgetMove(grp->colour,wsize.x,wsize.y+offy);
411 0 : GGadgetGetSize(grp->line2,&wsize);
412 0 : GGadgetMove(grp->line2,wsize.x,wsize.y+offy);
413 : } else {
414 0 : GGadgetGetSize(grp->compact,&wsize);
415 0 : GGadgetMove(grp->compact,wsize.x,wsize.y+offy);
416 : }
417 0 : GDrawRequestExpose(grp->v,NULL,true);
418 0 : GDrawRequestExpose(grp->gw,NULL,true);
419 0 : }
420 :
421 0 : static void GroupWChangeCurrent(struct groupdlg *grp,Group *current,Group *next ) {
422 0 : if ( current!=NULL )
423 0 : current->selected = false;
424 0 : next->selected = true;
425 0 : if ( next->lpos<grp->off_top || next->lpos>=grp->off_top+grp->lines_page ) {
426 0 : if ( next->lpos>=grp->off_top+grp->lines_page )
427 0 : grp->off_top = next->lpos;
428 : else {
429 0 : grp->off_top = next->lpos-grp->lines_page-1;
430 0 : if ( grp->off_top<0 ) grp->off_top = 0;
431 : }
432 0 : GScrollBarSetPos(grp->vsb,grp->off_top);
433 0 : GDrawRequestExpose(grp->v,NULL,false);
434 : }
435 0 : }
436 :
437 0 : static int GroupChar(struct groupdlg *grp,GEvent *event) {
438 0 : int depth = 0;
439 : int pos;
440 0 : Group *current = GroupCurrentlySelected(grp);
441 :
442 0 : switch (event->u.chr.keysym) {
443 : case GK_F1: case GK_Help:
444 0 : help("groups.html");
445 0 : return( true );
446 : case GK_Return: case GK_KP_Enter:
447 0 : if ( current!=NULL ) {
448 0 : current->open = !current->open;
449 0 : GroupSBSizes(grp);
450 0 : GDrawRequestExpose(grp->v,NULL,false);
451 : }
452 0 : return( true );
453 : case GK_Page_Down: case GK_KP_Page_Down:
454 0 : pos = grp->off_top+(grp->lines_page<=1?1:grp->lines_page-1);
455 0 : if ( pos >= grp->open_cnt-grp->lines_page )
456 0 : pos = grp->open_cnt-grp->lines_page;
457 0 : if ( pos<0 ) pos = 0;
458 0 : grp->off_top = pos;
459 0 : GScrollBarSetPos(grp->vsb,pos);
460 0 : GDrawRequestExpose(grp->v,NULL,false);
461 0 : return( true );
462 : case GK_Down: case GK_KP_Down:
463 0 : if ( current==NULL || (event->u.chr.state&ksm_control)) {
464 0 : if ( grp->off_top<grp->open_cnt-1 ) {
465 0 : ++grp->off_top;
466 0 : GScrollBarSetPos(grp->vsb,grp->off_top);
467 0 : GDrawScroll(grp->v,NULL,0,grp->fh);
468 : }
469 : } else
470 0 : GroupWChangeCurrent(grp,current,GroupNext(current,&depth));
471 0 : return( true );
472 : case GK_Up: case GK_KP_Up:
473 0 : if ( current==NULL || (event->u.chr.state&ksm_control)) {
474 0 : if (grp->off_top!=0 ) {
475 0 : --grp->off_top;
476 0 : GScrollBarSetPos(grp->vsb,grp->off_top);
477 0 : GDrawScroll(grp->v,NULL,0,-grp->fh);
478 : }
479 : } else
480 0 : GroupWChangeCurrent(grp,current,GroupPrev(grp,current,&depth));
481 0 : return( true );
482 : case GK_Page_Up: case GK_KP_Page_Up:
483 0 : pos = grp->off_top-(grp->lines_page<=1?1:grp->lines_page-1);
484 0 : if ( pos<0 ) pos = 0;
485 0 : grp->off_top = pos;
486 0 : GScrollBarSetPos(grp->vsb,pos);
487 0 : GDrawRequestExpose(grp->v,NULL,false);
488 0 : return( true );
489 : case GK_Left: case GK_KP_Left:
490 0 : if ( !grp->select_many && current!=NULL )
491 0 : GroupWChangeCurrent(grp,current,current->parent);
492 0 : return( true );
493 : case GK_Right: case GK_KP_Right:
494 0 : if ( !grp->select_many && current != NULL && current->kid_cnt!=0 ) {
495 0 : if ( !current->open ) {
496 0 : current->open = !current->open;
497 0 : GroupSBSizes(grp);
498 : }
499 0 : GroupWChangeCurrent(grp,current,current->kids[0]);
500 : }
501 0 : return( true );
502 : case GK_Home: case GK_KP_Home:
503 0 : if ( grp->off_top!=0 ) {
504 0 : grp->off_top = 0;
505 0 : GScrollBarSetPos(grp->vsb,0);
506 0 : GDrawRequestExpose(grp->v,NULL,false);
507 : }
508 0 : if ( !grp->select_many )
509 0 : GroupWChangeCurrent(grp,current,grp->root);
510 0 : return( true );
511 : case GK_End: case GK_KP_End:
512 0 : pos = grp->open_cnt-grp->lines_page;
513 0 : if ( pos<0 ) pos = 0;
514 0 : if ( pos!=grp->off_top ) {
515 0 : grp->off_top = pos;
516 0 : GScrollBarSetPos(grp->vsb,pos);
517 0 : GDrawRequestExpose(grp->v,NULL,false);
518 : }
519 0 : if ( !grp->select_many )
520 0 : GroupWChangeCurrent(grp,current,GroupFindLPos(grp->root,grp->open_cnt-1,&depth));
521 0 : return( true );
522 : }
523 0 : return( false );
524 : }
525 :
526 0 : static int grpv_e_h(GWindow gw, GEvent *event) {
527 0 : struct groupdlg *grp = (struct groupdlg *) GDrawGetUserData(gw);
528 :
529 0 : if (( event->type==et_mouseup || event->type==et_mousedown ) &&
530 0 : (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
531 0 : return( GGadgetDispatchEvent(grp->vsb,event));
532 : }
533 :
534 0 : switch ( event->type ) {
535 : case et_expose:
536 0 : GroupWExpose(grp,gw,&event->u.expose.rect);
537 0 : break;
538 : case et_char:
539 0 : return( GroupChar(grp,event));
540 : case et_mouseup:
541 0 : GroupWMouse(grp,event);
542 0 : break;
543 : }
544 0 : return( true );
545 : }
546 :
547 0 : static void GroupWCreate(struct groupdlg *grp,GRect *pos) {
548 : FontRequest rq;
549 : int as, ds, ld;
550 : GGadgetCreateData gcd[5];
551 : GTextInfo label[4];
552 0 : int sbsize = GDrawPointsToPixels(NULL,_GScrollBar_Width);
553 : GWindowAttrs wattrs;
554 : static GFont *font=NULL;
555 :
556 0 : if ( font==NULL ) {
557 0 : memset(&rq,'\0',sizeof(rq));
558 0 : rq.utf8_family_name = SANS_UI_FAMILIES;
559 0 : rq.point_size = 12;
560 0 : rq.weight = 400;
561 0 : font = GDrawInstanciateFont(grp->gw,&rq);
562 0 : font = GResourceFindFont("Groups.Font",font);
563 : }
564 0 : grp->font = font;
565 0 : GDrawWindowFontMetrics(grp->gw,grp->font,&as,&ds,&ld);
566 0 : grp->fh = as+ds; grp->as = as;
567 :
568 0 : grp->lines_page = (pos->height-grp->bmargin)/grp->fh;
569 0 : grp->page_width = pos->width-sbsize;
570 0 : wattrs.mask = wam_events|wam_cursor/*|wam_bordwidth|wam_bordcol*/;
571 0 : wattrs.event_masks = ~0;
572 0 : wattrs.border_width = 1;
573 0 : wattrs.border_color = 0x000000;
574 0 : wattrs.cursor = ct_pointer;
575 0 : pos->x = 0; pos->y = 0;
576 0 : pos->width -= sbsize; pos->height = grp->lines_page*grp->fh;
577 0 : grp->v = GWidgetCreateSubWindow(grp->gw,pos,grpv_e_h,grp,&wattrs);
578 0 : GDrawSetVisible(grp->v,true);
579 :
580 0 : memset(&label,0,sizeof(label));
581 0 : memset(&gcd,0,sizeof(gcd));
582 :
583 0 : gcd[0].gd.pos.x = pos->width; gcd[0].gd.pos.y = 0;
584 0 : gcd[0].gd.pos.width = sbsize;
585 0 : gcd[0].gd.pos.height = pos->height;
586 0 : gcd[0].gd.flags = gg_visible | gg_enabled | gg_pos_in_pixels | gg_sb_vert;
587 0 : gcd[0].creator = GScrollBarCreate;
588 :
589 0 : gcd[1].gd.pos.x = 0; gcd[1].gd.pos.y = pos->height;
590 0 : gcd[1].gd.pos.height = sbsize;
591 0 : gcd[1].gd.pos.width = pos->width;
592 0 : gcd[1].gd.flags = gg_visible | gg_enabled | gg_pos_in_pixels;
593 0 : gcd[1].creator = GScrollBarCreate;
594 :
595 0 : GGadgetsCreate(grp->gw,gcd);
596 0 : grp->vsb = gcd[0].ret;
597 0 : grp->hsb = gcd[1].ret;
598 0 : }
599 :
600 : /******************************************************************************/
601 : /******************************** Group Dialogs *******************************/
602 : /******************************************************************************/
603 :
604 0 : static int FindDuplicateNumberInString(int seek,char *str) {
605 : char *start;
606 :
607 0 : if ( str==NULL )
608 0 : return( false );
609 :
610 0 : while ( *str!='\0' ) {
611 0 : while ( *str==' ' ) ++str;
612 0 : start = str;
613 0 : while ( *str!=' ' && *str!='\0' ) ++str;
614 0 : if ( start==str )
615 0 : break;
616 0 : if ( (start[0]=='U' || start[0]=='u') && start[1]=='+' ) {
617 : char *end;
618 0 : int val = strtol(start+2,&end,16), val2=val;
619 0 : if ( *end=='-' ) {
620 0 : if ( (end[1]=='u' || end[1]=='U') && end[2]=='+' )
621 0 : end+=2;
622 0 : val2 = strtol(end+1,NULL,16);
623 : }
624 0 : if ( seek>=val && seek<=val2 )
625 0 : return( true );
626 : }
627 : }
628 0 : return( false );
629 : }
630 :
631 0 : static int FindDuplicateNameInString(char *name,char *str) {
632 : char *start;
633 :
634 0 : if ( str==NULL )
635 0 : return( false );
636 :
637 0 : while ( *str!='\0' ) {
638 0 : while ( *str==' ' ) ++str;
639 0 : start = str;
640 0 : while ( *str!=' ' && *str!='\0' ) ++str;
641 0 : if ( start==str )
642 0 : break;
643 0 : if ( (start[0]=='U' || start[0]=='u') && start[1]=='+' )
644 : /* Skip it */;
645 : else {
646 0 : int ch = *str;
647 0 : *str = '\0';
648 0 : if ( strcmp(name,start)==0 ) {
649 0 : *str = ch;
650 0 : return( true );
651 : }
652 0 : *str = ch;
653 : }
654 : }
655 0 : return( false );
656 : }
657 :
658 0 : static Group *FindDuplicateNumber(Group *top,int val,Group *cur,char *str) {
659 : int i;
660 : Group *grp;
661 :
662 0 : if ( FindDuplicateNumberInString(val,str))
663 0 : return( cur );
664 0 : if ( top==cur )
665 0 : return( NULL );
666 0 : if ( FindDuplicateNumberInString(val,top->glyphs))
667 0 : return( top );
668 0 : for ( i=0; i<top->kid_cnt; ++i )
669 0 : if ( (grp = FindDuplicateNumber(top->kids[i],val,cur,NULL))!=NULL )
670 0 : return( grp );
671 :
672 0 : return( NULL );
673 : }
674 :
675 0 : static Group *FindDuplicateName(Group *top,char *name,Group *cur,char *str) {
676 : int i;
677 : Group *grp;
678 :
679 0 : if ( FindDuplicateNameInString(name,str))
680 0 : return( cur );
681 0 : if ( top==cur )
682 0 : return( NULL );
683 0 : if ( FindDuplicateNameInString(name,top->glyphs))
684 0 : return( top );
685 0 : for ( i=0; i<top->kid_cnt; ++i )
686 0 : if ( (grp = FindDuplicateName(top->kids[i],name,cur,NULL))!=NULL )
687 0 : return( grp );
688 :
689 0 : return( NULL );
690 : }
691 :
692 0 : static int GroupValidateGlyphs(Group *cur,char *g,const unichar_t *gu,int unique) {
693 : char *gpt, *start;
694 : Group *top, *grp;
695 :
696 0 : if ( gu!=NULL ) {
697 0 : for ( ; *gu!='\0'; ++gu ) {
698 0 : if ( *gu<' ' || *gu>=0x7f || *gu=='(' || *gu==')' ||
699 0 : *gu=='[' || *gu==']' || *gu=='{' || *gu=='}' ||
700 0 : *gu=='<' || *gu=='>' || *gu=='%' || *gu=='/' ) {
701 0 : ff_post_error(_("Glyph names must be valid postscript names"),_("Glyph names must be valid postscript names"));
702 0 : return( false );
703 : }
704 : }
705 : }
706 0 : if ( unique ) { /* Can't use cur->unique because it hasn't been set yet */
707 0 : top = cur;
708 0 : while ( top->parent!=NULL && top->parent->unique )
709 0 : top = top->parent;
710 0 : for ( gpt=g; *gpt!='\0' ; ) {
711 0 : while ( *gpt==' ' ) ++gpt;
712 0 : start = gpt;
713 0 : while ( *gpt!=' ' && *gpt!='\0' ) ++gpt;
714 0 : if ( start==gpt )
715 0 : break;
716 0 : if ( (start[0]=='U' || start[0]=='u') && start[1]=='+' ) {
717 : char *end;
718 0 : int val = strtol(start+2,&end,16), val2=val;
719 0 : if ( *end=='-' ) {
720 0 : if ( (end[1]=='u' || end[1]=='U') && end[2]=='+' )
721 0 : end+=2;
722 0 : val2 = strtol(end+1,NULL,16);
723 : }
724 0 : if ( val2<val ) {
725 0 : ff_post_error(_("Bad Range"),_("Bad Range, start (%1$04X) is greater than end (%2$04X)"), val, val2 );
726 0 : return( false );
727 : }
728 0 : for ( ; val<=val2; ++val )
729 0 : if ( (grp=FindDuplicateNumber(top,val,cur,gpt))!=NULL ) {
730 0 : ff_post_error(_("Duplicate Name"),_("The code point U+%1$04X occurs in groups %2$.30s and %3$.30s"), val, cur->name, grp->name);
731 0 : return( false );
732 : }
733 : } else {
734 0 : int ch = *gpt;
735 0 : *gpt = '\0';
736 0 : if ( (grp=FindDuplicateName(top,start,cur,ch!='\0'?gpt+1:NULL))!=NULL ) {
737 0 : ff_post_error(_("Duplicate Name"),_("The glyph name \"%1$.30s\" occurs in groups %2$.30s and %3$.30s"), start, cur->name, grp->name);
738 0 : *gpt = ch;
739 0 : return( false );
740 : }
741 0 : *gpt = ch;
742 : }
743 : }
744 : }
745 0 : return( true );
746 : }
747 :
748 0 : static int GroupSetKidsUnique(Group *group) {
749 : int i;
750 :
751 0 : group->unique = true;
752 0 : for ( i=0; i<group->kid_cnt; ++i )
753 0 : if ( !GroupSetKidsUnique(group->kids[i]))
754 0 : return( false );
755 0 : if ( group->glyphs!=NULL ) {
756 0 : if ( !GroupValidateGlyphs(group,group->glyphs,NULL,true))
757 0 : return( false );
758 : }
759 0 : return( true );
760 : }
761 :
762 0 : static int GroupFinishOld(struct groupdlg *grp) {
763 0 : if ( grp->oldsel!=NULL ) {
764 0 : const unichar_t *gu = _GGadgetGetTitle(grp->glyphs);
765 0 : char *g = cu_copy(gu);
766 0 : int oldunique = grp->oldsel->unique;
767 :
768 0 : if ( !GroupValidateGlyphs(grp->oldsel,g,gu,GGadgetIsChecked(grp->unique))) {
769 0 : free(g);
770 0 : return( false );
771 : }
772 :
773 0 : free(grp->oldsel->name);
774 0 : grp->oldsel->name = GGadgetGetTitle8(grp->gpname);
775 0 : free(grp->oldsel->glyphs);
776 0 : if ( *g=='\0' ) {
777 0 : grp->oldsel->glyphs = NULL;
778 0 : free(g);
779 : } else
780 0 : grp->oldsel->glyphs = g;
781 :
782 0 : grp->oldsel->unique = GGadgetIsChecked(grp->unique);
783 0 : if ( grp->oldsel->unique && !oldunique ) {
784 : /* The just set the unique bit. We must force it set in all */
785 : /* kids. We really should check for uniqueness too!!!!! */
786 0 : if ( !GroupSetKidsUnique(grp->oldsel))
787 0 : return( false );
788 : }
789 : }
790 0 : return( true );
791 : }
792 :
793 0 : static void GroupSelected(struct groupdlg *grp) {
794 0 : Group *current = GroupCurrentlySelected(grp);
795 :
796 0 : if ( !GroupFinishOld(grp)) {
797 0 : if ( current!=NULL )
798 0 : current->selected=false;
799 0 : if ( grp->oldsel!=NULL )
800 0 : grp->oldsel->selected = true;
801 0 : return;
802 : }
803 0 : grp->oldsel = current;
804 0 : if ( current == NULL ) {
805 0 : GGadgetSetEnabled(grp->newsub,false);
806 0 : GGadgetSetEnabled(grp->delete,false);
807 0 : GGadgetSetEnabled(grp->gpnamelab,false);
808 0 : GGadgetSetEnabled(grp->gpname,false);
809 0 : GGadgetSetEnabled(grp->glyphslab,false);
810 0 : GGadgetSetEnabled(grp->glyphs,false);
811 0 : GGadgetSetEnabled(grp->set,false);
812 0 : GGadgetSetEnabled(grp->select,false);
813 0 : GGadgetSetEnabled(grp->unique,false);
814 0 : GGadgetSetEnabled(grp->colour,false);
815 : } else {
816 0 : unichar_t *glyphs = uc_copy(current->glyphs);
817 0 : GGadgetSetTitle8(grp->gpname,current->name);
818 0 : if ( glyphs==NULL ) glyphs = uc_copy("");
819 0 : GGadgetSetTitle(grp->glyphs,glyphs);
820 0 : free(glyphs);
821 0 : GGadgetSetChecked(grp->unique,current->unique);
822 0 : GGadgetSetEnabled(grp->newsub,current->glyphs==NULL || *current->glyphs=='\0');
823 0 : GGadgetSetEnabled(grp->delete,current->parent!=NULL);
824 0 : GGadgetSetEnabled(grp->gpnamelab,true);
825 0 : GGadgetSetEnabled(grp->gpname,true);
826 0 : GGadgetSetEnabled(grp->glyphslab,current->kid_cnt==0);
827 0 : GGadgetSetEnabled(grp->glyphs,current->kid_cnt==0);
828 0 : GGadgetSetEnabled(grp->set,current->kid_cnt==0);
829 0 : GGadgetSetEnabled(grp->select,current->kid_cnt==0);
830 0 : GGadgetSetEnabled(grp->unique,current->parent==NULL || !current->parent->unique);
831 0 : GGadgetSetEnabled(grp->colour,current->kid_cnt==0);
832 : }
833 : }
834 :
835 0 : static void GroupShowChange(struct groupdlg *grp) {
836 0 : if ( GroupFinishOld(grp))
837 0 : GDrawRequestExpose(grp->v,NULL,false);
838 0 : grp->showchange = NULL;
839 0 : }
840 :
841 0 : static int Group_GlyphListChanged(GGadget *g, GEvent *e) {
842 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
843 0 : struct groupdlg *grp = GDrawGetUserData(GGadgetGetWindow(g));
844 0 : const unichar_t *glyphs = _GGadgetGetTitle(g);
845 0 : GGadgetSetEnabled(grp->newsub,*glyphs=='\0');
846 0 : if ( grp->showchange!=NULL )
847 0 : GDrawCancelTimer(grp->showchange);
848 0 : grp->showchange = GDrawRequestTimer(grp->gw,500,0,NULL);
849 : }
850 0 : return( true );
851 : }
852 :
853 0 : static int Group_ToSelection(GGadget *g, GEvent *e) {
854 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
855 0 : struct groupdlg *grp = GDrawGetUserData(GGadgetGetWindow(g));
856 0 : const unichar_t *ret = _GGadgetGetTitle(grp->glyphs);
857 0 : SplineFont *sf = grp->fv->b.sf;
858 0 : FontView *fv = grp->fv;
859 : const unichar_t *end;
860 0 : int pos, found=-1;
861 : char *nm;
862 :
863 0 : GDrawSetVisible(fv->gw,true);
864 0 : GDrawRaise(fv->gw);
865 0 : memset(fv->b.selected,0,fv->b.map->enccount);
866 0 : while ( *ret ) {
867 0 : end = u_strchr(ret,' ');
868 0 : if ( end==NULL ) end = ret+u_strlen(ret);
869 0 : nm = cu_copybetween(ret,end);
870 0 : for ( ret = end; isspace(*ret); ++ret);
871 0 : if ( (nm[0]=='U' || nm[0]=='u') && nm[1]=='+' ) {
872 : char *end;
873 0 : int val = strtol(nm+2,&end,16), val2=val;
874 0 : if ( *end=='-' ) {
875 0 : if ( (end[1]=='u' || end[1]=='U') && end[2]=='+' )
876 0 : end+=2;
877 0 : val2 = strtol(end+1,NULL,16);
878 : }
879 0 : for ( ; val<=val2; ++val ) {
880 0 : if (( pos = SFFindSlot(sf,fv->b.map,val,NULL))!=-1 ) {
881 0 : if ( found==-1 ) found = pos;
882 0 : if ( pos!=-1 )
883 0 : fv->b.selected[pos] = true;
884 : }
885 : }
886 0 : } else if ( strncasecmp(nm,"color=#",strlen("color=#"))==0 ) {
887 0 : Color col = strtoul(nm+strlen("color=#"),NULL,16);
888 : int gid; SplineChar *sc;
889 :
890 0 : for ( pos=0; pos<fv->b.map->enccount; ++pos )
891 0 : if ( (gid=fv->b.map->map[pos])!=-1 &&
892 0 : (sc = sf->glyphs[gid])!=NULL &&
893 0 : sc->color == col )
894 0 : fv->b.selected[pos] = true;
895 : } else {
896 0 : if (( pos = SFFindSlot(sf,fv->b.map,-1,nm))!=-1 ) {
897 0 : if ( found==-1 ) found = pos;
898 0 : if ( pos!=-1 )
899 0 : fv->b.selected[pos] = true;
900 : }
901 : }
902 0 : free(nm);
903 : }
904 :
905 0 : if ( found!=-1 )
906 0 : FVScrollToChar(fv,found);
907 0 : GDrawRequestExpose(fv->v,NULL,false);
908 : }
909 0 : return( true );
910 : }
911 :
912 0 : static int Group_FromSelection(GGadget *g, GEvent *e) {
913 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
914 0 : struct groupdlg *grp = GDrawGetUserData(GGadgetGetWindow(g));
915 0 : SplineFont *sf = grp->fv->b.sf;
916 0 : FontView *fv = grp->fv;
917 : unichar_t *vals, *pt;
918 : int i, len, max, gid, k;
919 : SplineChar *sc, dummy;
920 : char buffer[20];
921 :
922 0 : if ( GGadgetIsChecked(grp->idname) ) {
923 0 : for ( i=len=max=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i]) {
924 0 : gid = fv->b.map->map[i];
925 0 : if ( gid!=-1 && sf->glyphs[gid]!=NULL )
926 0 : sc = sf->glyphs[gid];
927 : else
928 0 : sc = SCBuildDummy(&dummy,sf,fv->b.map,i);
929 0 : len += strlen(sc->name)+1;
930 0 : if ( fv->b.selected[i]>max ) max = fv->b.selected[i];
931 : }
932 0 : pt = vals = malloc((len+1)*sizeof(unichar_t));
933 0 : *pt = '\0';
934 0 : for ( i=len=max=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i]) {
935 0 : gid = fv->b.map->map[i];
936 0 : if ( gid!=-1 && sf->glyphs[gid]!=NULL )
937 0 : sc = sf->glyphs[gid];
938 : else
939 0 : sc = SCBuildDummy(&dummy,sf,fv->b.map,i);
940 0 : uc_strcpy(pt,sc->name);
941 0 : pt += u_strlen(pt);
942 0 : *pt++ = ' ';
943 : }
944 0 : if ( pt>vals ) pt[-1]='\0';
945 : } else {
946 0 : vals = NULL;
947 0 : for ( k=0; k<2; ++k ) {
948 0 : int last=-2, start=-2;
949 0 : len = 0;
950 0 : for ( i=len=max=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i]) {
951 0 : gid = fv->b.map->map[i];
952 0 : if ( gid!=-1 && sf->glyphs[gid]!=NULL )
953 0 : sc = sf->glyphs[gid];
954 : else
955 0 : sc = SCBuildDummy(&dummy,sf,fv->b.map,i);
956 0 : if ( sc->unicodeenc==-1 )
957 0 : continue;
958 0 : if ( sc->unicodeenc==last+1 )
959 0 : last = sc->unicodeenc;
960 : else {
961 0 : if ( last!=-2 ) {
962 0 : if ( start!=last )
963 0 : sprintf( buffer, "U+%04X-U+%04X ", start, last );
964 : else
965 0 : sprintf( buffer, "U+%04X ", start );
966 0 : if ( vals!=NULL )
967 0 : uc_strcpy(vals+len,buffer);
968 0 : len += strlen(buffer);
969 : }
970 0 : start = last = sc->unicodeenc;
971 : }
972 : }
973 0 : if ( last!=-2 ) {
974 0 : if ( start!=last )
975 0 : sprintf( buffer, "U+%04X-U+%04X ", start, last );
976 : else
977 0 : sprintf( buffer, "U+%04X ", start );
978 0 : if ( vals!=NULL )
979 0 : uc_strcpy(vals+len,buffer);
980 0 : len += strlen(buffer);
981 : }
982 0 : if ( !k )
983 0 : vals = malloc((len+1)*sizeof(unichar_t));
984 0 : else if ( len!=0 )
985 0 : vals[len-1] = '\0';
986 : else
987 0 : *vals = '\0';
988 : }
989 : }
990 :
991 0 : GGadgetSetTitle(grp->glyphs,vals);
992 0 : free(vals);
993 : }
994 0 : return( true );
995 : }
996 :
997 0 : static int Group_AddColor(GGadget *g, GEvent *e) {
998 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
999 0 : struct groupdlg *grp = GDrawGetUserData(GGadgetGetWindow(g));
1000 0 : GTextInfo *ti = GGadgetGetListItemSelected(g);
1001 0 : int set=false;
1002 0 : Color xcol=0;
1003 :
1004 0 : if ( ti==NULL )
1005 : /* Can't happen */;
1006 0 : else if ( ti->userdata == (void *) COLOR_CHOOSE ) {
1007 : struct hslrgb col, font_cols[6];
1008 0 : memset(&col,0,sizeof(col));
1009 0 : col = GWidgetColor(_("Pick a color"),&col,SFFontCols(grp->fv->b.sf,font_cols));
1010 0 : if ( col.rgb ) {
1011 0 : xcol = (((int) rint(255.*col.r))<<16 ) |
1012 0 : (((int) rint(255.*col.g))<<8 ) |
1013 0 : (((int) rint(255.*col.b)) );
1014 0 : set = true;
1015 : }
1016 : } else {
1017 0 : xcol = (intpt) ti->userdata;
1018 0 : set = true;
1019 : }
1020 :
1021 0 : if ( set ) {
1022 : char buffer[40]; unichar_t ubuf[40];
1023 0 : sprintf(buffer," color=#%06x", xcol );
1024 0 : uc_strcpy(ubuf,buffer);
1025 0 : GTextFieldReplace(grp->glyphs,ubuf);
1026 0 : if ( grp->showchange==NULL )
1027 0 : GroupShowChange(grp);
1028 : }
1029 0 : GGadgetSelectOneListItem(g,0);
1030 : }
1031 0 : return( true );
1032 : }
1033 :
1034 0 : static int Group_NewSubGroup(GGadget *g, GEvent *e) {
1035 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1036 0 : struct groupdlg *grp = GDrawGetUserData(GGadgetGetWindow(g));
1037 : Group *new_grp;
1038 0 : if ( !GroupFinishOld(grp))
1039 0 : return( true );
1040 0 : GDrawRequestExpose(grp->v,NULL,false);
1041 0 : if ( grp->oldsel==NULL )
1042 0 : return( true );
1043 0 : if ( grp->oldsel->glyphs!=NULL && grp->oldsel->glyphs[0]!='\0' ) {
1044 0 : GGadgetSetEnabled(grp->newsub,false);
1045 0 : return( true );
1046 : }
1047 0 : grp->oldsel->kids = realloc(grp->oldsel->kids,(++grp->oldsel->kid_cnt)*sizeof(Group *));
1048 0 : grp->oldsel->kids[grp->oldsel->kid_cnt-1] = new_grp = chunkalloc(sizeof(Group));
1049 0 : new_grp->parent = grp->oldsel;
1050 0 : new_grp->unique = grp->oldsel->unique;
1051 0 : new_grp->name = copy(_("UntitledGroup"));
1052 0 : grp->oldsel->selected = false;
1053 0 : grp->oldsel->open = true;
1054 0 : new_grp->selected = true;
1055 0 : GroupSBSizes(grp);
1056 0 : GroupSelected(grp);
1057 0 : GDrawRequestExpose(grp->v,NULL,false);
1058 : }
1059 0 : return( true );
1060 : }
1061 :
1062 0 : static int Group_Delete(GGadget *g, GEvent *e) {
1063 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1064 0 : struct groupdlg *grp = GDrawGetUserData(GGadgetGetWindow(g));
1065 : Group *parent;
1066 : int pos, i;
1067 0 : if ( grp->oldsel==NULL || grp->oldsel->parent==NULL )
1068 0 : return( true );
1069 0 : parent = grp->oldsel->parent;
1070 0 : pos = GroupPosInParent(grp->oldsel);
1071 0 : if ( pos==-1 )
1072 0 : return( true );
1073 0 : for ( i=pos; i<parent->kid_cnt-1; ++i )
1074 0 : parent->kids[i] = parent->kids[i+1];
1075 0 : --parent->kid_cnt;
1076 0 : GroupFree(grp->oldsel);
1077 0 : grp->oldsel = NULL;
1078 0 : GroupSBSizes(grp);
1079 0 : GroupSelected(grp);
1080 0 : GDrawRequestExpose(grp->v,NULL,false);
1081 : }
1082 0 : return( true );
1083 : }
1084 :
1085 0 : static int displaygrp_e_h(GWindow gw, GEvent *event) {
1086 0 : struct groupdlg *grp = (struct groupdlg *) GDrawGetUserData(gw);
1087 :
1088 0 : if (( event->type==et_mouseup || event->type==et_mousedown ) &&
1089 0 : (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
1090 0 : return( GGadgetDispatchEvent(grp->vsb,event));
1091 : }
1092 :
1093 0 : if ( grp==NULL )
1094 0 : return( true );
1095 :
1096 0 : switch ( event->type ) {
1097 : case et_expose:
1098 0 : break;
1099 : case et_char:
1100 0 : return( GroupChar(grp,event));
1101 : break;
1102 : case et_timer:
1103 0 : GroupShowChange(grp);
1104 0 : break;
1105 : case et_resize:
1106 0 : if ( event->u.resize.sized )
1107 0 : GroupResize(grp,event);
1108 0 : break;
1109 : case et_controlevent:
1110 0 : switch ( event->u.control.subtype ) {
1111 : case et_scrollbarchange:
1112 0 : if ( event->u.control.g == grp->vsb )
1113 0 : GroupScroll(grp,&event->u.control.u.sb);
1114 : else
1115 0 : GroupHScroll(grp,&event->u.control.u.sb);
1116 0 : break;
1117 : case et_buttonactivate:
1118 0 : grp->done = true;
1119 0 : grp->oked = event->u.control.g == grp->ok;
1120 0 : break;
1121 : }
1122 0 : break;
1123 : case et_close:
1124 0 : grp->done = true;
1125 0 : break;
1126 : case et_destroy:
1127 0 : if ( grp->newsub!=NULL )
1128 0 : free(grp);
1129 0 : return( true );
1130 : }
1131 0 : if ( grp->done && grp->newsub!=NULL ) {
1132 0 : if ( grp->oked ) {
1133 0 : if ( !GroupFinishOld(grp)) {
1134 0 : grp->done = grp->oked = false;
1135 0 : return( true );
1136 : }
1137 0 : GroupFree(group_root);
1138 0 : if ( grp->root->kid_cnt==0 && grp->root->glyphs==NULL ) {
1139 0 : group_root = NULL;
1140 0 : GroupFree(grp->root);
1141 : } else
1142 0 : group_root = grp->root;
1143 0 : SaveGroupList();
1144 : } else
1145 0 : GroupFree(grp->root);
1146 0 : GDrawDestroyWindow(grp->gw);
1147 : }
1148 0 : return( true );
1149 : }
1150 :
1151 0 : void DefineGroups(FontView *fv) {
1152 : struct groupdlg *grp;
1153 : GRect pos;
1154 : GWindowAttrs wattrs;
1155 : GGadgetCreateData gcd[20];
1156 : GTextInfo label[19];
1157 : int h, k,kk;
1158 :
1159 0 : grp = calloc(1,sizeof(*grp));
1160 0 : grp->fv = fv;
1161 0 : grp->select_many = grp->select_kids_too = false;
1162 0 : grp->select_callback = GroupSelected;
1163 :
1164 0 : if ( group_root==NULL ) {
1165 0 : grp->root = chunkalloc(sizeof(Group));
1166 0 : grp->root->name = copy(_("Groups"));
1167 : } else
1168 0 : grp->root = GroupCopy(group_root);
1169 :
1170 0 : memset(&wattrs,0,sizeof(wattrs));
1171 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1172 0 : wattrs.event_masks = ~(1<<et_charup);
1173 0 : wattrs.is_dlg = true;
1174 0 : wattrs.restrict_input_to_me = false;
1175 0 : wattrs.undercursor = 1;
1176 0 : wattrs.cursor = ct_pointer;
1177 0 : wattrs.utf8_window_title = _("Define Groups");
1178 0 : pos.x = pos.y = 0;
1179 0 : pos.width =GDrawPointsToPixels(NULL,GGadgetScale(200));
1180 0 : pos.height = h = GDrawPointsToPixels(NULL,482);
1181 0 : grp->gw = GDrawCreateTopWindow(NULL,&pos,displaygrp_e_h,grp,&wattrs);
1182 :
1183 0 : grp->bmargin = GDrawPointsToPixels(NULL,248)+GDrawPointsToPixels(grp->gw,_GScrollBar_Width);
1184 :
1185 0 : GroupWCreate(grp,&pos);
1186 :
1187 0 : memset(&label,0,sizeof(label));
1188 0 : memset(&gcd,0,sizeof(gcd));
1189 :
1190 0 : k = 0;
1191 :
1192 0 : gcd[k].gd.pos.x = 20;
1193 0 : gcd[k].gd.pos.y = GDrawPixelsToPoints(NULL,h-grp->bmargin)+12;
1194 0 : gcd[k].gd.flags = gg_visible;
1195 0 : label[k].text = (unichar_t *) _("New Sub-Group");
1196 0 : label[k].text_is_1byte = true;
1197 0 : gcd[k].gd.label = &label[k];
1198 0 : gcd[k].gd.handle_controlevent = Group_NewSubGroup;
1199 0 : gcd[k++].creator = GButtonCreate;
1200 :
1201 0 : gcd[k].gd.pos.width = -1;
1202 0 : gcd[k].gd.pos.x = GDrawPixelsToPoints(NULL,(pos.width-30-GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor)));
1203 0 : gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
1204 0 : gcd[k].gd.flags = gg_visible;
1205 0 : label[k].text = (unichar_t *) _("_Delete");
1206 0 : label[k].text_is_1byte = true;
1207 0 : label[k].text_in_resource = true;
1208 0 : gcd[k].gd.label = &label[k];
1209 0 : gcd[k].gd.handle_controlevent = Group_Delete;
1210 0 : gcd[k++].creator = GButtonCreate;
1211 :
1212 0 : gcd[k].gd.pos.width = GDrawPixelsToPoints(NULL,pos.width)-20;
1213 0 : gcd[k].gd.pos.x = 10;
1214 0 : gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+26;
1215 0 : gcd[k].gd.flags = gg_visible | gg_enabled;
1216 0 : gcd[k++].creator = GLineCreate;
1217 :
1218 0 : gcd[k].gd.pos.x = 5;
1219 0 : gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+8;
1220 0 : gcd[k].gd.flags = gg_visible;
1221 0 : label[k].text = (unichar_t *) _("Group Name:");
1222 0 : label[k].text_is_1byte = true;
1223 0 : gcd[k].gd.label = &label[k];
1224 0 : gcd[k++].creator = GLabelCreate;
1225 :
1226 0 : gcd[k].gd.pos.x = 80; gcd[k].gd.pos.width = 115;
1227 0 : gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-3;
1228 0 : gcd[k].gd.flags = gg_visible;
1229 0 : gcd[k++].creator = GTextFieldCreate;
1230 :
1231 0 : gcd[k].gd.pos.x = 5;
1232 0 : gcd[k].gd.pos.y = gcd[k-2].gd.pos.y+16;
1233 0 : gcd[k].gd.flags = gg_visible;
1234 0 : label[k].text = (unichar_t *) _("Glyphs:");
1235 0 : label[k].text_is_1byte = true;
1236 0 : gcd[k].gd.label = &label[k];
1237 0 : gcd[k++].creator = GLabelCreate;
1238 :
1239 0 : gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14;
1240 0 : gcd[k].gd.pos.width = GDrawPixelsToPoints(NULL,pos.width)-10; gcd[k].gd.pos.height = 4*13+4;
1241 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_textarea_wrap;
1242 0 : gcd[k].gd.handle_controlevent = Group_GlyphListChanged;
1243 0 : gcd[k++].creator = GTextAreaCreate;
1244 :
1245 0 : gcd[k].gd.pos.x = 5;
1246 0 : gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+gcd[k-1].gd.pos.height+5;
1247 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
1248 0 : label[k].text = (unichar_t *) _("Identify by");
1249 0 : label[k].text_is_1byte = true;
1250 0 : gcd[k].gd.label = &label[k];
1251 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Glyphs may be either identified by name or by unicode code point.\nGenerally you control this by what you type in.\nTyping \"A\" would identify a glyph by name.\nTyping \"U+0041\" identifies a glyph by code point.\nWhen loading glyphs from the selection you must specify which format is desired.");
1252 0 : gcd[k++].creator = GLabelCreate;
1253 :
1254 0 : gcd[k].gd.pos.x = 90; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-2;
1255 0 : label[k].text = (unichar_t *) _("Name");
1256 0 : label[k].text_is_1byte = true;
1257 0 : gcd[k].gd.label = &label[k];
1258 0 : gcd[k].gd.flags = (gg_visible | gg_enabled | gg_cb_on | gg_utf8_popup);
1259 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Glyphs may be either identified by name or by unicode code point.\nGenerally you control this by what you type in.\nTyping \"A\" would identify a glyph by name.\nTyping \"U+0041\" identifies a glyph by code point.\nWhen loading glyphs from the selection you must specify which format is desired.");
1260 0 : gcd[k++].creator = GRadioCreate;
1261 :
1262 0 : gcd[k].gd.pos.x = 140; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
1263 0 : label[k].text = (unichar_t *) _("Unicode");
1264 0 : label[k].text_is_1byte = true;
1265 0 : gcd[k].gd.label = &label[k];
1266 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_utf8_popup;
1267 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Glyphs may be either identified by name or by unicode code point.\nGenerally you control this by what you type in.\nTyping \"A\" would identify a glyph by name.\nTyping \"U+0041\" identifies a glyph by code point.\nWhen loading glyphs from the selection you must specify which format is desired.");
1268 0 : gcd[k++].creator = GRadioCreate;
1269 :
1270 0 : label[k].text = (unichar_t *) _("Set From Font");
1271 0 : label[k].text_is_1byte = true;
1272 0 : gcd[k].gd.label = &label[k];
1273 0 : gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+18;
1274 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Set this glyph list to be the glyphs selected in the fontview");
1275 0 : gcd[k].gd.flags = gg_visible | gg_utf8_popup;
1276 0 : gcd[k].gd.handle_controlevent = Group_FromSelection;
1277 0 : gcd[k++].creator = GButtonCreate;
1278 :
1279 0 : label[k].text = (unichar_t *) _("Select In Font");
1280 0 : label[k].text_is_1byte = true;
1281 0 : gcd[k].gd.label = &label[k];
1282 0 : gcd[k].gd.pos.x = 110; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y;
1283 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Set the fontview's selection to be the glyphs named here");
1284 0 : gcd[k].gd.flags = gg_visible | gg_utf8_popup;
1285 0 : gcd[k].gd.handle_controlevent = Group_ToSelection;
1286 0 : gcd[k++].creator = GButtonCreate;
1287 :
1288 0 : gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+26;
1289 0 : label[k].text = (unichar_t *) _("No Glyph Duplicates");
1290 0 : label[k].text_is_1byte = true;
1291 0 : gcd[k].gd.label = &label[k];
1292 0 : gcd[k].gd.flags = gg_visible | gg_utf8_popup;
1293 0 : gcd[k].gd.popup_msg = (unichar_t *) _("Glyph names (or unicode code points) may occur at most once in this group and any of its sub-groups");
1294 0 : gcd[k++].creator = GCheckBoxCreate;
1295 :
1296 0 : for ( kk=0; kk<3; ++kk )
1297 0 : std_colors[kk].text = (unichar_t *) S_((char *) std_colors[kk].text);
1298 0 : std_colors[1].image = GGadgetImageCache("colorwheel.png");
1299 0 : std_colors[0].selected = true;
1300 0 : gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+15;
1301 0 : gcd[k].gd.label = &std_colors[0];
1302 0 : gcd[k].gd.u.list = std_colors;
1303 0 : gcd[k].gd.handle_controlevent = Group_AddColor;
1304 0 : gcd[k].gd.flags = gg_visible | gg_utf8_popup;
1305 0 : gcd[k++].creator = GListButtonCreate;
1306 :
1307 0 : gcd[k].gd.pos.width = GDrawPixelsToPoints(NULL,pos.width)-20;
1308 0 : gcd[k].gd.pos.x = 10;
1309 0 : gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+28;
1310 0 : gcd[k].gd.flags = gg_visible | gg_enabled;
1311 0 : gcd[k++].creator = GLineCreate;
1312 :
1313 0 : gcd[k].gd.pos.width = -1;
1314 0 : gcd[k].gd.pos.x = 30;
1315 0 : gcd[k].gd.pos.y = h-GDrawPointsToPixels(NULL,32);
1316 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default | gg_pos_in_pixels;
1317 0 : label[k].text = (unichar_t *) _("_OK");
1318 0 : label[k].text_is_1byte = true;
1319 0 : label[k].text_in_resource = true;
1320 0 : gcd[k].gd.label = &label[k];
1321 0 : gcd[k++].creator = GButtonCreate;
1322 :
1323 0 : gcd[k].gd.pos.width = -1;
1324 0 : gcd[k].gd.pos.x = (pos.width-30-GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor));
1325 0 : gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
1326 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel | gg_pos_in_pixels;
1327 0 : label[k].text = (unichar_t *) _("_Cancel");
1328 0 : label[k].text_is_1byte = true;
1329 0 : label[k].text_in_resource = true;
1330 0 : gcd[k].gd.label = &label[k];
1331 0 : gcd[k++].creator = GButtonCreate;
1332 :
1333 0 : GGadgetsCreate(grp->gw,gcd);
1334 0 : grp->newsub = gcd[0].ret;
1335 0 : grp->delete = gcd[1].ret;
1336 0 : grp->line1 = gcd[2].ret;
1337 0 : grp->gpnamelab = gcd[3].ret;
1338 0 : grp->gpname = gcd[4].ret;
1339 0 : grp->glyphslab = gcd[5].ret;
1340 0 : grp->glyphs = gcd[6].ret;
1341 0 : grp->idlab = gcd[7].ret;
1342 0 : grp->idname = gcd[8].ret;
1343 0 : grp->iduni = gcd[9].ret;
1344 0 : grp->set = gcd[10].ret;
1345 0 : grp->select = gcd[11].ret;
1346 0 : grp->unique = gcd[12].ret;
1347 0 : grp->colour = gcd[13].ret;
1348 0 : grp->line2 = gcd[14].ret;
1349 0 : grp->ok = gcd[15].ret;
1350 0 : grp->cancel = gcd[16].ret;
1351 :
1352 0 : GroupSBSizes(grp);
1353 0 : GroupResize(grp,NULL);
1354 :
1355 0 : GDrawSetVisible(grp->gw,true);
1356 0 : }
1357 :
1358 0 : static void MapEncAddGid(EncMap *map,SplineFont *sf, int compacted,
1359 : int gid, int uni, char *name) {
1360 :
1361 0 : if ( compacted && gid==-1 )
1362 0 : return;
1363 :
1364 0 : if ( gid!=-1 && map->backmap[gid]==-1 )
1365 0 : map->backmap[gid] = map->enccount;
1366 0 : if ( map->enccount>=map->encmax )
1367 0 : map->map = realloc(map->map,(map->encmax+=100)*sizeof(int));
1368 0 : map->map[map->enccount++] = gid;
1369 0 : if ( !compacted ) {
1370 0 : Encoding *enc = map->enc;
1371 0 : if ( enc->char_cnt>=enc->char_max ) {
1372 0 : enc->unicode = realloc(enc->unicode,(enc->char_max+=256)*sizeof(int));
1373 0 : enc->psnames = realloc(enc->psnames,enc->char_max*sizeof(char *));
1374 : }
1375 0 : if ( uni==-1 && name!=NULL ) {
1376 0 : if ( gid!=-1 && sf->glyphs[gid]!=NULL )
1377 0 : uni = sf->glyphs[gid]->unicodeenc;
1378 : else
1379 0 : uni = UniFromName(name,ui_none,&custom);
1380 : }
1381 0 : enc->unicode[enc->char_cnt] = uni;
1382 0 : enc->psnames[enc->char_cnt++] = copy( name );
1383 : }
1384 : }
1385 :
1386 0 : static void MapAddGroupGlyph(EncMap *map,SplineFont *sf,char *name, int compacted) {
1387 : int gid;
1388 :
1389 0 : if ( (name[0]=='u' || name[0]=='U') && name[1]=='+' && ishexdigit(name[2])) {
1390 : char *end;
1391 0 : int val = strtol(name+2,&end,16), val2=val;
1392 0 : if ( *end=='-' ) {
1393 0 : if ( (end[1]=='u' || end[1]=='U') && end[2]=='+' )
1394 0 : end+=2;
1395 0 : val2 = strtol(end+1,NULL,16);
1396 : }
1397 0 : for ( ; val<=val2; ++val ) {
1398 0 : gid = SFFindExistingSlot(sf,val,NULL);
1399 0 : MapEncAddGid(map,sf,compacted,gid,val,NULL);
1400 : }
1401 0 : } else if ( strncasecmp(name,"color=#",strlen("color=#"))==0 ) {
1402 0 : Color col = strtoul(name+strlen("color=#"),NULL,16);
1403 : int gid; SplineChar *sc;
1404 :
1405 0 : for ( gid=0; gid<sf->glyphcnt; ++gid )
1406 0 : if ( (sc = sf->glyphs[gid])!=NULL &&
1407 0 : sc->color == col )
1408 0 : MapEncAddGid(map,sf,compacted,gid,sc->unicodeenc,NULL);
1409 : } else {
1410 0 : gid = SFFindExistingSlot(sf,-1,name);
1411 0 : MapEncAddGid(map,sf,compacted,gid,-1,name);
1412 : }
1413 0 : }
1414 :
1415 0 : static int MapAddSelectedGroups(EncMap *map,SplineFont *sf,Group *group, int compacted) {
1416 0 : int i, cnt=0;
1417 : char *start, *pt;
1418 : int ch;
1419 :
1420 0 : if ( group->glyphs==NULL ) {
1421 0 : for ( i=0; i<group->kid_cnt; ++i )
1422 0 : cnt += MapAddSelectedGroups(map,sf,group->kids[i], compacted);
1423 0 : } else if ( group->selected ) {
1424 0 : for ( pt=group->glyphs; *pt!='\0'; ) {
1425 0 : while ( *pt==' ' ) ++pt;
1426 0 : start = pt;
1427 0 : while ( *pt!=' ' && *pt!='\0' ) ++pt;
1428 0 : ch = *pt; *pt='\0';
1429 0 : if ( *start!='\0' )
1430 0 : MapAddGroupGlyph(map,sf,start, compacted);
1431 0 : *pt=ch;
1432 : }
1433 0 : ++cnt;
1434 : }
1435 0 : return( cnt );
1436 : }
1437 :
1438 0 : static int GroupSelCnt(Group *group, Group **first, Group **second) {
1439 0 : int cnt = 0, i;
1440 :
1441 0 : if ( group->glyphs==NULL ) {
1442 0 : for ( i=0; i<group->kid_cnt; ++i )
1443 0 : cnt += GroupSelCnt(group->kids[i],first,second);
1444 0 : } else if ( group->selected ) {
1445 0 : if ( *first==NULL )
1446 0 : *first = group;
1447 0 : else if ( *second==NULL )
1448 0 : *second = group;
1449 0 : ++cnt;
1450 : }
1451 0 : return( cnt );
1452 : }
1453 :
1454 0 : static char *EncNameFromGroups(Group *group) {
1455 0 : Group *first = NULL, *second = NULL;
1456 0 : int cnt = GroupSelCnt(group,&first,&second);
1457 0 : char *prefix = P_("Group","Groups",cnt);
1458 : char *ret;
1459 :
1460 0 : switch ( cnt ) {
1461 : case 0:
1462 0 : return( copy( _("No Groups")) );
1463 : case 1:
1464 0 : ret = malloc(strlen(prefix) + strlen(first->name) + 3 );
1465 0 : sprintf( ret, "%s: %s", prefix, first->name);
1466 0 : break;
1467 : case 2:
1468 0 : ret = malloc(strlen(prefix) + strlen(first->name) + strlen(second->name) + 5 );
1469 0 : sprintf( ret, "%s: %s, %s", prefix, first->name, second->name );
1470 0 : break;
1471 : default:
1472 0 : ret = malloc(strlen(prefix) + strlen(first->name) + strlen(second->name) + 9 );
1473 0 : sprintf( ret, "%s: %s, %s ...", prefix, first->name, second->name );
1474 0 : break;
1475 : }
1476 0 : return( ret );
1477 : }
1478 :
1479 0 : static void EncodeToGroups(FontView *fv,Group *group, int compacted) {
1480 0 : SplineFont *sf = fv->b.sf;
1481 : EncMap *map;
1482 0 : if ( compacted )
1483 0 : map = EncMapNew(0,sf->glyphcnt,&custom);
1484 : else {
1485 0 : Encoding *enc = calloc(1,sizeof(Encoding));
1486 0 : enc->enc_name = EncNameFromGroups(group);
1487 0 : enc->is_temporary = true;
1488 0 : enc->char_max = 256;
1489 0 : enc->unicode = malloc(256*sizeof(int32));
1490 0 : enc->psnames = malloc(256*sizeof(char *));
1491 0 : map = EncMapNew(0,sf->glyphcnt,enc);
1492 : }
1493 :
1494 0 : if ( MapAddSelectedGroups(map,sf,group,compacted)==0 ) {
1495 0 : ff_post_error(_("Nothing Selected"),_("Nothing Selected"));
1496 0 : EncMapFree(map);
1497 0 : } else if ( map->enccount==0 ) {
1498 0 : ff_post_error(_("Nothing Selected"),_("None of the glyphs in the current font match any names or code points in the selected groups"));
1499 0 : EncMapFree(map);
1500 : } else {
1501 0 : fv->b.selected = realloc(fv->b.selected,map->enccount);
1502 0 : memset(fv->b.selected,0,map->enccount);
1503 0 : EncMapFree(fv->b.map);
1504 0 : fv->b.map = map;
1505 0 : FVSetTitle((FontViewBase *) fv);
1506 0 : FontViewReformatOne((FontViewBase *) fv);
1507 : }
1508 0 : }
1509 :
1510 0 : void DisplayGroups(FontView *fv) {
1511 : struct groupdlg grp;
1512 : GRect pos;
1513 : GWindowAttrs wattrs;
1514 : GGadgetCreateData gcd[6];
1515 : GTextInfo label[5];
1516 : int h;
1517 :
1518 0 : memset( &grp,0,sizeof(grp));
1519 0 : grp.fv = fv;
1520 0 : grp.select_many = grp.select_kids_too = true;
1521 0 : grp.root = group_root;
1522 :
1523 0 : if ( grp.root==NULL ) {
1524 0 : grp.root = chunkalloc(sizeof(Group));
1525 0 : grp.root->name = copy(_("Groups"));
1526 : }
1527 :
1528 0 : memset(&wattrs,0,sizeof(wattrs));
1529 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1530 0 : wattrs.event_masks = ~(1<<et_charup);
1531 0 : wattrs.is_dlg = true;
1532 0 : wattrs.restrict_input_to_me = 1;
1533 0 : wattrs.undercursor = 1;
1534 0 : wattrs.cursor = ct_pointer;
1535 0 : wattrs.utf8_window_title = _("Display By Groups");
1536 0 : pos.x = pos.y = 0;
1537 0 : pos.width =GDrawPointsToPixels(NULL,GGadgetScale(200));
1538 0 : pos.height = h = GDrawPointsToPixels(NULL,317);
1539 0 : grp.gw = GDrawCreateTopWindow(NULL,&pos,displaygrp_e_h,&grp,&wattrs);
1540 :
1541 0 : grp.bmargin = GDrawPointsToPixels(NULL,50)+GDrawPointsToPixels(grp.gw,_GScrollBar_Width);
1542 :
1543 0 : GroupWCreate(&grp,&pos);
1544 :
1545 0 : memset(&label,0,sizeof(label));
1546 0 : memset(&gcd,0,sizeof(gcd));
1547 :
1548 0 : gcd[0].gd.pos.width = -1;
1549 0 : gcd[0].gd.pos.x = 30;
1550 0 : gcd[0].gd.pos.y = h-GDrawPointsToPixels(NULL,30);
1551 0 : gcd[0].gd.flags = gg_visible | gg_enabled | gg_but_default | gg_pos_in_pixels;
1552 0 : label[0].text = (unichar_t *) _("_OK");
1553 0 : label[0].text_is_1byte = true;
1554 0 : label[0].text_in_resource = true;
1555 0 : gcd[0].gd.label = &label[0];
1556 0 : gcd[0].creator = GButtonCreate;
1557 :
1558 0 : gcd[1].gd.pos.width = -1;
1559 0 : gcd[1].gd.pos.x = (pos.width-30-GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor));
1560 0 : gcd[1].gd.pos.y = gcd[0].gd.pos.y+3;
1561 0 : gcd[1].gd.flags = gg_visible | gg_enabled | gg_but_cancel | gg_pos_in_pixels;
1562 0 : label[1].text = (unichar_t *) _("_Cancel");
1563 0 : label[1].text_is_1byte = true;
1564 0 : label[1].text_in_resource = true;
1565 0 : gcd[1].gd.label = &label[1];
1566 0 : gcd[1].creator = GButtonCreate;
1567 :
1568 0 : gcd[2].gd.pos.width = -1;
1569 0 : gcd[2].gd.pos.x = 10;
1570 0 : gcd[2].gd.pos.y = gcd[0].gd.pos.y-GDrawPointsToPixels(NULL,17);
1571 0 : gcd[2].gd.flags = gg_visible | gg_enabled | gg_cb_on | gg_pos_in_pixels;
1572 0 : label[2].text = (unichar_t *) _("Compacted");
1573 0 : label[2].text_is_1byte = true;
1574 0 : label[2].text_in_resource = true;
1575 0 : gcd[2].gd.label = &label[2];
1576 0 : gcd[2].creator = GCheckBoxCreate;
1577 :
1578 0 : GGadgetsCreate(grp.gw,gcd);
1579 0 : grp.ok = gcd[0].ret;
1580 0 : grp.cancel = gcd[1].ret;
1581 0 : grp.compact = gcd[2].ret;
1582 :
1583 0 : GroupSBSizes(&grp);
1584 :
1585 0 : GDrawSetVisible(grp.gw,true);
1586 :
1587 0 : while ( !grp.done )
1588 0 : GDrawProcessOneEvent(NULL);
1589 0 : GDrawSetUserData(grp.gw,NULL);
1590 0 : if ( grp.oked )
1591 0 : EncodeToGroups(fv,grp.root, GGadgetIsChecked(gcd[2].ret));
1592 0 : if ( grp.root!=group_root )
1593 0 : GroupFree(grp.root);
1594 0 : GDrawDestroyWindow(grp.gw);
1595 0 : }
|