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