1 /* Copyright (C) 2000-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
28 #include <fontforge-config.h>
29
30 #include "cvundoes.h"
31 #include "dlist.h"
32 #include "fontforgeui.h"
33 #include "gkeysym.h"
34 #include "lookups.h"
35 #include "parsettf.h"
36 #include "spiro.h"
37 #include "splineorder2.h"
38 #include "splineutil.h"
39 #include "splineutil2.h"
40 #include "tottfgpos.h"
41 #include "ustring.h"
42 #include "utype.h"
43
44 #include <math.h>
45
46 #define RAD2DEG (180/FF_PI)
47 #define TCnt 3
48
49 typedef struct gidata {
50 struct dlistnode ln;
51 CharView *cv;
52 SplineChar *sc;
53 RefChar *rf;
54 ImageList *img;
55 AnchorPoint *ap;
56 SplinePoint *cursp;
57 spiro_cp *curcp;
58 SplinePointList *curspl;
59 SplinePointList *oldstate;
60 AnchorPoint *oldaps;
61 GWindow gw;
62 int done, first, changed;
63 int prevchanged, nextchanged;
64 int normal_start, normal_end;
65 int interp_start, interp_end;
66 GGadgetCreateData* gcd;
67 GGadget *group1ret, *group2ret;
68 } GIData;
69
70 #define CID_BaseX 2001
71 #define CID_BaseY 2002
72 #define CID_NextXOff 2003
73 #define CID_NextYOff 2004
74 #define CID_NextPos 2005
75 #define CID_PrevXOff 2006
76 #define CID_PrevYOff 2007
77 #define CID_PrevPos 2008
78 #define CID_NextDef 2009
79 #define CID_PrevDef 2010
80 #define CID_NextR 2014
81 #define CID_NextTheta 2015
82 #define CID_PrevR 2016
83 #define CID_PrevTheta 2017
84 #define CID_HintMask 2020
85 #define CID_ActiveHints 2030
86 #define CID_NextX 2031
87 #define CID_NextY 2032
88 #define CID_PrevX 2033
89 #define CID_PrevY 2034
90 #define CID_BasePos 2035
91 #define CID_Normal 2036
92 #define CID_Interpolated 2037
93 #define CID_NeverInterpolate 2038
94 /* Also use CID_Next, CID_Prev below */
95 #define CID_NextC 2041
96 #define CID_PrevC 2042
97 #define CID_PrevCurvature 2043
98 #define CID_NextCurvature 2044
99 #define CID_DeltaCurvature 2045
100 #define CID_Curve 2050 /* Next four must be in order */
101 #define CID_Corner 2051
102 #define CID_Tangent 2052
103 #define CID_HVCurve 2053
104 #define CID_SpiroLeft 2054
105 #define CID_SpiroRight 2055
106 #define CID_TabSet 2100
107
108 #define CID_X 3001
109 #define CID_Y 3002
110 #define CID_NameList 3003
111 #define CID_Mark 3004
112 #define CID_BaseChar 3005
113 #define CID_BaseLig 3006
114 #define CID_BaseMark 3007
115 #define CID_CursEntry 3008
116 #define CID_CursExit 3009
117 #define CID_LigIndex 3010
118 #define CID_Next 3011
119 #define CID_Prev 3012
120 #define CID_Delete 3013
121 #define CID_New 3014
122 #define CID_MatchPt 3015
123
124 #define RI_Width 225
125 #define RI_Height 246
126 #define CID_Match_Pt_Base 1010
127 #define CID_Match_Pt_Ref 1011
128
129 #define II_Width 130
130 #define II_Height 70
131
132 #define PI_Width 228
133 #define PI_Height 434
134
135 #define AI_Width 160
136 #define AI_Height 258
137
GI_Cancel(GGadget * g,GEvent * e)138 static int GI_Cancel(GGadget *g, GEvent *e) {
139 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
140 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
141 ci->done = true;
142 }
143 return( true );
144 }
145
GI_TransChange(GGadget * g,GEvent * e)146 static int GI_TransChange(GGadget *g, GEvent *e) {
147 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
148 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
149 ci->changed = true;
150 }
151 return( true );
152 }
153
GI_MatchPtChange(GGadget * g,GEvent * e)154 static int GI_MatchPtChange(GGadget *g, GEvent *e) {
155 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
156 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
157 const unichar_t *t1 = _GGadgetGetTitle(GWidgetGetControl(ci->gw,CID_Match_Pt_Base));
158 const unichar_t *t2 = _GGadgetGetTitle(GWidgetGetControl(ci->gw,CID_Match_Pt_Ref));
159 while ( *t1==' ' ) ++t1;
160 while ( *t2==' ' ) ++t2;
161 GGadgetSetEnabled(GWidgetGetControl(ci->gw,1004),*t1=='\0' && *t2=='\0' );
162 GGadgetSetEnabled(GWidgetGetControl(ci->gw,1005),*t1=='\0' && *t2=='\0' );
163 if ( isdigit(*t1) && isdigit(*t2)) {
164 BasePoint inbase, inref;
165 int basept, refpt;
166 basept = u_strtol(t1,NULL,10);
167 refpt = u_strtol(t2,NULL,10);
168 if ( ttfFindPointInSC(ci->cv->b.sc,CVLayer((CharViewBase *) ci->cv),basept,&inbase,ci->rf)==-1 &&
169 ttfFindPointInSC(ci->rf->sc,CVLayer((CharViewBase *) ci->cv),refpt,&inref,NULL)==-1 ) {
170 char buffer[40];
171 sprintf(buffer,"%g",(double) (inbase.x-inref.x));
172 GGadgetSetTitle8(GWidgetGetControl(ci->gw,1004),buffer);
173 sprintf(buffer,"%g",(double) (inbase.y-inref.y));
174 GGadgetSetTitle8(GWidgetGetControl(ci->gw,1005),buffer);
175 }
176 }
177 }
178 return( true );
179 }
180
GI_ROK_Do(GIData * ci)181 static int GI_ROK_Do(GIData *ci) {
182 int errs=false,i;
183 real trans[6];
184 SplinePointList *spl, *new;
185 RefChar *ref = ci->rf, *subref;
186 int usemy = GGadgetIsChecked(GWidgetGetControl(ci->gw,6+1000));
187 int round = GGadgetIsChecked(GWidgetGetControl(ci->gw,7+1000));
188 int basept=-1, refpt=-1;
189 BasePoint inbase, inref;
190
191 for ( i=0; i<6; ++i ) {
192 trans[i] = GetReal8(ci->gw,1000+i,_("Transformation Matrix"),&errs);
193 if ( !errs &&
194 ((i<4 && (trans[i]>30 || trans[i]<-30)) ||
195 (i>=4 && (trans[i]>16000 || trans[i]<-16000))) ) {
196 /* Don't want the user to insert an enormous scale factor or */
197 /* it will move points outside the legal range. */
198 GTextFieldSelect(GWidgetGetControl(ci->gw,1000+i),0,-1);
199 ff_post_error(_("Value out of range"),_("Value out of range"));
200 errs = true;
201 }
202 if ( errs )
203 return( false );
204 }
205 if ( !ci->cv->b.sc->layers[ly_fore].order2 )
206 /* No point matching */;
207 else {
208 const unichar_t *txt;
209 txt = _GGadgetGetTitle(GWidgetGetControl(ci->gw,CID_Match_Pt_Base));
210 while ( isspace(*txt)) ++txt;
211 if ( *txt!='\0' )
212 basept = GetInt8(ci->gw,CID_Match_Pt_Base,_("_Base:"),&errs);
213 txt = _GGadgetGetTitle(GWidgetGetControl(ci->gw,CID_Match_Pt_Ref));
214 while ( isspace(*txt)) ++txt;
215 if ( *txt!='\0' )
216 refpt = GetInt8(ci->gw,CID_Match_Pt_Ref,_("Ref:"),&errs);
217 if ( errs )
218 return( false );
219 if ( (basept!=-1) ^ (refpt!=-1) ) {
220 ff_post_error(_("Bad Point Match"),_("Both points must be specified, or neither"));
221 }
222 if ( basept!=-1 ) {
223 if ( ttfFindPointInSC(ci->cv->b.sc,CVLayer((CharViewBase *) ci->cv),basept,&inbase,ci->rf)!=-1 ) {
224 ff_post_error(_("Bad Point Match"),_("Couldn't find base point"));
225 return( false );
226 } else if ( ttfFindPointInSC(ci->rf->sc,CVLayer((CharViewBase *) ci->cv),refpt,&inref,NULL)!=-1 ) {
227 ff_post_error(_("Bad Point Match"),_("Couldn't find point in reference"));
228 return( false );
229 }
230 /* Override user specified value */
231 trans[4] = inbase.x-inref.x;
232 trans[5] = inbase.y-inref.y;
233 }
234 }
235
236 for ( i=0; i<6 && ref->transform[i]==trans[i]; ++i );
237 if ( i==6 &&
238 usemy==ref->use_my_metrics &&
239 round==ref->round_translation_to_grid &&
240 (basept!=-1)==ref->point_match &&
241 (basept==-1 ||
242 (ref->match_pt_base==basept && ref->match_pt_ref==refpt))) {
243 ref->point_match_out_of_date = false;
244 return( true ); /* Didn't really change */
245 }
246
247 for ( i=0; i<6; ++i )
248 ref->transform[i] = trans[i];
249 SplinePointListsFree(ref->layers[0].splines);
250 ref->layers[0].splines = SplinePointListTransform(SplinePointListCopy(ref->sc->layers[ly_fore].splines),trans,tpt_AllPoints);
251 spl = NULL;
252 if ( ref->layers[0].splines!=NULL )
253 for ( spl = ref->layers[0].splines; spl->next!=NULL; spl = spl->next );
254 for ( subref = ref->sc->layers[ly_fore].refs; subref!=NULL; subref=subref->next ) {
255 new = SplinePointListTransform(SplinePointListCopy(subref->layers[0].splines),trans,tpt_AllPoints);
256 if ( spl==NULL )
257 ref->layers[0].splines = new;
258 else
259 spl->next = new;
260 if ( new!=NULL )
261 for ( spl = new; spl->next!=NULL; spl = spl->next );
262 }
263 ref->use_my_metrics = usemy;
264 ref->round_translation_to_grid = round;
265 ref->point_match = basept!=-1;
266 ref->match_pt_base = basept; ref->match_pt_ref = refpt;
267 ref->point_match_out_of_date = false;
268
269 SplineSetFindBounds(ref->layers[0].splines,&ref->bb);
270 CVCharChangedUpdate(&ci->cv->b);
271 return( true );
272 }
273
GI_ROK(GGadget * g,GEvent * e)274 static int GI_ROK(GGadget *g, GEvent *e) {
275 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
276 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
277 if ( GI_ROK_Do(ci))
278 ci->done = true;
279 }
280 return( true );
281 }
282
GI_Show(GGadget * g,GEvent * e)283 static int GI_Show(GGadget *g, GEvent *e) {
284 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
285 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
286 if ( ci->changed ) {
287 char *buts[4];
288 int ans;
289 buts[0] = _("C_hange");
290 buts[1] = _("_Retain");
291 buts[2] = _("_Cancel");
292 buts[3] = NULL;
293 ans = gwwv_ask(_("Transformation Matrix Changed"),(const char **)buts,0,2,_("You have changed the transformation matrix, do you wish to use the new version?"));
294 if ( ans==2 )
295 return( true );
296 else if ( ans==0 ) {
297 if ( !GI_ROK_Do(ci))
298 return( true );
299 }
300 }
301 ci->done = true;
302 CharViewCreate(ci->rf->sc,(FontView *) (ci->cv->b.fv),-1);
303 }
304 return( true );
305 }
306
gi_e_h(GWindow gw,GEvent * event)307 static int gi_e_h(GWindow gw, GEvent *event) {
308 if ( event->type==et_close ) {
309 GIData *ci = GDrawGetUserData(gw);
310 ci->done = true;
311 } else if ( event->type==et_char ) {
312 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
313 help("ui/dialogs/getinfo.html", NULL);
314 return( true );
315 }
316 return( false );
317 } else if ( event->type == et_map ) {
318 /* Above palettes */
319 GDrawRaise(gw);
320 }
321 return( true );
322 }
323
RefGetInfo(CharView * cv,RefChar * ref)324 static void RefGetInfo(CharView *cv, RefChar *ref) {
325 static GIData gi;
326 GRect pos;
327 GWindowAttrs wattrs;
328 GGadgetCreateData gcd[33], boxes[7];
329 GGadgetCreateData *varray[19], *hvarray[16], *harray1[6], *harray2[4],
330 *harray3[7], *hvarray2[4][6];
331 GTextInfo label[33];
332 char tbuf[6][40], bbbuf[4][40];
333 char basebuf[20], refbuf[20];
334 char namebuf[100];
335 char ubuf[40];
336 int i,j,l;
337
338 gi.cv = cv;
339 gi.sc = cv->b.sc;
340 gi.rf = ref;
341 gi.changed = false;
342 gi.done = false;
343
344 memset(&wattrs,0,sizeof(wattrs));
345 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
346 wattrs.event_masks = ~(1<<et_charup);
347 wattrs.restrict_input_to_me = 1;
348 wattrs.undercursor = 1;
349 wattrs.cursor = ct_pointer;
350 wattrs.utf8_window_title = _("Reference Info");
351 wattrs.is_dlg = true;
352 pos.x = pos.y = 0;
353 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,RI_Width));
354 pos.height = GDrawPointsToPixels(NULL,
355 ref->sc->unicodeenc!=-1?RI_Height+12:RI_Height);
356 gi.gw = GDrawCreateTopWindow(NULL,&pos,gi_e_h,&gi,&wattrs);
357
358 memset(&gcd,0,sizeof(gcd));
359 memset(&label,0,sizeof(label));
360 memset(&boxes,0,sizeof(boxes));
361
362 snprintf( namebuf, sizeof(namebuf),
363 _("Reference to character %1$.20s at %2$d"),
364 ref->sc->name, (int) cv->b.fv->map->backmap[ref->sc->orig_pos]);
365 label[0].text = (unichar_t *) namebuf;
366 label[0].text_is_1byte = true;
367 gcd[0].gd.label = &label[0];
368 gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5;
369 gcd[0].gd.flags = gg_enabled|gg_visible;
370 gcd[0].creator = GLabelCreate;
371 l = 0;
372 varray[l++] = &gcd[0];
373 j = 1;
374
375 if ( ref->sc->unicodeenc!=-1 ) {
376 sprintf( ubuf, " Unicode: U+%04x", ref->sc->unicodeenc );
377 label[1].text = (unichar_t *) ubuf;
378 label[1].text_is_1byte = true;
379 gcd[1].gd.label = &label[1];
380 gcd[1].gd.pos.x = 5; gcd[1].gd.pos.y = 17;
381 gcd[1].gd.flags = gg_enabled|gg_visible;
382 gcd[1].creator = GLabelCreate;
383 varray[l++] = &gcd[1];
384 j=2;
385 }
386
387 label[j].text = (unichar_t *) _("Transformed by:");
388 label[j].text_is_1byte = true;
389 gcd[j].gd.label = &label[j];
390 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+14;
391 gcd[j].gd.flags = gg_enabled|gg_visible;
392 gcd[j].gd.popup_msg = _("The transformation matrix specifies how the points in\nthe source glyph should be transformed before\nthey are drawn in the current glyph.\n x(new) = tm[1,1]*x + tm[2,1]*y + tm[3,1]\n y(new) = tm[1,2]*x + tm[2,2]*y + tm[3,2]");
393 gcd[j].creator = GLabelCreate;
394 varray[l++] = &gcd[j];
395 ++j;
396
397 for ( i=0; i<6; ++i ) {
398 if ( !(i&1) ) hvarray[5*(i/2)] = GCD_Glue;
399 sprintf(tbuf[i],"%g", (double) ref->transform[i]);
400 label[i+j].text = (unichar_t *) tbuf[i];
401 label[i+j].text_is_1byte = true;
402 gcd[i+j].gd.label = &label[i+j];
403 gcd[i+j].gd.pos.x = 20+((i&1)?85:0); gcd[i+j].gd.pos.width=75;
404 gcd[i+j].gd.pos.y = gcd[j-1].gd.pos.y+14+(i/2)*26;
405 gcd[i+j].gd.flags = gg_enabled|gg_visible;
406 gcd[i+j].gd.cid = i+1000;
407 gcd[i+j].gd.handle_controlevent = GI_TransChange;
408 gcd[i+j].creator = (i>=4 ? GNumericFieldCreate : GTextFieldCreate);
409 hvarray[5*(i/2)+1+(i&1)] = &gcd[i+j];
410 if ( (i&1) ) { hvarray[5*(i/2)+3] = GCD_Glue; hvarray[5*(i/2)+4] = NULL; }
411 }
412 if ( ref->point_match )
413 gcd[4+j].gd.flags = gcd[5+j].gd.flags = gg_visible;
414 hvarray[15] = NULL;
415
416 boxes[2].gd.flags = gg_enabled|gg_visible;
417 boxes[2].gd.u.boxelements = hvarray;
418 boxes[2].creator = GHVBoxCreate;
419 varray[l++] = &boxes[2];
420
421 label[6+j].text = (unichar_t *) _("_Use My Metrics");
422 label[6+j].text_in_resource = true;
423 label[6+j].text_is_1byte = true;
424 gcd[6+j].gd.label = &label[6+j];
425 gcd[6+j].gd.pos.x = 5; gcd[6+j].gd.pos.y = gcd[6+j-1].gd.pos.y+21;
426 gcd[6+j].gd.flags = gg_enabled|gg_visible| (ref->use_my_metrics?gg_cb_on:0);
427 gcd[i+j].gd.cid = 6+1000;
428 gcd[6+j].gd.popup_msg = _("Only relevant in a truetype font, this flag indicates that the width\nof the composite glyph should be the same as the width of this reference.");
429 varray[l++] = &gcd[6+j];
430 gcd[6+j++].creator = GCheckBoxCreate;
431
432 label[6+j].text = (unichar_t *) _("_Round To Grid");
433 label[6+j].text_in_resource = true;
434 label[6+j].text_is_1byte = true;
435 gcd[6+j].gd.label = &label[6+j];
436 gcd[6+j].gd.pos.x = 5; gcd[6+j].gd.pos.y = gcd[6+j-1].gd.pos.y+14;
437 gcd[6+j].gd.flags = gg_enabled|gg_visible| (ref->round_translation_to_grid?gg_cb_on:0);
438 gcd[i+j].gd.cid = 7+1000;
439 gcd[6+j].gd.popup_msg = _("Only relevant in a truetype font, this flag indicates that if the reference\nis translated, then the translation should be rounded during grid fitting.");
440 varray[l++] = &gcd[6+j];
441 gcd[6+j++].creator = GCheckBoxCreate;
442
443 label[6+j].text = (unichar_t *) _("TrueType Point _Matching:");
444 label[6+j].text_in_resource = true;
445 label[6+j].text_is_1byte = true;
446 gcd[6+j].gd.label = &label[6+j];
447 gcd[6+j].gd.pos.x = 5; gcd[6+j].gd.pos.y = gcd[6+j-1].gd.pos.y+17;
448 gcd[6+j].gd.flags = cv->b.sc->layers[ly_fore].order2 ? (gg_enabled|gg_visible) : (gg_visible);
449 gcd[6+j].gd.popup_msg = _("Only relevant in a truetype font, this flag indicates that this\nreference should not be translated normally, but rather its position\nshould be determined by moving the reference so that the indicated\npoint in the reference falls on top of the indicated point in the base\ncharacter.");
450 varray[l++] = &gcd[6+j];
451 gcd[6+j++].creator = GLabelCreate;
452
453 label[6+j].text = (unichar_t *) _("_Base:");
454 label[6+j].text_is_1byte = true;
455 label[6+j].text_in_resource = true;
456 gcd[6+j].gd.label = &label[6+j];
457 gcd[6+j].gd.pos.x = 8; gcd[6+j].gd.pos.y = gcd[6+j-1].gd.pos.y+19;
458 gcd[6+j].gd.flags = cv->b.sc->layers[ly_fore].order2 ? (gg_enabled|gg_visible) : (gg_visible);
459 gcd[6+j].gd.popup_msg = _("Only relevant in a truetype font, this flag indicates that this\nreference should not be translated normally, but rather its position\nshould be determined by moving the reference so that the indicated\npoint in the reference falls on top of the indicated point in the base\ncharacter.");
460 harray1[0] = &gcd[6+j];
461 gcd[6+j++].creator = GLabelCreate;
462
463 if ( ref->point_match ) {
464 sprintf(basebuf,"%d", ref->match_pt_base);
465 label[6+j].text = (unichar_t *) basebuf;
466 label[6+j].text_is_1byte = true;
467 gcd[6+j].gd.label = &label[6+j];
468 }
469 gcd[6+j].gd.pos.x = 40; gcd[6+j].gd.pos.width=50;
470 gcd[6+j].gd.pos.y = gcd[6+j-1].gd.pos.y-4;
471 gcd[6+j].gd.flags = gcd[6+j-1].gd.flags;
472 gcd[6+j].gd.cid = CID_Match_Pt_Base;
473 gcd[6+j].gd.handle_controlevent = GI_MatchPtChange;
474 harray1[1] = &gcd[6+j];
475 gcd[6+j++].creator = GTextFieldCreate;
476
477 label[6+j].text = (unichar_t *) _("Ref:");
478 label[6+j].text_is_1byte = true;
479 gcd[6+j].gd.label = &label[6+j];
480 gcd[6+j].gd.pos.x = 95; gcd[6+j].gd.pos.y = gcd[6+j-2].gd.pos.y;
481 gcd[6+j].gd.flags = gcd[6+j-1].gd.flags;
482 gcd[6+j].gd.popup_msg = _("Only relevant in a truetype font, this flag indicates that this\nreference should not be translated normally, but rather its position\nshould be determined by moving the reference so that the indicated\npoint in the reference falls on top of the indicated point in the base\ncharacter.");
483 harray1[2] = &gcd[6+j];
484 gcd[6+j++].creator = GLabelCreate;
485
486 if ( ref->point_match ) {
487 sprintf(refbuf,"%d", ref->match_pt_ref);
488 label[6+j].text = (unichar_t *) refbuf;
489 label[6+j].text_is_1byte = true;
490 gcd[6+j].gd.label = &label[6+j];
491 }
492 gcd[6+j].gd.pos.x = 127; gcd[6+j].gd.pos.width=50;
493 gcd[6+j].gd.pos.y = gcd[6+j-2].gd.pos.y;
494 gcd[6+j].gd.flags = gcd[6+j-1].gd.flags;
495 gcd[6+j].gd.cid = CID_Match_Pt_Ref;
496 gcd[6+j].gd.handle_controlevent = GI_MatchPtChange;
497 harray1[3] = &gcd[6+j];
498 gcd[6+j++].creator = GTextFieldCreate;
499 harray1[4] = GCD_Glue; harray1[5] = NULL;
500
501 boxes[3].gd.flags = gg_enabled|gg_visible;
502 boxes[3].gd.u.boxelements = harray1;
503 boxes[3].creator = GHBoxCreate;
504 varray[l++] = &boxes[3];
505
506 varray[l++] = GCD_Glue;
507
508 gcd[6+j].gd.pos.x = 5; gcd[6+j].gd.pos.y = RI_Height+(j==10?12:0)-70;
509 gcd[6+j].gd.pos.width = RI_Width-10;
510 gcd[6+j].gd.flags = gg_visible | gg_enabled;
511 varray[l++] = &gcd[6+j];
512 gcd[6+j++].creator = GLineCreate;
513
514 label[6+j].text = (unichar_t *) _("Bounding Box:");
515 label[6+j].text_is_1byte = true;
516 gcd[6+j].gd.label = &label[6+j];
517 gcd[6+j].gd.flags = gg_enabled|gg_visible;
518 gcd[6+j].creator = GLabelCreate;
519 varray[l++] = &gcd[6+j];
520 ++j;
521
522 hvarray2[0][0] = GCD_Glue; hvarray2[0][1] = GCD_Glue;
523
524 label[6+j].text = (unichar_t *) _("Min");
525 label[6+j].text_is_1byte = true;
526 gcd[6+j].gd.label = &label[6+j];
527 gcd[6+j].gd.flags = gg_enabled|gg_visible;
528 gcd[6+j].creator = GLabelCreate;
529 hvarray2[0][2] = &gcd[6+j++];
530
531 label[6+j].text = (unichar_t *) _("Max");
532 label[6+j].text_is_1byte = true;
533 gcd[6+j].gd.label = &label[6+j];
534 gcd[6+j].gd.flags = gg_enabled|gg_visible;
535 gcd[6+j].creator = GLabelCreate;
536 hvarray2[0][3] = &gcd[6+j++]; hvarray2[0][4] = GCD_Glue; hvarray2[0][5] = NULL;
537
538 hvarray2[1][0] = hvarray2[1][4] = GCD_Glue; hvarray2[1][5] = NULL;
539 hvarray2[2][0] = hvarray2[2][4] = GCD_Glue; hvarray2[2][5] = NULL;
540
541 label[6+j].text = (unichar_t *) _("X:");
542 label[6+j].text_is_1byte = true;
543 gcd[6+j].gd.label = &label[6+j];
544 gcd[6+j].gd.flags = gg_enabled|gg_visible;
545 gcd[6+j].creator = GLabelCreate;
546 hvarray2[1][1] = &gcd[6+j++];
547
548 label[6+j].text = (unichar_t *) _("Y:");
549 label[6+j].text_is_1byte = true;
550 gcd[6+j].gd.label = &label[6+j];
551 gcd[6+j].gd.flags = gg_enabled|gg_visible;
552 gcd[6+j].creator = GLabelCreate;
553 hvarray2[2][1] = &gcd[6+j++];
554
555 for ( i=0; i<4; ++i ) {
556 sprintf(bbbuf[i],"%g", (double) ((&ref->bb.minx)[i]));
557 label[6+j].text = (unichar_t *) bbbuf[i];
558 label[6+j].text_is_1byte = true;
559 gcd[6+j].gd.label = &label[6+j];
560 gcd[6+j].gd.flags = gg_enabled|gg_visible;
561 gcd[6+j].creator = GLabelCreate;
562 hvarray2[1+i/2][2+(i&1)] = &gcd[6+j++];
563 }
564 hvarray2[3][0] = NULL;
565
566 boxes[4].gd.flags = gg_enabled|gg_visible;
567 boxes[4].gd.u.boxelements = hvarray2[0];
568 boxes[4].creator = GHVBoxCreate;
569 varray[l++] = &boxes[4];
570
571 gcd[6+j].gd.pos.x = 5; gcd[6+j].gd.pos.y = RI_Height+(j==10?12:0)-70;
572 gcd[6+j].gd.pos.width = RI_Width-10;
573 gcd[6+j].gd.flags = gg_visible | gg_enabled;
574 varray[l++] = &gcd[6+j];
575 gcd[6+j++].creator = GLineCreate;
576
577 gcd[6+j].gd.pos.x = (RI_Width-GIntGetResource(_NUM_Buttonsize))/2;
578 gcd[6+j].gd.pos.y = gcd[6+j-1].gd.pos.y+6;
579 gcd[6+j].gd.pos.width = -1; gcd[6+j].gd.pos.height = 0;
580 gcd[6+j].gd.flags = gg_visible | gg_enabled ;
581 label[6+j].text = (unichar_t *) _("_Show");
582 label[6+j].text_is_1byte = true;
583 label[6+j].text_in_resource = true;
584 gcd[6+j].gd.mnemonic = 'S';
585 gcd[6+j].gd.label = &label[6+j];
586 gcd[6+j].gd.handle_controlevent = GI_Show;
587 harray2[0] = GCD_Glue; harray2[1] = &gcd[6+j]; harray2[2] = GCD_Glue; harray2[3] = NULL;
588 gcd[6+j++].creator = GButtonCreate;
589
590 boxes[5].gd.flags = gg_enabled|gg_visible;
591 boxes[5].gd.u.boxelements = harray2;
592 boxes[5].creator = GHBoxCreate;
593 varray[l++] = &boxes[5];
594
595 gcd[6+j] = gcd[6+j-2];
596 varray[l++] = &gcd[6+j++];
597
598 gcd[6+j].gd.pos.x = 30-3; gcd[6+j].gd.pos.y = RI_Height+(j==13?12:0)-30-3;
599 gcd[6+j].gd.pos.width = -1; gcd[6+j].gd.pos.height = 0;
600 gcd[6+j].gd.flags = gg_visible | gg_enabled | gg_but_default;
601 label[6+j].text = (unichar_t *) _("_OK");
602 label[6+j].text_is_1byte = true;
603 label[6+j].text_in_resource = true;
604 gcd[6+j].gd.mnemonic = 'O';
605 gcd[6+j].gd.label = &label[6+j];
606 gcd[6+j].gd.handle_controlevent = GI_ROK;
607 gcd[6+j++].creator = GButtonCreate;
608
609 gcd[6+j].gd.pos.x = -30; gcd[6+j].gd.pos.y = gcd[6+j-1].gd.pos.y+3;
610 gcd[6+j].gd.pos.width = -1; gcd[6+j].gd.pos.height = 0;
611 gcd[6+j].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
612 label[6+j].text = (unichar_t *) _("_Cancel");
613 label[6+j].text_is_1byte = true;
614 label[6+j].text_in_resource = true;
615 gcd[6+j].gd.mnemonic = 'C';
616 gcd[6+j].gd.label = &label[6+j];
617 gcd[6+j].gd.handle_controlevent = GI_Cancel;
618 gcd[6+j].creator = GButtonCreate;
619
620 harray3[0] = GCD_Glue; harray3[1] = &gcd[6+j-1]; harray3[2] = GCD_Glue;
621 harray3[3] = GCD_Glue; harray3[4] = &gcd[6+j]; harray3[5] = GCD_Glue;
622 harray3[6] = NULL;
623 boxes[6].gd.flags = gg_enabled|gg_visible;
624 boxes[6].gd.u.boxelements = harray3;
625 boxes[6].creator = GHBoxCreate;
626 varray[l++] = &boxes[6];
627 varray[l] = NULL;
628
629 boxes[0].gd.flags = gg_enabled|gg_visible;
630 boxes[0].gd.u.boxelements = varray;
631 boxes[0].creator = GVBoxCreate;
632
633 GGadgetsCreate(gi.gw,boxes);
634 GWidgetIndicateFocusGadget(gcd[j].ret);
635 GHVBoxSetExpandableRow(boxes[0].ret,0);
636 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue);
637 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue);
638 GHVBoxSetPadding(boxes[3].ret,6,2);
639 GHVBoxSetExpandableCol(boxes[4].ret,gb_expandglue);
640 GHVBoxSetExpandableCol(boxes[5].ret,gb_expandglue);
641 GHVBoxSetExpandableCol(boxes[6].ret,gb_expandgluesame);
642 GHVBoxFitWindow(boxes[0].ret);
643
644 GWidgetHidePalettes();
645 GDrawSetVisible(gi.gw,true);
646 while ( !gi.done )
647 GDrawProcessOneEvent(NULL);
648 GDrawDestroyWindow(gi.gw);
649 }
650
ImgGetInfo(CharView * cv,ImageList * img)651 static void ImgGetInfo(CharView *cv, ImageList *img) {
652 static GIData gi;
653 GRect pos;
654 GWindowAttrs wattrs;
655 GGadgetCreateData gcd[12], boxes[3], *varray[11], *harray[6];
656 GTextInfo label[12];
657 char posbuf[100], scalebuf[100], sizebuf[100];
658 struct _GImage *base = img->image->list_len==0?
659 img->image->u.image:img->image->u.images[0];
660
661 gi.cv = cv;
662 gi.sc = cv->b.sc;
663 gi.img = img;
664 gi.done = false;
665
666 memset(&wattrs,0,sizeof(wattrs));
667 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
668 wattrs.event_masks = ~(1<<et_charup);
669 wattrs.restrict_input_to_me = 1;
670 wattrs.undercursor = 1;
671 wattrs.cursor = ct_pointer;
672 wattrs.utf8_window_title = _("Image Info");
673 wattrs.is_dlg = true;
674 pos.x = pos.y = 0;
675 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,II_Width));
676 pos.height = GDrawPointsToPixels(NULL,II_Height);
677 gi.gw = GDrawCreateTopWindow(NULL,&pos,gi_e_h,&gi,&wattrs);
678
679 memset(&gcd,0,sizeof(gcd));
680 memset(&label,0,sizeof(label));
681
682 sprintf( posbuf, _("Image at: (%.0f,%.0f)"), (double) img->xoff,
683 (double) (img->yoff-GImageGetHeight(img->image)*img->yscale));
684 label[0].text = (unichar_t *) posbuf;
685 label[0].text_is_1byte = true;
686 gcd[0].gd.label = &label[0];
687 gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5;
688 gcd[0].gd.flags = gg_enabled|gg_visible;
689 gcd[0].creator = GLabelCreate;
690 varray[0] = &gcd[0]; varray[1] = NULL;
691
692 sprintf( scalebuf, _("Scaled by: (%.2f,%.2f)"), (double) img->xscale, (double) img->yscale );
693 label[1].text = (unichar_t *) scalebuf;
694 label[1].text_is_1byte = true;
695 gcd[1].gd.label = &label[1];
696 gcd[1].gd.pos.x = 5; gcd[1].gd.pos.y = 19;
697 gcd[1].gd.flags = gg_enabled|gg_visible;
698 gcd[1].creator = GLabelCreate;
699 varray[2] = &gcd[1]; varray[3] = NULL;
700
701 sprintf( sizebuf, _("Image Size: %d x %d pixels"), (int) base->width, (int) base->height );
702 label[2].text = (unichar_t *) sizebuf;
703 label[2].text_is_1byte = true;
704 gcd[2].gd.label = &label[2];
705 gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = 19;
706 gcd[2].gd.flags = gg_enabled|gg_visible;
707 gcd[2].creator = GLabelCreate;
708 varray[4] = &gcd[2]; varray[5] = NULL;
709 varray[6] = GCD_Glue; varray[7] = NULL;
710
711 gcd[3].gd.pos.x = (II_Width-GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor)-6)/2; gcd[3].gd.pos.y = II_Height-32-3;
712 gcd[3].gd.pos.width = -1; gcd[3].gd.pos.height = 0;
713 gcd[3].gd.flags = gg_visible | gg_enabled | gg_but_default | gg_but_cancel;
714 label[3].text = (unichar_t *) _("_OK");
715 label[3].text_is_1byte = true;
716 label[3].text_in_resource = true;
717 gcd[3].gd.mnemonic = 'O';
718 gcd[3].gd.label = &label[3];
719 gcd[3].gd.handle_controlevent = GI_Cancel;
720 gcd[3].creator = GButtonCreate;
721 harray[0] = GCD_Glue; harray[1] = &gcd[3]; harray[2] = GCD_Glue; harray[3] = NULL;
722 varray[8] = &boxes[2]; varray[9] = NULL;
723 varray[10] = NULL;
724
725 memset(boxes,0,sizeof(boxes));
726 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
727 boxes[0].gd.flags = gg_enabled|gg_visible;
728 boxes[0].gd.u.boxelements = varray;
729 boxes[0].creator = GHVGroupCreate;
730
731 boxes[2].gd.flags = gg_enabled|gg_visible;
732 boxes[2].gd.u.boxelements = harray;
733 boxes[2].creator = GHBoxCreate;
734
735 GGadgetsCreate(gi.gw,boxes);
736 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
737 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue);
738 GHVBoxFitWindow(boxes[0].ret);
739
740 GWidgetHidePalettes();
741 GDrawSetVisible(gi.gw,true);
742 while ( !gi.done )
743 GDrawProcessOneEvent(NULL);
744 GDrawDestroyWindow(gi.gw);
745 }
746
_AnchorClassUnused(SplineChar * sc,int * waslig,int classmatch)747 static AnchorClass *_AnchorClassUnused(SplineChar *sc,int *waslig, int classmatch) {
748 AnchorClass *an, *maybe;
749 int val, maybelig;
750 SplineFont *sf;
751 int ismarkglyph, isligatureglyph;
752 PST *pst;
753 /* Are there any anchors with this name? If so can't reuse it */
754 /* unless they are ligature anchors */
755 /* or 'curs' anchors, which allow exactly two points (entry, exit) */
756 /* or 'mkmk' anchors, which allow a mark to be both a base and an attach */
757
758 ismarkglyph = (sc->width==0) || sc->glyph_class==(3+1) ||
759 ( sc->unicodeenc!=-1 && sc->unicodeenc<0x10000 && iscombining(sc->unicodeenc)) ||
760 ( sc->anchor!=NULL && (sc->anchor->type == at_mark || sc->anchor->type == at_basemark));
761 for ( pst = sc->possub; pst!=NULL && pst->type!=pst_ligature; pst=pst->next );
762 isligatureglyph = (pst!=NULL) || sc->glyph_class==2+1;
763
764 *waslig = false; maybelig = false; maybe = NULL;
765 sf = sc->parent;
766 if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
767 for ( an=sf->anchor; an!=NULL; an=an->next ) {
768 if ( classmatch ) {
769 if (( an->type == act_mklg && !isligatureglyph && !ismarkglyph ) ||
770 ( an->type == act_mkmk && !ismarkglyph ))
771 continue;
772 }
773 val = IsAnchorClassUsed(sc,an);
774 if ( val>=0 ) {
775 *waslig = val;
776 return( an );
777 } else if ( val!=-1 && maybe==NULL ) {
778 maybe = an;
779 maybelig = val;
780 }
781 }
782 *waslig = maybelig;
783 return( maybe );
784 }
785
AnchorClassUnused(SplineChar * sc,int * waslig)786 AnchorClass *AnchorClassUnused(SplineChar *sc,int *waslig) {
787 return( _AnchorClassUnused(sc,waslig,false));
788 }
789
AnchorPointNew(CharView * cv)790 static AnchorPoint *AnchorPointNew(CharView *cv) {
791 AnchorClass *an;
792 AnchorPoint *ap;
793 int waslig;
794 SplineChar *sc = cv->b.sc;
795 PST *pst;
796
797 an = _AnchorClassUnused(sc,&waslig,true);
798 if ( an==NULL )
799 an = AnchorClassUnused(sc,&waslig);
800
801 if ( an==NULL )
802 return(NULL);
803 ap = chunkalloc(sizeof(AnchorPoint));
804 ap->anchor = an;
805 ap->me.x = cv->p.cx; /* cv->p.cx = 0; */
806 ap->me.y = cv->p.cy; /* cv->p.cy = 0; */
807 ap->type = an->type==act_mark ? at_basechar :
808 an->type==act_mkmk ? at_basemark :
809 an->type==act_mklg ? at_baselig :
810 an->type==act_curs ? at_centry :
811 at_basechar;
812 for ( pst = cv->b.sc->possub; pst!=NULL && pst->type!=pst_ligature; pst=pst->next );
813 if ( waslig<-1 && an->type==act_mkmk ) {
814 ap->type = waslig==-2 ? at_basemark : at_mark;
815 } else if ( waslig==-2 && an->type==act_curs )
816 ap->type = at_cexit;
817 else if ( waslig==-3 || an->type==act_curs )
818 ap->type = at_centry;
819 else if (( sc->unicodeenc!=-1 && sc->unicodeenc<0x10000 &&
820 iscombining(sc->unicodeenc)) || sc->width==0 || sc->glyph_class==(3+1) /* mark class+1 */)
821 ap->type = at_mark;
822 else if ( an->type==act_mkmk )
823 ap->type = at_basemark;
824 else if (( pst!=NULL || waslig || sc->glyph_class==2+1) && an->type==act_mklg )
825 ap->type = at_baselig;
826 if (( ap->type==at_basechar || ap->type==at_baselig ) && an->type==act_mkmk )
827 ap->type = at_basemark;
828 ap->next = sc->anchor;
829 if ( waslig>=0 )
830 ap->lig_index = waslig;
831 sc->anchor = ap;
832 return( ap );
833 }
834
AI_SelectList(GIData * ci,AnchorPoint * ap)835 static void AI_SelectList(GIData *ci,AnchorPoint *ap) {
836 int i;
837 AnchorClass *an;
838 SplineFont *sf = ci->sc->parent;
839
840 if ( sf->cidmaster ) sf = sf->cidmaster;
841
842 for ( i=0, an=sf->anchor; an!=ap->anchor; ++i, an=an->next );
843 GGadgetSelectOneListItem(GWidgetGetControl(ci->gw,CID_NameList),i);
844 }
845
AI_DisplayClass(GIData * ci,AnchorPoint * ap)846 static void AI_DisplayClass(GIData *ci,AnchorPoint *ap) {
847 AnchorClass *ac = ap->anchor;
848 AnchorPoint *aps;
849 int saw[at_max];
850
851 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_BaseChar),ac->type==act_mark || ac->type==act_unknown);
852 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_BaseLig),ac->type==act_mklg);
853 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_BaseMark),ac->type==act_mkmk);
854 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_CursEntry),ac->type==act_curs);
855 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_CursExit),ac->type==act_curs);
856 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_Mark),ac->type!=act_curs);
857
858 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_LigIndex),ap->type==at_baselig);
859
860 if ( ac->type==act_mkmk && (ap->type==at_basechar || ap->type==at_baselig)) {
861 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_BaseMark),true);
862 ap->type = at_basemark;
863 } else if ( ac->type==act_mark && ap->type==at_basemark ) {
864 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_BaseChar),true);
865 ap->type = at_basechar;
866 } else if ( ac->type==act_curs && ap->type!=at_centry && ap->type!=at_cexit ) {
867 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_CursEntry),true);
868 ap->type = at_centry;
869 }
870
871 memset(saw,0,sizeof(saw));
872 for ( aps=ci->sc->anchor; aps!=NULL; aps=aps->next ) if ( aps!=ap ) {
873 if ( aps->anchor==ac ) saw[aps->type] = true;
874 }
875 if ( ac->type==act_curs ) {
876 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_CursEntry),!saw[at_centry]);
877 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_CursExit),!saw[at_cexit]);
878 } else {
879 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_Mark),!saw[at_mark]);
880 if ( saw[at_basechar]) GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_BaseChar),false);
881 if ( saw[at_basemark]) GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_BaseMark),false);
882 }
883 }
884
AI_DisplayIndex(GIData * ci,AnchorPoint * ap)885 static void AI_DisplayIndex(GIData *ci,AnchorPoint *ap) {
886 char buffer[12];
887
888 sprintf(buffer,"%d", ap->lig_index );
889
890 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_LigIndex),buffer);
891 }
892
AI_DisplayRadio(GIData * ci,enum anchor_type type)893 static void AI_DisplayRadio(GIData *ci,enum anchor_type type) {
894 switch ( type ) {
895 case at_mark:
896 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Mark),true);
897 break;
898 case at_basechar:
899 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_BaseChar),true);
900 break;
901 case at_baselig:
902 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_BaseLig),true);
903 break;
904 case at_basemark:
905 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_BaseMark),true);
906 break;
907 case at_centry:
908 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_CursEntry),true);
909 break;
910 case at_cexit:
911 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_CursExit),true);
912 break;
913 }
914 }
915
AI_Display(GIData * ci,AnchorPoint * ap)916 static void AI_Display(GIData *ci,AnchorPoint *ap) {
917 char val[40];
918 unichar_t uval[40];
919 AnchorPoint *aps;
920
921 if ( ap==NULL) {
922 SCUpdateAll(ci->sc);
923 return;
924 }
925
926 ci->ap = ap;
927 for ( aps=ci->sc->anchor; aps!=NULL; aps=aps->next )
928 aps->selected = false;
929 ap->selected = true;
930 sprintf(val,"%g",(double) ap->me.x);
931 uc_strcpy(uval,val);
932 GGadgetSetTitle(GWidgetGetControl(ci->gw,CID_X),uval);
933 sprintf(val,"%g",(double) ap->me.y);
934 uc_strcpy(uval,val);
935 GGadgetSetTitle(GWidgetGetControl(ci->gw,CID_Y),uval);
936 sprintf(val,"%d",ap->type==at_baselig?ap->lig_index:0);
937 uc_strcpy(uval,val);
938 GGadgetSetTitle(GWidgetGetControl(ci->gw,CID_LigIndex),uval);
939 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_LigIndex),ap->type==at_baselig);
940 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_Next),ap->next!=NULL);
941 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_Prev),ci->sc->anchor!=ap);
942 if ( ap->has_ttf_pt )
943 sprintf(val,"%d",ap->ttf_pt_index);
944 else
945 val[0] = '\0';
946 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_MatchPt),val);
947 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_X),!ap->has_ttf_pt);
948 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_Y),!ap->has_ttf_pt);
949
950 AI_DisplayClass(ci,ap);
951 AI_DisplayRadio(ci,ap->type);
952
953 AI_SelectList(ci,ap);
954 SCUpdateAll(ci->sc);
955 }
956
AI_Next(GGadget * g,GEvent * e)957 static int AI_Next(GGadget *g, GEvent *e) {
958 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
959 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
960
961 if ( ci->ap->next==NULL )
962 return( true );
963 AI_Display(ci,ci->ap->next);
964 }
965 return( true );
966 }
967
AI_Prev(GGadget * g,GEvent * e)968 static int AI_Prev(GGadget *g, GEvent *e) {
969 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
970 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
971 AnchorPoint *ap, *prev;
972
973 prev = NULL;
974 for ( ap=ci->sc->anchor; ap!=ci->ap; ap = ap->next )
975 prev = ap;
976 if ( prev==NULL )
977 return( true );
978 AI_Display(ci,prev);
979 }
980 return( true );
981 }
982
983 static int AI_Ok(GGadget *g, GEvent *e);
AI_Delete(GGadget * g,GEvent * e)984 static int AI_Delete(GGadget *g, GEvent *e) {
985 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
986 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
987 AnchorPoint *ap, *prev, *delete_it;
988
989 prev=NULL;
990 for ( ap=ci->sc->anchor; ap!=ci->ap; ap=ap->next )
991 prev = ap;
992 if ( prev==NULL && ci->ap->next==NULL ) {
993 static char *buts[3];
994 buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL;
995 if ( gwwv_ask(_("Last Anchor Point"),(const char **) buts,0,1, _("You are deleting the last anchor point in this character.\nDoing so will cause this dialog to close, is that what you want?"))==1 ) {
996 AI_Ok(g,e);
997 return( true );
998 }
999 }
1000
1001 delete_it = ci->ap;
1002
1003 if ((prev == NULL) && (ci->ap->next == NULL)) {
1004 ci->sc->anchor = NULL;
1005 AnchorPointsFree(delete_it);
1006 AI_Ok(g,e);
1007 SCUpdateAll(ci->sc);
1008 }
1009 else if (ci->ap->next == NULL) {
1010 prev->next = NULL;
1011 AnchorPointsFree(delete_it);
1012 AI_Display(ci,prev);
1013 }
1014 else if (prev == NULL) {
1015 ci->sc->anchor = delete_it->next;
1016 delete_it->next = NULL;
1017 AnchorPointsFree(delete_it);
1018 AI_Display(ci,ci->sc->anchor);
1019 }
1020 else {
1021 prev->next = delete_it->next;
1022 delete_it->next = NULL;
1023 AnchorPointsFree(delete_it);
1024 AI_Display(ci,prev->next);
1025 }
1026
1027 _CVCharChangedUpdate(&ci->cv->b,2);
1028 }
1029 return( true );
1030 }
1031
AnchorClassesLList(SplineFont * sf)1032 static GTextInfo **AnchorClassesLList(SplineFont *sf) {
1033 AnchorClass *an;
1034 int cnt;
1035 GTextInfo **ti;
1036
1037 if ( sf->cidmaster ) sf=sf->cidmaster;
1038
1039 for ( cnt=0, an=sf->anchor; an!=NULL; ++cnt, an=an->next );
1040 ti = calloc(cnt+1,sizeof(GTextInfo*));
1041 for ( cnt=0, an=sf->anchor; an!=NULL; ++cnt, an=an->next ) {
1042 ti[cnt] = calloc(1,sizeof(GTextInfo));
1043 ti[cnt]->text = utf82u_copy(an->name);
1044 ti[cnt]->fg = ti[cnt]->bg = COLOR_DEFAULT;
1045 ti[cnt]->userdata = an;
1046 }
1047 ti[cnt] = calloc(1,sizeof(GTextInfo));
1048 return( ti );
1049 }
1050
AI_NewClass(GGadget * g,GEvent * e)1051 static int AI_NewClass(GGadget *g, GEvent *e) {
1052 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1053 SplineFont *sf = ci->sc->parent;
1054 AnchorClass *ac;
1055 GTextInfo **ti;
1056 int j;
1057 char *name = gwwv_ask_string(_("Anchor Class Name"),"",_("Please enter the name of a Anchor point class to create"));
1058 if ( name==NULL )
1059 return( true );
1060 ac = SFFindOrAddAnchorClass(sf,name,NULL);
1061 GGadgetSetList(GWidgetGetControl(ci->gw,CID_NameList),
1062 ti = AnchorClassesLList(sf),false);
1063 for ( j=0; ti[j]->text!=NULL && ti[j]->userdata!=ac; ++j )
1064 GGadgetSelectOneListItem(GWidgetGetControl(ci->gw,CID_NameList),j);
1065 return( true );
1066 }
1067
AI_New(GGadget * g,GEvent * e)1068 static int AI_New(GGadget *g, GEvent *e) {
1069 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1070 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1071 int waslig;
1072 AnchorPoint *ap;
1073 SplineFont *sf = ci->sc->parent;
1074
1075 if ( sf->cidmaster ) sf = sf->cidmaster;
1076
1077 if ( AnchorClassUnused(ci->sc,&waslig)==NULL ) {
1078 if ( !AI_NewClass(g, e) )
1079 return( false );
1080 }
1081 ap = AnchorPointNew(ci->cv);
1082 if ( ap==NULL )
1083 return( true );
1084 AI_Display(ci,ap);
1085 }
1086 return( true );
1087 }
1088
AI_TypeChanged(GGadget * g,GEvent * e)1089 static int AI_TypeChanged(GGadget *g, GEvent *e) {
1090 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
1091 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1092 AnchorPoint *ap = ci->ap;
1093
1094 if ( GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_Mark)) )
1095 ap->type = at_mark;
1096 else if ( GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_BaseChar)) )
1097 ap->type = at_basechar;
1098 else if ( GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_BaseLig)) )
1099 ap->type = at_baselig;
1100 else if ( GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_BaseMark)) )
1101 ap->type = at_basemark;
1102 else if ( GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_CursEntry)) )
1103 ap->type = at_centry;
1104 else if ( GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_CursExit)) )
1105 ap->type = at_cexit;
1106 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_LigIndex),ap->type==at_baselig);
1107 _CVCharChangedUpdate(&ci->cv->b,2);
1108 }
1109 return( true );
1110 }
1111
AI_TestOrdering(GIData * ci,real x)1112 static void AI_TestOrdering(GIData *ci,real x) {
1113 AnchorPoint *aps, *ap=ci->ap;
1114 AnchorClass *ac = ap->anchor;
1115 int isr2l;
1116
1117 isr2l = SCRightToLeft(ci->sc);
1118 for ( aps=ci->sc->anchor; aps!=NULL; aps=aps->next ) {
1119 if ( aps->anchor==ac && aps!=ci->ap ) {
1120 if (( aps->lig_index<ap->lig_index &&
1121 ((!isr2l && aps->me.x>x) ||
1122 ( isr2l && aps->me.x<x))) ||
1123 ( aps->lig_index>ap->lig_index &&
1124 (( isr2l && aps->me.x>x) ||
1125 (!isr2l && aps->me.x<x))) ) {
1126 ff_post_error(_("Out Of Order"),_("Marks within a ligature should be ordered with the direction of writing.\nThis one and %d are out of order."),aps->lig_index);
1127 return;
1128 }
1129 }
1130 }
1131 return;
1132 }
1133
AI_LigIndexChanged(GGadget * g,GEvent * e)1134 static int AI_LigIndexChanged(GGadget *g, GEvent *e) {
1135 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
1136 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1137 int index, max;
1138 int err=false;
1139 AnchorPoint *ap = ci->ap, *aps;
1140
1141 index = GetCalmReal8(ci->gw,CID_LigIndex,_("Lig Index:"),&err);
1142 if ( index<0 || err )
1143 return( true );
1144 if ( *_GGadgetGetTitle(g)=='\0' )
1145 return( true );
1146 max = 0;
1147 AI_TestOrdering(ci,ap->me.x);
1148 for ( aps=ci->sc->anchor; aps!=NULL; aps=aps->next ) {
1149 if ( aps->anchor==ap->anchor && aps!=ap ) {
1150 if ( aps->lig_index==index ) {
1151 ff_post_error(_("Index in use"),_("This ligature index is already in use"));
1152 return( true );
1153 } else if ( aps->lig_index>max )
1154 max = aps->lig_index;
1155 }
1156 }
1157 if ( index>max+10 ) {
1158 char buf[20];
1159 ff_post_error(_("Too Big"),_("This index is much larger than the closest neighbor"));
1160 sprintf(buf,"%d", max+1);
1161 GGadgetSetTitle8(g,buf);
1162 index = max+1;
1163 }
1164 ap->lig_index = index;
1165 _CVCharChangedUpdate(&ci->cv->b,2);
1166 }
1167 return( true );
1168 }
1169
AI_ANameChanged(GGadget * g,GEvent * e)1170 static int AI_ANameChanged(GGadget *g, GEvent *e) {
1171 if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
1172 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1173 AnchorPoint *ap;
1174 GTextInfo *ti = GGadgetGetListItemSelected(g);
1175 AnchorClass *an = ti->userdata;
1176 int change=0, max=0;
1177 int ntype;
1178 int sawentry, sawexit;
1179
1180 if ( an==ci->ap->anchor )
1181 return( true ); /* No op */
1182
1183 ntype = ci->ap->type;
1184 if ( an->type==act_curs ) {
1185 if ( ntype!=at_centry && ntype!=at_cexit )
1186 ntype = at_centry;
1187 } else if ( an->type==act_mkmk ) {
1188 if ( ntype!=at_basemark && ntype!=at_mark )
1189 ntype = at_basemark;
1190 } else if ( ntype==at_centry || ntype==at_cexit || ntype==at_basemark ||
1191 ntype==at_baselig || ntype == at_basechar ) {
1192 PST *pst;
1193 for ( pst = ci->sc->possub; pst!=NULL && pst->type!=pst_ligature; pst=pst->next );
1194 if (ci->sc->glyph_class==3+1 ||
1195 (ci->sc->unicodeenc!=-1 && ci->sc->unicodeenc<0x10000 &&
1196 iscombining(ci->sc->unicodeenc)))
1197 ntype = at_mark;
1198 else if (( pst!=NULL || ci->sc->glyph_class==2+1 ) && an->type==act_mklg )
1199 ntype = at_baselig;
1200 else
1201 ntype = at_basechar;
1202 }
1203
1204 sawentry = sawexit = false;
1205 for ( ap=ci->sc->anchor; ap!=NULL; ap = ap->next ) {
1206 if ( ap!=ci->ap && ap->anchor==an ) {
1207 if ( an->type==act_curs ) {
1208 if ( ap->type == at_centry ) sawentry = true;
1209 else if ( ap->type== at_cexit ) sawexit = true;
1210 } else if ( an->type==act_mkmk ) {
1211 if ( ap->type == at_mark ) sawentry = true;
1212 else if ( ap->type== at_basemark ) sawexit = true;
1213 } else {
1214 if ( ap->type!=at_baselig )
1215 break;
1216 if ( ap->lig_index==ci->ap->lig_index )
1217 change = true;
1218 else if ( ap->lig_index>max )
1219 max = ap->lig_index;
1220 }
1221 } else if ( ap!=ci->ap && ap->anchor->subtable==an->subtable &&
1222 ap->type==at_mark )
1223 break;
1224 }
1225 if ( ap!=NULL || (sawentry && sawexit)) {
1226 AI_SelectList(ci,ci->ap);
1227 ff_post_error(_("Class already used"),_("This anchor class already is associated with a point in this character"));
1228 } else {
1229 ci->ap->anchor = an;
1230 if ( an->type==act_curs ) {
1231 if ( sawentry ) ntype = at_cexit;
1232 else if ( sawexit ) ntype = at_centry;
1233 } else if ( an->type==act_mkmk ) {
1234 if ( sawentry ) ntype = at_basemark;
1235 else if ( sawexit ) ntype = at_mark;
1236 }
1237 if ( ci->ap->type!=ntype ) {
1238 ci->ap->type = ntype;
1239 AI_DisplayRadio(ci,ntype);
1240 }
1241 if ( ci->ap->type!=at_baselig )
1242 ci->ap->lig_index = 0;
1243 else if ( change ) {
1244 ci->ap->lig_index = max+1;
1245 AI_DisplayIndex(ci,ci->ap);
1246 }
1247 AI_DisplayClass(ci,ci->ap);
1248 AI_TestOrdering(ci,ci->ap->me.x);
1249 }
1250 _CVCharChangedUpdate(&ci->cv->b,2);
1251 }
1252 return( true );
1253 }
1254
AI_PosChanged(GGadget * g,GEvent * e)1255 static int AI_PosChanged(GGadget *g, GEvent *e) {
1256 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
1257 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1258 real dx=0, dy=0;
1259 int err=false;
1260 AnchorPoint *ap = ci->ap;
1261
1262 if ( GGadgetGetCid(g)==CID_X ) {
1263 dx = GetCalmReal8(ci->gw,CID_X,_("_X"),&err)-ap->me.x;
1264 AI_TestOrdering(ci,ap->me.x+dx);
1265 } else
1266 dy = GetCalmReal8(ci->gw,CID_Y,_("_Y"),&err)-ap->me.y;
1267 if ( (dx==0 && dy==0) || err )
1268 return( true );
1269 ap->me.x += dx;
1270 ap->me.y += dy;
1271 _CVCharChangedUpdate(&ci->cv->b,2);
1272 }
1273 return( true );
1274 }
1275
AI_MatchChanged(GGadget * g,GEvent * e)1276 static int AI_MatchChanged(GGadget *g, GEvent *e) {
1277 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
1278 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1279 const unichar_t *t1 = _GGadgetGetTitle(GWidgetGetControl(ci->gw,CID_MatchPt));
1280 unichar_t *end;
1281 AnchorPoint *ap = ci->ap;
1282
1283 while ( *t1==' ' ) ++t1;
1284 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_X),*t1=='\0');
1285 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_Y),*t1=='\0');
1286 if ( isdigit(*t1)) {
1287 BasePoint here;
1288 int pt;
1289 pt = u_strtol(t1,&end,10);
1290 if ( *end=='\0' && ttfFindPointInSC(ci->cv->b.sc,CVLayer((CharViewBase *) ci->cv),pt,&here,NULL)==-1 ) {
1291 char buffer[40];
1292 sprintf(buffer,"%g",(double) here.x);
1293 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_X),buffer);
1294 sprintf(buffer,"%g",(double) here.y);
1295 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_Y),buffer);
1296 ap->me = here;
1297 ap->has_ttf_pt = true;
1298 ap->ttf_pt_index = pt;
1299 _CVCharChangedUpdate(&ci->cv->b,2);
1300 }
1301 } else
1302 ap->has_ttf_pt = false;
1303 }
1304 return( true );
1305 }
1306
AI_DoCancel(GIData * ci)1307 static void AI_DoCancel(GIData *ci) {
1308 CharView *cv = ci->cv;
1309 ci->done = true;
1310 AnchorPointsFree(cv->b.sc->anchor);
1311 cv->b.sc->anchor = ci->oldaps;
1312 ci->oldaps = NULL;
1313 CVRemoveTopUndo(&cv->b);
1314 SCUpdateAll(cv->b.sc);
1315 }
1316
ai_e_h(GWindow gw,GEvent * event)1317 static int ai_e_h(GWindow gw, GEvent *event) {
1318 if ( event->type==et_close ) {
1319 AI_DoCancel( GDrawGetUserData(gw));
1320 } else if ( event->type==et_char ) {
1321 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
1322 help("ui/dialogs/getinfo.html", NULL);
1323 return( true );
1324 }
1325 return( false );
1326 } else if ( event->type == et_map ) {
1327 /* Above palettes */
1328 GDrawRaise(gw);
1329 }
1330 return( true );
1331 }
1332
AI_Cancel(GGadget * g,GEvent * e)1333 static int AI_Cancel(GGadget *g, GEvent *e) {
1334 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1335 AI_DoCancel( GDrawGetUserData(GGadgetGetWindow(g)));
1336 }
1337 return( true );
1338 }
1339
AI_Ok(GGadget * g,GEvent * e)1340 static int AI_Ok(GGadget *g, GEvent *e) {
1341 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1342 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1343 ci->done = true;
1344 /* All the work has been done as we've gone along */
1345 /* Well, we should reorder the list... */
1346 SCOrderAP(ci->cv->b.sc);
1347 }
1348 return( true );
1349 }
1350
ApGetInfo(CharView * cv,AnchorPoint * ap)1351 void ApGetInfo(CharView *cv, AnchorPoint *ap) {
1352 static GIData gi;
1353 GRect pos;
1354 GWindowAttrs wattrs;
1355 GGadgetCreateData gcd[25], boxes[10], *varray[21], *harray1[5], *harray2[3],
1356 *hvarray[13], *harray3[4], *harray4[6], *harray5[6], *harray6[7];
1357 GTextInfo label[25];
1358 int j;
1359 SplineFont *sf;
1360 GTextInfo **ti;
1361
1362 memset(&gi,0,sizeof(gi));
1363 gi.cv = cv;
1364 gi.sc = cv->b.sc;
1365 gi.oldaps = AnchorPointsCopy(cv->b.sc->anchor);
1366 CVPreserveState(&cv->b);
1367 if ( ap==NULL ) {
1368 ap = AnchorPointNew(cv);
1369 if ( ap==NULL )
1370 return;
1371 }
1372
1373 gi.ap = ap;
1374 gi.changed = false;
1375 gi.done = false;
1376
1377 memset(&wattrs,0,sizeof(wattrs));
1378 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1379 wattrs.event_masks = ~(1<<et_charup);
1380 wattrs.restrict_input_to_me = 1;
1381 wattrs.undercursor = 1;
1382 wattrs.cursor = ct_pointer;
1383 wattrs.utf8_window_title = _("Anchor Point Info");
1384 wattrs.is_dlg = true;
1385 pos.x = pos.y = 0;
1386 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,AI_Width));
1387 pos.height = GDrawPointsToPixels(NULL,AI_Height);
1388 gi.gw = GDrawCreateTopWindow(NULL,&pos,ai_e_h,&gi,&wattrs);
1389
1390 memset(&gcd,0,sizeof(gcd));
1391 memset(&label,0,sizeof(label));
1392 memset(&boxes,0,sizeof(boxes));
1393
1394 j=0;
1395 label[j].text = (unichar_t *) ap->anchor->name;
1396 label[j].text_is_1byte = true;
1397 gcd[j].gd.label = &label[j];
1398 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = 5;
1399 gcd[j].gd.pos.width = AI_Width-10;
1400 gcd[j].gd.flags = gg_enabled|gg_visible;
1401 gcd[j].gd.cid = CID_NameList;
1402 sf = cv->b.sc->parent;
1403 if ( sf->cidmaster ) sf = sf->cidmaster;
1404 gcd[j].gd.handle_controlevent = AI_ANameChanged;
1405 gcd[j].creator = GListButtonCreate;
1406 varray[0] = &gcd[j]; varray[1] = NULL;
1407 ++j;
1408
1409 label[j].text = (unichar_t *) _("_X:");
1410 label[j].text_is_1byte = true;
1411 label[j].text_in_resource = true;
1412 gcd[j].gd.label = &label[j];
1413 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+34;
1414 gcd[j].gd.flags = gg_enabled|gg_visible;
1415 gcd[j].creator = GLabelCreate;
1416 harray1[0] = &gcd[j];
1417 ++j;
1418
1419 gcd[j].gd.pos.x = 23; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-4;
1420 gcd[j].gd.pos.width = 50;
1421 gcd[j].gd.flags = gg_enabled|gg_visible;
1422 gcd[j].gd.cid = CID_X;
1423 gcd[j].gd.handle_controlevent = AI_PosChanged;
1424 gcd[j].creator = GNumericFieldCreate;
1425 harray1[1] = &gcd[j];
1426 ++j;
1427
1428 label[j].text = (unichar_t *) _("_Y:");
1429 label[j].text_is_1byte = true;
1430 label[j].text_in_resource = true;
1431 gcd[j].gd.label = &label[j];
1432 gcd[j].gd.pos.x = 85; gcd[j].gd.pos.y = gcd[j-2].gd.pos.y;
1433 gcd[j].gd.flags = gg_enabled|gg_visible;
1434 gcd[j].creator = GLabelCreate;
1435 harray1[2] = &gcd[j];
1436 ++j;
1437
1438 gcd[j].gd.pos.x = 103; gcd[j].gd.pos.y = gcd[j-2].gd.pos.y;
1439 gcd[j].gd.pos.width = 50;
1440 gcd[j].gd.flags = gg_enabled|gg_visible;
1441 gcd[j].gd.cid = CID_Y;
1442 gcd[j].gd.handle_controlevent = AI_PosChanged;
1443 gcd[j].creator = GNumericFieldCreate;
1444 harray1[3] = &gcd[j]; harray1[4] = NULL;
1445 ++j;
1446
1447 boxes[2].gd.flags = gg_enabled|gg_visible;
1448 boxes[2].gd.u.boxelements = harray1;
1449 boxes[2].creator = GHBoxCreate;
1450 varray[2] = &boxes[2]; varray[3] = NULL;
1451
1452 label[j].text = (unichar_t *) _("Matching TTF Point:");
1453 label[j].text_is_1byte = true;
1454 gcd[j].gd.label = &label[j];
1455 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-2].gd.pos.y+24;
1456 gcd[j].gd.flags = cv->b.sc->layers[ly_fore].order2 ? (gg_enabled|gg_visible) : gg_visible;
1457 gcd[j].creator = GLabelCreate;
1458 harray2[0] = &gcd[j];
1459 ++j;
1460
1461 gcd[j].gd.pos.x = 103; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-2;
1462 gcd[j].gd.pos.width = 50;
1463 gcd[j].gd.flags = gcd[j-1].gd.flags;
1464 gcd[j].gd.cid = CID_MatchPt;
1465 gcd[j].gd.handle_controlevent = AI_MatchChanged;
1466 gcd[j].creator = GTextFieldCreate;
1467 harray2[1] = &gcd[j]; harray2[2] = NULL;
1468 ++j;
1469
1470 boxes[3].gd.flags = gg_enabled|gg_visible;
1471 boxes[3].gd.u.boxelements = harray2;
1472 boxes[3].creator = GHBoxCreate;
1473 varray[4] = &boxes[3]; varray[5] = NULL;
1474
1475 label[j].text = (unichar_t *) _("Mark");
1476 label[j].text_is_1byte = true;
1477 gcd[j].gd.label = &label[j];
1478 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+28;
1479 gcd[j].gd.flags = gg_enabled|gg_visible;
1480 gcd[j].gd.cid = CID_Mark;
1481 gcd[j].gd.handle_controlevent = AI_TypeChanged;
1482 gcd[j].creator = GRadioCreate;
1483 hvarray[0] = &gcd[j];
1484 ++j;
1485
1486 label[j].text = (unichar_t *) _("Base Glyph");
1487 label[j].text_is_1byte = true;
1488 gcd[j].gd.label = &label[j];
1489 gcd[j].gd.pos.x = 70; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
1490 gcd[j].gd.flags = gg_enabled|gg_visible;
1491 gcd[j].gd.cid = CID_BaseChar;
1492 gcd[j].gd.handle_controlevent = AI_TypeChanged;
1493 gcd[j].creator = GRadioCreate;
1494 hvarray[1] = &gcd[j]; hvarray[2] = NULL;
1495 ++j;
1496
1497 label[j].text = (unichar_t *) _("Base Lig");
1498 label[j].text_is_1byte = true;
1499 gcd[j].gd.label = &label[j];
1500 gcd[j].gd.pos.x = gcd[j-2].gd.pos.x; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+14;
1501 gcd[j].gd.flags = gg_enabled|gg_visible;
1502 gcd[j].gd.cid = CID_BaseLig;
1503 gcd[j].gd.handle_controlevent = AI_TypeChanged;
1504 gcd[j].creator = GRadioCreate;
1505 hvarray[3] = &gcd[j];
1506 ++j;
1507
1508 label[j].text = (unichar_t *) _("Base Mark");
1509 label[j].text_is_1byte = true;
1510 gcd[j].gd.label = &label[j];
1511 gcd[j].gd.pos.x = gcd[j-2].gd.pos.x; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
1512 gcd[j].gd.flags = gg_enabled|gg_visible;
1513 gcd[j].gd.cid = CID_BaseMark;
1514 gcd[j].gd.handle_controlevent = AI_TypeChanged;
1515 gcd[j].creator = GRadioCreate;
1516 hvarray[4] = &gcd[j]; hvarray[5] = NULL;
1517 ++j;
1518
1519 /* GT: Cursive Entry. This defines a point on the glyph that should be matched */
1520 /* GT: with the "Cursive Exit" point of the preceding glyph. */
1521 /* GT: This is a special way of joining letters which was developed for Urdu */
1522 /* GT: fonts. Essentially every glyph has an entry point and an exit point. */
1523 /* GT: When written the glyphs in sequence are aligned so that the exit point */
1524 /* GT: of each glyph matches the entry point of the following. It means you */
1525 /* GT: get a join such as might be expected for script. Urdu is odd because */
1526 /* GT: letters within a word crawl diagonally up the page, but with each word */
1527 /* GT: the writing point starts at the baseline. */
1528 label[j].text = (unichar_t *) _("CursEntry");
1529 label[j].text_is_1byte = true;
1530 gcd[j].gd.label = &label[j];
1531 gcd[j].gd.pos.x = gcd[j-2].gd.pos.x; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+14;
1532 gcd[j].gd.flags = gg_enabled|gg_visible;
1533 gcd[j].gd.cid = CID_CursEntry;
1534 gcd[j].gd.handle_controlevent = AI_TypeChanged;
1535 gcd[j].creator = GRadioCreate;
1536 hvarray[6] = &gcd[j];
1537 ++j;
1538
1539 /* GT: Cursive Exit. This defines a point on the glyph that should be matched */
1540 /* GT: with the "Cursive Entry" point of the following glyph. This allows */
1541 /* GT: scripts such as Urdu to work */
1542 label[j].text = (unichar_t *) _("CursExit");
1543 label[j].text_is_1byte = true;
1544 gcd[j].gd.label = &label[j];
1545 gcd[j].gd.pos.x = gcd[j-2].gd.pos.x; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
1546 gcd[j].gd.flags = gg_enabled|gg_visible;
1547 gcd[j].gd.cid = CID_CursExit;
1548 gcd[j].gd.handle_controlevent = AI_TypeChanged;
1549 gcd[j].creator = GRadioCreate;
1550 hvarray[7] = &gcd[j]; hvarray[8] = NULL; hvarray[9] = NULL;
1551 ++j;
1552
1553 boxes[4].gd.flags = gg_enabled|gg_visible;
1554 boxes[4].gd.u.boxelements = hvarray;
1555 boxes[4].creator = GHVBoxCreate;
1556 varray[6] = &boxes[4]; varray[7] = NULL;
1557
1558 label[j].text = (unichar_t *) _("Lig Index:");
1559 label[j].text_is_1byte = true;
1560 gcd[j].gd.label = &label[j];
1561 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+26;
1562 gcd[j].gd.flags = gg_enabled|gg_visible;
1563 gcd[j].creator = GLabelCreate;
1564 harray3[0] = &gcd[j];
1565 ++j;
1566
1567 gcd[j].gd.pos.x = 65; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-4;
1568 gcd[j].gd.pos.width = 50;
1569 gcd[j].gd.flags = gg_enabled|gg_visible;
1570 gcd[j].gd.cid = CID_LigIndex;
1571 gcd[j].gd.handle_controlevent = AI_LigIndexChanged;
1572 gcd[j].creator = GNumericFieldCreate;
1573 harray3[1] = &gcd[j]; harray3[2] = NULL;
1574 ++j;
1575
1576 boxes[5].gd.flags = gg_enabled|gg_visible;
1577 boxes[5].gd.u.boxelements = harray3;
1578 boxes[5].creator = GHBoxCreate;
1579 varray[8] = &boxes[5]; varray[9] = NULL;
1580
1581 label[j].text = (unichar_t *) S_("AnchorPoint|_New");
1582 label[j].text_is_1byte = true;
1583 label[j].text_in_resource = true;
1584 gcd[j].gd.label = &label[j];
1585 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+30;
1586 gcd[j].gd.pos.width = -1;
1587 gcd[j].gd.flags = gg_enabled|gg_visible;
1588 gcd[j].gd.cid = CID_New;
1589 gcd[j].gd.handle_controlevent = AI_New;
1590 gcd[j].creator = GButtonCreate;
1591 harray4[0] = &gcd[j]; harray4[1] = GCD_Glue;
1592 ++j;
1593
1594 label[j].text = (unichar_t *) S_("AnchorClass|New _Class");
1595 label[j].text_is_1byte = true;
1596 label[j].text_in_resource = true;
1597 gcd[j].gd.label = &label[j];
1598 gcd[j].gd.pos.x = 30; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
1599 gcd[j].gd.pos.width = -1;
1600 gcd[j].gd.flags = gg_enabled|gg_visible;
1601 gcd[j].gd.cid = CID_New;
1602 gcd[j].gd.handle_controlevent = AI_NewClass;
1603 gcd[j].creator = GButtonCreate;
1604 harray4[2] = &gcd[j]; harray4[3] = GCD_Glue;
1605 ++j;
1606
1607 label[j].text = (unichar_t *) _("_Delete");
1608 label[j].text_is_1byte = true;
1609 label[j].text_in_resource = true;
1610 gcd[j].gd.label = &label[j];
1611 gcd[j].gd.pos.x = -5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
1612 gcd[j].gd.pos.width = -1;
1613 gcd[j].gd.flags = gg_enabled|gg_visible;
1614 gcd[j].gd.cid = CID_Delete;
1615 gcd[j].gd.handle_controlevent = AI_Delete;
1616 gcd[j].creator = GButtonCreate;
1617 harray4[4] = &gcd[j]; harray4[5] = NULL;
1618 ++j;
1619
1620 boxes[6].gd.flags = gg_enabled|gg_visible;
1621 boxes[6].gd.u.boxelements = harray4;
1622 boxes[6].creator = GHBoxCreate;
1623 varray[10] = &boxes[6]; varray[11] = NULL;
1624
1625 label[j].text = (unichar_t *) _("< _Prev");
1626 label[j].text_is_1byte = true;
1627 label[j].text_in_resource = true;
1628 gcd[j].gd.label = &label[j];
1629 gcd[j].gd.pos.x = 15; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+28;
1630 gcd[j].gd.pos.width = -1;
1631 gcd[j].gd.flags = gg_enabled|gg_visible;
1632 gcd[j].gd.cid = CID_Prev;
1633 gcd[j].gd.handle_controlevent = AI_Prev;
1634 gcd[j].creator = GButtonCreate;
1635 harray5[0] = GCD_Glue; harray5[1] = &gcd[j]; harray5[2] = GCD_Glue;
1636 ++j;
1637
1638 label[j].text = (unichar_t *) _("_Next >");
1639 label[j].text_is_1byte = true;
1640 label[j].text_in_resource = true;
1641 gcd[j].gd.label = &label[j];
1642 gcd[j].gd.pos.x = -15; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
1643 gcd[j].gd.pos.width = -1;
1644 gcd[j].gd.flags = gg_enabled|gg_visible;
1645 gcd[j].gd.cid = CID_Next;
1646 gcd[j].gd.handle_controlevent = AI_Next;
1647 gcd[j].creator = GButtonCreate;
1648 harray5[3] = &gcd[j]; harray5[4] = GCD_Glue; harray5[5] = NULL;
1649 ++j;
1650
1651 boxes[7].gd.flags = gg_enabled|gg_visible;
1652 boxes[7].gd.u.boxelements = harray5;
1653 boxes[7].creator = GHBoxCreate;
1654 varray[12] = &boxes[7]; varray[13] = NULL;
1655
1656 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+26;
1657 gcd[j].gd.pos.width = AI_Width-10;
1658 gcd[j].gd.flags = gg_enabled|gg_visible;
1659 gcd[j].creator = GLineCreate;
1660 varray[14] = GCD_Glue; varray[15] = NULL;
1661 varray[16] = &gcd[j]; varray[17] = NULL;
1662 ++j;
1663
1664 label[j].text = (unichar_t *) _("_OK");
1665 label[j].text_is_1byte = true;
1666 label[j].text_in_resource = true;
1667 gcd[j].gd.label = &label[j];
1668 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+4;
1669 gcd[j].gd.pos.width = -1;
1670 gcd[j].gd.flags = gg_enabled|gg_visible|gg_but_default;
1671 gcd[j].gd.handle_controlevent = AI_Ok;
1672 gcd[j].creator = GButtonCreate;
1673 harray6[0] = &gcd[j]; harray6[1] = GCD_Glue;
1674 ++j;
1675
1676 label[j].text = (unichar_t *) _("_Cancel");
1677 label[j].text_is_1byte = true;
1678 label[j].text_in_resource = true;
1679 gcd[j].gd.label = &label[j];
1680 gcd[j].gd.pos.x = -5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+3;
1681 gcd[j].gd.pos.width = -1;
1682 gcd[j].gd.flags = gg_enabled|gg_visible|gg_but_cancel;
1683 gcd[j].gd.handle_controlevent = AI_Cancel;
1684 gcd[j].creator = GButtonCreate;
1685 harray6[2] = &gcd[j]; harray6[3] = NULL;
1686 ++j;
1687
1688 boxes[8].gd.flags = gg_enabled|gg_visible;
1689 boxes[8].gd.u.boxelements = harray6;
1690 boxes[8].creator = GHBoxCreate;
1691 varray[18] = &boxes[8]; varray[19] = NULL;
1692 varray[20] = NULL;
1693
1694 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
1695 boxes[0].gd.flags = gg_enabled|gg_visible;
1696 boxes[0].gd.u.boxelements = varray;
1697 boxes[0].creator = GHVGroupCreate;
1698
1699 GGadgetsCreate(gi.gw,boxes);
1700 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
1701 GHVBoxSetExpandableCol(boxes[8].ret,gb_expandgluesame);
1702 GHVBoxSetExpandableCol(boxes[7].ret,gb_expandgluesame);
1703 GHVBoxSetExpandableCol(boxes[6].ret,gb_expandgluesame);
1704 GHVBoxFitWindow(boxes[0].ret);
1705
1706 GGadgetSetList(GWidgetGetControl(gi.gw,CID_NameList),
1707 ti = AnchorClassesLList(gi.sc->parent),false);
1708 for ( j=0; ti[j]->text!=NULL && ti[j]->userdata!=ap->anchor; ++j )
1709 GGadgetSelectOneListItem(GWidgetGetControl(gi.gw,CID_NameList),j);
1710
1711 AI_Display(&gi,ap);
1712 GWidgetIndicateFocusGadget(GWidgetGetControl(gi.gw,CID_X));
1713
1714 GWidgetHidePalettes();
1715 GDrawSetVisible(gi.gw,true);
1716 while ( !gi.done )
1717 GDrawProcessOneEvent(NULL);
1718 GDrawDestroyWindow(gi.gw);
1719 AnchorPointsFree(gi.oldaps);
1720 }
1721
PI_ShowHints(SplineChar * sc,GGadget * list,int set)1722 void PI_ShowHints(SplineChar *sc, GGadget *list, int set) {
1723 StemInfo *h;
1724 int32 i, len;
1725
1726 if ( !set ) {
1727 for ( h = sc->hstem; h!=NULL; h=h->next )
1728 h->active = false;
1729 for ( h = sc->vstem; h!=NULL; h=h->next )
1730 h->active = false;
1731 } else {
1732 GTextInfo **ti = GGadgetGetList(list,&len);
1733 for ( h = sc->hstem, i=0; h!=NULL && i<len; h=h->next, ++i )
1734 h->active = ti[i]->selected;
1735 for ( h = sc->vstem; h!=NULL && i<len; h=h->next, ++i )
1736 h->active = ti[i]->selected;
1737 }
1738 SCOutOfDateBackground(sc);
1739 SCUpdateAll(sc);
1740 }
1741
_PI_ShowHints(GIData * ci,int set)1742 static void _PI_ShowHints(GIData *ci,int set) {
1743 PI_ShowHints(ci->cv->b.sc,GWidgetGetControl(ci->gw,CID_HintMask),set);
1744 }
1745
PI_DoCancel(GIData * ci)1746 static void PI_DoCancel(GIData *ci) {
1747 CharView *cv = ci->cv;
1748 ci->done = true;
1749 if ( cv->b.drawmode==dm_fore )
1750 MDReplace(cv->b.sc->md,cv->b.sc->layers[ly_fore].splines,ci->oldstate);
1751 SplinePointListsFree(cv->b.layerheads[cv->b.drawmode]->splines);
1752 cv->b.layerheads[cv->b.drawmode]->splines = ci->oldstate;
1753 CVRemoveTopUndo(&cv->b);
1754 SCClearSelPt(cv->b.sc);
1755 _PI_ShowHints(ci,false);
1756 SCUpdateAll(cv->b.sc);
1757 }
1758
1759 static void PIFillup(GIData *ci, int except_cid);
1760
PI_FigureNext(GIData * ci)1761 static void PI_FigureNext(GIData *ci) {
1762 if ( ci->prevchanged ) {
1763 SplinePoint *cursp = ci->cursp;
1764 if ( !ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 && (cursp->pointtype==pt_curve || cursp->pointtype==pt_hvcurve)) {
1765 double dx, dy, len, len2;
1766 dx = cursp->prevcp.x - cursp->me.x;
1767 dy = cursp->prevcp.y - cursp->me.y;
1768 len = sqrt(dx*dx+dy*dy);
1769 if ( len!=0 ) {
1770 len2 = sqrt((cursp->nextcp.x-cursp->me.x)*(cursp->nextcp.x-cursp->me.x)+
1771 (cursp->nextcp.y-cursp->me.y)*(cursp->nextcp.y-cursp->me.y));
1772 cursp->nextcp.x=cursp->me.x-dx*len2/len;
1773 cursp->nextcp.y=cursp->me.y-dy*len2/len;
1774 if ( cursp->next!=NULL )
1775 SplineRefigure(cursp->next);
1776 CVCharChangedUpdate(&ci->cv->b);
1777 PIFillup(ci,-1);
1778 }
1779 }
1780 }
1781 ci->prevchanged = false;
1782 }
1783
PI_FigurePrev(GIData * ci)1784 static void PI_FigurePrev(GIData *ci) {
1785 if ( ci->nextchanged ) {
1786 SplinePoint *cursp = ci->cursp;
1787 if ( !ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 && (cursp->pointtype==pt_curve || cursp->pointtype==pt_hvcurve)) {
1788 double dx, dy, len, len2;
1789 dx = cursp->nextcp.x - cursp->me.x;
1790 dy = cursp->nextcp.y - cursp->me.y;
1791 len = sqrt(dx*dx+dy*dy);
1792 if ( len!=0 ) {
1793 len2 = sqrt((cursp->prevcp.x-cursp->me.x)*(cursp->prevcp.x-cursp->me.x)+
1794 (cursp->prevcp.y-cursp->me.y)*(cursp->prevcp.y-cursp->me.y));
1795 cursp->prevcp.x=cursp->me.x-dx*len2/len;
1796 cursp->prevcp.y=cursp->me.y-dy*len2/len;
1797 if ( cursp->prev!=NULL )
1798 SplineRefigure(cursp->prev);
1799 CVCharChangedUpdate(&ci->cv->b);
1800 PIFillup(ci,-1);
1801 }
1802 }
1803 }
1804 ci->nextchanged = false;
1805 }
1806
PI_FigureHintMask(GIData * ci)1807 static void PI_FigureHintMask(GIData *ci) {
1808 int32 i, len;
1809 GTextInfo **ti = GGadgetGetList(GWidgetGetControl(ci->gw,CID_HintMask),&len);
1810
1811 for ( i=0; i<len; ++i )
1812 if ( ti[i]->selected )
1813 break;
1814
1815 if ( i==len ) {
1816 chunkfree(ci->cursp->hintmask,sizeof(HintMask));
1817 ci->cursp->hintmask = NULL;
1818 } else {
1819 if ( ci->cursp->hintmask==NULL )
1820 ci->cursp->hintmask = chunkalloc(sizeof(HintMask));
1821 else
1822 memset(ci->cursp->hintmask,0,sizeof(HintMask));
1823 for ( i=0; i<len; ++i )
1824 if ( ti[i]->selected )
1825 (*ci->cursp->hintmask)[i>>3] |= (0x80>>(i&7));
1826 }
1827 }
1828
PI_FixStuff(GIData * ci)1829 static void PI_FixStuff(GIData *ci) {
1830 SplinePoint *sp = ci->cursp;
1831
1832 PI_FigureHintMask(ci);
1833 PI_FigureNext(ci);
1834 PI_FigurePrev(ci);
1835
1836 if ( sp->pointtype == pt_hvcurve ) {
1837 if (
1838 ((sp->nextcp.x==sp->me.x && sp->prevcp.x==sp->me.x && sp->nextcp.y!=sp->me.y) ||
1839 (sp->nextcp.y==sp->me.y && sp->prevcp.y==sp->me.y && sp->nextcp.x!=sp->me.x)))
1840 /* Do Nothing */;
1841 else
1842 sp->pointtype = pt_curve;
1843 } else if ( sp->pointtype == pt_tangent )
1844 SplinePointCategorize(sp); /* Users can change cps so it isn't a tangent, so check */
1845 }
1846
PI_Destroy(struct dlistnode * node)1847 void PI_Destroy(struct dlistnode *node) {
1848 GIData *d = (GIData *)node;
1849 GDrawDestroyWindow(d->gw);
1850 dlist_erase(&d->cv->pointInfoDialogs,(struct dlistnode *)d);
1851 free(d);
1852 }
1853
PI_Close(GIData * d)1854 static void PI_Close(GIData *d) {
1855 PI_Destroy((struct dlistnode *)d);
1856 }
1857
PI_Cancel(GGadget * g,GEvent * e)1858 static int PI_Cancel(GGadget *g, GEvent *e) {
1859 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1860 GIData *d = GDrawGetUserData(GGadgetGetWindow(g));
1861 PI_DoCancel(d);
1862 PI_Close(d);
1863 }
1864 return( true );
1865 }
1866
PI_DoOk(GIData * ci)1867 static void PI_DoOk(GIData *ci) {
1868 PI_FixStuff(ci);
1869 _PI_ShowHints(ci,false);
1870
1871 ci->done = true;
1872 /* All the work has been done as we've gone along */
1873 PI_Close(ci);
1874 }
1875
PI_Ok(GGadget * g,GEvent * e)1876 static int PI_Ok(GGadget *g, GEvent *e) {
1877 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1878 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
1879 PI_DoOk(ci);
1880 }
1881 return( true );
1882 }
1883
pi_e_h(GWindow gw,GEvent * event)1884 static int pi_e_h(GWindow gw, GEvent *event) {
1885 if ( event->type==et_close ) {
1886 PI_DoOk(GDrawGetUserData(gw));
1887 } else if ( event->type==et_char ) {
1888 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
1889 help("ui/dialogs/getinfo.html", NULL);
1890 return( true );
1891 }
1892 return( false );
1893 } else if ( event->type == et_map ) {
1894 /* Above palettes */
1895 GDrawRaise(gw);
1896 }
1897 return( true );
1898 }
1899
mysprintf(char * buffer,char * format,real v)1900 static void mysprintf( char *buffer, char *format, real v) {
1901 char *pt;
1902
1903 if ( v<.0001 && v>-.0001 && v!=0 )
1904 sprintf( buffer, "%e", (double) v );
1905 else if ( v<1 && v>0 )
1906 sprintf( buffer, "%f", (double) v );
1907 else if ( v<0 && v>-1 )
1908 sprintf( buffer, "%.5f", (double) v );
1909 else
1910 sprintf( buffer, format, (double) v );
1911 pt = buffer + strlen(buffer);
1912 while ( pt>buffer && pt[-1]=='0' )
1913 *--pt = '\0';
1914 if ( pt>buffer && pt[-1]=='.' )
1915 pt[-1] = '\0';
1916 }
1917
mysprintf2(char * buffer,real v1,real v2)1918 static void mysprintf2( char *buffer, real v1, real v2) {
1919 char *pt;
1920
1921 mysprintf(buffer,"%.2f", v1);
1922 pt = buffer+strlen(buffer);
1923 *pt++ = ',';
1924 mysprintf(pt,"%.2f", v2);
1925 }
1926
PIFillup(GIData * ci,int except_cid)1927 static void PIFillup(GIData *ci, int except_cid) {
1928 char buffer[51];
1929 double dx, dy;
1930 double kappa, kappa2;
1931 int emsize;
1932
1933 mysprintf(buffer, "%.2f", ci->cursp->me.x );
1934 if ( except_cid!=CID_BaseX )
1935 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_BaseX),buffer);
1936
1937 mysprintf(buffer, "%.2f", ci->cursp->me.y );
1938 if ( except_cid!=CID_BaseY )
1939 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_BaseY),buffer);
1940
1941 dx = ci->cursp->nextcp.x-ci->cursp->me.x;
1942 dy = ci->cursp->nextcp.y-ci->cursp->me.y;
1943 mysprintf(buffer, "%.2f", dx );
1944 if ( except_cid!=CID_NextXOff )
1945 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_NextXOff),buffer);
1946
1947 mysprintf(buffer, "%.2f", dy );
1948 if ( except_cid!=CID_NextYOff )
1949 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_NextYOff),buffer);
1950
1951 if ( except_cid!=CID_NextR ) {
1952 mysprintf(buffer, "%.2f", sqrt( dx*dx+dy*dy ));
1953 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_NextR),buffer);
1954 }
1955
1956 if ( except_cid!=CID_NextTheta ) {
1957 if ( ci->cursp->pointtype==pt_tangent && ci->cursp->prev!=NULL ) {
1958 dx = ci->cursp->me.x-ci->cursp->prev->from->me.x;
1959 dy = ci->cursp->me.y-ci->cursp->prev->from->me.y;
1960 }
1961 mysprintf(buffer, "%.1f", atan2(dy,dx)*RAD2DEG);
1962 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_NextTheta),buffer);
1963 }
1964
1965 mysprintf2(buffer, ci->cursp->nextcp.x,ci->cursp->nextcp.y );
1966 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_NextPos),buffer);
1967
1968 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_NextDef), ci->cursp->nextcpdef );
1969
1970 dx = ci->cursp->prevcp.x-ci->cursp->me.x;
1971 dy = ci->cursp->prevcp.y-ci->cursp->me.y;
1972 mysprintf(buffer, "%.2f", dx );
1973 if ( except_cid!=CID_PrevXOff )
1974 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_PrevXOff),buffer);
1975
1976 mysprintf(buffer, "%.2f", dy );
1977 if ( except_cid!=CID_PrevYOff )
1978 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_PrevYOff),buffer);
1979
1980 if ( except_cid!=CID_PrevR ) {
1981 mysprintf(buffer, "%.2f", sqrt( dx*dx+dy*dy ));
1982 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_PrevR),buffer);
1983 }
1984
1985 if ( except_cid!=CID_PrevTheta ) {
1986 if ( ci->cursp->pointtype==pt_tangent && ci->cursp->next!=NULL ) {
1987 dx = ci->cursp->me.x-ci->cursp->next->to->me.x;
1988 dy = ci->cursp->me.y-ci->cursp->next->to->me.y;
1989 }
1990 mysprintf(buffer, "%.1f", atan2(dy,dx)*RAD2DEG);
1991 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_PrevTheta),buffer);
1992 }
1993
1994 mysprintf2(buffer, ci->cursp->prevcp.x,ci->cursp->prevcp.y );
1995 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_PrevPos),buffer);
1996
1997
1998 mysprintf2(buffer, ci->cursp->me.x,ci->cursp->me.y );
1999 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_BasePos),buffer);
2000
2001 mysprintf(buffer, "%.2f", ci->cursp->nextcp.x );
2002 if ( except_cid!=CID_NextX )
2003 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_NextX),buffer);
2004
2005 mysprintf(buffer, "%.2f", ci->cursp->nextcp.y );
2006 if ( except_cid!=CID_NextY )
2007 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_NextY),buffer);
2008
2009 mysprintf(buffer, "%.2f", ci->cursp->prevcp.x );
2010 if ( except_cid!=CID_PrevX )
2011 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_PrevX),buffer);
2012
2013 mysprintf(buffer, "%.2f", ci->cursp->prevcp.y );
2014 if ( except_cid!=CID_PrevY )
2015 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_PrevY),buffer);
2016
2017
2018 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_PrevDef), ci->cursp->prevcpdef );
2019
2020 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Curve), ci->cursp->pointtype==pt_curve );
2021 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_HVCurve), ci->cursp->pointtype==pt_hvcurve );
2022 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Corner), ci->cursp->pointtype==pt_corner );
2023 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Tangent), ci->cursp->pointtype==pt_tangent );
2024
2025 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_PrevTheta), ci->cursp->pointtype!=pt_tangent );
2026 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_NextTheta), ci->cursp->pointtype!=pt_tangent );
2027
2028 kappa = SplineCurvature(ci->cursp->next,0);
2029 kappa2 = SplineCurvature(ci->cursp->prev,1);
2030 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_PrevCurvature), kappa2!=CURVATURE_ERROR );
2031 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_NextCurvature), kappa!=CURVATURE_ERROR );
2032 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_DeltaCurvature),
2033 kappa!=CURVATURE_ERROR && kappa2!=CURVATURE_ERROR );
2034 emsize = ci->cv->b.sc->parent->ascent + ci->cv->b.sc->parent->descent;
2035 /* If we normalize by the em-size, the curvature is often more */
2036 /* readable */
2037 if ( kappa!=CURVATURE_ERROR )
2038 sprintf( buffer, _("Curvature: %g"), kappa*emsize );
2039 else
2040 strcpy( buffer, _("Curvature: ?"));
2041 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_NextCurvature),buffer);
2042 if ( kappa2!=CURVATURE_ERROR )
2043 sprintf( buffer, _("Curvature: %g"), kappa2*emsize );
2044 else
2045 strncpy( buffer, _("Curvature: ?"),sizeof(buffer)-1 );
2046 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_PrevCurvature),buffer);
2047 if ( kappa!=CURVATURE_ERROR && kappa2!=CURVATURE_ERROR )
2048 sprintf( buffer, "∆: %g", (kappa-kappa2)*emsize );
2049 else
2050 strcpy( buffer, "∆: ?");
2051 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_DeltaCurvature),buffer);
2052 }
2053
PIShowHide(GIData * ci)2054 static void PIShowHide(GIData *ci) {
2055 int normal = GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_Normal));
2056 int i;
2057
2058 for ( i=ci->normal_start; i<ci->normal_end; ++i )
2059 if ( ci->gcd[i].ret!=NULL )
2060 GGadgetSetVisible(ci->gcd[i].ret,normal);
2061 GGadgetSetVisible(ci->group1ret,normal);
2062 GGadgetSetVisible(ci->group2ret,normal);
2063 for ( i=ci->interp_start; i<ci->interp_end; ++i )
2064 if ( ci->gcd[i].ret!=NULL )
2065 GGadgetSetVisible(ci->gcd[i].ret,!normal);
2066 GWidgetFlowGadgets(GGadgetGetWindow(GWidgetGetControl(ci->gw,CID_Normal)));
2067 }
2068
PIChangePoint(GIData * ci)2069 void PIChangePoint(GIData *ci) {
2070 int aspect = GTabSetGetSel(GWidgetGetControl(ci->gw,CID_TabSet));
2071 GGadget *list = GWidgetGetControl(ci->gw,CID_HintMask);
2072 int32 i, len;
2073 HintMask *hm;
2074 SplinePoint *sp;
2075 SplineSet *spl;
2076 int interpolate;
2077
2078 GGadgetGetList(list,&len);
2079
2080 PIFillup(ci,0);
2081
2082 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_Interpolated),
2083 !ci->cursp->dontinterpolate && !(ci->cursp->nonextcp && ci->cursp->noprevcp) );
2084 interpolate = SPInterpolate(ci->cursp) && ci->cv->b.layerheads[ci->cv->b.drawmode]->order2;
2085 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Normal), !interpolate );
2086 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Interpolated), interpolate );
2087 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_NeverInterpolate), ci->cursp->dontinterpolate );
2088 PIShowHide(ci);
2089
2090 if ( ci->cursp->hintmask==NULL ) {
2091 for ( i=0; i<len; ++i )
2092 GGadgetSelectListItem(list,i,false);
2093 } else {
2094 for ( i=0; i<len && i<HntMax; ++i )
2095 GGadgetSelectListItem(list,i, (*ci->cursp->hintmask)[i>>3]&(0x80>>(i&7))?true:false );
2096 }
2097 _PI_ShowHints(ci,aspect==1);
2098
2099 list = GWidgetGetControl(ci->gw,CID_ActiveHints);
2100 hm = NULL;
2101 /* Figure out what hintmask is active at the current point */
2102 /* Note: we must walk each ss backwards because we reverse the splineset */
2103 /* when we output postscript */
2104 for ( spl = ci->sc->layers[ly_fore].splines; spl!=NULL; spl=spl->next ) {
2105 for ( sp=spl->first; ; ) {
2106 if ( sp->hintmask )
2107 hm = sp->hintmask;
2108 if ( sp==ci->cursp )
2109 break;
2110 if ( sp->prev==NULL )
2111 break;
2112 sp = sp->prev->from;
2113 if ( sp==spl->first )
2114 break;
2115 }
2116 if ( sp==ci->cursp )
2117 break;
2118 }
2119 if ( hm==NULL ) {
2120 for ( i=0; i<len; ++i )
2121 GGadgetSelectListItem(list,i,false);
2122 } else {
2123 for ( i=0; i<len && i<HntMax; ++i )
2124 GGadgetSelectListItem(list,i, (*hm)[i>>3]&(0x80>>(i&7))?true:false );
2125 }
2126 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_NextDef),ci->cursp->next!=NULL);
2127 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_PrevDef),ci->cursp->prev!=NULL);
2128 }
2129
PI_NextPrev(GGadget * g,GEvent * e)2130 static int PI_NextPrev(GGadget *g, GEvent *e) {
2131 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2132 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2133 CharView *cv = ci->cv;
2134 int cid = GGadgetGetCid(g);
2135 SplinePointList *spl;
2136
2137 PI_FixStuff(ci);
2138
2139 ci->cursp->selected = false;
2140 if ( cid == CID_Next ) {
2141 if ( ci->cursp->next!=NULL && ci->cursp->next->to!=ci->curspl->first )
2142 ci->cursp = ci->cursp->next->to;
2143 else {
2144 if ( ci->curspl->next == NULL ) {
2145 ci->curspl = cv->b.layerheads[cv->b.drawmode]->splines;
2146 GDrawBeep(NULL);
2147 } else
2148 ci->curspl = ci->curspl->next;
2149 ci->cursp = ci->curspl->first;
2150 }
2151 } else if ( cid == CID_Prev ) {
2152 if ( ci->cursp!=ci->curspl->first ) {
2153 ci->cursp = ci->cursp->prev->from;
2154 } else {
2155 if ( ci->curspl==cv->b.layerheads[cv->b.drawmode]->splines ) {
2156 for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl->next!=NULL; spl=spl->next );
2157 GDrawBeep(NULL);
2158 } else {
2159 for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl->next!=ci->curspl; spl=spl->next );
2160 }
2161 ci->curspl = spl;
2162 ci->cursp = spl->last;
2163 if ( spl->last==spl->first && spl->last->prev!=NULL )
2164 ci->cursp = ci->cursp->prev->from;
2165 }
2166 } else if ( cid==CID_NextC ) {
2167 if ( ci->cursp->next!=NULL )
2168 ci->cursp = ci->cursp->next->to;
2169 else {
2170 ci->cursp = ci->curspl->first;
2171 GDrawBeep(NULL);
2172 }
2173 } else /* CID_PrevC */ {
2174 if ( ci->cursp->prev!=NULL )
2175 ci->cursp = ci->cursp->prev->from;
2176 else {
2177 ci->cursp = ci->curspl->last;
2178 GDrawBeep(NULL);
2179 }
2180 }
2181 ci->cursp->selected = true;
2182 PIChangePoint(ci);
2183 CVShowPoint(cv,&ci->cursp->me);
2184 SCUpdateAll(cv->b.sc);
2185 }
2186 return( true );
2187 }
2188
PI_InterpChanged(GGadget * g,GEvent * e)2189 static int PI_InterpChanged(GGadget *g, GEvent *e) {
2190 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
2191 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2192 SplinePoint *cursp = ci->cursp;
2193
2194 if ( GGadgetGetCid(g)==CID_Interpolated ) {
2195 if ( cursp->nonextcp && cursp->noprevcp )
2196 /* Do Nothing */;
2197 else {
2198 if ( cursp->nonextcp && cursp->next ) {
2199 SplinePoint *n = cursp->next->to;
2200 cursp->nextcp.x = rint((n->me.x+cursp->me.x)/2);
2201 cursp->nextcp.y = rint((n->me.y+cursp->me.y)/2);
2202 n->prevcp = cursp->nextcp;
2203 cursp->nonextcp = n->noprevcp = false;
2204 }
2205 if ( cursp->noprevcp && cursp->prev ) {
2206 SplinePoint *p = cursp->prev->from;
2207 cursp->prevcp.x = rint((p->me.x+cursp->me.x)/2);
2208 cursp->prevcp.y = rint((p->me.y+cursp->me.y)/2);
2209 p->nextcp = cursp->prevcp;
2210 cursp->noprevcp = p->nonextcp = false;
2211 }
2212 cursp->me.x = (cursp->nextcp.x + cursp->prevcp.x)/2;
2213 cursp->me.y = (cursp->nextcp.y + cursp->prevcp.y)/2;
2214 if ( cursp->pointtype==pt_tangent ) {
2215 cursp->pointtype = pt_curve;
2216 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Curve),true);
2217 }
2218 if ( cursp->next!=NULL )
2219 SplineRefigure(cursp->next);
2220 if ( cursp->prev!=NULL )
2221 SplineRefigure(cursp->prev);
2222 SplineSetSpirosClear(ci->curspl);
2223 CVCharChangedUpdate(&ci->cv->b);
2224 }
2225 PIFillup(ci,0);
2226 }
2227 PIShowHide(ci);
2228 }
2229 return( true );
2230 }
2231
PI_NeverInterpChanged(GGadget * g,GEvent * e)2232 static int PI_NeverInterpChanged(GGadget *g, GEvent *e) {
2233 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
2234 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2235 int never = GGadgetIsChecked(g);
2236
2237 GGadgetSetEnabled(GWidgetGetControl(ci->gw,CID_Interpolated),!never);
2238
2239 if ( never )
2240 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Normal),true);
2241 ci->cursp->dontinterpolate = never;
2242 PIShowHide(ci);
2243 }
2244 return( true );
2245 }
2246
PI_BaseChanged(GGadget * g,GEvent * e)2247 static int PI_BaseChanged(GGadget *g, GEvent *e) {
2248 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
2249 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2250 real dx=0, dy=0;
2251 int err=false;
2252 SplinePoint *cursp = ci->cursp;
2253
2254 if ( GGadgetGetCid(g)==CID_BaseX )
2255 dx = GetCalmReal8(ci->gw,CID_BaseX,_("Base X"),&err)-cursp->me.x;
2256 else
2257 dy = GetCalmReal8(ci->gw,CID_BaseY,_("Base Y"),&err)-cursp->me.y;
2258 if ( (dx==0 && dy==0) || err )
2259 return( true );
2260 cursp->me.x += dx;
2261 cursp->nextcp.x += dx;
2262 cursp->prevcp.x += dx;
2263 cursp->me.y += dy;
2264 cursp->nextcp.y += dy;
2265 cursp->prevcp.y += dy;
2266 if ( ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 ) {
2267 SplinePointNextCPChanged2(cursp);
2268 SplinePointPrevCPChanged2(cursp);
2269 }
2270 if ( cursp->next!=NULL )
2271 SplineRefigure(cursp->next);
2272 if ( cursp->prev!=NULL )
2273 SplineRefigure(cursp->prev);
2274 SplineSetSpirosClear(ci->curspl);
2275 CVCharChangedUpdate(&ci->cv->b);
2276 PIFillup(ci,GGadgetGetCid(g));
2277 } else if ( e->type==et_controlevent &&
2278 e->u.control.subtype == et_textfocuschanged &&
2279 e->u.control.u.tf_focus.gained_focus ) {
2280 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2281 PI_FigureNext(ci);
2282 PI_FigurePrev(ci);
2283 }
2284 return( true );
2285 }
2286
PI_NextChanged(GGadget * g,GEvent * e)2287 static int PI_NextChanged(GGadget *g, GEvent *e) {
2288 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
2289 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2290 real dx=0, dy=0;
2291 int err=false;
2292 SplinePoint *cursp = ci->cursp;
2293
2294 if ( GGadgetGetCid(g)==CID_NextXOff ) {
2295 dx = GetCalmReal8(ci->gw,CID_NextXOff,_("Next CP X"),&err)-(cursp->nextcp.x-cursp->me.x);
2296 if ( cursp->pointtype==pt_tangent && cursp->prev!=NULL ) {
2297 if ( cursp->prev->from->me.x==cursp->me.x ) {
2298 dy = dx; dx = 0; /* They should be constrained not to change in the x direction */
2299 } else
2300 dy = dx*(cursp->prev->from->me.y-cursp->me.y)/(cursp->prev->from->me.x-cursp->me.x);
2301 }
2302 } else if ( GGadgetGetCid(g)==CID_NextYOff ) {
2303 dy = GetCalmReal8(ci->gw,CID_NextYOff,_("Next CP Y"),&err)-(cursp->nextcp.y-cursp->me.y);
2304 if ( cursp->pointtype==pt_tangent && cursp->prev!=NULL ) {
2305 if ( cursp->prev->from->me.y==cursp->me.y ) {
2306 dx = dy; dy = 0; /* They should be constrained not to change in the y direction */
2307 } else
2308 dx = dy*(cursp->prev->from->me.x-cursp->me.x)/(cursp->prev->from->me.y-cursp->me.y);
2309 }
2310 } else {
2311 double len, theta;
2312 len = GetCalmReal8(ci->gw,CID_NextR,_("Next CP Dist"),&err);
2313 theta = GetCalmReal8(ci->gw,CID_NextTheta,_("Next CP Angle"),&err)/RAD2DEG;
2314 dx = len*cos(theta) - (cursp->nextcp.x-cursp->me.x);
2315 dy = len*sin(theta) - (cursp->nextcp.y-cursp->me.y);
2316 }
2317 if ( (dx==0 && dy==0) || err )
2318 return( true );
2319 if ( cursp->pointtype==pt_hvcurve ) {
2320 BasePoint diff;
2321 diff.x = cursp->nextcp.x+dx - cursp->me.x;
2322 diff.y = cursp->nextcp.y+dy - cursp->me.y;
2323 BP_HVForce(&diff);
2324 dx = diff.x + (cursp->me.x - cursp->nextcp.x);
2325 dy = diff.y + (cursp->me.y - cursp->nextcp.y);
2326 }
2327 cursp->nextcp.x += dx;
2328 cursp->nextcp.y += dy;
2329 cursp->nonextcp = false;
2330 SplineSetSpirosClear(ci->curspl);
2331 ci->nextchanged = true;
2332 if (( dx>.1 || dx<-.1 || dy>.1 || dy<-.1 ) && cursp->nextcpdef ) {
2333 cursp->nextcpdef = false;
2334 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_NextDef), false );
2335 }
2336 if (( cursp->pointtype==pt_curve || cursp->pointtype==pt_hvcurve) && cursp->prev!=NULL ) {
2337 double plen, ntheta;
2338 double ndx, ndy;
2339 ndx = ci->cursp->nextcp.x-ci->cursp->me.x;
2340 ndy = ci->cursp->nextcp.y-ci->cursp->me.y;
2341 ntheta = atan2(ndy,ndx);
2342 plen = GetCalmReal8(ci->gw,CID_PrevR,_("Prev CP Dist"),&err);
2343 ci->cursp->prevcp.x = ci->cursp->me.x - plen*cos(ntheta);
2344 ci->cursp->prevcp.y = ci->cursp->me.y - plen*sin(ntheta);
2345 if ( ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 )
2346 SplinePointPrevCPChanged2(cursp);
2347 SplineRefigure(cursp->prev);
2348 }
2349 if ( ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 )
2350 SplinePointNextCPChanged2(cursp);
2351 if ( cursp->next!=NULL )
2352 SplineRefigure(cursp->next);
2353 CVCharChangedUpdate(&ci->cv->b);
2354 PIFillup(ci,GGadgetGetCid(g));
2355 } else if ( e->type==et_controlevent &&
2356 e->u.control.subtype == et_textfocuschanged &&
2357 e->u.control.u.tf_focus.gained_focus ) {
2358 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2359 PI_FigureNext(ci);
2360 }
2361 return( true );
2362 }
2363
PI_PrevChanged(GGadget * g,GEvent * e)2364 static int PI_PrevChanged(GGadget *g, GEvent *e) {
2365 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
2366 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2367 real dx=0, dy=0;
2368 int err=false;
2369 SplinePoint *cursp = ci->cursp;
2370
2371 if ( GGadgetGetCid(g)==CID_PrevXOff ) {
2372 dx = GetCalmReal8(ci->gw,CID_PrevXOff,_("Prev CP X"),&err)-(cursp->prevcp.x-cursp->me.x);
2373 if ( cursp->pointtype==pt_tangent && cursp->next!=NULL ) {
2374 if ( cursp->next->to->me.x==cursp->me.x ) {
2375 dy = dx; dx = 0; /* They should be constrained not to change in the x direction */
2376 } else
2377 dy = dx*(cursp->next->to->me.y-cursp->me.y)/(cursp->next->to->me.x-cursp->me.x);
2378 }
2379 } else if ( GGadgetGetCid(g)==CID_PrevYOff ) {
2380 dy = GetCalmReal8(ci->gw,CID_PrevYOff,_("Prev CP Y"),&err)-(cursp->prevcp.y-cursp->me.y);
2381 if ( cursp->pointtype==pt_tangent && cursp->next!=NULL ) {
2382 if ( cursp->next->to->me.y==cursp->me.y ) {
2383 dx = dy; dy = 0; /* They should be constrained not to change in the y direction */
2384 } else
2385 dx = dy*(cursp->next->to->me.x-cursp->me.x)/(cursp->next->to->me.y-cursp->me.y);
2386 }
2387 } else {
2388 double len, theta;
2389 len = GetCalmReal8(ci->gw,CID_PrevR,_("Prev CP Dist"),&err);
2390 theta = GetCalmReal8(ci->gw,CID_PrevTheta,_("Prev CP Angle"),&err)/RAD2DEG;
2391 dx = len*cos(theta) - (cursp->prevcp.x-cursp->me.x);
2392 dy = len*sin(theta) - (cursp->prevcp.y-cursp->me.y);
2393 }
2394 if ( (dx==0 && dy==0) || err )
2395 return( true );
2396 if ( cursp->pointtype==pt_hvcurve ) {
2397 BasePoint diff;
2398 diff.x = cursp->prevcp.x+dx - cursp->me.x;
2399 diff.y = cursp->prevcp.y+dy - cursp->me.y;
2400 BP_HVForce(&diff);
2401 dx = diff.x - (cursp->prevcp.x - cursp->me.x);
2402 dy = diff.y - (cursp->prevcp.y - cursp->me.y);
2403 }
2404 cursp->prevcp.x += dx;
2405 cursp->prevcp.y += dy;
2406 cursp->noprevcp = false;
2407 ci->prevchanged = true;
2408 SplineSetSpirosClear(ci->curspl);
2409 if (( dx>.1 || dx<-.1 || dy>.1 || dy<-.1 ) && cursp->prevcpdef ) {
2410 cursp->prevcpdef = false;
2411 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_PrevDef), false );
2412 }
2413 if (( cursp->pointtype==pt_curve || cursp->pointtype==pt_hvcurve) && cursp->next!=NULL ) {
2414 double nlen, ptheta;
2415 double pdx, pdy;
2416 pdx = ci->cursp->prevcp.x-ci->cursp->me.x;
2417 pdy = ci->cursp->prevcp.y-ci->cursp->me.y;
2418 ptheta = atan2(pdy,pdx);
2419 nlen = GetCalmReal8(ci->gw,CID_NextR,_("Next CP Dist"),&err);
2420 ci->cursp->nextcp.x = ci->cursp->me.x - nlen*cos(ptheta);
2421 ci->cursp->nextcp.y = ci->cursp->me.y - nlen*sin(ptheta);
2422 if ( ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 )
2423 SplinePointNextCPChanged2(cursp);
2424 SplineRefigure(cursp->next);
2425 }
2426 if ( ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 )
2427 SplinePointPrevCPChanged2(cursp);
2428 if ( cursp->prev!=NULL )
2429 SplineRefigure(cursp->prev);
2430 CVCharChangedUpdate(&ci->cv->b);
2431 PIFillup(ci,GGadgetGetCid(g));
2432 } else if ( e->type==et_controlevent &&
2433 e->u.control.subtype == et_textfocuschanged &&
2434 e->u.control.u.tf_focus.gained_focus ) {
2435 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2436 PI_FigurePrev(ci);
2437 }
2438 return( true );
2439 }
2440
PI_NextIntChanged(GGadget * g,GEvent * e)2441 static int PI_NextIntChanged(GGadget *g, GEvent *e) {
2442 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
2443 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2444 real x=0, y=0;
2445 int err=false;
2446 SplinePoint *cursp = ci->cursp;
2447
2448 x = GetCalmReal8(ci->gw,CID_NextX,_("Next CP X"),&err);
2449 y = GetCalmReal8(ci->gw,CID_NextY,_("Next CP Y"),&err);
2450 if ( err || (x==cursp->nextcp.x && y==cursp->nextcp.y) )
2451 return( true );
2452 cursp->nextcp.x = x;
2453 cursp->nextcp.y = y;
2454 cursp->me.x = (cursp->nextcp.x + cursp->prevcp.x)/2;
2455 cursp->me.y = (cursp->nextcp.y + cursp->prevcp.y)/2;
2456 SplineSetSpirosClear(ci->curspl);
2457 if ( ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 )
2458 SplinePointNextCPChanged2(cursp);
2459 if ( cursp->next!=NULL )
2460 SplineRefigure(cursp->next);
2461 CVCharChangedUpdate(&ci->cv->b);
2462 PIFillup(ci,GGadgetGetCid(g));
2463 } else if ( e->type==et_controlevent &&
2464 e->u.control.subtype == et_textfocuschanged &&
2465 e->u.control.u.tf_focus.gained_focus ) {
2466 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2467 PI_FigureNext(ci);
2468 }
2469 return( true );
2470 }
2471
PI_PrevIntChanged(GGadget * g,GEvent * e)2472 static int PI_PrevIntChanged(GGadget *g, GEvent *e) {
2473 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
2474 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2475 real x=0, y=0;
2476 int err=false;
2477 SplinePoint *cursp = ci->cursp;
2478
2479 x = GetCalmReal8(ci->gw,CID_PrevX,_("Prev CP X"),&err);
2480 y = GetCalmReal8(ci->gw,CID_PrevY,_("Prev CP Y"),&err);
2481 if ( err || (x==cursp->prevcp.x && y==cursp->prevcp.y) )
2482 return( true );
2483 cursp->prevcp.x = x;
2484 cursp->prevcp.y = y;
2485 cursp->me.x = (cursp->nextcp.x + cursp->prevcp.x)/2;
2486 cursp->me.y = (cursp->nextcp.y + cursp->prevcp.y)/2;
2487 SplineSetSpirosClear(ci->curspl);
2488 if ( ci->cv->b.layerheads[ci->cv->b.drawmode]->order2 )
2489 SplinePointPrevCPChanged2(cursp);
2490 if ( cursp->prev!=NULL )
2491 SplineRefigure(cursp->prev);
2492 CVCharChangedUpdate(&ci->cv->b);
2493 PIFillup(ci,GGadgetGetCid(g));
2494 } else if ( e->type==et_controlevent &&
2495 e->u.control.subtype == et_textfocuschanged &&
2496 e->u.control.u.tf_focus.gained_focus ) {
2497 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2498 PI_FigureNext(ci);
2499 }
2500 return( true );
2501 }
2502
PI_NextDefChanged(GGadget * g,GEvent * e)2503 static int PI_NextDefChanged(GGadget *g, GEvent *e) {
2504 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
2505 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2506 SplinePoint *cursp = ci->cursp;
2507
2508 cursp->nextcpdef = GGadgetIsChecked(g);
2509 /* If they turned def off, that's a noop, but if they turned it on... */
2510 /* then set things to the default */
2511 if ( cursp->nextcpdef ) {
2512 BasePoint temp = cursp->prevcp;
2513 SplineCharDefaultNextCP(cursp);
2514 if ( !cursp->prevcpdef ) {
2515 cursp->prevcp = temp;
2516 SplineSetSpirosClear(ci->curspl);
2517 }
2518 CVCharChangedUpdate(&ci->cv->b);
2519 PIFillup(ci,GGadgetGetCid(g));
2520 }
2521 }
2522 return( true );
2523 }
2524
PI_PrevDefChanged(GGadget * g,GEvent * e)2525 static int PI_PrevDefChanged(GGadget *g, GEvent *e) {
2526 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
2527 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2528 SplinePoint *cursp = ci->cursp;
2529
2530 cursp->prevcpdef = GGadgetIsChecked(g);
2531 /* If they turned def off, that's a noop, but if they turned it on... */
2532 /* then set things to the default */
2533 if ( cursp->prevcpdef ) {
2534 BasePoint temp = cursp->nextcp;
2535 SplineCharDefaultPrevCP(cursp);
2536 if ( !cursp->nextcpdef ) {
2537 cursp->nextcp = temp;
2538 SplineSetSpirosClear(ci->curspl);
2539 }
2540 CVCharChangedUpdate(&ci->cv->b);
2541 PIFillup(ci,GGadgetGetCid(g));
2542 }
2543 }
2544 return( true );
2545 }
2546
PI_PTypeChanged(GGadget * g,GEvent * e)2547 static int PI_PTypeChanged(GGadget *g, GEvent *e) {
2548 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
2549 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2550 SplinePoint *cursp = ci->cursp;
2551 enum pointtype pt = GGadgetGetCid(g)-CID_Curve + pt_curve;
2552
2553 if ( pt==cursp->pointtype ) {
2554 /* Can't happen */
2555 } else if ( pt==pt_corner ) {
2556 cursp->pointtype = pt_corner;
2557 CVCharChangedUpdate(&ci->cv->b);
2558 } else {
2559 SPChangePointType(cursp,pt);
2560 SplineSetSpirosClear(ci->curspl);
2561 CVCharChangedUpdate(&ci->cv->b);
2562 PIFillup(ci,GGadgetGetCid(g));
2563 }
2564 }
2565 return( true );
2566 }
2567
PI_AspectChange(GGadget * g,GEvent * e)2568 static int PI_AspectChange(GGadget *g, GEvent *e) {
2569 if ( e==NULL || (e->type==et_controlevent && e->u.control.subtype == et_radiochanged )) {
2570 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2571 int aspect = GTabSetGetSel(g);
2572
2573 _PI_ShowHints(ci,aspect==1);
2574 }
2575 return( true );
2576 }
2577
PI_HintSel(GGadget * g,GEvent * e)2578 static int PI_HintSel(GGadget *g, GEvent *e) {
2579 if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
2580 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
2581
2582 _PI_ShowHints(ci,true);
2583
2584 if ( GGadgetIsListItemSelected(g,e->u.control.u.list.changed_index)) {
2585 /* If we just selected something, check to make sure it doesn't */
2586 /* conflict with any other hints. */
2587 /* Adobe says this is an error, but in "three" in AdobeSansMM */
2588 /* (in black,extended) we have a hintmask which contains two */
2589 /* overlapping hints */
2590 /* So just make it a warning */
2591 int i,j;
2592 StemInfo *h, *h2=NULL;
2593 for ( i=0, h=ci->cv->b.sc->hstem; h!=NULL && i!=e->u.control.u.list.changed_index; h=h->next, ++i );
2594 if ( h!=NULL ) {
2595 for ( h2 = ci->cv->b.sc->hstem, i=0 ; h2!=NULL; h2=h2->next, ++i ) {
2596 if ( h2!=h && GGadgetIsListItemSelected(g,i)) {
2597 if (( h2->start<h->start && h2->start+h2->width>h->start ) ||
2598 ( h2->start>=h->start && h->start+h->width>h2->start ))
2599 break;
2600 }
2601 }
2602 } else {
2603 j = i;
2604 for ( h=ci->cv->b.sc->vstem; h!=NULL && i!=e->u.control.u.list.changed_index; h=h->next, ++i );
2605 if ( h==NULL )
2606 IError("Failed to find hint");
2607 else {
2608 for ( h2 = ci->cv->b.sc->vstem, i=j ; h2!=NULL; h2=h2->next, ++i ) {
2609 if ( h2!=h && GGadgetIsListItemSelected(g,i)) {
2610 if (( h2->start<h->start && h2->start+h2->width>h->start ) ||
2611 ( h2->start>=h->start && h->start+h->width>h2->start ))
2612 break;
2613 }
2614 }
2615 }
2616 }
2617 if ( h2!=NULL )
2618 ff_post_error(_("Overlapped Hints"),_("The hint you have just selected overlaps with <%.2f,%.2f>. You should deselect one of the two."),
2619 h2->start,h2->width);
2620 }
2621 }
2622 return( true );
2623 }
2624
SCHintList(SplineChar * sc,HintMask * hm)2625 GTextInfo *SCHintList(SplineChar *sc,HintMask *hm) {
2626 StemInfo *h;
2627 int i;
2628 GTextInfo *ti;
2629 char buffer[100];
2630
2631 for ( h=sc->hstem, i=0; h!=NULL; h=h->next, ++i );
2632 for ( h=sc->vstem ; h!=NULL; h=h->next, ++i );
2633 ti = calloc(i+1,sizeof(GTextInfo));
2634
2635 for ( h=sc->hstem, i=0; h!=NULL; h=h->next, ++i ) {
2636 ti[i].fg = ti[i].bg = COLOR_DEFAULT;
2637 ti[i].userdata = h;
2638 if ( h->ghost && h->width>0 )
2639 sprintf( buffer, "H<%g,%g>",
2640 rint(h->start*100)/100+rint(h->width*100)/100, -rint(h->width*100)/100 );
2641 else
2642 sprintf( buffer, "H<%g,%g>",
2643 rint(h->start*100)/100, rint(h->width*100)/100 );
2644 ti[i].text = uc_copy(buffer);
2645 if ( hm!=NULL && ((*hm)[i>>3]&(0x80>>(i&7))))
2646 ti[i].selected = true;
2647 }
2648
2649 for ( h=sc->vstem ; h!=NULL; h=h->next, ++i ) {
2650 ti[i].fg = ti[i].bg = COLOR_DEFAULT;
2651 ti[i].userdata = h;
2652 if ( h->ghost && h->width>0 )
2653 sprintf( buffer, "V<%g,%g>",
2654 rint(h->start*100)/100+rint(h->width*100)/100, -rint(h->width*100)/100 );
2655 else
2656 sprintf( buffer, "V<%g,%g>",
2657 rint(h->start*100)/100, rint(h->width*100)/100 );
2658 ti[i].text = uc_copy(buffer);
2659 if ( hm!=NULL && ((*hm)[i>>3]&(0x80>>(i&7))))
2660 ti[i].selected = true;
2661 }
2662 return( ti );
2663 }
2664
PointGetInfo(CharView * cv,SplinePoint * sp,SplinePointList * spl)2665 static void PointGetInfo(CharView *cv, SplinePoint *sp, SplinePointList *spl) {
2666 CharViewTab* tab = CVGetActiveTab(cv);
2667 GIData* gi = 0;
2668 GRect pos;
2669 GWindowAttrs wattrs;
2670 const int gcdcount = 54;
2671 GGadgetCreateData gcd[gcdcount], hgcd[2], h2gcd[2], mgcd[11];
2672 GGadgetCreateData mb[5], pb[9];
2673 GGadgetCreateData *marray[11], *marray2[5], *marray3[5], *marray4[7],
2674 *varray[11], *harray1[4], *harray2[6], *hvarray1[25], *hvarray2[25],
2675 *hvarray3[16], *harray3[13];
2676 GTextInfo label[54], mlabel[11];
2677 GTabInfo aspects[4];
2678 static GBox cur, nextcp, prevcp;
2679 extern Color nextcpcol, prevcpcol;
2680 GWindow root;
2681 GRect screensize;
2682 GPoint pt;
2683 int j, defxpos, nextstarty, k, l;
2684
2685 gi = calloc(1,sizeof(GIData));
2686
2687 cur.main_background = nextcp.main_background = prevcp.main_background = COLOR_DEFAULT;
2688 cur.main_foreground = 0xff0000;
2689 nextcp.main_foreground = nextcpcol;
2690 prevcp.main_foreground = prevcpcol;
2691 gi->cv = cv;
2692 gi->sc = cv->b.sc;
2693 gi->cursp = sp;
2694 gi->curspl = spl;
2695 gi->oldstate = SplinePointListCopy(cv->b.layerheads[cv->b.drawmode]->splines);
2696 gi->done = false;
2697 CVPreserveState(&cv->b);
2698
2699 root = GDrawGetRoot(NULL);
2700 GDrawGetSize(root,&screensize);
2701
2702 memset(&wattrs,0,sizeof(wattrs));
2703 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_positioned|wam_isdlg;
2704 wattrs.event_masks = ~(1<<et_charup);
2705 wattrs.restrict_input_to_me = 1;
2706 wattrs.positioned = 1;
2707 wattrs.cursor = ct_pointer;
2708 wattrs.utf8_window_title = _("Point Info");
2709 wattrs.is_dlg = true;
2710 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,PI_Width));
2711 pos.height = GDrawPointsToPixels(NULL,PI_Height);
2712 pt.x = tab->xoff + rint(sp->me.x*tab->scale);
2713 pt.y = -tab->yoff + cv->height - rint(sp->me.y*tab->scale);
2714 GDrawTranslateCoordinates(cv->v,root,&pt);
2715 if ( pt.x+20+pos.width<=screensize.width )
2716 pos.x = pt.x+20;
2717 else if ( (pos.x = pt.x-10-screensize.width)<0 )
2718 pos.x = 0;
2719 pos.y = pt.y;
2720 if ( pos.y+pos.height+20 > screensize.height )
2721 pos.y = screensize.height - pos.height - 20;
2722 if ( pos.y<0 ) pos.y = 0;
2723 gi->gw = GDrawCreateTopWindow(NULL,&pos,pi_e_h,gi,&wattrs);
2724
2725 memset(&gcd,0,sizeof(gcd));
2726 memset(&label,0,sizeof(label));
2727 memset(&hgcd,0,sizeof(hgcd));
2728 memset(&h2gcd,0,sizeof(h2gcd));
2729 memset(&mgcd,0,sizeof(mgcd));
2730 memset(&mlabel,0,sizeof(mlabel));
2731 memset(&aspects,0,sizeof(aspects));
2732 memset(&pb,0,sizeof(pb));
2733
2734 j=k=0;
2735 gi->gcd = malloc( gcdcount*sizeof(GGadgetCreateData) );
2736 memcpy( gi->gcd, gcd, gcdcount*sizeof(GGadgetCreateData) );
2737
2738 label[j].text = (unichar_t *) _("_Normal");
2739 label[j].text_is_1byte = true;
2740 label[j].text_in_resource = true;
2741 gcd[j].gd.label = &label[j];
2742 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = 5;
2743 gcd[j].gd.flags = gg_enabled|gg_visible|gg_cb_on;
2744 gcd[j].gd.cid = CID_Normal;
2745 gcd[j].gd.handle_controlevent = PI_InterpChanged;
2746 gcd[j].creator = GRadioCreate;
2747 harray1[0] = &gcd[j];
2748 ++j;
2749
2750 label[j].text = (unichar_t *) _("_Interpolated");
2751 label[j].text_is_1byte = true;
2752 label[j].text_in_resource = true;
2753 gcd[j].gd.label = &label[j];
2754 gcd[j].gd.pos.x = 70; gcd[j].gd.pos.y = 5;
2755 gcd[j].gd.flags = gg_enabled|gg_visible | gg_rad_continueold;
2756 gcd[j].gd.cid = CID_Interpolated;
2757 gcd[j].gd.handle_controlevent = PI_InterpChanged;
2758 gcd[j].creator = GRadioCreate;
2759 harray1[1] = &gcd[j]; harray1[2] = GCD_Glue; harray1[3] = NULL;
2760 ++j;
2761
2762 pb[2].gd.flags = gg_enabled|gg_visible;
2763 pb[2].gd.u.boxelements = harray1;
2764 pb[2].creator = GHBoxCreate;
2765 varray[k++] = &pb[2];
2766
2767 label[j].text = (unichar_t *) _("N_ever Interpolate");
2768 label[j].text_is_1byte = true;
2769 label[j].text_in_resource = true;
2770 gcd[j].gd.label = &label[j];
2771 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+16;
2772 gcd[j].gd.flags = cv->b.layerheads[cv->b.drawmode]->order2 ? (gg_enabled|gg_visible) : gg_visible;
2773 gcd[j].gd.cid = CID_NeverInterpolate;
2774 gcd[j].gd.handle_controlevent = PI_NeverInterpChanged;
2775 gcd[j].creator = GCheckBoxCreate;
2776 varray[k++] = &gcd[j];
2777 ++j;
2778
2779 gi->normal_start = j;
2780 label[j].text = (unichar_t *) _("_Base:");
2781 label[j].text_is_1byte = true;
2782 label[j].text_in_resource = true;
2783 gcd[j].gd.label = &label[j];
2784 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+17+6;
2785 gcd[j].gd.flags = gg_enabled|gg_visible|gg_dontcopybox;
2786 gcd[j].gd.box = &cur;
2787 gcd[j].creator = GLabelCreate;
2788 harray2[0] = &gcd[j]; harray2[1] = GCD_Glue;
2789 ++j;
2790
2791 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-6; gcd[j].gd.pos.width = 70;
2792 gcd[j].gd.flags = gg_enabled|gg_visible;
2793 gcd[j].gd.cid = CID_BaseX;
2794 gcd[j].gd.handle_controlevent = PI_BaseChanged;
2795 gcd[j].creator = GNumericFieldCreate;
2796 harray2[2] = &gcd[j];
2797 ++j;
2798
2799 gcd[j].gd.pos.x = 137; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 70;
2800 gcd[j].gd.flags = gg_enabled|gg_visible;
2801 gcd[j].gd.cid = CID_BaseY;
2802 gcd[j].gd.handle_controlevent = PI_BaseChanged;
2803 gcd[j].creator = GNumericFieldCreate;
2804 harray2[3] = &gcd[j]; harray2[4] = GCD_Glue; harray2[5] = NULL;
2805 ++j;
2806
2807 pb[3].gd.flags = gg_enabled|gg_visible;
2808 pb[3].gd.u.boxelements = harray2;
2809 pb[3].creator = GHBoxCreate;
2810 varray[k++] = &pb[3];
2811
2812 l = 0;
2813 label[j].text = (unichar_t *) _("Prev CP:");
2814 label[j].text_is_1byte = true;
2815 gcd[j].gd.label = &label[j];
2816 gcd[j].gd.pos.x = 9; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+24+4;
2817 gcd[j].gd.flags = gg_enabled|gg_visible|gg_dontcopybox;
2818 gcd[j].gd.box = &prevcp;
2819 gcd[j].creator = GLabelCreate;
2820 hvarray1[l++] = &gcd[j]; hvarray1[l++] = GCD_Glue;
2821 ++j;
2822
2823 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 65;
2824 gcd[j].gd.flags = gg_enabled|gg_visible;
2825 gcd[j].gd.cid = CID_PrevPos;
2826 gcd[j].creator = GLabelCreate;
2827 hvarray1[l++] = &gcd[j];
2828 ++j;
2829
2830 defxpos = 130;
2831 label[j].text = (unichar_t *) S_("ControlPoint|Default");
2832 label[j].text_is_1byte = true;
2833 gcd[j].gd.label = &label[j];
2834 gcd[j].gd.pos.x = defxpos; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-3;
2835 gcd[j].gd.flags = (gg_enabled|gg_visible);
2836 gcd[j].gd.cid = CID_PrevDef;
2837 gcd[j].gd.handle_controlevent = PI_PrevDefChanged;
2838 gcd[j].creator = GCheckBoxCreate;
2839 hvarray1[l++] = &gcd[j]; hvarray1[l++] = GCD_ColSpan; hvarray1[l++] = NULL;
2840 ++j;
2841
2842 label[j].text = (unichar_t *) _("Offset");
2843 label[j].text_is_1byte = true;
2844 gcd[j].gd.label = &label[j];
2845 gcd[j].gd.pos.x = gcd[3].gd.pos.x+10; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+18+4;
2846 gcd[j].gd.flags = gg_enabled|gg_visible;
2847 gcd[j].creator = GLabelCreate;
2848 hvarray1[l++] = &gcd[j]; hvarray1[l++] = GCD_Glue;
2849 ++j;
2850
2851 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-4; gcd[j].gd.pos.width = 70;
2852 gcd[j].gd.flags = gg_enabled|gg_visible;
2853 gcd[j].gd.cid = CID_PrevXOff;
2854 gcd[j].gd.handle_controlevent = PI_PrevChanged;
2855 gcd[j].creator = GNumericFieldCreate;
2856 hvarray1[l++] = &gcd[j];
2857 ++j;
2858
2859 gcd[j].gd.pos.x = 137; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 70;
2860 gcd[j].gd.flags = gg_enabled|gg_visible;
2861 gcd[j].gd.cid = CID_PrevYOff;
2862 gcd[j].gd.handle_controlevent = PI_PrevChanged;
2863 gcd[j].creator = GNumericFieldCreate;
2864 hvarray1[l++] = &gcd[j]; hvarray1[l++] = GCD_ColSpan; hvarray1[l++] = NULL;
2865 ++j;
2866
2867 label[j].text = (unichar_t *) _("Dist");
2868 label[j].text_is_1byte = true;
2869 gcd[j].gd.label = &label[j];
2870 gcd[j].gd.pos.x = gcd[3].gd.pos.x+10; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+28;
2871 gcd[j].gd.flags = gg_enabled|gg_visible;
2872 gcd[j].creator = GLabelCreate;
2873 hvarray1[l++] = &gcd[j]; hvarray1[l++] = GCD_Glue;
2874 ++j;
2875
2876 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-4; gcd[j].gd.pos.width = 70;
2877 gcd[j].gd.flags = gg_enabled|gg_visible;
2878 gcd[j].gd.cid = CID_PrevR;
2879 gcd[j].gd.handle_controlevent = PI_PrevChanged;
2880 gcd[j].creator = GNumericFieldCreate;
2881 hvarray1[l++] = &gcd[j];
2882 ++j;
2883
2884 gcd[j].gd.pos.x = 137; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 60;
2885 gcd[j].gd.flags = gg_enabled|gg_visible;
2886 gcd[j].gd.cid = CID_PrevTheta;
2887 gcd[j].gd.handle_controlevent = PI_PrevChanged;
2888 gcd[j].creator = GTextFieldCreate;
2889 hvarray1[l++] = &gcd[j];
2890 ++j;
2891
2892 label[j].text = (unichar_t *) U_("°");
2893 label[j].text_is_1byte = true;
2894 gcd[j].gd.label = &label[j];
2895 gcd[j].gd.pos.x = gcd[j-1].gd.pos.x+gcd[j-1].gd.pos.width+2; gcd[j].gd.pos.y = gcd[j-3].gd.pos.y;
2896 gcd[j].gd.flags = gg_enabled|gg_visible;
2897 gcd[j].creator = GLabelCreate;
2898 hvarray1[l++] = &gcd[j]; hvarray1[l++] = NULL;
2899 ++j;
2900
2901 label[j].text = (unichar_t *) _("Curvature: -0.00000000");
2902 label[j].text_is_1byte = true;
2903 gcd[j].gd.label = &label[j];
2904 gcd[j].gd.pos.x = 9; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+20;
2905 gcd[j].gd.flags = gg_enabled|gg_visible;
2906 gcd[j].gd.cid = CID_PrevCurvature;
2907 gcd[j].creator = GLabelCreate;
2908 hvarray1[l++] = &gcd[j]; hvarray1[l++] = GCD_ColSpan; hvarray1[l++] = GCD_ColSpan;
2909 hvarray1[l++] = GCD_Glue; hvarray1[l++] = GCD_Glue; hvarray1[l++] = NULL;
2910 hvarray1[l++] = NULL;
2911 ++j;
2912
2913 pb[4].gd.pos.x = pb[4].gd.pos.y = 2;
2914 pb[4].gd.flags = gg_enabled|gg_visible;
2915 pb[4].gd.u.boxelements = hvarray1;
2916 pb[4].creator = GHVGroupCreate;
2917 varray[k++] = &pb[4];
2918
2919 l = 0;
2920 nextstarty = gcd[j-2].gd.pos.y+28;
2921 label[j].text = (unichar_t *) _("Next CP:");
2922 label[j].text_is_1byte = true;
2923 gcd[j].gd.label = &label[j];
2924 gcd[j].gd.pos.x = 9; gcd[j].gd.pos.y = nextstarty;
2925 gcd[j].gd.flags = gg_enabled|gg_visible|gg_dontcopybox;
2926 gcd[j].gd.box = &nextcp;
2927 gcd[j].creator = GLabelCreate;
2928 hvarray2[l++] = &gcd[j]; hvarray2[l++] = GCD_Glue;
2929 ++j;
2930
2931 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = nextstarty; gcd[j].gd.pos.width = 65;
2932 gcd[j].gd.flags = gg_enabled|gg_visible;
2933 gcd[j].gd.cid = CID_NextPos;
2934 gcd[j].creator = GLabelCreate;
2935 hvarray2[l++] = &gcd[j];
2936 ++j;
2937
2938 label[j].text = (unichar_t *) S_("ControlPoint|Default");
2939 label[j].text_is_1byte = true;
2940 gcd[j].gd.label = &label[j];
2941 gcd[j].gd.pos.x = defxpos; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-3;
2942 gcd[j].gd.flags = (gg_enabled|gg_visible);
2943 gcd[j].gd.cid = CID_NextDef;
2944 gcd[j].gd.handle_controlevent = PI_NextDefChanged;
2945 gcd[j].creator = GCheckBoxCreate;
2946 hvarray2[l++] = &gcd[j]; hvarray2[l++] = GCD_ColSpan; hvarray2[l++] = NULL;
2947 ++j;
2948
2949 label[j].text = (unichar_t *) _("Offset");
2950 label[j].text_is_1byte = true;
2951 gcd[j].gd.label = &label[j];
2952 gcd[j].gd.pos.x = gcd[3].gd.pos.x+10; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+18+4;
2953 gcd[j].gd.flags = gg_enabled|gg_visible;
2954 gcd[j].creator = GLabelCreate;
2955 hvarray2[l++] = &gcd[j]; hvarray2[l++] = GCD_Glue;
2956 ++j;
2957
2958 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-4; gcd[j].gd.pos.width = 70;
2959 gcd[j].gd.flags = gg_enabled|gg_visible;
2960 gcd[j].gd.cid = CID_NextXOff;
2961 gcd[j].gd.handle_controlevent = PI_NextChanged;
2962 gcd[j].creator = GNumericFieldCreate;
2963 hvarray2[l++] = &gcd[j];
2964 ++j;
2965
2966 gcd[j].gd.pos.x = 137; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 70;
2967 gcd[j].gd.flags = gg_enabled|gg_visible;
2968 gcd[j].gd.cid = CID_NextYOff;
2969 gcd[j].gd.handle_controlevent = PI_NextChanged;
2970 gcd[j].creator = GNumericFieldCreate;
2971 hvarray2[l++] = &gcd[j]; hvarray2[l++] = GCD_ColSpan; hvarray2[l++] = NULL;
2972 ++j;
2973
2974 label[j].text = (unichar_t *) _("Dist");
2975 label[j].text_is_1byte = true;
2976 gcd[j].gd.label = &label[j];
2977 gcd[j].gd.pos.x = gcd[3].gd.pos.x+10; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+28;
2978 gcd[j].gd.flags = gg_enabled|gg_visible;
2979 gcd[j].creator = GLabelCreate;
2980 hvarray2[l++] = &gcd[j]; hvarray2[l++] = GCD_Glue;
2981 ++j;
2982
2983 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-4; gcd[j].gd.pos.width = 70;
2984 gcd[j].gd.flags = gg_enabled|gg_visible;
2985 gcd[j].gd.cid = CID_NextR;
2986 gcd[j].gd.handle_controlevent = PI_NextChanged;
2987 gcd[j].creator = GNumericFieldCreate;
2988 hvarray2[l++] = &gcd[j];
2989 ++j;
2990
2991 gcd[j].gd.pos.x = 137; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 60;
2992 gcd[j].gd.flags = gg_enabled|gg_visible;
2993 gcd[j].gd.cid = CID_NextTheta;
2994 gcd[j].gd.handle_controlevent = PI_NextChanged;
2995 gcd[j].creator = GTextFieldCreate;
2996 hvarray2[l++] = &gcd[j];
2997 ++j;
2998
2999 label[j].text = (unichar_t *) U_("°");
3000 label[j].text_is_1byte = true;
3001 gcd[j].gd.label = &label[j];
3002 gcd[j].gd.pos.x = gcd[j-1].gd.pos.x+gcd[j-1].gd.pos.width+2; gcd[j].gd.pos.y = gcd[j-3].gd.pos.y;
3003 gcd[j].gd.flags = gg_enabled|gg_visible;
3004 gcd[j].creator = GLabelCreate;
3005 hvarray2[l++] = &gcd[j]; hvarray2[l++] = NULL;
3006 ++j;
3007
3008 label[j].text = (unichar_t *) _("Curvature: -0.00000000");
3009 label[j].text_is_1byte = true;
3010 gcd[j].gd.label = &label[j];
3011 gcd[j].gd.pos.x = 9; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+20;
3012 gcd[j].gd.flags = gg_enabled|gg_visible;
3013 gcd[j].gd.cid = CID_NextCurvature;
3014 gcd[j].creator = GLabelCreate;
3015 hvarray2[l++] = &gcd[j]; hvarray2[l++] = GCD_ColSpan; hvarray2[l++] = GCD_ColSpan;
3016 ++j;
3017
3018 label[j].text = (unichar_t *) "∆: -0.00000000";
3019 label[j].text_is_1byte = true;
3020 gcd[j].gd.label = &label[j];
3021 gcd[j].gd.pos.x = 130; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
3022 gcd[j].gd.flags = gg_enabled|gg_visible;
3023 gcd[j].gd.popup_msg = _("This is the difference of the curvature between\nthe next and previous splines. Contours often\nlook nicer as this number approaches 0." );
3024 gcd[j].gd.cid = CID_DeltaCurvature;
3025 gcd[j].creator = GLabelCreate;
3026 hvarray2[l++] = &gcd[j]; hvarray2[l++] = GCD_ColSpan; hvarray2[l++] = NULL;
3027 hvarray2[l++] = NULL;
3028 ++j;
3029
3030 pb[5].gd.pos.x = pb[5].gd.pos.y = 2;
3031 pb[5].gd.flags = gg_enabled|gg_visible;
3032 pb[5].gd.u.boxelements = hvarray2;
3033 pb[5].creator = GHVGroupCreate;
3034 varray[k++] = &pb[5];
3035 gi->normal_end = j;
3036
3037 gi->interp_start = j;
3038 l = 0;
3039 label[j].text = (unichar_t *) _("_Base:");
3040 label[j].text_is_1byte = true;
3041 label[j].text_in_resource = true;
3042 gcd[j].gd.label = &label[j];
3043 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[gi->normal_start].gd.pos.y;
3044 gcd[j].gd.flags = gg_enabled|gg_visible|gg_dontcopybox;
3045 gcd[j].gd.box = &cur;
3046 gcd[j].creator = GLabelCreate;
3047 hvarray3[l++] = &gcd[j]; hvarray3[l++] = GCD_Glue;
3048 ++j;
3049
3050 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 65;
3051 gcd[j].gd.flags = gg_enabled|gg_visible;
3052 gcd[j].gd.cid = CID_BasePos;
3053 gcd[j].creator = GLabelCreate;
3054 hvarray3[l++] = &gcd[j]; hvarray3[l++] = GCD_Glue; hvarray3[l++] = NULL;
3055 ++j;
3056
3057 label[j].text = (unichar_t *) _("Prev CP:");
3058 label[j].text_is_1byte = true;
3059 gcd[j].gd.label = &label[j];
3060 gcd[j].gd.pos.x = 9; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+14+4;
3061 gcd[j].gd.flags = gg_enabled|gg_visible|gg_dontcopybox;
3062 gcd[j].gd.box = &prevcp;
3063 gcd[j].creator = GLabelCreate;
3064 hvarray3[l++] = &gcd[j]; hvarray3[l++] = GCD_Glue;
3065 ++j;
3066
3067 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-4; gcd[j].gd.pos.width = 70;
3068 gcd[j].gd.flags = gg_enabled|gg_visible;
3069 gcd[j].gd.cid = CID_PrevX;
3070 gcd[j].gd.handle_controlevent = PI_PrevIntChanged;
3071 gcd[j].creator = GNumericFieldCreate;
3072 hvarray3[l++] = &gcd[j];
3073 ++j;
3074
3075 gcd[j].gd.pos.x = 137; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 70;
3076 gcd[j].gd.flags = gg_enabled|gg_visible;
3077 gcd[j].gd.cid = CID_PrevY;
3078 gcd[j].gd.handle_controlevent = PI_PrevIntChanged;
3079 gcd[j].creator = GNumericFieldCreate;
3080 hvarray3[l++] = &gcd[j]; hvarray3[l++] = NULL;
3081 ++j;
3082
3083 label[j].text = (unichar_t *) _("Next CP:");
3084 label[j].text_is_1byte = true;
3085 gcd[j].gd.label = &label[j];
3086 gcd[j].gd.pos.x = 9; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+24+4;
3087 gcd[j].gd.flags = gg_enabled|gg_visible|gg_dontcopybox;
3088 gcd[j].gd.box = &nextcp;
3089 gcd[j].creator = GLabelCreate;
3090 hvarray3[l++] = &gcd[j]; hvarray3[l++] = GCD_Glue;
3091 ++j;
3092
3093 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-4; gcd[j].gd.pos.width = 70;
3094 gcd[j].gd.flags = gg_enabled|gg_visible;
3095 gcd[j].gd.cid = CID_NextX;
3096 gcd[j].gd.handle_controlevent = PI_NextIntChanged;
3097 gcd[j].creator = GNumericFieldCreate;
3098 hvarray3[l++] = &gcd[j];
3099 ++j;
3100
3101 gcd[j].gd.pos.x = 137; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 70;
3102 gcd[j].gd.flags = gg_enabled|gg_visible;
3103 gcd[j].gd.cid = CID_NextY;
3104 gcd[j].gd.handle_controlevent = PI_NextIntChanged;
3105 gcd[j].creator = GNumericFieldCreate;
3106 hvarray3[l++] = &gcd[j]; hvarray3[l++] = NULL; hvarray3[l++] = NULL;
3107 ++j;
3108 gi->interp_end = j;
3109
3110 pb[6].gd.flags = gg_enabled|gg_visible;
3111 pb[6].gd.u.boxelements = hvarray3;
3112 pb[6].creator = GHVBoxCreate;
3113 varray[k++] = &pb[6];
3114 varray[k++] = GCD_Glue;
3115
3116 label[j].text = (unichar_t *) _("Type:");
3117 label[j].text_is_1byte = true;
3118 gcd[j].gd.label = &label[j];
3119 gcd[j].gd.pos.x = gcd[0].gd.pos.x; gcd[j].gd.pos.y = gcd[gi->normal_end-2].gd.pos.y+26;
3120 gcd[j].gd.flags = gg_enabled|gg_visible;
3121 gcd[j].creator = GLabelCreate;
3122 harray3[0] = &gcd[j]; harray3[1] = GCD_Glue; harray3[2] = GCD_Glue;
3123 ++j;
3124
3125 label[j].image = &GIcon_midcurve;
3126 gcd[j].gd.label = &label[j];
3127 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-2;
3128 gcd[j].gd.flags = gg_enabled|gg_visible;
3129 gcd[j].gd.cid = CID_Curve;
3130 gcd[j].gd.handle_controlevent = PI_PTypeChanged;
3131 gcd[j].creator = GRadioCreate;
3132 harray3[3] = &gcd[j]; harray3[4] = GCD_Glue;
3133 ++j;
3134
3135 label[j].image = &GIcon_midhvcurve;
3136 gcd[j].gd.label = &label[j];
3137 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-2;
3138 gcd[j].gd.flags = gg_enabled|gg_visible;
3139 gcd[j].gd.cid = CID_HVCurve;
3140 gcd[j].gd.handle_controlevent = PI_PTypeChanged;
3141 gcd[j].creator = GRadioCreate;
3142 harray3[5] = &gcd[j]; harray3[6] = GCD_Glue;
3143 ++j;
3144
3145 label[j].image = &GIcon_midcorner;
3146 gcd[j].gd.label = &label[j];
3147 gcd[j].gd.pos.x = 100; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
3148 gcd[j].gd.flags = gg_enabled|gg_visible | gg_rad_continueold;
3149 gcd[j].gd.cid = CID_Corner;
3150 gcd[j].gd.handle_controlevent = PI_PTypeChanged;
3151 gcd[j].creator = GRadioCreate;
3152 harray3[7] = &gcd[j]; harray3[8] = GCD_Glue;
3153 ++j;
3154
3155 label[j].image = &GIcon_midtangent;
3156 gcd[j].gd.label = &label[j];
3157 gcd[j].gd.pos.x = 140; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
3158 gcd[j].gd.flags = gg_enabled|gg_visible | gg_rad_continueold;
3159 gcd[j].gd.cid = CID_Tangent;
3160 gcd[j].gd.handle_controlevent = PI_PTypeChanged;
3161 gcd[j].creator = GRadioCreate;
3162 harray3[9] = &gcd[j]; harray3[10] = GCD_Glue; harray3[11] = GCD_Glue;
3163 harray3[12] = NULL;
3164 ++j;
3165
3166 pb[7].gd.flags = gg_enabled|gg_visible;
3167 pb[7].gd.u.boxelements = harray3;
3168 pb[7].creator = GHBoxCreate;
3169 varray[k++] = &pb[7];
3170 varray[k++] = NULL;
3171
3172 pb[0].gd.flags = gg_enabled|gg_visible;
3173 pb[0].gd.u.boxelements = varray;
3174 pb[0].creator = GVBoxCreate;
3175
3176 hgcd[0].gd.pos.x = 5; hgcd[0].gd.pos.y = 5;
3177 hgcd[0].gd.pos.width = PI_Width-20; hgcd[0].gd.pos.height = gcd[j-1].gd.pos.y+10;
3178 hgcd[0].gd.flags = gg_visible | gg_enabled | gg_list_multiplesel;
3179 hgcd[0].gd.cid = CID_HintMask;
3180 hgcd[0].gd.u.list = SCHintList(cv->b.sc,NULL);
3181 hgcd[0].gd.handle_controlevent = PI_HintSel;
3182 hgcd[0].creator = GListCreate;
3183
3184 h2gcd[0].gd.pos.x = 5; h2gcd[0].gd.pos.y = 5;
3185 h2gcd[0].gd.pos.width = PI_Width-20; h2gcd[0].gd.pos.height = gcd[j-1].gd.pos.y+10;
3186 h2gcd[0].gd.flags = gg_visible | gg_list_multiplesel;
3187 h2gcd[0].gd.cid = CID_ActiveHints;
3188 h2gcd[0].gd.u.list = SCHintList(cv->b.sc,NULL);
3189 h2gcd[0].creator = GListCreate;
3190
3191 j = 0;
3192
3193 aspects[j].text = (unichar_t *) _("Location");
3194 aspects[j].text_is_1byte = true;
3195 aspects[j++].gcd = pb;
3196
3197 aspects[j].text = (unichar_t *) _("Hint Mask");
3198 aspects[j].text_is_1byte = true;
3199 aspects[j++].gcd = hgcd;
3200
3201 aspects[j].text = (unichar_t *) _("Active Hints");
3202 aspects[j].text_is_1byte = true;
3203 aspects[j++].gcd = h2gcd;
3204
3205 j = 0;
3206
3207 mgcd[j].gd.pos.x = 4; mgcd[j].gd.pos.y = 6;
3208 mgcd[j].gd.pos.width = PI_Width-8;
3209 mgcd[j].gd.pos.height = hgcd[0].gd.pos.height+10+24;
3210 mgcd[j].gd.u.tabs = aspects;
3211 mgcd[j].gd.flags = gg_visible | gg_enabled;
3212 mgcd[j].gd.handle_controlevent = PI_AspectChange;
3213 mgcd[j].gd.cid = CID_TabSet;
3214 mgcd[j++].creator = GTabSetCreate;
3215
3216 mgcd[j].gd.pos.x = (PI_Width-2*50-10)/2; mgcd[j].gd.pos.y = mgcd[j-1].gd.pos.y+mgcd[j-1].gd.pos.height+5;
3217 mgcd[j].gd.pos.width = 53; mgcd[j].gd.pos.height = 0;
3218 mgcd[j].gd.flags = gg_visible | gg_enabled;
3219 mlabel[j].text = (unichar_t *) _("< _Prev");
3220 mlabel[j].text_is_1byte = true;
3221 mlabel[j].text_in_resource = true;
3222 mgcd[j].gd.label = &mlabel[j];
3223 mgcd[j].gd.cid = CID_Prev;
3224 mgcd[j].gd.handle_controlevent = PI_NextPrev;
3225 mgcd[j].creator = GButtonCreate;
3226 ++j;
3227
3228 mgcd[j].gd.pos.x = PI_Width-50-(PI_Width-2*50-10)/2; mgcd[j].gd.pos.y = mgcd[j-1].gd.pos.y;
3229 mgcd[j].gd.pos.width = 53; mgcd[j].gd.pos.height = 0;
3230 mgcd[j].gd.flags = gg_visible | gg_enabled;
3231 mlabel[j].text = (unichar_t *) _("_Next >");
3232 mlabel[j].text_is_1byte = true;
3233 mlabel[j].text_in_resource = true;
3234 mgcd[j].gd.label = &mlabel[j];
3235 mgcd[j].gd.cid = CID_Next;
3236 mgcd[j].gd.handle_controlevent = PI_NextPrev;
3237 mgcd[j].creator = GButtonCreate;
3238 ++j;
3239
3240 /* Why 3? */
3241 mgcd[j].gd.pos.x = mgcd[j-2].gd.pos.x-50+3; mgcd[j].gd.pos.y = mgcd[j-1].gd.pos.y+26;
3242 mgcd[j].gd.flags = gg_visible | gg_enabled;
3243 mlabel[j].text = (unichar_t *) _("Prev On Contour");
3244 mlabel[j].text_is_1byte = true;
3245 mgcd[j].gd.label = &mlabel[j];
3246 mgcd[j].gd.cid = CID_PrevC;
3247 mgcd[j].gd.handle_controlevent = PI_NextPrev;
3248 mgcd[j].creator = GButtonCreate;
3249 ++j;
3250
3251 mgcd[j].gd.pos.x = mgcd[j-2].gd.pos.x; mgcd[j].gd.pos.y = mgcd[j-1].gd.pos.y;
3252 mgcd[j].gd.flags = gg_visible | gg_enabled;
3253 mlabel[j].text = (unichar_t *) _("Next On Contour");
3254 mlabel[j].text_is_1byte = true;
3255 mgcd[j].gd.label = &mlabel[j];
3256 mgcd[j].gd.cid = CID_NextC;
3257 mgcd[j].gd.handle_controlevent = PI_NextPrev;
3258 mgcd[j].creator = GButtonCreate;
3259 ++j;
3260
3261 mgcd[j].gd.pos.x = 5; mgcd[j].gd.pos.y = mgcd[j-1].gd.pos.y+28;
3262 mgcd[j].gd.pos.width = PI_Width-10;
3263 mgcd[j].gd.flags = gg_enabled|gg_visible;
3264 mgcd[j].creator = GLineCreate;
3265 ++j;
3266
3267 mgcd[j].gd.pos.x = 20-3; mgcd[j].gd.pos.y = PI_Height-33-3;
3268 mgcd[j].gd.pos.width = -1; mgcd[j].gd.pos.height = 0;
3269 mgcd[j].gd.flags = gg_visible | gg_enabled | gg_but_default;
3270 mlabel[j].text = (unichar_t *) _("_OK");
3271 mlabel[j].text_is_1byte = true;
3272 mlabel[j].text_in_resource = true;
3273 mgcd[j].gd.mnemonic = 'O';
3274 mgcd[j].gd.label = &mlabel[j];
3275 mgcd[j].gd.handle_controlevent = PI_Ok;
3276 mgcd[j].creator = GButtonCreate;
3277 ++j;
3278
3279 mgcd[j].gd.pos.x = -20; mgcd[j].gd.pos.y = PI_Height-33;
3280 mgcd[j].gd.pos.width = -1; mgcd[j].gd.pos.height = 0;
3281 mgcd[j].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
3282 mlabel[j].text = (unichar_t *) _("_Cancel");
3283 mlabel[j].text_is_1byte = true;
3284 mlabel[j].text_in_resource = true;
3285 mgcd[j].gd.label = &mlabel[j];
3286 mgcd[j].gd.mnemonic = 'C';
3287 mgcd[j].gd.handle_controlevent = PI_Cancel;
3288 mgcd[j].creator = GButtonCreate;
3289 ++j;
3290
3291 marray[0] = &mgcd[0]; marray[1] = NULL;
3292 marray[2] = &mb[2]; marray[3] = NULL;
3293 marray[4] = &mb[3]; marray[5] = NULL;
3294 marray[6] = &mgcd[5]; marray[7] = NULL;
3295 marray[8] = &mb[4]; marray[9] = NULL;
3296 marray[10] = NULL;
3297 marray2[0] = GCD_Glue; marray2[1] = &mgcd[1]; marray2[2] = &mgcd[2]; marray2[3] = GCD_Glue; marray2[4] = NULL;
3298 marray3[0] = GCD_Glue; marray3[1] = &mgcd[3]; marray3[2] = &mgcd[4]; marray3[3] = GCD_Glue; marray3[4] = NULL;
3299 marray4[0] = GCD_Glue; marray4[1] = &mgcd[6]; marray4[2] = GCD_Glue; marray4[3] = GCD_Glue; marray4[4] = &mgcd[7]; marray4[5] = GCD_Glue; marray4[6] = NULL;
3300
3301 memset(mb,0,sizeof(mb));
3302 mb[0].gd.pos.x = mb[0].gd.pos.y = 2;
3303 mb[0].gd.flags = gg_enabled|gg_visible;
3304 mb[0].gd.u.boxelements = marray;
3305 mb[0].creator = GHVGroupCreate;
3306
3307 mb[2].gd.flags = gg_enabled|gg_visible;
3308 mb[2].gd.u.boxelements = marray2;
3309 mb[2].creator = GHBoxCreate;
3310
3311 mb[3].gd.flags = gg_enabled|gg_visible;
3312 mb[3].gd.u.boxelements = marray3;
3313 mb[3].creator = GHBoxCreate;
3314
3315 mb[4].gd.flags = gg_enabled|gg_visible;
3316 mb[4].gd.u.boxelements = marray4;
3317 mb[4].creator = GHBoxCreate;
3318
3319 GGadgetsCreate(gi->gw,mb);
3320 gi->group1ret = pb[4].ret; gi->group2ret = pb[5].ret;
3321 memcpy( gi->gcd, gcd, gcdcount*sizeof(GGadgetCreateData) ); // This copies pointers, but only to static things.
3322 GTextInfoListFree(hgcd[0].gd.u.list);
3323 GTextInfoListFree(h2gcd[0].gd.u.list);
3324
3325 GHVBoxSetExpandableRow(mb[0].ret,0);
3326 GHVBoxSetExpandableCol(mb[2].ret,gb_expandgluesame);
3327 GHVBoxSetExpandableCol(mb[3].ret,gb_expandgluesame);
3328 GHVBoxSetExpandableCol(mb[4].ret,gb_expandgluesame);
3329 GHVBoxSetExpandableRow(pb[0].ret,gb_expandglue);
3330 GHVBoxSetExpandableCol(pb[2].ret,gb_expandglue);
3331 GHVBoxSetExpandableCol(pb[3].ret,gb_expandglue);
3332 GHVBoxSetExpandableCol(pb[4].ret,gb_expandglue);
3333 GHVBoxSetExpandableCol(pb[5].ret,gb_expandglue);
3334 GHVBoxSetExpandableCol(pb[6].ret,gb_expandglue);
3335 GHVBoxSetExpandableCol(pb[7].ret,gb_expandglue);
3336
3337 PIChangePoint(gi);
3338
3339 GHVBoxFitWindow(mb[0].ret);
3340
3341 dlist_pushfront( &cv->pointInfoDialogs, (struct dlistnode *)gi );
3342 GWidgetHidePalettes();
3343 GDrawResize(gi->gw,
3344 GGadgetScale(GDrawPointsToPixels(NULL,PI_Width)),
3345 GDrawPointsToPixels(NULL,PI_Height));
3346 GDrawSetVisible(gi->gw,true);
3347 }
3348
3349 /* ************************************************************************** */
3350 /* ****************************** Spiro Points ****************************** */
3351 /* ************************************************************************** */
3352
SpiroFillup(GIData * ci,int except_cid)3353 static void SpiroFillup(GIData *ci, int except_cid) {
3354 char buffer[50];
3355 int ty;
3356
3357 mysprintf(buffer, "%.2f", ci->curcp->x );
3358 if ( except_cid!=CID_BaseX )
3359 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_BaseX),buffer);
3360
3361 mysprintf(buffer, "%.2f", ci->curcp->y );
3362 if ( except_cid!=CID_BaseY )
3363 GGadgetSetTitle8(GWidgetGetControl(ci->gw,CID_BaseY),buffer);
3364
3365 ty = ci->curcp->ty&0x7f;
3366 if ( ty == SPIRO_OPEN_CONTOUR )
3367 ty = SPIRO_G4;
3368 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Curve), ty==SPIRO_G4 );
3369 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Tangent), ty==SPIRO_G2 );
3370 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_Corner), ty==SPIRO_CORNER );
3371 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_SpiroLeft), ty==SPIRO_LEFT );
3372 GGadgetSetChecked(GWidgetGetControl(ci->gw,CID_SpiroRight), ty==SPIRO_RIGHT );
3373 }
3374
SpiroChangePoint(GIData * ci)3375 static void SpiroChangePoint(GIData *ci) {
3376
3377 SpiroFillup(ci,0);
3378 }
3379
PI_SpiroNextPrev(GGadget * g,GEvent * e)3380 static int PI_SpiroNextPrev(GGadget *g, GEvent *e) {
3381 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
3382 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
3383 CharView *cv = ci->cv;
3384 int cid = GGadgetGetCid(g);
3385 SplinePointList *spl;
3386 int index = ci->curcp - ci->curspl->spiros;
3387 BasePoint here;
3388
3389 SPIRO_DESELECT(ci->curcp);
3390 if ( cid == CID_Next ) {
3391 if ( index < ci->curspl->spiro_cnt-2 )
3392 ci->curcp = &ci->curspl->spiros[index+1];
3393 else {
3394 if ( ci->curspl->next == NULL ) {
3395 ci->curspl = cv->b.layerheads[cv->b.drawmode]->splines;
3396 GDrawBeep(NULL);
3397 } else
3398 ci->curspl = ci->curspl->next;
3399 ci->curcp = &ci->curspl->spiros[0];
3400 }
3401 } else if ( cid == CID_Prev ) {
3402 if ( index!=0 ) {
3403 ci->curcp = &ci->curspl->spiros[index-1];
3404 } else {
3405 if ( ci->curspl==cv->b.layerheads[cv->b.drawmode]->splines ) {
3406 for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl->next!=NULL; spl=spl->next );
3407 GDrawBeep(NULL);
3408 } else {
3409 for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl->next!=ci->curspl; spl=spl->next );
3410 }
3411 ci->curspl = spl;
3412 ci->curcp = &ci->curspl->spiros[ci->curspl->spiro_cnt-2];
3413 }
3414 } else if ( cid==CID_NextC ) {
3415 if ( index < ci->curspl->spiro_cnt-2 )
3416 ci->curcp = &ci->curspl->spiros[index+1];
3417 else {
3418 ci->curcp = &ci->curspl->spiros[0];
3419 GDrawBeep(NULL);
3420 }
3421 } else /* CID_PrevC */ {
3422 if ( index!=0 )
3423 ci->curcp = &ci->curspl->spiros[index-1];
3424 else {
3425 ci->curcp = &ci->curspl->spiros[ci->curspl->spiro_cnt-2];
3426 GDrawBeep(NULL);
3427 }
3428 }
3429 SPIRO_SELECT(ci->curcp);
3430 SpiroChangePoint(ci);
3431 here.x = ci->curcp->x; here.y = ci->curcp->y;
3432 CVShowPoint(cv,&here);
3433 SCUpdateAll(cv->b.sc);
3434 }
3435 return( true );
3436 }
3437
PI_SpiroChanged(GGadget * g,GEvent * e)3438 static int PI_SpiroChanged(GGadget *g, GEvent *e) {
3439 if ( e->type==et_controlevent &&
3440 (e->u.control.subtype == et_textchanged ||
3441 e->u.control.subtype == et_radiochanged)) {
3442 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
3443 double x,y;
3444 int ty;
3445 int err=false;
3446 spiro_cp *curcp = ci->curcp;
3447
3448 x = GetCalmReal8(ci->gw,CID_BaseX,_("X"),&err);
3449 y = GetCalmReal8(ci->gw,CID_BaseY,_("Y"),&err);
3450 ty = GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_Curve))? SPIRO_G4 :
3451 GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_Tangent))? SPIRO_G2 :
3452 GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_Corner))? SPIRO_CORNER :
3453 GGadgetIsChecked(GWidgetGetControl(ci->gw,CID_SpiroLeft))? SPIRO_LEFT :
3454 SPIRO_RIGHT;
3455 curcp->x = x;
3456 curcp->y = y;
3457 curcp->ty = ty | 0x80;
3458 SSRegenerateFromSpiros(ci->curspl);
3459 CVCharChangedUpdate(&ci->cv->b);
3460 }
3461 return( true );
3462 }
3463
PI_SpiroDoOk(GIData * ci)3464 static void PI_SpiroDoOk(GIData *ci) {
3465 ci->done = true;
3466 /* All the work has been done as we've gone along */
3467 PI_Close(ci);
3468 }
3469
PI_SpiroOk(GGadget * g,GEvent * e)3470 static int PI_SpiroOk(GGadget *g, GEvent *e) {
3471 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
3472 GIData *ci = GDrawGetUserData(GGadgetGetWindow(g));
3473 PI_SpiroDoOk(ci);
3474 }
3475 return( true );
3476 }
3477
spi_e_h(GWindow gw,GEvent * event)3478 static int spi_e_h(GWindow gw, GEvent *event) {
3479 if ( event->type==et_close ) {
3480 PI_SpiroDoOk(GDrawGetUserData(gw));
3481 } else if ( event->type==et_char ) {
3482 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
3483 help("ui/dialogs/getinfo.html", NULL);
3484 return( true );
3485 }
3486 return( false );
3487 } else if ( event->type == et_map ) {
3488 /* Above palettes */
3489 GDrawRaise(gw);
3490 }
3491 return( true );
3492 }
3493
SpiroPointGetInfo(CharView * cv,spiro_cp * scp,SplinePointList * spl)3494 static void SpiroPointGetInfo(CharView *cv, spiro_cp *scp, SplinePointList *spl) {
3495 CharViewTab* tab = CVGetActiveTab(cv);
3496 GIData *gip = calloc(1, sizeof(GIData));
3497 GRect pos;
3498 GWindowAttrs wattrs;
3499 GGadgetCreateData gcd[20];
3500 GGadgetCreateData pb[9];
3501 GGadgetCreateData *varray[20], *harray2[10], *harray3[15], *harray4[6],
3502 *harray5[6], *harray6[9];
3503 GTextInfo label[20];
3504 GWindow root;
3505 GRect screensize;
3506 GPoint pt;
3507 int j,k;
3508
3509 gip->cv = cv;
3510 gip->sc = cv->b.sc;
3511 gip->curcp = scp;
3512 gip->curspl = spl;
3513 gip->oldstate = SplinePointListCopy(cv->b.layerheads[cv->b.drawmode]->splines);
3514 gip->done = false;
3515 CVPreserveState(&cv->b);
3516
3517 root = GDrawGetRoot(NULL);
3518 GDrawGetSize(root,&screensize);
3519
3520 memset(&wattrs,0,sizeof(wattrs));
3521 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_positioned|wam_isdlg|wam_restrict;
3522 wattrs.event_masks = ~(1<<et_charup);
3523 wattrs.restrict_input_to_me = 1;
3524 wattrs.positioned = 1;
3525 wattrs.cursor = ct_pointer;
3526 wattrs.utf8_window_title = _("Spiro Point Info");
3527 wattrs.is_dlg = true;
3528 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,PI_Width));
3529 pos.height = GDrawPointsToPixels(NULL,PI_Height);
3530 pt.x = tab->xoff + rint(scp->x*tab->scale);
3531 pt.y = -tab->yoff + cv->height - rint(scp->y*tab->scale);
3532 GDrawTranslateCoordinates(cv->v,root,&pt);
3533 if ( pt.x+20+pos.width<=screensize.width )
3534 pos.x = pt.x+20;
3535 else if ( (pos.x = pt.x-10-screensize.width)<0 )
3536 pos.x = 0;
3537 pos.y = pt.y;
3538 if ( pos.y+pos.height+20 > screensize.height )
3539 pos.y = screensize.height - pos.height - 20;
3540 if ( pos.y<0 ) pos.y = 0;
3541 gip->gw = GDrawCreateTopWindow(NULL,&pos,spi_e_h,gip,&wattrs);
3542
3543 memset(&gcd,0,sizeof(gcd));
3544 memset(&label,0,sizeof(label));
3545 memset(&pb,0,sizeof(pb));
3546
3547 j=k=0;
3548 gip->gcd = gcd;
3549
3550 label[j].text = (unichar_t *) _("_X:");
3551 label[j].text_is_1byte = true;
3552 label[j].text_in_resource = true;
3553 gcd[j].gd.label = &label[j];
3554 gcd[j].gd.flags = gg_enabled|gg_visible;
3555 gcd[j].creator = GLabelCreate;
3556 harray2[0] = &gcd[j]; harray2[1] = GCD_Glue;
3557 ++j;
3558
3559 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-6; gcd[j].gd.pos.width = 70;
3560 gcd[j].gd.flags = gg_enabled|gg_visible;
3561 gcd[j].gd.cid = CID_BaseX;
3562 gcd[j].gd.handle_controlevent = PI_SpiroChanged;
3563 gcd[j].creator = GNumericFieldCreate;
3564 harray2[2] = &gcd[j]; harray2[3] = GCD_Glue; harray2[4] = GCD_Glue;
3565 ++j;
3566
3567 label[j].text = (unichar_t *) _("_Y:");
3568 label[j].text_is_1byte = true;
3569 label[j].text_in_resource = true;
3570 gcd[j].gd.label = &label[j];
3571 gcd[j].gd.flags = gg_enabled|gg_visible;
3572 gcd[j].creator = GLabelCreate;
3573 harray2[5] = &gcd[j]; harray2[6] = GCD_Glue;
3574 ++j;
3575
3576 gcd[j].gd.pos.x = 137; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y; gcd[j].gd.pos.width = 70;
3577 gcd[j].gd.flags = gg_enabled|gg_visible;
3578 gcd[j].gd.cid = CID_BaseY;
3579 gcd[j].gd.handle_controlevent = PI_SpiroChanged;
3580 gcd[j].creator = GNumericFieldCreate;
3581 harray2[7] = &gcd[j]; harray2[8] = NULL;
3582 ++j;
3583
3584 pb[2].gd.flags = gg_enabled|gg_visible;
3585 pb[2].gd.u.boxelements = harray2;
3586 pb[2].creator = GHBoxCreate;
3587 varray[k++] = &pb[2]; varray[k++] = NULL;
3588
3589 label[j].text = (unichar_t *) _("Type:");
3590 label[j].text_is_1byte = true;
3591 gcd[j].gd.label = &label[j];
3592 gcd[j].gd.pos.x = gcd[0].gd.pos.x;
3593 gcd[j].gd.flags = gg_enabled|gg_visible;
3594 gcd[j].creator = GLabelCreate;
3595 harray3[0] = &gcd[j]; harray3[1] = GCD_Glue; harray3[2] = GCD_Glue;
3596 ++j;
3597
3598 label[j].image = &GIcon_smallspirocurve;
3599 gcd[j].gd.label = &label[j];
3600 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-2;
3601 gcd[j].gd.flags = gg_enabled|gg_visible;
3602 gcd[j].gd.cid = CID_Curve;
3603 gcd[j].gd.handle_controlevent = PI_SpiroChanged;
3604 gcd[j].creator = GRadioCreate;
3605 harray3[3] = &gcd[j]; harray3[4] = GCD_Glue;
3606 ++j;
3607
3608 label[j].image = &GIcon_smallspirog2curve;
3609 gcd[j].gd.label = &label[j];
3610 gcd[j].gd.pos.x = 60; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y-2;
3611 gcd[j].gd.flags = gg_enabled|gg_visible;
3612 gcd[j].gd.cid = CID_Tangent;
3613 gcd[j].gd.handle_controlevent = PI_SpiroChanged;
3614 gcd[j].creator = GRadioCreate;
3615 harray3[5] = &gcd[j]; harray3[6] = GCD_Glue;
3616 ++j;
3617
3618 label[j].image = &GIcon_smallspirocorner;
3619 gcd[j].gd.label = &label[j];
3620 gcd[j].gd.pos.x = 100; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
3621 gcd[j].gd.flags = gg_enabled|gg_visible | gg_rad_continueold;
3622 gcd[j].gd.cid = CID_Corner;
3623 gcd[j].gd.handle_controlevent = PI_SpiroChanged;
3624 gcd[j].creator = GRadioCreate;
3625 harray3[7] = &gcd[j]; harray3[8] = GCD_Glue;
3626 ++j;
3627
3628 label[j].image = &GIcon_smallspiroleft;
3629 gcd[j].gd.label = &label[j];
3630 gcd[j].gd.pos.x = 140; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
3631 gcd[j].gd.flags = gg_enabled|gg_visible | gg_rad_continueold;
3632 gcd[j].gd.cid = CID_SpiroLeft;
3633 gcd[j].gd.handle_controlevent = PI_SpiroChanged;
3634 gcd[j].creator = GRadioCreate;
3635 harray3[9] = &gcd[j]; harray3[10] = GCD_Glue;
3636 ++j;
3637
3638 label[j].image = &GIcon_smallspiroright;
3639 gcd[j].gd.label = &label[j];
3640 gcd[j].gd.pos.x = 140; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y;
3641 gcd[j].gd.flags = gg_enabled|gg_visible | gg_rad_continueold;
3642 gcd[j].gd.cid = CID_SpiroRight;
3643 gcd[j].gd.handle_controlevent = PI_SpiroChanged;
3644 gcd[j].creator = GRadioCreate;
3645 harray3[11] = &gcd[j]; harray3[12] = GCD_Glue; harray3[13] = GCD_Glue;
3646 harray3[14] = NULL;
3647 ++j;
3648
3649 pb[3].gd.flags = gg_enabled|gg_visible;
3650 pb[3].gd.u.boxelements = harray3;
3651 pb[3].creator = GHBoxCreate;
3652 varray[k++] = &pb[3];
3653 varray[k++] = NULL;
3654 varray[k++] = GCD_Glue;
3655 varray[k++] = NULL;
3656
3657 gcd[j].gd.flags = gg_visible | gg_enabled;
3658 label[j].text = (unichar_t *) _("< _Prev");
3659 label[j].text_is_1byte = true;
3660 label[j].text_in_resource = true;
3661 gcd[j].gd.label = &label[j];
3662 gcd[j].gd.cid = CID_Prev;
3663 gcd[j].gd.handle_controlevent = PI_SpiroNextPrev;
3664 gcd[j].creator = GButtonCreate;
3665 harray4[0] = GCD_Glue; harray4[1] = &gcd[j];
3666 ++j;
3667
3668 gcd[j].gd.flags = gg_visible | gg_enabled;
3669 label[j].text = (unichar_t *) _("_Next >");
3670 label[j].text_is_1byte = true;
3671 label[j].text_in_resource = true;
3672 gcd[j].gd.label = &label[j];
3673 gcd[j].gd.cid = CID_Next;
3674 gcd[j].gd.handle_controlevent = PI_SpiroNextPrev;
3675 gcd[j].creator = GButtonCreate;
3676 harray4[2] = &gcd[j]; harray4[3] = GCD_Glue; harray4[4] = NULL;
3677 ++j;
3678
3679 pb[4].gd.flags = gg_enabled|gg_visible;
3680 pb[4].gd.u.boxelements = harray4;
3681 pb[4].creator = GHBoxCreate;
3682 varray[k++] = &pb[4];
3683 varray[k++] = NULL;
3684
3685 gcd[j].gd.flags = gg_visible | gg_enabled;
3686 label[j].text = (unichar_t *) _("Prev On Contour");
3687 label[j].text_is_1byte = true;
3688 gcd[j].gd.label = &label[j];
3689 gcd[j].gd.cid = CID_PrevC;
3690 gcd[j].gd.handle_controlevent = PI_SpiroNextPrev;
3691 gcd[j].creator = GButtonCreate;
3692 harray5[0] = GCD_Glue; harray5[1] = &gcd[j];
3693 ++j;
3694
3695 gcd[j].gd.flags = gg_visible | gg_enabled;
3696 label[j].text = (unichar_t *) _("Next On Contour");
3697 label[j].text_is_1byte = true;
3698 gcd[j].gd.label = &label[j];
3699 gcd[j].gd.cid = CID_NextC;
3700 gcd[j].gd.handle_controlevent = PI_SpiroNextPrev;
3701 gcd[j].creator = GButtonCreate;
3702 harray5[2] = &gcd[j]; harray5[3] = GCD_Glue; harray5[4] = NULL;
3703 ++j;
3704
3705 pb[5].gd.flags = gg_enabled|gg_visible;
3706 pb[5].gd.u.boxelements = harray5;
3707 pb[5].creator = GHBoxCreate;
3708 varray[k++] = &pb[5];
3709 varray[k++] = NULL;
3710
3711 gcd[j].gd.pos.x = 5; gcd[j].gd.pos.y = gcd[j-1].gd.pos.y+28;
3712 gcd[j].gd.pos.width = PI_Width-10;
3713 gcd[j].gd.flags = gg_enabled|gg_visible;
3714 gcd[j].creator = GLineCreate;
3715 ++j;
3716 varray[k++] = &gcd[j-1];
3717 varray[k++] = NULL;
3718 varray[k++] = GCD_Glue;
3719 varray[k++] = NULL;
3720
3721 gcd[j].gd.pos.x = 20-3; gcd[j].gd.pos.y = PI_Height-33-3;
3722 gcd[j].gd.flags = gg_visible | gg_enabled | gg_but_default;
3723 label[j].text = (unichar_t *) _("_OK");
3724 label[j].text_is_1byte = true;
3725 label[j].text_in_resource = true;
3726 gcd[j].gd.mnemonic = 'O';
3727 gcd[j].gd.label = &label[j];
3728 gcd[j].gd.handle_controlevent = PI_SpiroOk;
3729 gcd[j].creator = GButtonCreate;
3730 harray6[0] = GCD_Glue; harray6[1] = &gcd[j]; harray6[2] = GCD_Glue; harray6[3] = GCD_Glue;
3731 ++j;
3732
3733 gcd[j].gd.pos.x = -20; gcd[j].gd.pos.y = PI_Height-33;
3734 gcd[j].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
3735 label[j].text = (unichar_t *) _("_Cancel");
3736 label[j].text_is_1byte = true;
3737 label[j].text_in_resource = true;
3738 gcd[j].gd.label = &label[j];
3739 gcd[j].gd.mnemonic = 'C';
3740 gcd[j].gd.handle_controlevent = PI_Cancel;
3741 gcd[j].creator = GButtonCreate;
3742 harray6[4] = GCD_Glue; harray6[5] = &gcd[j]; harray6[6] = GCD_Glue; harray6[7] = NULL;
3743 ++j;
3744
3745 pb[6].gd.flags = gg_enabled|gg_visible;
3746 pb[6].gd.u.boxelements = harray6;
3747 pb[6].creator = GHBoxCreate;
3748 varray[k++] = &pb[6];
3749 varray[k++] = NULL;
3750 varray[k++] = NULL;
3751
3752 pb[0].gd.pos.x = pb[0].gd.pos.y = 2;
3753 pb[0].gd.flags = gg_enabled|gg_visible;
3754 pb[0].gd.u.boxelements = varray;
3755 pb[0].creator = GHVGroupCreate;
3756
3757 GGadgetsCreate(gip->gw,pb);
3758
3759 GHVBoxSetExpandableRow(pb[0].ret,gb_expandglue);
3760 GHVBoxSetExpandableCol(pb[2].ret,gb_expandglue);
3761 GHVBoxSetExpandableCol(pb[3].ret,gb_expandglue);
3762 GHVBoxSetExpandableCol(pb[4].ret,gb_expandglue);
3763 GHVBoxSetExpandableCol(pb[5].ret,gb_expandglue);
3764 GHVBoxSetExpandableCol(pb[6].ret,gb_expandgluesame);
3765
3766 SpiroChangePoint(gip);
3767
3768 GHVBoxFitWindow(pb[0].ret);
3769
3770 GWidgetHidePalettes();
3771 GDrawSetVisible(gip->gw,true);
3772 while ( !gip->done )
3773 GDrawProcessOneEvent(NULL);
3774 }
3775
CVGetInfo(CharView * cv)3776 void CVGetInfo(CharView *cv) {
3777 SplinePoint *sp;
3778 SplinePointList *spl;
3779 RefChar *ref;
3780 ImageList *img;
3781 AnchorPoint *ap;
3782 spiro_cp *scp;
3783
3784 if ( !CVOneThingSel(cv,&sp,&spl,&ref,&img,&ap,&scp)) {
3785 } else if ( ref!=NULL )
3786 RefGetInfo(cv,ref);
3787 else if ( img!=NULL )
3788 ImgGetInfo(cv,img);
3789 else if ( ap!=NULL )
3790 ApGetInfo(cv,ap);
3791 else if ( scp!=NULL )
3792 SpiroPointGetInfo(cv,scp,spl);
3793 else
3794 PointGetInfo(cv,sp,spl);
3795 }
3796
CVPGetInfo(CharView * cv)3797 void CVPGetInfo(CharView *cv) {
3798
3799 if ( cv->p.ref!=NULL )
3800 RefGetInfo(cv,cv->p.ref);
3801 else if ( cv->p.img!=NULL )
3802 ImgGetInfo(cv,cv->p.img);
3803 else if ( cv->p.ap!=NULL )
3804 ApGetInfo(cv,cv->p.ap);
3805 else if ( cv->p.sp!=NULL )
3806 PointGetInfo(cv,cv->p.sp,cv->p.spl);
3807 else if ( cv->p.spiro!=NULL )
3808 SpiroPointGetInfo(cv,cv->p.spiro,cv->p.spl);
3809 }
3810
SCRefBy(SplineChar * sc)3811 void SCRefBy(SplineChar *sc) {
3812 int cnt,i,tot=0;
3813 char **deps = NULL;
3814 struct splinecharlist *d;
3815 char *buts[3];
3816
3817 buts[0] = _("_Show");
3818 buts[1] = _("_Cancel");
3819 buts[2] = NULL;
3820
3821 for ( i=0; i<2; ++i ) {
3822 cnt = 0;
3823 for ( d = sc->dependents; d!=NULL; d=d->next ) {
3824 if ( deps!=NULL )
3825 deps[tot-cnt] = copy(d->sc->name);
3826 ++cnt;
3827 }
3828 if ( cnt==0 )
3829 return;
3830 if ( i==0 )
3831 deps = calloc(cnt+1,sizeof(unichar_t *));
3832 tot = cnt-1;
3833 }
3834
3835 i = gwwv_choose_with_buttons(_("Dependents"),(const char **) deps, cnt, 0, buts, _("Dependents") );
3836 if ( i!=-1 ) {
3837 i = tot-i;
3838 for ( d = sc->dependents, cnt=0; d!=NULL && cnt<i; d=d->next, ++cnt );
3839 CharViewCreate(d->sc,(FontView *) (sc->parent->fv),-1);
3840 }
3841 for ( i=0; i<=tot; ++i )
3842 free( deps[i] );
3843 free(deps);
3844 }
3845
UsedIn(char * name,char * subs)3846 static int UsedIn(char *name, char *subs) {
3847 int nlen = strlen( name );
3848 while ( *subs!='\0' ) {
3849 if ( strncmp(subs,name,nlen)==0 && (subs[nlen]==' ' || subs[nlen]=='\0'))
3850 return( true );
3851 while ( *subs!=' ' && *subs!='\0' ) ++subs;
3852 while ( *subs==' ' ) ++subs;
3853 }
3854 return( false );
3855 }
3856
SCUsedBySubs(SplineChar * sc)3857 int SCUsedBySubs(SplineChar *sc) {
3858 int k, i;
3859 SplineFont *_sf, *sf;
3860 PST *pst;
3861
3862 if ( sc==NULL )
3863 return( false );
3864
3865 _sf = sc->parent;
3866 if ( _sf->cidmaster!=NULL ) _sf=_sf->cidmaster;
3867 k=0;
3868 do {
3869 sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
3870 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
3871 for ( pst=sf->glyphs[i]->possub; pst!=NULL; pst=pst->next ) {
3872 if ( pst->type==pst_substitution || pst->type==pst_alternate ||
3873 pst->type==pst_multiple || pst->type==pst_ligature )
3874 if ( UsedIn(sc->name,pst->u.mult.components))
3875 return( true );
3876 }
3877 }
3878 ++k;
3879 } while ( k<_sf->subfontcnt );
3880 return( false );
3881 }
3882
SCSubBy(SplineChar * sc)3883 void SCSubBy(SplineChar *sc) {
3884 int i,j,k,tot;
3885 char **deps = NULL;
3886 SplineChar **depsc;
3887 char ubuf[200];
3888 SplineFont *sf, *_sf;
3889 PST *pst;
3890 char *buts[3];
3891
3892 buts[0] = _("Show");
3893 buts[1] = _("_Cancel");
3894 buts[2] = NULL;
3895
3896 if ( sc==NULL )
3897 return;
3898
3899 _sf = sc->parent;
3900 if ( _sf->cidmaster!=NULL ) _sf=_sf->cidmaster;
3901 for ( j=0; j<2; ++j ) {
3902 tot = 0;
3903 k=0;
3904 do {
3905 sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
3906 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
3907 for ( pst=sf->glyphs[i]->possub; pst!=NULL; pst=pst->next ) {
3908 if ( pst->type==pst_substitution || pst->type==pst_alternate ||
3909 pst->type==pst_multiple || pst->type==pst_ligature )
3910 if ( UsedIn(sc->name,pst->u.mult.components)) {
3911 if ( deps!=NULL ) {
3912 snprintf(ubuf,sizeof(ubuf),
3913 _("Subtable %.60s in glyph %.60s"),
3914 pst->subtable->subtable_name,
3915 sf->glyphs[i]->name);
3916 deps[tot] = copy(ubuf);
3917 depsc[tot] = sf->glyphs[i];
3918 }
3919 ++tot;
3920 }
3921 }
3922 }
3923 ++k;
3924 } while ( k<_sf->subfontcnt );
3925 if ( tot==0 )
3926 return;
3927 if ( j==0 ) {
3928 deps = calloc(tot+1,sizeof(char *));
3929 depsc = malloc(tot*sizeof(SplineChar *));
3930 }
3931 }
3932
3933 i = gwwv_choose_with_buttons(_("Dependent Substitutions"),(const char **) deps, tot, 0, buts, _("Dependent Substitutions") );
3934 if ( i>-1 ) {
3935 CharViewCreate(depsc[i],(FontView *) (sc->parent->fv),-1);
3936 }
3937 for ( i=0; i<=tot; ++i )
3938 free( deps[i] );
3939 free(deps);
3940 free(depsc);
3941 }
3942