1 /* Copyright (C) 2001-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 "fontforgeui.h"
32 #include "gkeysym.h"
33 #include "splineutil.h"
34 #include "ttf.h"
35 #include "ttfinstrs.h"
36 #include "ustring.h"
37 #include "utype.h"
38
39 extern GBox _ggadget_Default_Box;
40 #define ACTIVE_BORDER (_ggadget_Default_Box.active_border)
41 #define MAIN_FOREGROUND (_ggadget_Default_Box.main_foreground)
42
43 extern int _GScrollBar_Width;
44 #define EDGE_SPACING 2
45
46 #define ttf_width 16
47 #define ttf_height 16
48 static unsigned char ttf_bits[] = {
49 0xff, 0x07, 0x21, 0x04, 0x20, 0x00, 0xfc, 0x7f, 0x24, 0x40, 0xf4, 0x5e,
50 0xbc, 0x72, 0xa0, 0x02, 0xa0, 0x02, 0xa0, 0x02, 0xf0, 0x02, 0x80, 0x02,
51 0xc0, 0x06, 0x40, 0x04, 0xc0, 0x07, 0x00, 0x00};
52 GWindow ttf_icon = NULL;
53
54 static char *instrhelppopup[256];
55
ihaddr(int bottom,int top,char * msg)56 static void ihaddr(int bottom,int top,char *msg) {
57 while ( bottom<=top )
58 instrhelppopup[bottom++] = msg;
59 }
60
ihadd(int p,char * msg)61 static void ihadd(int p,char *msg) {
62 ihaddr(p,p,msg);
63 }
64
instrhelpsetup(void)65 static void instrhelpsetup(void) {
66 if ( instrhelppopup[0]!=NULL )
67 return;
68 ihadd(0x7f,N_("Adjust Angle\nObsolete instruction\nPops one value"));
69 ihadd(0x64,N_("ABSolute Value\nReplaces top of stack with its abs"));
70 ihadd(0x60,N_("ADD\nPops two 26.6 fixed numbers from stack\nadds them, pushes result"));
71 ihadd(0x27,N_("ALIGN PoinTS\nAligns (&pops) the two points which are on the stack\nby moving along freedom vector to the average of their\npositions on projection vector"));
72 ihadd(0x3c,N_("ALIGN to Reference Point\nPops as many points as specified in loop counter\nAligns points with RP0 by moving each\nalong freedom vector until distance to\nRP0 on projection vector is 0"));
73 ihadd(0x5a,N_("logical AND\nPops two values, ands them, pushes result"));
74 ihadd(0x2b,N_("CALL function\nPops a value, calls the function represented by it"));
75 ihadd(0x67,N_("CEILING\nPops one 26.6 value, rounds upward to an int\npushes result"));
76 ihadd(0x25,N_("Copy INDEXed element to stack\nPops an index & copies stack\nelement[index] to top of stack"));
77 ihadd(0x22,N_("CLEAR\nPops all elements on stack"));
78 ihadd(0x4f,N_("DEBUG call\nPops a value and executes a debugging interpreter\n(if available)"));
79 ihadd(0x73,N_("DELTA exception C1\nPops a value n & then n exception specifications & cvt entries\nchanges each cvt entry at a given size by the pixel amount"));
80 ihadd(0x74,N_("DELTA exception C2\nPops a value n & then n exception specifications & cvt entries\nchanges each cvt entry at a given size by the amount"));
81 ihadd(0x75,N_("DELTA exception C3\nPops a value n & then n exception specifications & cvt entries\nchanges each cvt entry at a given size by the amount"));
82 ihadd(0x5D,N_("DELTA exception P1\nPops a value n & then n exception specifications & points\nmoves each point at a given size by the amount"));
83 ihadd(0x71,N_("DELTA exception P2\nPops a value n & then n exception specifications & points\nmoves each point at a given size by the amount"));
84 ihadd(0x72,N_("DELTA exception P3\nPops a value n & then n exception specifications & points\nmoves each point at a given size by the amount"));
85 ihadd(0x24,N_("DEPTH of stack\nPushes the number of elements on the stack"));
86 ihadd(0x62,N_("DIVide\nPops two 26.6 numbers, divides them, pushes result"));
87 ihadd(0x20,N_("DUPlicate top stack element\nPushes the top stack element again"));
88 ihadd(0x59,N_("End IF\nEnds an IF or IF-ELSE sequence"));
89 ihadd(0x1b,N_("ELSE clause\nStart of Else clause of preceding IF"));
90 ihadd(0x2d,N_("END Function definition"));
91 ihadd(0x54,N_("EQual\nPops two values, tests for equality, pushes result(0/1)"));
92 ihadd(0x57,N_("EVEN\nPops one value, rounds it and tests if it is even(0/1)"));
93 ihadd(0x2C,N_("Function DEFinition\nPops a value (n) and starts the nth\nfunction definition"));
94 ihadd(0x4e,N_("set the auto FLIP boolean to OFF"));
95 ihadd(0x4d,N_("set the auto FLIP boolean to ON"));
96 ihadd(0x80,N_("FLIP PoinT\nPops as many points as specified in loop counter\nFlips whether each point is on/off curve"));
97 ihadd(0x82,N_("FLIP RanGe OFF\nPops two point numbers\nsets all points between to be off curve points"));
98 ihadd(0x81,N_("FLIP RanGe ON\nPops two point numbers\nsets all points between to be on curve points"));
99 ihadd(0x66,N_("FLOOR\nPops a value, rounds to lowest int, pushes result"));
100 ihaddr(0x46,0x47,N_("Get Coordinate[a] projected onto projection vector\n 0=>use current pos\n 1=>use original pos\nPops one point, pushes the coordinate of\nthe point along projection vector"));
101 ihadd(0x88,N_("GET INFOrmation\nPops information type, pushes result"));
102 ihadd(0x0d,N_("Get Freedom Vector\nDecomposes freedom vector, pushes its\ntwo coordinates onto stack as 2.14"));
103 ihadd(0x0c,N_("Get Projection Vector\nDecomposes projection vector, pushes its\ntwo coordinates onto stack as 2.14"));
104 ihadd(0x52,N_("Greater Than\nPops two values, pushes (0/1) if bottom el > top"));
105 ihadd(0x53,N_("Greater Than or EQual\nPops two values, pushes (0/1) if bottom el >= top"));
106 ihadd(0x89,N_("Instruction DEFinition\nPops a value which becomes the opcode\nand begins definition of new instruction"));
107 ihadd(0x58,N_("IF test\nPops an integer,\nif 0 (false) next instruction is ELSE or EIF\nif non-0 execution continues normally\n(unless there's an ELSE)"));
108 ihadd(0x8e,N_("INSTRuction execution ConTRoL\nPops a selector and value\nSets a state variable"));
109 ihadd(0x39,N_("Interpolate Point\nPops as many points as specified in loop counter\nInterpolates each point to preserve original status\nwith respect to RP1 and RP2"));
110 ihadd(0x0f,N_("moves point to InterSECTion of two lines\nPops start,end start,end points of two lines\nand a point to move. Point is moved to\nintersection"));
111 ihaddr(0x30,0x31,N_("Interpolate Untouched Points[a]\n 0=> interpolate in y direction\n 1=> x direction"));
112 ihadd(0x1c,N_("JuMP Relative\nPops offset (in bytes) to move the instruction pointer"));
113 ihadd(0x79,N_("Jump Relative On False\nPops a boolean and an offset\nChanges instruction pointer by offset bytes\nif boolean is false"));
114 ihadd(0x78,N_("Jump Relative On True\nPops a boolean and an offset\nChanges instruction pointer by offset bytes\nif boolean is true"));
115 ihadd(0x2a,N_("LOOP and CALL function\nPops a function number & count\nCalls function count times"));
116 ihadd(0x50,N_("Less Than\nPops two values, pushes (0/1) if bottom el < top"));
117 ihadd(0x51,N_("Less Than or EQual\nPops two values, pushes (0/1) if bottom el <= top"));
118 ihadd(0x8b,N_("MAXimum of top two stack entries\nPops two values, pushes the maximum back"));
119 ihaddr(0x49,0x4a,N_("Measure Distance[a]\n 0=>distance with current positions\n 1=>distance with original positions\nPops two point numbers, pushes distance between them"));
120 ihaddr(0x2e,0x2f,N_("Move Direct Absolute Point[a]\n 0=>do not round\n 1=>round\nPops a point number, touches that point\nand perhaps rounds it to the grid along\nthe projection vector. Sets rp0&rp1 to the point"));
121 ihaddr(0xc0,0xdf,N_("Move Direct Relative Point[abcde]\n a=0=>don't set rp0\n a=1=>set rp0 to p\n b=0=>do not keep distance more than minimum\n b=1=>keep distance at least minimum\n c=0 do not round\n c=1 round\n de=0 => grey distance\n de=1 => black distance\n de=2 => white distance\nPops a point moves it so that it maintains\nits original distance to the rp0. Sets\nrp1 to rp0, rp2 to point, sometimes rp0 to point"));
122 ihaddr(0x3e,0x3f,N_("Move Indirect Absolute Point[a]\n 0=>do not round, don't use cvt cutin\n 1=>round\nPops a point number & a cvt entry,\ntouches the point and moves it to the coord\nspecified in the cvt (along the projection vector).\nSets rp0&rp1 to the point"));
123 ihadd(0x8c,N_("Minimum of top two stack entries\nPops two values, pushes the minimum back"));
124 ihadd(0x26,N_("Move INDEXed element to stack\nPops an index & moves stack\nelement[index] to top of stack\n(removing it from where it was)"));
125 ihaddr(0xe0,0xff,N_("Move Indirect Relative Point[abcde]\n a=0=>don't set rp0\n a=1=>set rp0 to p\n b=0=>do not keep distance more than minimum\n b=1=>keep distance at least minimum\n c=0 do not round nor use cvt cutin\n c=1 round & use cvt cutin\n de=0 => grey distance\n de=1 => black distance\n de=2 => white distance\nPops a cvt index and a point moves it so that it\nis cvt[index] from rp0. Sets\nrp1 to rp0, rp2 to point, sometimes rp0 to point"));
126 ihadd(0x4b,N_("Measure Pixels Per EM\nPushs the pixels per em (for current rasterization)"));
127 ihadd(0x4c,N_("Measure Point Size\nPushes the current point size"));
128 ihaddr(0x3a,0x3b,N_("Move Stack Indirect Relative Point[a]\n 0=>do not set rp0\n 1=>set rp0 to point\nPops a 26.6 distance and a point\nMoves point so it is distance from rp0"));
129 ihadd(0x63,N_("MULtiply\nPops two 26.6 numbers, multiplies them, pushes result"));
130 ihadd(0x65,N_("NEGate\nNegates the top of the stack"));
131 ihadd(0x55,N_("Not EQual\nPops two values, tests for inequality, pushes result(0/1)"));
132 ihadd(0x5c,N_("logical NOT\nPops a number, if 0 pushes 1, else pushes 0"));
133 ihadd(0x40,N_("N PUSH Bytes\nReads an (unsigned) count byte from the\ninstruction stream, then reads and pushes\nthat many unsigned bytes"));
134 ihadd(0x41,N_("N PUSH Words\nReads an (unsigned) count byte from the\ninstruction stream, then reads and pushes\nthat many signed 2byte words"));
135 ihaddr(0x6c,0x6f,N_("No ROUNDing of value[ab]\n ab=0 => grey distance\n ab=1 => black distance\n ab=2 => white distance\nPops a coordinate (26.6), changes it (without\nrounding) to compensate for engine effects\npushes it back"));
136 ihadd(0x56,N_("ODD\nPops one value, rounds it and tests if it is odd(0/1)"));
137 ihadd(0x5b,N_("logical OR\nPops two values, ors them, pushes result"));
138 ihadd(0x21,N_("POP top stack element"));
139 ihaddr(0xb0,0xb7,N_("PUSH Byte[abc]\n abc is the number-1 of bytes to push\nReads abc+1 unsigned bytes from\nthe instruction stream and pushes them"));
140 ihaddr(0xb8,0xbf,N_("PUSH Word[abc]\n abc is the number-1 of words to push\nReads abc+1 signed words from\nthe instruction stream and pushes them"));
141 ihadd(0x45,N_("Read Control Value Table entry\nPops an index to the CVT and\npushes it in 26.6 format"));
142 ihadd(0x7d,N_("Round Down To Grid\n\nSets round state to the obvious"));
143 ihadd(0x7a,N_("Round OFF\nSets round state so that no rounding occurs\nbut engine compensation does"));
144 ihadd(0x8a,N_("ROLL the top three stack elements"));
145 ihaddr(0x68,0x6b,N_("ROUND value[ab]\n ab=0 => grey distance\n ab=1 => black distance\n ab=2 => white distance\nRounds a coordinate (26.6) at top of stack\nand compensates for engine effects"));
146 ihadd(0x43,N_("Read Store\nPops an index into store array\nPushes value at that index"));
147 ihadd(0x3d,N_("Round To Double Grid\nSets the round state (round to closest .5/int)"));
148 ihadd(0x18,N_("Round To Grid\nSets the round state"));
149 ihadd(0x19,N_("Round To Half Grid\nSets the round state (round to closest .5 not int)"));
150 ihadd(0x7c,N_("Round Up To Grid\nSets the round state"));
151 ihadd(0x77,N_("Super 45\302\260 ROUND\nToo complicated. Look it up"));
152 ihadd(0x7e,N_("Set ANGle Weight\nPops an int, and sets the angle\nweight state variable to it\nObsolete"));
153 ihadd(0x85,N_("SCAN conversion ConTRoL\nPops a number which sets the\ndropout control mode"));
154 ihadd(0x8d,N_("SCANTYPE\nPops number which sets which scan\nconversion rules to use"));
155 ihadd(0x48,N_("Sets Coordinate From Stack using projection & freedom vectors\nPops a coordinate 26.6 and a point\nMoves point to given coordinate"));
156 ihadd(0x1d,N_("Sets Control Value Table Cut-In\nPops 26.6 from stack, sets cvt cutin"));
157 ihadd(0x5e,N_("Set Delta Base\nPops value sets delta base"));
158 ihaddr(0x86,0x87,N_("Set Dual Projection Vector To Line[a]\n 0 => parallel to line\n 1=>orthogonal to line\nPops two points used to establish the line\nSets a second projection vector based on original\npositions of points"));
159 ihadd(0x5F,N_("Set Delta Shift\nPops a new value for delta shift"));
160 ihadd(0x0b,N_("Set Freedom Vector From Stack\npops 2 2.14 values (x,y) from stack\nmust be a unit vector"));
161 ihaddr(0x04,0x05,N_("Set Freedom Vector To Coordinate Axis[a]\n 0=>y axis\n 1=>x axis\n"));
162 ihaddr(0x08,0x09,N_("Set Freedom Vector To Line[a]\n 0 => parallel to line\n 1=>orthogonal to line\nPops two points used to establish the line\nSets the freedom vector"));
163 ihadd(0x0e,N_("Set Freedom Vector To Projection Vector"));
164 ihaddr(0x34,0x35,N_("SHift Contour using reference point[a]\n 0=>uses rp2 in zp1\n 1=>uses rp1 in zp0\nPops number of contour to be shifted\nShifts the entire contour by the amount\nreference point was shifted"));
165 ihaddr(0x32,0x33,N_("SHift Point using reference point[a]\n 0=>uses rp2 in zp1\n 1=>uses rp1 in zp0\nPops as many points as specified by the loop count\nShifts each by the amount the reference\npoint was shifted"));
166 ihadd(0x38,N_("SHift point by a PIXel amount\nPops an amount (26.6) and as many points\nas the loop counter specifies\neach point is shifted along the FREEDOM vector"));
167 ihaddr(0x36,0x37,N_("SHift Zone using reference point[a]\n 0=>uses rp2 in zp1\n 1=>uses rp1 in zp0\nPops the zone to be shifted\nShifts all points in zone by the amount\nthe reference point was shifted"));
168 ihadd(0x17,N_("Set LOOP variable\nPops the new value for the loop counter\nDefaults to 1 after each use"));
169 ihadd(0x1a,N_("Set Minimum Distance\nPops a 26.6 value from stack to be new minimum distance"));
170 ihadd(0x0a,N_("Set Projection Vector From Stack\npops 2 2.14 values (x,y) from stack\nmust be a unit vector"));
171 ihaddr(0x02,0x03,N_("Set Projection Vector To Coordinate Axis[a]\n 0=>y axis\n 1=>x axis\n" ));
172 ihaddr(0x06,0x07,N_("Set Projection Vector To Line[a]\n 0 => parallel to line\n 1=>orthogonal to line\nPops two points used to establish the line\nSets the projection vector" ));
173 ihadd(0x76,N_("Super ROUND\nToo complicated. Look it up"));
174 ihadd(0x10,N_("Set Reference Point 0\nPops a point which becomes the new rp0"));
175 ihadd(0x11,N_("Set Reference Point 1\nPops a point which becomes the new rp1"));
176 ihadd(0x12,N_("Set Reference Point 2\nPops a point which becomes the new rp2"));
177 ihadd(0x1f,N_("Set Single Width\nPops value for single width value (FUnit)"));
178 ihadd(0x1e,N_("Set Single Width Cut-In\nPops value for single width cut-in value (26.6)"));
179 ihadd(0x61,N_("SUBtract\nPops two 26.6 fixed numbers from stack\nsubtracts them, pushes result"));
180 ihaddr(0x00,0x01,N_("Set freedom & projection Vectors To Coordinate Axis[a]\n 0=>both to y axis\n 1=>both to x axis\n" ));
181 ihadd(0x23,N_("SWAP top two elements on stack"));
182 ihadd(0x13,N_("Set Zone Pointer 0\nPops the zone number into zp0"));
183 ihadd(0x14,N_("Set Zone Pointer 1\nPops the zone number into zp1"));
184 ihadd(0x15,N_("Set Zone Pointer 2\nPops the zone number into zp2"));
185 ihadd(0x16,N_("Set Zone PointerS\nPops the zone number into zp0,zp1 and zp2"));
186 ihadd(0x29,N_("UnTouch Point\nPops a point number and marks it untouched"));
187 ihadd(0x70,N_("Write Control Value Table in Funits\nPops a number(Funits) and a\nCVT index and writes the number to cvt[index]"));
188 ihadd(0x44,N_("Write Control Value Table in Pixel units\nPops a number(26.6) and a\nCVT index and writes the number to cvt[index]"));
189 ihadd(0x42,N_("Write Store\nPops a value and an index and writes the value to storage[index]"));
190 }
191
192 typedef struct instrdlg /* : InstrBase */{
193 unsigned int inedit: 1;
194 struct instrdata *instrdata;
195 struct instrinfo instrinfo;
196 int oc_height;
197 GWindow gw, v;
198 GGadget *ok, *cancel, *edit, *parse, *text, *topbox;
199 } InstrDlg;
200
instr_info_init(struct instrinfo * instrinfo)201 static void instr_info_init(struct instrinfo *instrinfo) {
202
203 instrinfo->lheight = instr_typify(instrinfo->instrdata);
204 if ( instrinfo->fh!=0 ) {
205 if ( instrinfo->lpos > instrinfo->lheight-instrinfo->vheight/instrinfo->fh )
206 instrinfo->lpos = instrinfo->lheight-instrinfo->vheight/instrinfo->fh;
207 if ( instrinfo->lpos<0 )
208 instrinfo->lpos = 0;
209 }
210 }
211
instr_resize(InstrDlg * iv,GEvent * event)212 static void instr_resize(InstrDlg *iv,GEvent *event) {
213 GRect size;
214 int lh;
215 struct instrinfo *ii = &iv->instrinfo;
216
217 GGadgetGetSize(iv->text,&size);
218 GDrawMove(ii->v,size.x,size.y);
219 GDrawResize(ii->v,size.width,size.height);
220 ii->vheight = size.height; ii->vwidth = size.width;
221 lh = ii->lheight;
222
223 GScrollBarSetBounds(ii->vsb,0,lh+2,ii->vheight<ii->fh ? 1 : ii->vheight/ii->fh);
224 if ( ii->lpos + ii->vheight/ii->fh > lh )
225 ii->lpos = lh-ii->vheight/ii->fh;
226 if ( ii->lpos<0 ) ii->lpos = 0;
227 GScrollBarSetPos(ii->vsb,ii->lpos);
228 GDrawRequestExpose(iv->gw,NULL,false);
229 }
230
IVError(void * _iv,char * msg,int offset)231 static void IVError(void *_iv,char *msg,int offset) {
232 InstrDlg *iv = _iv;
233
234 if ( iv!=NULL ) {
235 GTextFieldSelect(iv->text,offset,offset);
236 GTextFieldShow(iv->text,offset);
237 GWidgetIndicateFocusGadget(iv->text);
238 }
239 ff_post_error(_("Parse Error"),msg);
240 }
241
IVParse(InstrDlg * iv)242 static int IVParse(InstrDlg *iv) {
243 char *text = GGadgetGetTitle8(iv->text);
244 int icnt=0, i;
245 uint8 *instrs;
246
247 instrs = _IVParse(iv->instrdata->sf, text, &icnt, IVError, iv);
248 free(text);
249
250 if ( instrs==NULL )
251 return( false );
252 if ( icnt!=iv->instrdata->instr_cnt )
253 iv->instrdata->changed = true;
254 else {
255 for ( i=0; i<icnt; ++i )
256 if ( instrs[i]!=iv->instrdata->instrs[i])
257 break;
258 if ( i==icnt ) { /* Unchanged */
259 free(instrs);
260 return( true );
261 }
262 }
263 free( iv->instrdata->instrs );
264 iv->instrdata->instrs = instrs;
265 iv->instrdata->instr_cnt = icnt;
266 iv->instrdata->max = icnt;
267 iv->instrdata->changed = true;
268 free(iv->instrdata->bts );
269 iv->instrdata->bts = NULL;
270 instr_info_init(&iv->instrinfo);
271 GScrollBarSetBounds(iv->instrinfo.vsb,0,iv->instrinfo.lheight+2,
272 iv->instrinfo.vheight<iv->instrinfo.fh? 1 : iv->instrinfo.vheight/iv->instrinfo.fh);
273 return( true );
274 }
275
IVOk(InstrDlg * iv)276 static void IVOk(InstrDlg *iv) {
277 struct instrdata *id = iv->instrdata;
278
279 /* We need to update bits like instructions_out_of_date even if they */
280 /* make no change. */
281 if ( /*id->changed*/true ) {
282 if ( id->sc!=NULL ) {
283 SplineChar *sc = id->sc;
284 CharView *cv;
285 free(sc->ttf_instrs);
286 sc->ttf_instrs_len = id->instr_cnt;
287 if ( id->instr_cnt==0 )
288 sc->ttf_instrs = NULL;
289 else {
290 sc->ttf_instrs = malloc( id->instr_cnt );
291 memcpy(sc->ttf_instrs,id->instrs,id->instr_cnt );
292 }
293 for ( cv=(CharView *) (sc->views); cv!=NULL; cv=(CharView *) (cv->b.next) )
294 cv->showpointnumbers = false;
295 sc->instructions_out_of_date = true;
296 SCCharChangedUpdate(sc,ly_none);
297 sc->instructions_out_of_date = false;
298 FVRefreshAll(sc->parent);
299 } else {
300 struct ttf_table *tab, *prev;
301 if ( id->instr_cnt==0 ) {
302 for ( prev=NULL, tab=id->sf->ttf_tables; tab!=NULL && tab->tag!=id->tag; prev=tab, tab=tab->next );
303 if ( tab==NULL )
304 /* Nothing to be done */;
305 else if ( prev==NULL )
306 id->sf->ttf_tables = tab->next;
307 else
308 prev->next = tab->next;
309 if ( tab!=NULL ) {
310 tab->next = NULL;
311 TtfTablesFree(tab);
312 }
313 } else {
314 tab = SFFindTable(id->sf,id->tag);
315 if ( tab==NULL ) {
316 tab = chunkalloc(sizeof(struct ttf_table));
317 tab->next = id->sf->ttf_tables;
318 id->sf->ttf_tables = tab;
319 tab->tag = id->tag;
320 }
321 free( tab->data );
322 tab->data = malloc( id->instr_cnt );
323 memcpy(tab->data,id->instrs,id->instr_cnt );
324 tab->len = id->instr_cnt;
325 }
326 }
327 }
328 /* Instructions get freed in et_destroy */
329 }
330
IVBuildEdit(InstrDlg * iv)331 static void IVBuildEdit(InstrDlg *iv) {
332 char *ret;
333 ret = __IVUnParseInstrs((InstrBase *) iv);
334 if ( iv->text!=NULL ) {
335 GGadgetSetTitle8(iv->text,ret);
336 GTextFieldSelect(iv->text,iv->instrinfo.offset-ret,iv->instrinfo.offset-ret);
337 GTextFieldShow(iv->text,iv->instrinfo.scroll-ret);
338 }
339 }
340
instr_expose(struct instrinfo * ii,GWindow pixmap,GRect * rect)341 static void instr_expose(struct instrinfo *ii,GWindow pixmap,GRect *rect) {
342 int low, high;
343 int i,x,y;
344 char loc[8], ins[8], val[8]; unichar_t uins[8], uname[30];
345 int addr_end, num_end;
346 static unichar_t nums[] = { '0', '0', '0', '0', '0', '0', '\0' };
347 int indent;
348 extern GBox _ggadget_Default_Box;
349
350 GDrawSetFont(pixmap,ii->gfont);
351 GDrawSetLineWidth(pixmap,0);
352 addr_end = 0;
353 if ( ii->showaddr )
354 addr_end = GDrawGetTextWidth(pixmap,nums,4)+EDGE_SPACING;
355 num_end = addr_end;
356 if ( ii->showhex )
357 num_end = addr_end + GDrawGetTextWidth(pixmap,nums,5)+4;
358 else if ( addr_end<36+2*EDGE_SPACING )
359 num_end = addr_end = 36+2*EDGE_SPACING;
360
361 low = ( (rect->y-EDGE_SPACING)/ii->fh ) * ii->fh +EDGE_SPACING;
362 high = ( (rect->y+rect->height+ii->fh-1-EDGE_SPACING)/ii->fh ) * ii->fh +EDGE_SPACING;
363
364 if ( ii->isel_pos!=-1 ) {
365 GRect r;
366 r.x = 0; r.width = ii->vwidth;
367 r.y = (ii->isel_pos-ii->lpos)*ii->fh+EDGE_SPACING; r.height = ii->fh;
368 GDrawFillRect(pixmap,&r,ACTIVE_BORDER);
369 }
370
371 if ( ii->showaddr )
372 GDrawDrawLine(pixmap,addr_end,rect->y,addr_end,rect->y+rect->height,0x000000);
373 if ( ii->showhex )
374 GDrawDrawLine(pixmap,num_end,rect->y,num_end,rect->y+rect->height,0x000000);
375
376 indent = 0;
377 for ( i=0, y=EDGE_SPACING-ii->lpos*ii->fh; y<low && i<ii->instrdata->instr_cnt; ++i ) {
378 if ( ii->instrdata->bts[i]==bt_instr ) {
379 int instr = ii->instrdata->instrs[i];
380 if ( instr == ttf_if || instr==ttf_idef || instr == ttf_fdef )
381 ++indent;
382 else if ( instr == ttf_eif || instr==ttf_endf )
383 --indent;
384 } else if ( ii->instrdata->bts[i]==bt_wordhi )
385 ++i;
386 y += ii->fh;
387 }
388 if ( y<=high && ii->instrdata->instr_cnt==0 && i==0 ) {
389 if ( ii->instrdata->in_composit ) {
390 GDrawDrawText8(pixmap,num_end+EDGE_SPACING,y+ii->as,_("<instrs inherited>"),-1,0xff0000);
391 y += ii->fh;
392 }
393 GDrawDrawText8(pixmap,num_end+EDGE_SPACING,y+ii->as,_("<no instrs>"),-1,0xff0000);
394 } else {
395 int temp_indent;
396 for ( ; y<=high && i<ii->instrdata->instr_cnt+1; ++i ) {
397 temp_indent = indent;
398 sprintf( loc, "%d", i );
399 if ( ii->instrdata->bts[i]==bt_wordhi ) {
400 sprintf( ins, " %02x%02x", ii->instrdata->instrs[i], ii->instrdata->instrs[i+1]); uc_strcpy(uins,ins);
401 sprintf( val, " %d", (short) ((ii->instrdata->instrs[i]<<8) | ii->instrdata->instrs[i+1]) );
402 uc_strcpy(uname,val);
403 ++i;
404 } else if ( ii->instrdata->bts[i]==bt_cnt || ii->instrdata->bts[i]==bt_byte ) {
405 sprintf( ins, " %02x", ii->instrdata->instrs[i] ); uc_strcpy(uins,ins);
406 sprintf( val, " %d", ii->instrdata->instrs[i]);
407 uc_strcpy(uname,val);
408 } else if ( ii->instrdata->bts[i]==bt_impliedreturn ) {
409 uc_strcpy(uname,_("<return>"));
410 uins[0] = '\0';
411 } else {
412 int instr = ii->instrdata->instrs[i];
413 if ( instr == ttf_eif || instr==ttf_endf )
414 --indent;
415 temp_indent = indent;
416 if ( instr == ttf_else )
417 --temp_indent;
418 sprintf( ins, "%02x", instr ); uc_strcpy(uins,ins);
419 uc_strcpy(uname, ff_ttf_instrnames[instr]);
420 if ( instr == ttf_if || instr==ttf_idef || instr == ttf_fdef )
421 ++indent;
422 }
423
424 if ( ii->showaddr ) {
425 GRect size;
426 GDrawLayoutInit(pixmap,loc,-1,NULL);
427 GDrawLayoutExtents(pixmap,&size);
428 x = addr_end - EDGE_SPACING - size.width;
429 GDrawLayoutDraw(pixmap,x,y+ii->as,MAIN_FOREGROUND);
430 if ( ii->bpcheck && ii->bpcheck(ii,i))
431 GDrawDrawImage(pixmap,&GIcon_Stop,NULL,EDGE_SPACING,
432 y+(ii->fh-8)/2-5);
433 }
434 x = addr_end + EDGE_SPACING;
435 if ( ii->showhex )
436 GDrawDrawText(pixmap,x,y+ii->as,uins,-1,MAIN_FOREGROUND);
437 GDrawDrawText(pixmap,num_end+EDGE_SPACING+temp_indent*4,y+ii->as,uname,-1,MAIN_FOREGROUND);
438 y += ii->fh;
439 }
440 if ( ii->showaddr && ii->lstopped!=-1 ) {
441 GDrawDrawImage(pixmap,&GIcon_Stopped,NULL,EDGE_SPACING,
442 (ii->lstopped-ii->lpos)*ii->fh+(ii->fh-8)/2);
443 }
444 }
445 }
446
instr_mousedown(struct instrinfo * ii,int pos)447 static void instr_mousedown(struct instrinfo *ii,int pos) {
448 int i,l;
449
450 pos = (pos-2)/ii->fh + ii->lpos;
451 if ( pos>=ii->lheight )
452 pos = -1;
453
454 for ( i=l=0; l<pos && i<ii->instrdata->instr_cnt; ++i, ++l ) {
455 if ( ii->instrdata->bts[i]==bt_wordhi )
456 ++i;
457 }
458
459 ii->isel_pos=pos;
460 if ( ii->selection_callback!=NULL )
461 (ii->selection_callback)(ii,i);
462 GDrawRequestExpose(ii->v,NULL,false);
463 }
464
instr_mousemove(struct instrinfo * ii,int pos)465 static void instr_mousemove(struct instrinfo *ii,int pos) {
466 int i,y;
467 char *msg;
468
469 if ( ii->mousedown ) {
470 instr_mousedown(ii,pos);
471 return;
472 }
473 if ( ii->instrdata->bts==NULL )
474 return;
475
476 pos = ((pos-2)/ii->fh) * ii->fh + 2;
477
478 for ( i=0, y=2-ii->lpos*ii->fh; y<pos && i<ii->instrdata->instr_cnt; ++i ) {
479 if ( ii->instrdata->bts[i]==bt_wordhi )
480 ++i;
481 y += ii->fh;
482 }
483 switch ( ii->instrdata->bts[i] ) {
484 case bt_wordhi: case bt_wordlo:
485 msg = _("A short to be pushed on the stack");
486 break;
487 case bt_cnt:
488 msg = _("A count specifying how many bytes/shorts\nshould be pushed on the stack");
489 break;
490 case bt_byte:
491 msg = _("An unsigned byte to be pushed on the stack");
492 break;
493 case bt_instr:
494 msg = _(instrhelppopup[ii->instrdata->instrs[i]]);
495 if ( msg==NULL ) msg = "???";
496 break;
497 default:
498 msg = "???";
499 break;
500 }
501 GGadgetPreparePopup8(GDrawGetParentWindow(ii->v),msg);
502 }
503
instr_scroll(struct instrinfo * ii,struct sbevent * sb)504 void instr_scroll(struct instrinfo *ii,struct sbevent *sb) {
505 int newpos = ii->lpos;
506
507 switch( sb->type ) {
508 case et_sb_top:
509 newpos = 0;
510 break;
511 case et_sb_uppage:
512 newpos -= ii->vheight/ii->fh;
513 break;
514 case et_sb_up:
515 --newpos;
516 break;
517 case et_sb_down:
518 ++newpos;
519 break;
520 case et_sb_downpage:
521 newpos += ii->vheight/ii->fh;
522 break;
523 case et_sb_bottom:
524 newpos = ii->lheight-ii->vheight/ii->fh;
525 break;
526 case et_sb_thumb:
527 case et_sb_thumbrelease:
528 newpos = sb->pos;
529 break;
530 }
531 if ( newpos>ii->lheight+1-ii->vheight/ii->fh )
532 newpos = ii->lheight+1-ii->vheight/ii->fh;
533 if ( newpos<0 ) newpos =0;
534 if ( newpos!=ii->lpos ) {
535 GRect r;
536 int diff = newpos-ii->lpos;
537 ii->lpos = newpos;
538 GScrollBarSetPos(ii->vsb,ii->lpos);
539 r.x=0; r.y = EDGE_SPACING; r.width=ii->vwidth; r.height=ii->vheight-2*EDGE_SPACING;
540 GDrawScroll(ii->v,&r,0,diff*ii->fh);
541 }
542 }
543
IIChar(struct instrinfo * ii,GEvent * event)544 static int IIChar(struct instrinfo *ii,GEvent *event) {
545 int pos = ii->isel_pos;
546
547 if ( ii->handle_char )
548 return( (ii->handle_char)(ii,event));
549
550 if ( event->u.chr.keysym == GK_Up || event->u.chr.keysym == GK_KP_Up )
551 --pos;
552 else if ( event->u.chr.keysym == GK_Down || event->u.chr.keysym == GK_KP_Down )
553 ++pos;
554 else if ( event->u.chr.keysym == GK_Home || event->u.chr.keysym == GK_KP_Home ||
555 event->u.chr.keysym == GK_Begin || event->u.chr.keysym == GK_KP_Begin )
556 pos = 0;
557 else if ( event->u.chr.keysym == GK_End || event->u.chr.keysym == GK_KP_End ) {
558 pos = ii->lheight-1;
559 } else
560 return( false );
561 if ( pos==-2 ) pos = -1;
562 if ( pos!=ii->isel_pos ) {
563 ii->isel_pos = pos;
564 if ( pos!=-1 && (pos<ii->lpos || pos>=ii->lpos+ii->vheight/ii->fh )) {
565 ii->lpos = pos-(ii->vheight/(3*ii->fh));
566 if ( ii->lpos>=ii->lheight-ii->vheight/ii->fh )
567 ii->lpos = ii->lheight-ii->vheight/ii->fh-1;
568 if ( ii->lpos<0 ) ii->lpos = 0;
569 GScrollBarSetPos(ii->vsb,ii->lpos);
570 }
571 }
572 if ( ii->selection_callback!=NULL ) {
573 int i,l;
574 for ( i=l=0; l<pos && i<ii->instrdata->instr_cnt; ++i, ++l ) {
575 if ( ii->instrdata->bts[i]==bt_wordhi )
576 ++i;
577 }
578 (ii->selection_callback)(ii,i);
579 }
580 GDrawRequestExpose(ii->v,NULL,false);
581 return( true );
582 }
583
ii_v_e_h(GWindow gw,GEvent * event)584 int ii_v_e_h(GWindow gw, GEvent *event) {
585 struct instrinfo *ii = (struct instrinfo *) GDrawGetUserData(gw);
586
587 switch ( event->type ) {
588 case et_expose:
589 instr_expose(ii,gw,&event->u.expose.rect);
590 break;
591 case et_char:
592 if ( IIChar(ii,event)) {
593 /* All Done */
594 ;
595 } else if ( event->u.chr.keysym == GK_Help || event->u.chr.keysym == GK_F1 ) {
596 help("ui/dialogs/ttfinstrs.html", NULL);
597 }
598 break;
599 case et_mousemove: case et_mousedown: case et_mouseup:
600 GGadgetEndPopup();
601 if ( event->type==et_mousemove ) {
602 instr_mousemove(ii,event->u.mouse.y);
603 } else if ( event->type==et_mousedown ) {
604 instr_mousedown(ii,event->u.mouse.y);
605 if ( event->u.mouse.clicks==2 ) {
606 /*InstrModCreate(ii)*/
607 ;
608 }
609 } else {
610 instr_mousemove(ii,event->u.mouse.y);
611 ii->mousedown = false;
612 }
613 break;
614 case et_timer:
615 break;
616 case et_focus:
617 break;
618 }
619 return( true );
620 }
621
iv_e_h(GWindow gw,GEvent * event)622 static int iv_e_h(GWindow gw, GEvent *event) {
623 InstrDlg *iv = (InstrDlg *) GDrawGetUserData(gw);
624
625 switch ( event->type ) {
626 case et_expose:
627 break;
628 case et_resize:
629 instr_resize(iv,event);
630 break;
631 case et_char:
632 if ( event->u.chr.keysym == GK_Help || event->u.chr.keysym == GK_F1 )
633 help("ui/dialogs/ttfinstrs.html", NULL);
634 break;
635 case et_controlevent:
636 switch ( event->u.control.subtype ) {
637 case et_scrollbarchange:
638 instr_scroll(&iv->instrinfo,&event->u.control.u.sb);
639 break;
640 case et_buttonactivate:
641 if ( event->u.control.g==iv->ok || event->u.control.g==iv->cancel ) {
642 if ( event->u.control.g == iv->ok ) {
643 if ( iv->inedit )
644 if ( !IVParse(iv))
645 break;
646 IVOk(iv);
647 }
648 GDrawDestroyWindow(iv->gw);
649 } else if ( event->u.control.g==iv->edit || event->u.control.g==iv->parse ) {
650 int toedit = event->u.control.g==iv->edit;
651 GRect size;
652 if ( toedit ) {
653 IVBuildEdit(iv);
654 GGadgetGetSize(iv->instrinfo.vsb,&size);
655 size.width = -1;
656 GGadgetSetDesiredSize(iv->text,&size,NULL);
657 } else if ( !IVParse(iv))
658 break;
659 GGadgetSetVisible(iv->parse,toedit);
660 /*GGadgetSetVisible(iv->text,toedit);*/
661 GGadgetSetVisible(iv->edit,!toedit);
662 GGadgetSetVisible(iv->instrinfo.vsb,!toedit);
663 GDrawSetVisible(iv->instrinfo.v,!toedit);
664 GHVBoxFitWindow(iv->topbox);
665 iv->inedit = toedit;
666 }
667 break;
668 }
669 break;
670 case et_close:
671 GDrawDestroyWindow(iv->gw);
672 break;
673 case et_destroy: {
674 SplineFont *sf = iv->instrdata->sf;
675 struct instrdata *id, *prev;
676 for ( prev = NULL, id=sf->instr_dlgs; id!=iv->instrdata && id!=NULL; prev=id, id=id->next );
677 if ( prev==NULL )
678 sf->instr_dlgs = iv->instrdata->next;
679 else
680 prev->next = iv->instrdata->next;
681 free(iv->instrdata->instrs);
682 free(iv->instrdata->bts);
683 free(iv->instrdata);
684 free(iv);
685 } break;
686 }
687 return( true );
688 }
689
InstrDlgCreate(struct instrdata * id,char * title)690 static void InstrDlgCreate(struct instrdata *id,char *title) {
691 InstrDlg *iv = calloc(1,sizeof(*iv));
692 GRect pos;
693 GWindow gw;
694 GWindowAttrs wattrs;
695 FontRequest rq;
696 int as,ds,ld, lh;
697 GGadgetCreateData gcd[11], *butarray[9], *harray[3], *varray[8];
698 GTextInfo label[6];
699 static GFont *font=NULL;
700
701 instrhelpsetup();
702
703 id->next = id->sf->instr_dlgs;
704 id->sf->instr_dlgs = id;
705 id->id = iv;
706
707 iv->instrdata = id;
708 iv->instrinfo.instrdata = id;
709 iv->instrinfo.showhex = iv->instrinfo.showaddr = true;
710 iv->instrinfo.lstopped = -1;
711 instr_info_init(&iv->instrinfo);
712
713 if ( ttf_icon==NULL )
714 ttf_icon = GDrawCreateBitmap(NULL,ttf_width,ttf_height,ttf_bits);
715
716 memset(&wattrs,0,sizeof(wattrs));
717 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_icon;
718 wattrs.event_masks = ~(1<<et_charup);
719 wattrs.restrict_input_to_me = 1;
720 wattrs.undercursor = 1;
721 wattrs.cursor = ct_pointer;
722 wattrs.utf8_window_title = title;
723 wattrs.icon = ttf_icon;
724 pos.x = pos.y = 0;
725 if ( GIntGetResource(_NUM_Buttonsize)>65 )
726 pos.width = GDrawPointsToPixels(NULL,3*GIntGetResource(_NUM_Buttonsize)+40);
727 else
728 pos.width = GDrawPointsToPixels(NULL,250);
729 iv->oc_height = GDrawPointsToPixels(NULL,37);
730 pos.height = GDrawPointsToPixels(NULL,100) + iv->oc_height;
731 iv->gw = gw = GDrawCreateTopWindow(NULL,&pos,iv_e_h,iv,&wattrs);
732
733 memset(&label,0,sizeof(label));
734 memset(&gcd,0,sizeof(gcd));
735 gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 105;
736 gcd[0].gd.pos.width = -1;
737 label[0].text = (unichar_t *) _("_OK");
738 label[0].text_is_1byte = true;
739 label[0].text_in_resource = true;
740 gcd[0].gd.label = &label[0];
741 gcd[0].gd.flags = gg_visible|gg_enabled|gg_but_default;
742 gcd[0].creator = GButtonCreate;
743 gcd[0].data = iv;
744
745 gcd[1].gd.pos.x = -8; gcd[1].gd.pos.y = 3;
746 gcd[1].gd.pos.width = -1;
747 label[1].text = (unichar_t *) _("_Cancel");
748 label[1].text_is_1byte = true;
749 label[1].text_in_resource = true;
750 gcd[1].gd.label = &label[1];
751 gcd[1].gd.flags = gg_visible|gg_enabled|gg_but_cancel;
752 gcd[1].creator = GButtonCreate;
753 gcd[1].data = iv;
754
755 gcd[2] = gcd[1];
756 label[2].text = (unichar_t *) _("_Edit");
757 label[2].text_is_1byte = true;
758 label[2].text_in_resource = true;
759 gcd[2].gd.flags = gg_visible|gg_enabled;
760 gcd[2].gd.label = &label[2];
761 gcd[2].creator = GButtonCreate;
762 gcd[2].data = iv;
763
764 gcd[3] = gcd[1];
765 label[3] = label[2];
766 label[3].text = (unichar_t *) _("_Parse");
767 gcd[3].gd.flags = gg_enabled;
768 gcd[3].gd.label = &label[3];
769 gcd[3].creator = GButtonCreate;
770 gcd[3].data = iv;
771
772 butarray[0] = GCD_Glue; butarray[1] = &gcd[0];
773 butarray[2] = GCD_Glue; butarray[3] = &gcd[2];
774 butarray[4] = &gcd[3]; butarray[5] = GCD_Glue;
775 butarray[6] = &gcd[1]; butarray[7] = GCD_Glue;
776 butarray[8] = NULL;
777 gcd[4].gd.flags = gg_enabled|gg_visible;
778 gcd[4].gd.u.boxelements = butarray;
779 gcd[4].creator = GHBoxCreate;
780
781 gcd[5].gd.pos.x = 0; gcd[5].gd.pos.y = 0;
782 gcd[5].gd.pos.width = pos.width; gcd[5].gd.pos.height = pos.height-GDrawPointsToPixels(NULL,40);
783 gcd[5].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_textarea_wrap|gg_pos_use0;
784 gcd[5].creator = GTextAreaCreate;
785 gcd[5].data = iv;
786 harray[0] = &gcd[5];
787
788 gcd[6].gd.pos.y = 0; gcd[6].gd.pos.height = pos.height-GDrawPointsToPixels(NULL,40);
789 gcd[6].gd.pos.width = GDrawPointsToPixels(gw,_GScrollBar_Width);
790 gcd[6].gd.pos.x = pos.width-gcd[6].gd.pos.width;
791 gcd[6].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
792 gcd[6].creator = GScrollBarCreate;
793 gcd[6].data = iv;
794 harray[1] = &gcd[6]; harray[2] = NULL;
795
796 gcd[7].gd.flags = gg_enabled|gg_visible;
797 gcd[7].gd.u.boxelements = harray;
798 gcd[7].creator = GHBoxCreate;
799
800 varray[0] = &gcd[7]; varray[1] = NULL;
801 varray[2] = &gcd[8]; varray[3] = NULL;
802 varray[4] = &gcd[4]; varray[5] = NULL;
803 varray[6] = NULL;
804
805 gcd[8].gd.flags = gg_enabled|gg_visible;
806 gcd[8].gd.pos.width = 100;
807 gcd[8].creator = GLineCreate;
808
809 gcd[9].gd.pos.x = gcd[9].gd.pos.y = 2;
810 gcd[9].gd.flags = gg_enabled|gg_visible;
811 gcd[9].gd.u.boxelements = varray;
812 gcd[9].creator = GHVGroupCreate;
813
814 GGadgetsCreate(gw,&gcd[9]);
815 GHVBoxSetExpandableRow(gcd[9].ret,0);
816 GHVBoxSetExpandableCol(gcd[7].ret,0);
817 GHVBoxSetExpandableCol(gcd[4].ret,gb_expandgluesame);
818
819 iv->ok = gcd[0].ret;
820 iv->cancel = gcd[1].ret;
821 iv->edit = gcd[2].ret;
822 iv->parse = gcd[3].ret;
823 iv->text = gcd[5].ret;
824 iv->instrinfo.vsb = gcd[6].ret;
825 iv->topbox = gcd[9].ret;
826
827 wattrs.mask = wam_events|wam_cursor;
828 pos = gcd[5].gd.pos;
829 iv->instrinfo.v = GWidgetCreateSubWindow(gw,&pos,ii_v_e_h,&iv->instrinfo,&wattrs);
830 GDrawSetVisible(iv->instrinfo.v,true);
831
832 if ( font==NULL ) {
833 memset(&rq,0,sizeof(rq));
834 rq.utf8_family_name = MONO_UI_FAMILIES;
835 rq.point_size = -12;
836 rq.weight = 400;
837 font = GDrawInstanciateFont(gw,&rq);
838 font = GResourceFindFont("TTInstruction.Font",font);
839 }
840 iv->instrinfo.gfont = font;
841 GDrawSetFont(iv->instrinfo.v,iv->instrinfo.gfont);
842 GGadgetSetFont(iv->text,iv->instrinfo.gfont);
843 GDrawWindowFontMetrics(iv->instrinfo.v,iv->instrinfo.gfont,&as,&ds,&ld);
844 iv->instrinfo.as = as+1;
845 iv->instrinfo.fh = iv->instrinfo.as+ds;
846 iv->instrinfo.isel_pos = -1;
847
848 lh = iv->instrinfo.lheight;
849 if ( lh>40 ) lh = 40;
850 if ( lh<4 ) lh = 4;
851 GDrawResize(iv->gw,pos.width+gcd[6].gd.pos.width,iv->oc_height+lh*iv->instrinfo.fh+4);
852
853 GDrawSetVisible(gw,true);
854 }
855
SCEditInstructions(SplineChar * sc)856 void SCEditInstructions(SplineChar *sc) {
857 struct instrdata *id;
858 char title[100];
859 CharView *cv;
860 RefChar *ref;
861
862 /* In a multiple master font, the instructions for all glyphs reside in */
863 /* the "normal" instance of the font. The instructions are the same for */
864 /* all instances (the cvt table might be different) */
865 if ( sc->parent->mm!=NULL && sc->parent->mm->apple )
866 sc = sc->parent->mm->normal->glyphs[sc->orig_pos];
867
868 for ( id = sc->parent->instr_dlgs; id!=NULL && id->sc!=sc; id=id->next );
869 if ( id!=NULL ) {
870 GDrawSetVisible(id->id->gw,true);
871 GDrawRaise(id->id->gw);
872 return;
873 }
874
875 if ( sc->layers[ly_fore].refs!=NULL && sc->layers[ly_fore].splines!=NULL ) {
876 ff_post_error(_("Can't instruct this glyph"),
877 _("TrueType does not support mixed references and contours.\nIf you want instructions for %.30s you should either:\n * Unlink the reference(s)\n * Copy the inline contours into their own (unencoded\n glyph) and make a reference to that."),
878 sc->name );
879 return;
880 }
881 for ( ref = sc->layers[ly_fore].refs; ref!=NULL; ref=ref->next ) {
882 if ( ref->transform[0]>=2 || ref->transform[0]<-2 ||
883 ref->transform[1]>=2 || ref->transform[1]<-2 ||
884 ref->transform[2]>=2 || ref->transform[2]<-2 ||
885 ref->transform[3]>=2 || ref->transform[3]<-2 )
886 break;
887 }
888 if ( ref!=NULL ) {
889 ff_post_error(_("Can't instruct this glyph"),
890 _("TrueType does not support references which\nare scaled by more than 200%%. But %1$.30s\nhas been in %2$.30s. Any instructions\nadded would be meaningless."),
891 ref->sc->name, sc->name );
892 return;
893 }
894
895 for ( cv=(CharView *) (sc->views); cv!=NULL; cv=(CharView *) (cv->b.next) ) {
896 sc = cv->b.sc;
897 cv->showpointnumbers = true;
898 SCNumberPoints(sc,CVLayer((CharViewBase *) cv));
899 GDrawRequestExpose(cv->v,NULL,false);
900 }
901 id = calloc(1,sizeof(*id));
902 id->instr_cnt = id->max = sc->ttf_instrs_len;
903 id->sf = sc->parent;
904 id->sc = sc;
905 id->instrs = malloc(id->max+1);
906 if ( sc->ttf_instrs!=NULL )
907 memcpy(id->instrs,sc->ttf_instrs,id->instr_cnt);
908 sprintf(title,_("TrueType Instructions for %.50s"),sc->name);
909 InstrDlgCreate(id,title);
910 }
911
SC_MarkInstrDlgAsChanged(SplineChar * sc)912 void SC_MarkInstrDlgAsChanged(SplineChar *sc) {
913 struct instrdata *id;
914
915 for ( id = sc->parent->instr_dlgs; id!=NULL && id->sc!=sc; id=id->next );
916 if ( id!=NULL )
917 id->changed = true;
918 }
919
IIScrollTo(struct instrinfo * ii,int ip,int mark_stop)920 void IIScrollTo(struct instrinfo *ii,int ip,int mark_stop) {
921 int l, i;
922
923 for ( i=l=0; i<ip && i<ii->instrdata->instr_cnt; ++i, ++l ) {
924 if ( ii->instrdata->bts[i]==bt_wordhi || ii->instrdata->bts[i]==bt_wordlo )
925 ++i;
926 }
927 if ( ip==-1 )
928 ii->lstopped = -1;
929 else {
930 if ( mark_stop )
931 ii->lstopped = l;
932 if ( l<ii->lpos || l>=ii->lpos+ii->vheight/ii->fh-1 ) {
933 if ( l+ii->vheight/ii->fh-1 >= ii->lheight+1 )
934 l = ii->lheight+2-(ii->vheight/ii->fh);
935 if ( l<0 )
936 l = 0;
937 ii->lpos = l;
938 GScrollBarSetPos(ii->vsb,l);
939 }
940 }
941 GDrawRequestExpose(ii->v,NULL,false);
942 }
943
IIReinit(struct instrinfo * ii,int ip)944 void IIReinit(struct instrinfo *ii,int ip) {
945 instrhelpsetup();
946 free(ii->instrdata->bts);
947 ii->instrdata->bts = NULL;
948 instr_info_init(ii);
949 GScrollBarSetBounds(ii->vsb,0,ii->lheight+2, ii->vheight<ii->fh ? 1 : ii->vheight/ii->fh);
950 IIScrollTo(ii,ip,true);
951 }
952
953 /* ************************************************************************** */
954 /* **************************** CVT table editor **************************** */
955 /* ************************************************************************** */
956
957 #define ADDR_SPACER 4
958 #define EDGE_SPACER 2
959
960 typedef struct shortview /* : tableview */ {
961 struct ttf_table *table;
962 GWindow gw, v;
963 SplineFont *sf;
964 unsigned int destroyed: 1; /* window has been destroyed */
965 unsigned int changed: 1;
966 GGadget *vsb, *tf;
967 GGadget *ok, *cancel, *setsize;
968 int lpos, lheight;
969 int16 as, fh;
970 int16 vheight, vwidth;
971 int16 sbw, bh;
972 GFont *gfont;
973 int16 chrlen, addrend, valend;
974 int16 active;
975 int16 which;
976 int16 *edits;
977 char **comments;
978 uint8 *data;
979 int32 len;
980 uint32 tag;
981 } ShortView;
982
sfinishup(ShortView * sv,int showerr)983 static int sfinishup(ShortView *sv,int showerr) {
984 const unichar_t *ret = _GGadgetGetTitle(sv->tf);
985 unichar_t *end;
986 int val, oldval;
987
988 if ( sv->active==-1 )
989 return( true );
990
991 if ( sv->which ) {
992 if ( *ret=='\0' ) {
993 if ( sv->comments[sv->active]!=NULL ) {
994 free(sv->comments[sv->active]);
995 sv->comments[sv->active] = NULL;
996 sv->changed = true;
997 }
998 } else {
999 char *new = GGadgetGetTitle8(sv->tf);
1000 if ( sv->comments[sv->active]==NULL ) {
1001 sv->changed = true;
1002 } else {
1003 if ( strcmp(sv->comments[sv->active],new)!=0 )
1004 sv->changed = true;
1005 free(sv->comments[sv->active]);
1006 }
1007 sv->comments[sv->active] = new;
1008 }
1009 } else {
1010 val = u_strtol(ret,&end,10);
1011 if ( *ret=='\0' || *end!='\0' || val<-32768 || val>32767 ) {
1012 if ( showerr )
1013 ff_post_error(_("Bad Number"),_("Bad Number"));
1014 return( false );
1015 }
1016 oldval = sv->edits[sv->active];
1017 if ( val != oldval ) {
1018 sv->changed = true;
1019 sv->edits[sv->active] = val;
1020 }
1021 }
1022 sv->active = -1;
1023 GGadgetMove(sv->tf,sv->addrend,-100);
1024 return( true );
1025 }
1026
SV_SetScrollBar(ShortView * sv)1027 static void SV_SetScrollBar(ShortView *sv) {
1028 int lh;
1029 sv->lheight = lh = sv->len/2;
1030
1031 GScrollBarSetBounds(sv->vsb,0,lh,sv->vheight<sv->fh ? 1 : sv->vheight/sv->fh);
1032 if ( sv->lpos + sv->vheight/sv->fh > lh ) {
1033 int lpos = lh-sv->vheight/sv->fh;
1034 if ( lpos<0 ) lpos = 0;
1035 if ( sv->lpos!=lpos && sv->active!=-1 )
1036 GGadgetMove(sv->tf,sv->addrend,(sv->active-lpos)*sv->fh);
1037 sv->lpos = lpos;
1038 }
1039 GScrollBarSetPos(sv->vsb,sv->lpos);
1040 }
1041
SV_ChangeLength(GGadget * g,GEvent * e)1042 static int SV_ChangeLength(GGadget *g, GEvent *e) {
1043 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1044 ShortView *sv = GDrawGetUserData(GGadgetGetWindow(g));
1045 char buffer[12];
1046 char *ret, *e;
1047 int val,i;
1048
1049 sprintf( buffer, "%d", (int) (sv->len/2) );
1050 ret = gwwv_ask_string(_("Change Length"), buffer,_("How many entries should there be in the cvt table?"));
1051 if ( ret==NULL )
1052 return( true ); /* Cancelled */
1053 val = strtol(ret,&e,10);
1054 if ( *e || val<0 || val>65535 ) {
1055 free(ret);
1056 ff_post_error(_("Bad Number"),_("Bad Number"));
1057 return( false );
1058 }
1059 free(ret);
1060 if ( val*2>sv->len ) {
1061 sv->edits = realloc(sv->edits,val*2);
1062 for ( i=sv->len/2; i<val; ++i )
1063 sv->edits[i] = 0;
1064 sv->comments = realloc(sv->comments,val*sizeof(char *));
1065 for ( i=sv->len/2; i<val; ++i )
1066 sv->comments[i] = NULL;
1067 } else {
1068 for ( i=val; i<sv->len/2; ++i ) {
1069 free(sv->comments[i]);
1070 sv->comments[i] = NULL;
1071 }
1072 }
1073 sv->len = 2*val;
1074 SV_SetScrollBar(sv);
1075 GDrawRequestExpose(sv->v,NULL,true);
1076 }
1077 return( true );
1078 }
1079
_SV_DoClose(ShortView * sv)1080 static void _SV_DoClose(ShortView *sv) {
1081
1082 sv->destroyed = true;
1083 GDrawDestroyWindow(sv->gw);
1084 }
1085
SV_Cancel(GGadget * g,GEvent * e)1086 static int SV_Cancel(GGadget *g, GEvent *e) {
1087 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1088 ShortView *sv = GDrawGetUserData(GGadgetGetWindow(g));
1089
1090 _SV_DoClose(sv);
1091 }
1092 return( true );
1093 }
1094
SV_OK(GGadget * g,GEvent * e)1095 static int SV_OK(GGadget *g, GEvent *e) {
1096 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1097 ShortView *sv = GDrawGetUserData(GGadgetGetWindow(g));
1098 int i;
1099 struct ttf_table *prev, *tab;
1100 SplineFont *sf = sv->sf;
1101
1102 if ( !sfinishup(sv,true) )
1103 return( true );
1104 if ( sf->cvt_names!=NULL ) {
1105 for ( i=0; sf->cvt_names[i]!=END_CVT_NAMES; ++i )
1106 free(sf->cvt_names[i]);
1107 free(sf->cvt_names);
1108 sf->cvt_names = NULL;
1109 }
1110 if ( sv->len==0 ) {
1111 if ( sv->table!=NULL ) {
1112 prev = NULL;
1113 for ( tab=sf->ttf_tables; tab!=NULL && tab!=sv->table; prev=tab, tab=tab->next );
1114 if ( prev!=NULL )
1115 prev->next = tab->next;
1116 else
1117 sf->ttf_tables = tab->next;
1118 free(sv->table->data);
1119 chunkfree(sv->table,sizeof(struct ttf_table));
1120 sv->table = NULL;
1121 }
1122 } else {
1123 if ( sv->table!=NULL )
1124 free(sv->table->data);
1125 else {
1126 tab = chunkalloc(sizeof(struct ttf_table));
1127 tab->next = sf->ttf_tables;
1128 sf->ttf_tables = tab;
1129 tab->tag = sv->tag;
1130 sv->table = tab;
1131 }
1132 sv->table->data = malloc(sv->len);
1133 sf->cvt_names = malloc(((sv->len>>1)+1)*sizeof(char *));
1134 for ( i=0; i<sv->len/2; ++i ) {
1135 sv->table->data[i<<1] = (sv->edits[i]>>8)&0xff;
1136 sv->table->data[(i<<1)+1] = sv->edits[i]&0xff;
1137 sf->cvt_names[i] = sv->comments[i];
1138 sv->comments[i] = NULL;
1139 }
1140 sf->cvt_names[i] = END_CVT_NAMES;
1141 sv->table->len = sv->len;
1142 }
1143 sf->changed = true;
1144 _SV_DoClose(sv);
1145 }
1146 return( true );
1147 }
1148
short_resize(ShortView * sv,GEvent * event)1149 static void short_resize(ShortView *sv,GEvent *event) {
1150 GRect pos, gsize;
1151 int width;
1152
1153 /* height must be a multiple of the line height */
1154 if ( (event->u.resize.size.height-2*EDGE_SPACER-sv->bh)%sv->fh!=0 ||
1155 (event->u.resize.size.height-2*EDGE_SPACER-sv->fh-sv->bh)<0 ) {
1156 int lc = (event->u.resize.size.height+sv->fh/2-EDGE_SPACER)/sv->fh;
1157 if ( lc<=0 ) lc = 1;
1158 GDrawResize(sv->gw, event->u.resize.size.width,
1159 lc*sv->fh+2*EDGE_SPACER+sv->bh);
1160 return;
1161 }
1162
1163 pos.width = GDrawPointsToPixels(sv->gw,_GScrollBar_Width);
1164 pos.height = event->u.resize.size.height-sv->bh-sv->fh;
1165 pos.x = event->u.resize.size.width-pos.width; pos.y = sv->fh;
1166 GGadgetResize(sv->vsb,pos.width,pos.height+1);
1167 GGadgetMove(sv->vsb,pos.x,pos.y);
1168 pos.width = pos.x; pos.x = 0;
1169 GDrawResize(sv->v,pos.width,pos.height);
1170 GDrawMove(sv->v,0,sv->fh);
1171
1172 sv->vheight = pos.height; sv->vwidth = pos.width;
1173 SV_SetScrollBar(sv);
1174
1175 width = pos.width-sv->addrend;
1176 if ( width < 5 ) width = 5;
1177 GGadgetResize(sv->tf,width,sv->fh);
1178
1179 GGadgetGetSize(sv->ok,&gsize);
1180 GGadgetMove(sv->ok,gsize.x,event->u.resize.size.height-GDrawPointsToPixels(sv->gw,33));
1181 GGadgetMove(sv->cancel,event->u.resize.size.width-gsize.x-gsize.width,event->u.resize.size.height-GDrawPointsToPixels(sv->gw,30));
1182 GGadgetGetSize(sv->setsize,&gsize);
1183 GGadgetMove(sv->setsize,(event->u.resize.size.width-gsize.width)/2,
1184 event->u.resize.size.height-GDrawPointsToPixels(sv->gw,60));
1185
1186 GDrawRequestExpose(sv->gw,NULL,true);
1187 }
1188
short_expose(ShortView * sv,GWindow pixmap,GRect * rect)1189 static void short_expose(ShortView *sv,GWindow pixmap,GRect *rect) {
1190 int low, high;
1191 int x,y;
1192 char cval[8], caddr[8];
1193 int index;
1194
1195 GDrawSetFont(pixmap,sv->gfont);
1196
1197 low = ( (rect->y-EDGE_SPACER)/sv->fh ) * sv->fh + EDGE_SPACER;
1198 high = ( (rect->y+rect->height+sv->fh-1-EDGE_SPACER)/sv->fh ) * sv->fh +EDGE_SPACER;
1199 if ( high>sv->vheight-EDGE_SPACER ) high = sv->vheight-EDGE_SPACER;
1200
1201 GDrawDrawLine(pixmap,sv->addrend-ADDR_SPACER/2,rect->y,sv->addrend-ADDR_SPACER/2,rect->y+rect->height,0x000000);
1202 GDrawDrawLine(pixmap,sv->valend-ADDR_SPACER/2,rect->y,sv->valend-ADDR_SPACER/2,rect->y+rect->height,0x000000);
1203
1204 index = (sv->lpos+(low-EDGE_SPACER)/sv->fh);
1205 y = low;
1206 for ( ; y<=high && index<sv->len/2; ++index ) {
1207 sprintf( caddr, "%d", index );
1208 x = sv->addrend - ADDR_SPACER - GDrawGetText8Width(pixmap,caddr,-1);
1209 GDrawDrawText8(pixmap,x,y+sv->as,caddr,-1,MAIN_FOREGROUND);
1210
1211 sprintf( cval, "%d", sv->edits[index] );
1212 GDrawDrawText8(pixmap,sv->addrend,y+sv->as,cval,-1,MAIN_FOREGROUND);
1213
1214 if ( sv->comments[index]!=NULL )
1215 GDrawDrawText8(pixmap,sv->valend,y+sv->as,sv->comments[index],-1,MAIN_FOREGROUND);
1216 y += sv->fh;
1217 }
1218 }
1219
short_mousemove(ShortView * sv,int pos)1220 static void short_mousemove(ShortView *sv,int pos) {
1221 /*GGadgetPreparePopup(sv->gw,msg);*/
1222 }
1223
short_scroll(ShortView * sv,struct sbevent * sb)1224 static void short_scroll(ShortView *sv,struct sbevent *sb) {
1225 int newpos = sv->lpos;
1226
1227 switch( sb->type ) {
1228 case et_sb_top:
1229 newpos = 0;
1230 break;
1231 case et_sb_uppage:
1232 newpos -= sv->vheight/sv->fh;
1233 break;
1234 case et_sb_up:
1235 --newpos;
1236 break;
1237 case et_sb_down:
1238 ++newpos;
1239 break;
1240 case et_sb_downpage:
1241 newpos += sv->vheight/sv->fh;
1242 break;
1243 case et_sb_bottom:
1244 newpos = sv->lheight-sv->vheight/sv->fh;
1245 break;
1246 case et_sb_thumb:
1247 case et_sb_thumbrelease:
1248 newpos = sb->pos;
1249 break;
1250 }
1251 if ( newpos>sv->lheight-sv->vheight/sv->fh )
1252 newpos = sv->lheight-sv->vheight/sv->fh;
1253 if ( newpos<0 ) newpos =0;
1254 if ( newpos!=sv->lpos ) {
1255 int diff = newpos-sv->lpos;
1256 sv->lpos = newpos;
1257 GScrollBarSetPos(sv->vsb,sv->lpos);
1258 if ( sv->active!=-1 ) {
1259 GRect pos;
1260 GGadgetGetSize(sv->tf,&pos);
1261 GGadgetMove(sv->tf,sv->addrend,pos.y+diff*sv->fh);
1262 }
1263 GDrawScroll(sv->v,NULL,0,diff*sv->fh);
1264 }
1265 }
1266
ShortViewFree(ShortView * sv)1267 static void ShortViewFree(ShortView *sv) {
1268 sv->sf->cvt_dlg = NULL;
1269 free(sv->edits);
1270 free(sv);
1271 }
1272
sv_v_e_h(GWindow gw,GEvent * event)1273 static int sv_v_e_h(GWindow gw, GEvent *event) {
1274 ShortView *sv = (ShortView *) GDrawGetUserData(gw);
1275
1276 switch ( event->type ) {
1277 case et_expose:
1278 short_expose(sv,gw,&event->u.expose.rect);
1279 break;
1280 case et_char:
1281 if ( event->u.chr.keysym == GK_Help || event->u.chr.keysym == GK_F1 )
1282 help("ui/dialogs/ttfinstrs.html", "#ttfinstrs-cvt");
1283 break;
1284 case et_mousemove: case et_mousedown: case et_mouseup:
1285 GGadgetEndPopup();
1286 if ( event->type==et_mousemove )
1287 short_mousemove(sv,event->u.mouse.y);
1288 else if ( event->type == et_mousedown ) {
1289 int l = (event->u.mouse.y-EDGE_SPACER)/sv->fh + sv->lpos;
1290 int which = event->u.mouse.x > sv->valend;
1291 char buf[20];
1292 int old = sv->active;
1293 if ( sfinishup(sv,true) && event->u.mouse.x>sv->addrend &&
1294 l<sv->len/2 && l!=old ) {
1295 sv->active = l;
1296 sv->which = which;
1297 if ( !which ) {
1298 /* Change the value */
1299 GGadgetResize(sv->tf,sv->valend-sv->addrend-EDGE_SPACER,sv->fh);
1300 GGadgetMove(sv->tf, sv->addrend,
1301 (l-sv->lpos)*sv->fh+EDGE_SPACER+1);
1302 sprintf( buf, "%d", sv->edits[sv->active] );
1303 GGadgetSetTitle8(sv->tf,buf);
1304 } else {
1305 GGadgetResize(sv->tf,sv->vwidth-sv->valend-EDGE_SPACER,sv->fh);
1306 GGadgetMove(sv->tf, sv->valend,
1307 (l-sv->lpos)*sv->fh+EDGE_SPACER+1);
1308 GGadgetSetTitle8(sv->tf,sv->comments[l]==NULL?"":sv->comments[l]);
1309 }
1310 GDrawRequestExpose(sv->v,NULL,true);
1311 GDrawPostEvent(event); /* And we hope the tf catches it this time */
1312 }
1313 }
1314 break;
1315 case et_resize:
1316 GDrawRequestExpose(gw,NULL,true);
1317 break;
1318 case et_timer:
1319 break;
1320 case et_focus:
1321 break;
1322 }
1323 return( true );
1324 }
1325
sv_e_h(GWindow gw,GEvent * event)1326 static int sv_e_h(GWindow gw, GEvent *event) {
1327 ShortView *sv = (ShortView *) GDrawGetUserData(gw);
1328 GRect r;
1329 int x;
1330
1331 switch ( event->type ) {
1332 case et_expose:
1333 r.x = r.y = 0; r.width = sv->vwidth+40; r.height = sv->fh-1;
1334 GDrawFillRect(gw,&r,0x808080);
1335 GDrawSetFont(gw,sv->gfont);
1336 x = sv->addrend - ADDR_SPACER - 2 - GDrawGetText8Width(gw,_("Index"),-1);
1337 GDrawDrawText8(gw,x,sv->as,_("Index"),-1,0xffffff);
1338 GDrawDrawText8(gw,sv->addrend,sv->as,_("Value"),-1,0xffffff);
1339 GDrawDrawText8(gw,sv->valend,sv->as,_("Comment"),-1,0xffffff);
1340
1341 GDrawDrawLine(gw,0,sv->fh-1,r.width,sv->fh-1,0x000000);
1342 GDrawDrawLine(gw,0,sv->vheight+sv->fh,sv->vwidth,sv->vheight+sv->fh,0x000000);
1343 break;
1344 case et_resize:
1345 short_resize(sv,event);
1346 break;
1347 case et_char:
1348 if ( event->u.chr.keysym == GK_Help || event->u.chr.keysym == GK_F1 )
1349 help("ui/dialogs/ttfinstrs.html", "#ttfinstrs-cvt");
1350 break;
1351 case et_controlevent:
1352 switch ( event->u.control.subtype ) {
1353 case et_scrollbarchange:
1354 short_scroll(sv,&event->u.control.u.sb);
1355 break;
1356 }
1357 break;
1358 case et_close:
1359 _SV_DoClose(sv);
1360 break;
1361 case et_destroy:
1362 ShortViewFree(sv);
1363 break;
1364 }
1365 return( true );
1366 }
1367
1368 /* cvt table */
cvtCreateEditor(struct ttf_table * tab,SplineFont * sf,uint32 tag)1369 static void cvtCreateEditor(struct ttf_table *tab,SplineFont *sf,uint32 tag) {
1370 ShortView *sv = calloc(1,sizeof(ShortView));
1371 char title[60];
1372 GRect pos, subpos, gsize;
1373 GWindow gw;
1374 GWindowAttrs wattrs;
1375 FontRequest rq;
1376 int as,ds,ld, lh;
1377 GGadgetCreateData gcd[9], *butarray[8], *harray[4], *harray2[3], *varray[7];
1378 GTextInfo label[5], lab;
1379 GGadgetData gd;
1380 static unichar_t num[] = { '0', '\0' };
1381 int numlen;
1382 static GBox tfbox;
1383 int i;
1384 static GFont *font = NULL;
1385
1386 sv->table = tab;
1387 sv->sf = sf;
1388 sf->cvt_dlg = sv;
1389 sv->tag = tag;
1390
1391 if ( tab==NULL && sf->mm!=NULL && sf->mm->apple )
1392 tab = SFFindTable(sf->mm->normal,tag);
1393 if ( tab!=NULL ) {
1394 sv->len = tab->len;
1395 sv->edits = malloc(tab->len+1);
1396 sv->comments = calloc((tab->len/2+1),sizeof(char *));
1397 for ( i=0; i<tab->len/2; ++i )
1398 sv->edits[i] = (tab->data[i<<1]<<8) | tab->data[(i<<1)+1];
1399 if ( sf->cvt_names!=NULL )
1400 for ( i=0; i<tab->len/2 && sf->cvt_names[i]!=END_CVT_NAMES; ++i )
1401 sv->comments[i] = copy(sf->cvt_names[i]);
1402 } else {
1403 sv->edits = malloc(2);
1404 sv->len = 0;
1405 sv->comments = calloc(1,sizeof(char *));
1406 }
1407
1408 title[0] = (tag>>24)&0xff;
1409 title[1] = (tag>>16)&0xff;
1410 title[2] = (tag>>8 )&0xff;
1411 title[3] = (tag )&0xff;
1412 title[4] = ' ';
1413 strncpy(title+5, sf->fontname, sizeof(title)/sizeof(title[0])-6);
1414
1415 memset(&wattrs,0,sizeof(wattrs));
1416 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_icon;
1417 wattrs.event_masks = ~(1<<et_charup);
1418 wattrs.undercursor = 1;
1419 wattrs.cursor = ct_pointer;
1420 wattrs.utf8_window_title = title;
1421 wattrs.icon = ttf_icon;
1422 pos.x = pos.y = 0;
1423 if ( GIntGetResource(_NUM_Buttonsize)>60 )
1424 pos.width = GDrawPointsToPixels(NULL,2*GIntGetResource(_NUM_Buttonsize)+30);
1425 else
1426 pos.width = GDrawPointsToPixels(NULL,150);
1427 pos.height = GDrawPointsToPixels(NULL,200);
1428 sv->gw = gw = GDrawCreateTopWindow(NULL,&pos,sv_e_h,sv,&wattrs);
1429
1430 memset(&gcd,0,sizeof(gcd));
1431 memset(&label,0,sizeof(label));
1432
1433 gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 105;
1434 gcd[0].gd.pos.width = -1;
1435 label[0].text = (unichar_t *) _("_OK");
1436 label[0].text_is_1byte = true;
1437 label[0].text_in_resource = true;
1438 gcd[0].gd.label = &label[0];
1439 gcd[0].gd.flags = gg_visible|gg_enabled|gg_but_default;
1440 gcd[0].creator = GButtonCreate;
1441 gcd[0].data = sv;
1442 gcd[0].gd.handle_controlevent = SV_OK;
1443
1444 gcd[1].gd.pos.x = -8; gcd[1].gd.pos.y = 3;
1445 gcd[1].gd.pos.width = -1;
1446 label[1].text = (unichar_t *) _("_Cancel");
1447 label[1].text_is_1byte = true;
1448 label[1].text_in_resource = true;
1449 gcd[1].gd.label = &label[1];
1450 gcd[1].gd.flags = gg_visible|gg_enabled|gg_but_cancel;
1451 gcd[1].creator = GButtonCreate;
1452 gcd[1].data = sv;
1453 gcd[1].gd.handle_controlevent = SV_Cancel;
1454
1455 gcd[2] = gcd[1];
1456 label[2].text = (unichar_t *) _("Change Length");
1457 label[2].text_is_1byte = true;
1458 label[2].text_in_resource = true;
1459 gcd[2].gd.flags = gg_visible|gg_enabled;
1460 gcd[2].gd.label = &label[2];
1461 gcd[2].creator = GButtonCreate;
1462 gcd[2].data = sv;
1463 gcd[2].gd.handle_controlevent = SV_ChangeLength;
1464
1465 butarray[0] = GCD_Glue; butarray[1] = &gcd[0]; butarray[2] = GCD_Glue;
1466 butarray[3] = GCD_Glue; butarray[4] = &gcd[1]; butarray[5] = GCD_Glue;
1467 butarray[6] = NULL;
1468
1469 harray[0] = GCD_Glue; harray[1] = &gcd[2]; harray[2] = GCD_Glue;
1470 harray[3] = NULL;
1471
1472 gcd[3].gd.flags = gg_enabled|gg_visible;
1473 gcd[3].gd.u.boxelements = butarray;
1474 gcd[3].creator = GHBoxCreate;
1475
1476 gcd[4].gd.flags = gg_enabled|gg_visible;
1477 gcd[4].gd.u.boxelements = harray;
1478 gcd[4].creator = GHBoxCreate;
1479
1480 sv->bh = GDrawPointsToPixels(gw,64);
1481
1482 gcd[5].gd.pos.y = sv->fh; gcd[5].gd.pos.height = pos.height-sv->bh;
1483 gcd[5].gd.pos.width = GDrawPointsToPixels(gw,_GScrollBar_Width);
1484 gcd[5].gd.pos.x = pos.width-gcd[5].gd.pos.width;
1485 gcd[5].gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
1486 gcd[5].gd.handle_controlevent = NULL;
1487 gcd[5].creator = GScrollBarCreate;
1488 gcd[5].data = sv;
1489 harray2[0] = GCD_Glue; harray2[1] = &gcd[5]; harray2[2] = NULL;
1490
1491 gcd[6].gd.flags = gg_enabled|gg_visible;
1492 gcd[6].gd.u.boxelements = harray2;
1493 gcd[6].creator = GHBoxCreate;
1494
1495 varray[0] = &gcd[6]; varray[1] = NULL;
1496 varray[2] = &gcd[4]; varray[3] = NULL;
1497 varray[4] = &gcd[3]; varray[5] = NULL;
1498 varray[6] = NULL;
1499
1500 /*gcd[7].gd.pos.x = gcd[7].gd.pos.y = 2;*/
1501 gcd[7].gd.flags = gg_enabled|gg_visible;
1502 gcd[7].gd.u.boxelements = varray;
1503 gcd[7].creator = GHVBoxCreate;
1504
1505 GGadgetsCreate(gw,&gcd[7]);
1506 GHVBoxSetExpandableRow(gcd[7].ret,0);
1507 GHVBoxSetExpandableCol(gcd[6].ret,0);
1508 GHVBoxSetExpandableCol(gcd[3].ret,gb_expandgluesame);
1509 GHVBoxSetExpandableCol(gcd[4].ret,gb_expandglue);
1510
1511 sv->vsb = gcd[5].ret;
1512 sv->ok = gcd[0].ret;
1513 sv->cancel = gcd[1].ret;
1514 sv->setsize = gcd[2].ret;
1515 GGadgetGetSize(sv->vsb,&gsize);
1516 sv->sbw = gsize.width;
1517
1518 wattrs.mask = wam_events|wam_cursor;
1519 subpos.x = 0; subpos.y = sv->fh;
1520 subpos.width = 100; subpos.height = pos.height - sv->bh - sv->fh;
1521 sv->v = GWidgetCreateSubWindow(gw,&subpos,sv_v_e_h,sv,&wattrs);
1522 GDrawSetVisible(sv->v,true);
1523
1524 if ( font==NULL ) {
1525 memset(&rq,0,sizeof(rq));
1526 rq.utf8_family_name = MONO_UI_FAMILIES;
1527 rq.point_size = -12;
1528 rq.weight = 400;
1529 font = GDrawInstanciateFont(gw,&rq);
1530 font = GResourceFindFont("CVT.Font",font);
1531 }
1532 sv->gfont = font;
1533 GDrawSetFont(sv->v,sv->gfont);
1534 GDrawSetFont(sv->gw,sv->gfont);
1535 GDrawWindowFontMetrics(sv->gw,sv->gfont,&as,&ds,&ld);
1536 sv->as = as+1;
1537 sv->fh = sv->as+ds;
1538
1539 sv->chrlen = numlen = GDrawGetTextWidth(sv->v,num,1);
1540 sv->addrend = 6*numlen + ADDR_SPACER + EDGE_SPACER;
1541 sv->valend = sv->addrend + 7*numlen + ADDR_SPACER + EDGE_SPACER;
1542
1543 tfbox.main_background = tfbox.main_foreground = COLOR_DEFAULT;
1544 memset(&gd,0,sizeof(gd));
1545 gd.pos.y = -100; gd.pos.height = sv->fh;
1546 gd.pos.x = sv->addrend;
1547 memset(&lab,'\0',sizeof(lab));
1548 lab.text = num+1;
1549 lab.font = sv->gfont;
1550 gd.label = &lab;
1551 gd.box = &tfbox;
1552 gd.flags = gg_visible|gg_enabled|gg_sb_vert|gg_dontcopybox;
1553 sv->tf = GTextFieldCreate(sv->v,&gd,NULL);
1554 sv->active = -1;
1555
1556 lh = sv->len/2;
1557 if ( lh>40 ) lh = 40;
1558 if ( lh<4 ) lh = 4;
1559 if ( pos.width<sv->valend+6*numlen+EDGE_SPACER+sv->sbw )
1560 pos.width = sv->valend+6*numlen+EDGE_SPACER+sv->sbw;
1561 GDrawResize(sv->gw,pos.width,lh*sv->fh+2*EDGE_SPACER);
1562
1563 GDrawSetVisible(gw,true);
1564 }
1565
SF_CloseAllInstrs(SplineFont * sf)1566 int SF_CloseAllInstrs(SplineFont *sf) {
1567 struct instrdata *id, *next;
1568 int changed;
1569 char name[12], *npt;
1570 static char *buts[3];
1571 static int done = false;
1572
1573 if ( !done ) {
1574 buts[0] = _("_OK");
1575 buts[1] = _("_Cancel");
1576 done = true;
1577 }
1578
1579 for ( id = sf->instr_dlgs; id!=NULL; id=next ) {
1580 next = id->next;
1581 changed = id->changed;
1582 if ( !changed && id->id->inedit ) {
1583 if ( !IVParse(id->id))
1584 changed = true;
1585 else
1586 changed = id->changed;
1587 }
1588 if ( changed ) {
1589 if ( id->tag==0 )
1590 npt = id->sc->name;
1591 else {
1592 name[0] = name[5] = '\'';
1593 name[1] = id->tag>>24; name[2] = (id->tag>>16)&0xff; name[3] = (id->tag>>8)&0xff; name[4] = id->tag&0xff;
1594 name[6] = 0;
1595 npt = name;
1596 }
1597 GDrawRaise(id->id->gw);
1598 if ( gwwv_ask(_("Instructions were changed"),(const char **) buts,0,1,_("The instructions for %.80s have changed. Do you want to lose those changes?"),npt)==1 )
1599 return( false );
1600 }
1601 GDrawDestroyWindow(id->id->gw);
1602 }
1603 if ( sf->cvt_dlg!=NULL ) {
1604 if ( sf->cvt_dlg->changed ) {
1605 name[0] = name[5] = '\'';
1606 name[1] = id->tag>>24; name[2] = (id->tag>>16)&0xff; name[3] = (id->tag>>8)&0xff; name[4] = id->tag&0xff;
1607 name[6] = 0;
1608 npt = name;
1609 GDrawRaise(sf->cvt_dlg->gw);
1610 if ( gwwv_ask(_("Instructions were changed"),(const char **) buts,0,1,_("The instructions for %.80s have changed. Do you want to lose those changes?"),npt)==1 )
1611 return( false );
1612 }
1613 GDrawDestroyWindow(sf->cvt_dlg->gw);
1614 }
1615 if ( !no_windowing_ui ) {
1616 GDrawSync(NULL);
1617 GDrawProcessPendingEvents(NULL);
1618 }
1619 return( true );
1620 }
1621
1622 /* Maxp table editor (or that subset of it that ff can't figure out) */
1623 struct maxp_data {
1624 GWindow gw;
1625 SplineFont *sf;
1626 struct ttf_table *tab;
1627 int done;
1628 };
1629
1630 #define CID_Zones 1006
1631 #define CID_TPoints 1007
1632 #define CID_Storage 1008
1633 #define CID_FDefs 1009
1634 #define CID_IDefs 1010
1635 #define CID_SEl 1011
1636
MP_DoClose(struct maxp_data * mp)1637 static void MP_DoClose(struct maxp_data *mp) {
1638 mp->done = true;
1639 }
1640
Maxp_Cancel(GGadget * g,GEvent * e)1641 static int Maxp_Cancel(GGadget *g, GEvent *e) {
1642
1643 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1644 MP_DoClose(GDrawGetUserData(GGadgetGetWindow(g)));
1645 }
1646 return( true );
1647 }
1648
Maxp_OK(GGadget * g,GEvent * e)1649 static int Maxp_OK(GGadget *g, GEvent *e) {
1650 struct maxp_data *mp;
1651 int zones, tp, store, stack, fd, id, err=0;
1652
1653 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1654 mp = GDrawGetUserData(GGadgetGetWindow(g));
1655 zones = GetInt8(mp->gw,CID_Zones,_("Zones"),&err);
1656 tp = GetInt8(mp->gw,CID_TPoints,_("Twilight Zone Point Count"),&err);
1657 store = GetInt8(mp->gw,CID_Storage,_("Storage"),&err);
1658 stack = GetInt8(mp->gw,CID_SEl,_("Max Stack Depth"),&err);
1659 fd = GetInt8(mp->gw,CID_FDefs,_("Max # Functions"),&err);
1660 id = GetInt8(mp->gw,CID_IDefs,_("Max Instruction Defines"),&err);
1661 if ( err )
1662 return( true );
1663 mp->done = true;
1664 if ( mp->tab==NULL ) {
1665 mp->tab = chunkalloc(sizeof(struct ttf_table));
1666 mp->tab->tag = CHR('m','a','x','p');
1667 mp->tab->len = 32;
1668 mp->tab->data = calloc(32,1);
1669 mp->tab->next = mp->sf->ttf_tables;
1670 mp->sf->ttf_tables = mp->tab;
1671 } else if ( mp->tab->len<32 ) {
1672 free(mp->tab->data);
1673 mp->tab->len = 32;
1674 mp->tab->data = calloc(32,1);
1675 }
1676 mp->tab->data[14] = zones>>8; mp->tab->data[15] = zones&0xff;
1677 mp->tab->data[16] = tp>>8; mp->tab->data[17] = tp&0xff;
1678 mp->tab->data[18] = store>>8; mp->tab->data[19] = store&0xff;
1679 mp->tab->data[20] = fd>>8; mp->tab->data[21] = fd&0xff;
1680 mp->tab->data[22] = id>>8; mp->tab->data[23] = id&0xff;
1681 mp->tab->data[24] = stack>>8; mp->tab->data[25] = stack&0xff;
1682 mp->sf->changed = true;
1683 mp->done = true;
1684 }
1685 return( true );
1686 }
1687
mp_e_h(GWindow gw,GEvent * event)1688 static int mp_e_h(GWindow gw, GEvent *event) {
1689 struct maxp_data *mp = (struct maxp_data *) GDrawGetUserData(gw);
1690
1691 switch ( event->type ) {
1692 case et_char:
1693 if ( event->u.chr.keysym == GK_Help || event->u.chr.keysym == GK_F1 )
1694 help("ui/dialogs/ttfinstrs.html", "#ttfinstrs-maxp");
1695 else
1696 return( false );
1697 break;
1698 case et_close:
1699 MP_DoClose(mp);
1700 break;
1701 }
1702 return( true );
1703 }
1704
maxpCreateEditor(struct ttf_table * tab,SplineFont * sf,uint32 tag)1705 static void maxpCreateEditor(struct ttf_table *tab,SplineFont *sf,uint32 tag) {
1706 char title[60];
1707 GRect pos;
1708 GWindow gw;
1709 GWindowAttrs wattrs;
1710 struct maxp_data mp;
1711 GGadgetCreateData gcd[17], boxes[4], *hvarray[16], *butarray[8], *varray[7];
1712 GTextInfo label[17];
1713 uint8 dummy[32], *data;
1714 char buffer[6][20];
1715 int k, hv;
1716
1717 if ( tab==NULL && sf->mm!=NULL && sf->mm->apple ) {
1718 sf = sf->mm->normal;
1719 tab = SFFindTable(sf,tag);
1720 }
1721 memset(&mp,0,sizeof(mp));
1722 mp.sf = sf;
1723 mp.tab = tab;
1724 if ( tab==NULL || tab->len<32 ) {
1725 memset(dummy,0,sizeof(dummy));
1726 dummy[15]=2; /* default Zones to 2 */
1727 data = dummy;
1728 } else
1729 data = tab->data;
1730
1731 title[0] = (tag>>24)&0xff;
1732 title[1] = (tag>>16)&0xff;
1733 title[2] = (tag>>8 )&0xff;
1734 title[3] = (tag )&0xff;
1735 title[4] = ' ';
1736 strncpy(title+5, sf->fontname, sizeof(title)-6);
1737
1738 memset(&wattrs,0,sizeof(wattrs));
1739 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1740 wattrs.event_masks = ~(1<<et_charup);
1741 wattrs.undercursor = 1;
1742 wattrs.cursor = ct_pointer;
1743 wattrs.utf8_window_title = title;
1744 wattrs.restrict_input_to_me = 1;
1745 wattrs.undercursor = 1;
1746 wattrs.is_dlg = true;
1747 pos.x = pos.y = 0;
1748 pos.width = GDrawPointsToPixels(NULL,260);
1749 pos.height = GDrawPointsToPixels(NULL,125);
1750 mp.gw = gw = GDrawCreateTopWindow(NULL,&pos,mp_e_h,&mp,&wattrs);
1751
1752 memset(label,0,sizeof(label));
1753 memset(gcd,0,sizeof(gcd));
1754 memset(boxes,0,sizeof(boxes));
1755
1756 k=hv=0;
1757 label[k].text = (unichar_t *) _("_Zones:");
1758 label[k].text_is_1byte = true;
1759 label[k].text_in_resource = true;
1760 gcd[k].gd.label = &label[k];
1761 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 16;
1762 gcd[k].gd.flags = gg_enabled|gg_visible;
1763 gcd[k].gd.cid = CID_Zones+1000;
1764 gcd[k++].creator = GLabelCreate;
1765 hvarray[hv++] = &gcd[k-1];
1766
1767 sprintf( buffer[0], "%d", (data[14]<<8)|data[14+1] );
1768 label[k].text = (unichar_t *) buffer[0];
1769 label[k].text_is_1byte = true;
1770 gcd[k].gd.label = &label[k];
1771 gcd[k].gd.pos.x = 60; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6;
1772 gcd[k].gd.pos.width = 50;
1773 gcd[k].gd.flags = gg_enabled|gg_visible;
1774 gcd[k].gd.cid = CID_Zones;
1775 gcd[k++].creator = GTextFieldCreate;
1776 hvarray[hv++] = &gcd[k-1];
1777
1778 label[k].text = (unichar_t *) _("_Twilight Pnt Cnt:");
1779 label[k].text_is_1byte = true;
1780 label[k].text_in_resource = true;
1781 gcd[k].gd.label = &label[k];
1782 gcd[k].gd.pos.x = 120; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y;
1783 gcd[k].gd.flags = gg_enabled|gg_visible;
1784 gcd[k].gd.cid = CID_TPoints+1000;
1785 gcd[k++].creator = GLabelCreate;
1786 hvarray[hv++] = &gcd[k-1];
1787
1788 sprintf( buffer[1], "%d", (data[16]<<8)|data[16+1] );
1789 label[k].text = (unichar_t *) buffer[1];
1790 label[k].text_is_1byte = true;
1791 gcd[k].gd.label = &label[k];
1792 gcd[k].gd.pos.x = 202; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6;
1793 gcd[k].gd.pos.width = 50;
1794 gcd[k].gd.flags = gg_enabled|gg_visible;
1795 gcd[k].gd.cid = CID_TPoints;
1796 gcd[k++].creator = GTextFieldCreate;
1797 hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = NULL;
1798
1799 label[k].text = (unichar_t *) _("St_orage:");
1800 label[k].text_in_resource = true;
1801 label[k].text_is_1byte = true;
1802 gcd[k].gd.label = &label[k];
1803 gcd[k].gd.pos.x = gcd[k-4].gd.pos.x; gcd[k].gd.pos.y = gcd[k-3].gd.pos.y+24+6;
1804 gcd[k].gd.flags = gg_enabled|gg_visible;
1805 gcd[k].gd.cid = CID_Storage;
1806 gcd[k++].creator = GLabelCreate;
1807 hvarray[hv++] = &gcd[k-1];
1808
1809 sprintf( buffer[2], "%d", (data[18]<<8)|data[18+1] );
1810 label[k].text = (unichar_t *) buffer[2];
1811 label[k].text_is_1byte = true;
1812 gcd[k].gd.label = &label[k];
1813 gcd[k].gd.pos.x = gcd[k-4].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6;
1814 gcd[k].gd.pos.width = 50;
1815 gcd[k].gd.flags = gg_enabled|gg_visible;
1816 gcd[k].gd.cid = CID_Storage;
1817 gcd[k++].creator = GTextFieldCreate;
1818 hvarray[hv++] = &gcd[k-1];
1819
1820 label[k].text = (unichar_t *) _("Max _Stack Depth:");
1821 label[k].text_in_resource = true;
1822 label[k].text_is_1byte = true;
1823 gcd[k].gd.label = &label[k];
1824 gcd[k].gd.pos.x = gcd[k-4].gd.pos.x; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y;
1825 gcd[k].gd.flags = gg_enabled|gg_visible;
1826 gcd[k].gd.cid = CID_SEl+1000;
1827 gcd[k++].creator = GLabelCreate;
1828 hvarray[hv++] = &gcd[k-1];
1829
1830 sprintf( buffer[3], "%d", (data[24]<<8)|data[24+1] );
1831 label[k].text = (unichar_t *) buffer[3];
1832 label[k].text_is_1byte = true;
1833 gcd[k].gd.label = &label[k];
1834 gcd[k].gd.pos.x = gcd[k-4].gd.pos.x; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y;
1835 gcd[k].gd.pos.width = 50;
1836 gcd[k].gd.flags = gg_enabled|gg_visible;
1837 gcd[k].gd.cid = CID_SEl;
1838 gcd[k++].creator = GTextFieldCreate;
1839 hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = NULL;
1840
1841 label[k].text = (unichar_t *) _("_FDEF");
1842 label[k].text_in_resource = true;
1843 label[k].text_is_1byte = true;
1844 gcd[k].gd.label = &label[k];
1845 gcd[k].gd.pos.x = gcd[k-4].gd.pos.x; gcd[k].gd.pos.y = gcd[k-3].gd.pos.y+24+6;
1846 gcd[k].gd.flags = gg_enabled|gg_visible;
1847 gcd[k].gd.cid = CID_FDefs+1000;
1848 gcd[k++].creator = GLabelCreate;
1849 hvarray[hv++] = &gcd[k-1];
1850
1851 sprintf( buffer[4], "%d", (data[20]<<8)|data[20+1] );
1852 label[k].text = (unichar_t *) buffer[4];
1853 label[k].text_is_1byte = true;
1854 gcd[k].gd.label = &label[k];
1855 gcd[k].gd.pos.x = gcd[k-4].gd.pos.x; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6; gcd[k].gd.pos.width = 50;
1856 gcd[k].gd.flags = gg_enabled|gg_visible;
1857 gcd[k].gd.cid = CID_FDefs;
1858 gcd[k++].creator = GTextFieldCreate;
1859 hvarray[hv++] = &gcd[k-1];
1860
1861 label[k].text = (unichar_t *) _("_IDEFs");
1862 label[k].text_in_resource = true;
1863 label[k].text_is_1byte = true;
1864 gcd[k].gd.label = &label[k];
1865 gcd[k].gd.pos.x = gcd[k-4].gd.pos.x; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y;
1866 gcd[k].gd.flags = gg_enabled|gg_visible;
1867 gcd[k].gd.cid = CID_IDefs+1000;
1868 gcd[k++].creator = GLabelCreate;
1869 hvarray[hv++] = &gcd[k-1];
1870
1871 sprintf( buffer[5], "%d", (data[22]<<8)|data[22+1] );
1872 label[k].text = (unichar_t *) buffer[5];
1873 label[k].text_is_1byte = true;
1874 gcd[k].gd.label = &label[k];
1875 gcd[k].gd.pos.x = gcd[k-4].gd.pos.x; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y; gcd[k].gd.pos.width = 50;
1876 gcd[k].gd.flags = gg_enabled|gg_visible;
1877 gcd[k].gd.cid = CID_IDefs;
1878 gcd[k++].creator = GTextFieldCreate;
1879 hvarray[hv++] = &gcd[k-1]; hvarray[hv++] = NULL; hvarray[hv++] = NULL;
1880
1881 boxes[2].gd.flags = gg_enabled|gg_visible;
1882 boxes[2].gd.u.boxelements = hvarray;
1883 boxes[2].creator = GHVBoxCreate;
1884 varray[0] = &boxes[2]; varray[1] = NULL;
1885 varray[2] = GCD_Glue; varray[3] = NULL;
1886
1887 gcd[k].gd.pos.x = 20-3; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+35-3;
1888 gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
1889 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
1890 label[k].text = (unichar_t *) _("_OK");
1891 label[k].text_in_resource = true;
1892 label[k].text_is_1byte = true;
1893 gcd[k].gd.label = &label[k];
1894 gcd[k].gd.handle_controlevent = Maxp_OK;
1895 gcd[k++].creator = GButtonCreate;
1896 butarray[0] = GCD_Glue; butarray[1] = &gcd[k-1]; butarray[2] = GCD_Glue;
1897
1898 gcd[k].gd.pos.x = -20; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
1899 gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0;
1900 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
1901 label[k].text = (unichar_t *) _("_Cancel");
1902 label[k].text_is_1byte = true;
1903 label[k].text_in_resource = true;
1904 gcd[k].gd.label = &label[k];
1905 gcd[k].gd.handle_controlevent = Maxp_Cancel;
1906 gcd[k++].creator = GButtonCreate;
1907 butarray[3] = GCD_Glue; butarray[4] = &gcd[k-1]; butarray[5] = GCD_Glue;
1908 butarray[6] = NULL;
1909
1910 boxes[3].gd.flags = gg_enabled|gg_visible;
1911 boxes[3].gd.u.boxelements = butarray;
1912 boxes[3].creator = GHBoxCreate;
1913 varray[4] = &boxes[3]; varray[5] = NULL;
1914 varray[6] = NULL;
1915
1916 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
1917 boxes[0].gd.flags = gg_enabled|gg_visible;
1918 boxes[0].gd.u.boxelements = varray;
1919 boxes[0].creator = GHVGroupCreate;
1920
1921 GGadgetsCreate(gw,boxes);
1922 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
1923 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandgluesame);
1924 GHVBoxFitWindow(boxes[0].ret);
1925 GDrawSetVisible(gw,true);
1926 while ( !mp.done )
1927 GDrawProcessOneEvent(NULL);
1928 GDrawDestroyWindow(gw);
1929 }
1930
SFEditTable(SplineFont * sf,uint32 tag)1931 void SFEditTable(SplineFont *sf, uint32 tag) {
1932 struct instrdata *id;
1933 struct ttf_table *tab;
1934 char name[12];
1935 char title[100];
1936
1937 /* In multiple master fonts the 'fpgm' and 'prep' tables are stored in the*/
1938 /* normal instance of the font. The other instances must share it */
1939 /* On the other hand, everyone can have their own cvt table */
1940 if ( tag!=CHR('c','v','t',' ') )
1941 if ( sf->mm!=NULL && sf->mm->apple )
1942 sf = sf->mm->normal;
1943
1944 tab = SFFindTable(sf,tag);
1945 if ( tag==CHR('m','a','x','p') ) {
1946 maxpCreateEditor(tab,sf,tag);
1947 } else if ( tag!=CHR('c','v','t',' ') ) {
1948 for ( id = sf->instr_dlgs; id!=NULL && id->tag!=tag; id=id->next );
1949 if ( id!=NULL ) {
1950 GDrawSetVisible(id->id->gw,true);
1951 GDrawRaise(id->id->gw);
1952 return;
1953 }
1954
1955 id = calloc(1,sizeof(*id));
1956 id->sf = sf;
1957 id->tag = tag;
1958 id->instr_cnt = id->max = tab==NULL ? 0 : tab->len;
1959 id->instrs = malloc(id->max+1);
1960 if ( tab!=NULL && tab->data!=NULL )
1961 memcpy(id->instrs,tab->data,id->instr_cnt);
1962 else
1963 id->instrs[0]='\0';
1964 name[0] = name[5] = '\'';
1965 name[1] = tag>>24; name[2] = (tag>>16)&0xff; name[3] = (tag>>8)&0xff; name[4] = tag&0xff;
1966 name[6] = 0;
1967 sprintf(title,_("TrueType Instructions for %.50s"),name);
1968 InstrDlgCreate(id,title);
1969 } else {
1970 if ( sf->cvt_dlg!=NULL ) {
1971 GDrawSetVisible(sf->cvt_dlg->gw,true);
1972 GDrawRaise(sf->cvt_dlg->gw);
1973 return;
1974 }
1975 cvtCreateEditor(tab,sf,tag);
1976 }
1977 }
1978