1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/font.c,v 1.42 2011/05/16 16:21:57 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_FONT_C_
22 
23 #include "tgifdefs.h"
24 #include "cmdids.h"
25 
26 #include "auxtext.e"
27 #include "choice.e"
28 #include "cmd.e"
29 #include "color.e"
30 #include "cursor.e"
31 #include "dialog.e"
32 #include "drawing.e"
33 #include "exec.e"
34 #include "file.e"
35 #include "font.e"
36 #include "ini.e"
37 #include "list.e"
38 #include "mainmenu.e"
39 #include "mark.e"
40 #include "menu.e"
41 #include "menuinfo.e"
42 #include "miniline.e"
43 #include "msg.e"
44 #include "obj.e"
45 #include "pattern.e"
46 #include "page.e"
47 #include "ps.e"
48 #include "raster.e"
49 #include "rect.e"
50 #include "select.e"
51 #include "setup.e"
52 #include "strtbl.e"
53 #include "text.e"
54 #include "util.e"
55 #include "version.e"
56 #include "xpixmap.e"
57 
58 #define DEFAULT_FONT_SIZE 14
59 
60 struct FontSizeRec {
61    /*
62     * For a font (given face and style), the xfs for various font sizes
63     *      are stored in a link list.
64     * If the font is not scalable (faked==TRUE), the head of the link list
65     *      is used to scale fonts.
66     * The vert field is TRUE for double-byte vertical fonts.
67     */
68    XFontStruct		*xfs;
69    int			sz_unit, faked, vert;
70    struct FontSizeRec	*next;
71 };
72 
73 struct FontFmlyRec {
74    /* fr[i] points to the default size used for the given font */
75    /*	this font is used if the requested size is not found */
76    struct FontSizeRec	fr[MAXFONTSTYLES];
77    char			*name_faked;
78    int			bitmapped_ps_font;
79    int			double_byte;
80    char			choice_char[3];
81    char			*conv_from_utf8_cmd, *conv_to_utf8_cmd;
82 };
83 
84 typedef struct tagPSCharSubs {
85    char *token_name;
86    char *ps_char_name[128];
87 } PSCharSubs;
88 
89 XFontStruct	*canvasFontPtr=NULL;
90 int	canvasFontHeight=0;
91 int	canvasFontAsc=0;
92 int	canvasFontDes=0;
93 int	canvasFontDirection=0;
94 int	canvasFontDontReencode=FALSE;
95 int	canvasFontDoubleByte=FALSE;
96 int	canvasFontDoubleByteModBytes=FALSE;
97 int	canvasFontDoubleByteVertical=FALSE;
98 int	canvasFontSize=0;
99 int	canvasFontIsFaked=FALSE;
100 int	canvasLineAsc=0;
101 int	canvasLineDes=0;
102 
103 XFontStruct	*rulerFontPtr=NULL;
104 int	rulerFontWidth=0;
105 int	rulerFontHeight=0;
106 int	rulerFontAsc=0;
107 int	rulerFontDes=0;
108 static char *rulerFontName=NULL;
109 
110 XFontStruct	*defaultFontPtr=NULL;
111 int	defaultFontWidth=0;
112 int	defaultFontHeight=0;
113 int	defaultFontAsc=0;
114 int	defaultFontDes=0;
115 static char *defaultFontName=NULL;
116 
117 XFontStruct	*menuFontPtr=NULL;
118 int	menuFontWidth=0;
119 int	menuFontHeight=0;
120 int	menuFontAsc=0;
121 int	menuFontDes=0;
122 static char *menuFontName=NULL;
123 
124 #ifdef ENABLE_NLS
125 XFontSet	menuFontSet=NULL;
126 XFontSet	msgFontSet=NULL;
127 XFontSet	boldMsgFontSet=NULL;
128 XFontSet	italicMsgFontSet=NULL;
129 XFontSet	boldItalicMsgFontSet=NULL;
130 #else /* ~ENABLE_NLS */
131 char     	*menuFontSet=NULL;
132 char     	*msgFontSet=NULL;
133 char     	*boldMsgFontSet=NULL;
134 char     	*italicMsgFontSet=NULL;
135 char     	*boldItalicMsgFontSet=NULL;
136 #endif /* ENABLE_NLS */
137 int	boldMsgFontDoubleByte=FALSE;
138 
139 static char *menuFontSetName=NULL;
140 static char *msgFontSetName=NULL;
141 static char *boldMsgFontSetName=NULL;
142 static char *italicMsgFontSetName=NULL;
143 static char *boldItalicMsgFontSetName=NULL;
144 
145 XFontStruct	*boldMsgFontPtr=NULL;
146 int	boldMsgFontWidth=0;
147 int	boldMsgFontHeight=0;
148 int	boldMsgFontAsc=0;
149 int	boldMsgFontDes=0;
150 static char *boldMsgFontName=NULL;
151 
152 XFontStruct	*italicMsgFontPtr=NULL;
153 int	italicMsgFontWidth=0;
154 int	italicMsgFontHeight=0;
155 int	italicMsgFontAsc=0;
156 int	italicMsgFontDes=0;
157 static char *italicMsgFontName=NULL;
158 
159 XFontStruct	*boldItalicMsgFontPtr=NULL;
160 int	boldItalicMsgFontWidth=0;
161 int	boldItalicMsgFontHeight=0;
162 int	boldItalicMsgFontAsc=0;
163 int	boldItalicMsgFontDes=0;
164 static char *boldItalicMsgFontName=NULL;
165 
166 XFontStruct	*msgFontPtr=NULL;
167 int	msgFontWidth=0;
168 int	msgFontHeight=0;
169 int	msgFontAsc=0;
170 int	msgFontDes=0;
171 static char *msgFontName=NULL;
172 
173 int	curFont=FONT_COU;
174 int	initialFont=FONT_COU;
175 int	curSzUnit=(20*NUM_SZ_UNIT_PER_FONT_SIZE), curRealSzUnit=INVALID;
176 int	curStyle=STYLE_NR;
177 int	textRotation=0; /* degrees*64 */
178 int	curUnderlineOn=FALSE;
179 int	curOverlineOn=FALSE;
180 
181 int	actualCurFont=(-1);
182 int	actualCurSzUnit=(-1);
183 int	actualCurStyle=(-1);
184 
185 int	curUnderlineYOffset=2;
186 int	curOverlineYOffset=(-1);
187 
188 int	changePropertiesOfAttrs=FALSE;
189 
190 static int	defaultCurFont=(-1);
191 static int	defaultCurSzUnit=(-1);
192 static int	defaultCurStyle=(-1);
193 
194 static char	*initSizeMenuStr[] = {
195       "8", "10", "11", "12", "14", "17", "18", "20", "24", "25", "34"
196 };
197 char	**fontMenuStr=NULL;
198 char	*defFontMenuStr[] = {
199         "Times", "Courier", "Helvetica", "NewCenturySchlbk", "Symbol"
200 };
201 char	**sizeMenuStr=NULL;
202 int	*fontSzUnits=NULL;
203 int	numFonts=MAXFONTS;
204 int	numFontSizes=MAXFONTS;
205 
206 int	changingFontSizeFromRead=TRUE;
207 int	allowFontFaceSubstitution=TRUE;
208 
209 char	cmdLineDontReencode[MAXSTRING<<1];
210 
211 int	defaultFontSize=DEFAULT_FONT_SIZE;
212 
213 int	showFontSizeInPoints=FALSE;
214 
215 int	substitutedFont=INVALID;
216 int	substitutedFontSzUnit=0;
217 
218 int	defaultSingleByteFont=FONT_TIM;
219 
220 int		gnNumPSFontAliases=0;
221 KeyValInfo	*gaPSFontAliases=NULL;
222 
223 int		gnNumPSFontNeedCharSubs=0;
224 KeyValInfo	*gaPSFontNeedCharSubs=NULL;
225 
226 CVList		psCharSubsList;
227 
228 static int	numFakedFonts=0;
229 static char	fontNamePrefix[MAXSTRING+1];
230 static char	defaultLatin1FontCharEncoding[MAXSTRING+1];
231 static int	hasAlternateDefaultFonts=FALSE;
232 static int	reportMissingFonts=FALSE;
233 
234 static struct FontFmlyRec	*fontFamilies=NULL;
235 
236 static char	*initFontInfoStr[]={
237    /* do not translate -- program constants */
238    "times-medium-r-normal", "iso8859-1", "Times-Roman",
239    "times-bold-r-normal", "iso8859-1", "Times-Bold",
240    "times-medium-i-normal", "iso8859-1", "Times-Italic",
241    "times-bold-i-normal", "iso8859-1", "Times-BoldItalic",
242    "courier-medium-r-normal", "iso8859-1", "Courier",
243    "courier-bold-r-normal", "iso8859-1", "Courier-Bold",
244    "courier-medium-o-normal", "iso8859-1", "Courier-Oblique",
245    "courier-bold-o-normal", "iso8859-1", "Courier-BoldOblique",
246    "helvetica-medium-r-normal", "iso8859-1", "Helvetica",
247    "helvetica-bold-r-normal", "iso8859-1", "Helvetica-Bold",
248    "helvetica-medium-o-normal", "iso8859-1", "Helvetica-Oblique",
249    "helvetica-bold-o-normal", "iso8859-1", "Helvetica-BoldOblique",
250    "new century schoolbook-medium-r-normal", "iso8859-1",
251          "NewCenturySchlbk-Roman",
252    "new century schoolbook-bold-r-normal", "iso8859-1",
253          "NewCenturySchlbk-Bold",
254    "new century schoolbook-medium-i-normal", "iso8859-1",
255          "NewCenturySchlbk-Italic",
256    "new century schoolbook-bold-i-normal", "iso8859-1",
257          "NewCenturySchlbk-BoldItalic",
258    "*symbol*-medium-r-normal", "adobe-fontspecific", "Symbol",
259    "*symbol*-medium-r-normal", "adobe-fontspecific", "Symbol",
260    "*symbol*-medium-r-normal", "adobe-fontspecific", "Symbol",
261    "*symbol*-medium-r-normal", "adobe-fontspecific", "Symbol",
262    NULL, NULL, NULL
263 };
264 
265 static char	**altFontInfoStr=NULL;
266 
267 static char	**fontInfoStr=NULL;
268 
269 static char	*charCodeToName[] = {
270            /* do not translate -- program constants */
271 /* \200 */ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
272 /* \220 */ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
273 /* \240 */ "x",
274            "8#241 /exclamdown",
275            "8#242 /cent",
276            "8#243 /sterling",
277            "8#244 /currency",
278            "8#245 /yen",
279            "8#246 /bar",
280            "8#247 /section",
281            "8#250 /dieresis",
282            "8#251 /copyright",
283            "8#252 /ordfeminine",
284            "8#253 /guillemotleft",
285            "8#254 /logicalnot",
286            "8#255 /emdash",
287            "8#256 /registered",
288            "8#257 /macron",
289 /* \260 */ "8#260 /degree",
290            "8#261 /plusminus",
291            "8#262 /twosuperior",
292            "8#263 /threesuperior",
293            "8#264 /acute",
294            "8#265 /mu",
295            "8#266 /paragraph",
296            "8#267 /periodcentered",
297            "8#270 /cedilla",
298            "8#271 /onesuperior",
299            "8#272 /ordmasculine",
300            "8#273 /guillemotright",
301            "8#274 /onequarter",
302            "8#275 /onehalf",
303            "8#276 /threequarters",
304            "8#277 /questiondown",
305 /* \300 */ "8#300 /Agrave",
306            "8#301 /Aacute",
307            "8#302 /Acircumflex",
308            "8#303 /Atilde",
309            "8#304 /Adieresis",
310            "8#305 /Aring",
311            "8#306 /AE",
312            "8#307 /Ccedilla",
313            "8#310 /Egrave",
314            "8#311 /Eacute",
315            "8#312 /Ecircumflex",
316            "8#313 /Edieresis",
317            "8#314 /Igrave",
318            "8#315 /Iacute",
319            "8#316 /Icircumflex",
320            "8#317 /Idieresis",
321 /* \320 */ "8#320 /Eth",
322            "8#321 /Ntilde",
323            "8#322 /Ograve",
324            "8#323 /Oacute",
325            "8#324 /Ocircumflex",
326            "8#325 /Otilde",
327            "8#326 /Odieresis",
328            "8#327 /multiply",
329            "8#330 /Oslash",
330            "8#331 /Ugrave",
331            "8#332 /Uacute",
332            "8#333 /Ucircumflex",
333            "8#334 /Udieresis",
334            "8#335 /Yacute",
335            "8#336 /Thorn",
336            "8#337 /germandbls",
337 /* \340 */ "8#340 /agrave",
338            "8#341 /aacute",
339            "8#342 /acircumflex",
340            "8#343 /atilde",
341            "8#344 /adieresis",
342            "8#345 /aring",
343            "8#346 /ae",
344            "8#347 /ccedilla",
345            "8#350 /egrave",
346            "8#351 /eacute",
347            "8#352 /ecircumflex",
348            "8#353 /edieresis",
349            "8#354 /igrave",
350            "8#355 /iacute",
351            "8#356 /icircumflex",
352            "8#357 /idieresis",
353 /* \360 */ "8#360 /eth",
354            "8#361 /ntilde",
355            "8#362 /ograve",
356            "8#363 /oacute",
357            "8#364 /ocircumflex",
358            "8#365 /otilde",
359            "8#366 /odieresis",
360            "8#367 /divide",
361            "8#370 /oslash",
362            "8#371 /ugrave",
363            "8#372 /uacute",
364            "8#373 /ucircumflex",
365            "8#374 /udieresis",
366            "8#375 /yacute",
367            "8#376 /thorn",
368            "8#377 /ydieresis"
369 };
370 
371 #define InfoIndex(FontIdx,StyleIdx) (((FontIdx)*MAXFONTSTYLES+(StyleIdx))*3)
372 #define InfoIndexToFontIndex(InfoIdx) ((int)(((int)(InfoIdx/3))/MAXFONTSTYLES))
373 
374 static int	debugScalableFonts=FALSE; /* debug scalable font */
375 static char	gszAttemptedFontName[MAXSTRING+1];
376 
377 static struct PushedFontRec gstSavedFontInfo;
378 
IsFontDoubleByte(font_index)379 int IsFontDoubleByte(font_index)
380    int font_index;
381 {
382    return fontFamilies[font_index].double_byte;
383 }
384 
IsDoubleByteFontVertical(font_index,style)385 int IsDoubleByteFontVertical(font_index, style)
386    int font_index, style;
387 {
388    return fontFamilies[font_index].fr[style].vert;
389 }
390 
CanConvertUTF8ToFont(font_index)391 int CanConvertUTF8ToFont(font_index)
392    int font_index;
393 {
394    return (fontFamilies[font_index].double_byte &&
395          fontFamilies[font_index].conv_from_utf8_cmd != NULL);
396 }
397 
CanConvertFontToUTF8(font_index)398 int CanConvertFontToUTF8(font_index)
399    int font_index;
400 {
401    return (fontFamilies[font_index].double_byte &&
402          fontFamilies[font_index].conv_to_utf8_cmd != NULL);
403 }
404 
ConvertToOrFromUTF8(which,font_index,ppsz_cut_buffer)405 int ConvertToOrFromUTF8(which, font_index, ppsz_cut_buffer)
406    int which, font_index;
407    char **ppsz_cut_buffer;
408 {
409    int bytes_read=0, len=strlen(*ppsz_cut_buffer), total_bytes=0;
410    char *cmd=NULL, buf[1024], tmp_fname[MAXPATHLENGTH], *c_ptr=NULL;
411    FILE *fp=NULL, *pfp=NULL;
412    CVList list;
413    CVListElem *pElem=NULL;
414 
415    if (MkTempFile(tmp_fname, sizeof(tmp_fname), tmpDir, TOOL_NAME) == NULL) {
416       return FALSE;
417    }
418    if ((fp=fopen(tmp_fname, "w")) == NULL) {
419       return FailToOpenMessage(tmp_fname, "w", NULL);
420    }
421    if ((int)fwrite(*ppsz_cut_buffer, sizeof(char), len, fp) <= 0) {
422       fclose(fp);
423       FailToWriteFileMessage(tmp_fname);
424       unlink(tmp_fname);
425       return FALSE;
426    }
427    fclose(fp);
428 
429    if (which == CONVERT_TO_UTF8) {
430       if (strstr(fontFamilies[font_index].conv_to_utf8_cmd, "%s") == NULL) {
431          snprintf(gszMsgBox, sizeof(gszMsgBox), "%s %s",
432                fontFamilies[font_index].conv_to_utf8_cmd, tmp_fname);
433       } else {
434          snprintf(gszMsgBox, sizeof(gszMsgBox),
435                fontFamilies[font_index].conv_to_utf8_cmd, tmp_fname);
436       }
437    } else {
438       if (strstr(fontFamilies[font_index].conv_from_utf8_cmd, "%s") == NULL) {
439          snprintf(gszMsgBox, sizeof(gszMsgBox), "%s %s",
440                fontFamilies[font_index].conv_from_utf8_cmd, tmp_fname);
441       } else {
442          snprintf(gszMsgBox, sizeof(gszMsgBox),
443                fontFamilies[font_index].conv_from_utf8_cmd, tmp_fname);
444       }
445    }
446    cmd = UtilStrDup(gszMsgBox);
447    if (cmd == NULL) FailAllocMessage();
448 
449    sprintf(gszMsgBox, TgLoadCachedString(CSTID_EXECUTING_GIVEN_PROGRAM), cmd);
450    Msg(gszMsgBox);
451    SetStringStatus(gszMsgBox);
452    XSync(mainDisplay, False);
453 
454    if ((pfp=(FILE*)popen(cmd, "r")) == NULL) {
455       sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_EXECUTE_CMD), cmd);
456       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
457       unlink(tmp_fname);
458       UtilFree(cmd);
459       return FALSE;
460    }
461    CVListInit(&list);
462    *buf = '\0';
463    while ((bytes_read=fread(buf, sizeof(char), sizeof(buf), pfp)) > 0) {
464       struct DynStrRec *dyn_str=NewDynStr();
465 
466       total_bytes += bytes_read;
467       dyn_str->s = (char*)malloc(bytes_read+1);
468       if (dyn_str->s == NULL) FailAllocMessage();
469       memcpy(dyn_str->s, buf, bytes_read);
470       dyn_str->sz = bytes_read+1;
471       ListAppend(&list, dyn_str);
472    }
473    pclose(pfp);
474    unlink(tmp_fname);
475    UtilFree(cmd);
476 
477    UtilFree(*ppsz_cut_buffer);
478    *ppsz_cut_buffer = (char*)malloc(total_bytes+1);
479    if (*ppsz_cut_buffer == NULL) FailAllocMessage();
480 
481    c_ptr = (*ppsz_cut_buffer);
482    for (pElem=ListFirst(&list); pElem != NULL; pElem=ListNext(&list, pElem)) {
483       struct DynStrRec *dyn_str=(struct DynStrRec *)(pElem->obj);
484 
485       memcpy(c_ptr, dyn_str->s, dyn_str->sz-1);
486       c_ptr += dyn_str->sz-1;
487       FreeDynStrBuf(dyn_str);
488    }
489    ListUnlinkAll(&list);
490 
491    *c_ptr = '\0';
492 
493    return TRUE;
494 }
495 
GetInitialFont()496 int GetInitialFont()
497 {
498    return initialFont;
499 }
500 
501 static
DoesFontExist(font_name,double_byte)502 int DoesFontExist(font_name, double_byte)
503    char *font_name;
504    int double_byte;
505 {
506    char *buf=NULL, **font_list=NULL;
507    int actual_count_return=FALSE;
508 
509    if (font_name == NULL) return FALSE;
510 
511    UtilTrimBlanks(font_name);
512    buf = (char*)malloc((strlen(font_name)<<1) + 1);
513    if (buf == NULL) FailAllocMessage();
514    memset(buf, 0, (strlen(font_name)<<1) + 1);
515 
516    /* replace "%d" to "*" */
517    if (strchr(font_name, '%') == NULL) {
518       sprintf(buf, "*%s*", font_name);
519    } else {
520       char *dest=NULL, *src=NULL;
521 
522       dest = buf;
523       if (!double_byte) {
524          *dest++ = '*';
525       }
526       for (src=font_name; *src != '\0'; src++) {
527          char ch2=src[1];
528 
529          if (*src=='%' && ((ch2>='a' && ch2<='z') || (ch2>='A' && ch2<='Z'))) {
530             src++;
531             *dest++ = '*';
532          } else {
533             *dest++ = (*src);
534          }
535       }
536       if (!double_byte) {
537          *dest++ = '*';
538       }
539       *dest = '\0';
540    }
541    font_list = XListFonts(mainDisplay, buf, 1, &actual_count_return);
542    if (font_list) {
543       XFreeFontNames(font_list);
544    }
545    free(buf);
546 
547    return (actual_count_return > 0);
548 }
549 
SzUnitToFontSize(sz_unit)550 int SzUnitToFontSize(sz_unit)
551    int sz_unit;
552 {
553    double d=(double)(((double)sz_unit)/((double)NUM_SZ_UNIT_PER_FONT_SIZE));
554 
555    return ((int)(round(d)));
556 }
557 
SzUnitToPointSize(sz_unit)558 int SzUnitToPointSize(sz_unit)
559    int sz_unit;
560 {
561    double d=(double)(((double)sz_unit)/((double)NUM_SZ_UNIT_PER_POINT_SIZE));
562 
563    return ((int)(round(d)));
564 }
565 
BadDoubleByteString(pszStr,pszZero)566 int BadDoubleByteString(pszStr, pszZero)
567    char *pszStr, *pszZero;
568 {
569    fprintf(stderr, "%s\n", TgLoadString(STID_ILLEGAL_DOUBLE_BYTE_TRUNC));
570    SaveDoubleByteString(stderr, pszStr);
571    fprintf(stderr, "\n");
572    *(--pszZero) = '\0';
573    return FALSE;
574 }
575 
GetPrevChar(nDoubleByte,pszStr,pszCur)576 char *GetPrevChar(nDoubleByte, pszStr, pszCur)
577    int nDoubleByte;
578    char *pszStr, *pszCur;
579 {
580    if (pszStr == pszCur) return NULL;
581 
582    if (nDoubleByte) {
583       char *psz=NULL, *pszLast=NULL;
584 
585       for (psz=pszStr; *psz != '\0'; psz++) {
586          int double_byte=FALSE;
587 
588          if (psz == pszCur) return pszLast;
589 
590          pszLast = psz;
591          double_byte = ((*psz)&0x80);
592          if (double_byte) {
593             if (*(++psz) == '\0') {
594                BadDoubleByteString(pszStr, psz);
595                return NULL;
596             }
597          }
598       }
599       return pszLast;
600    } else {
601       return (--pszCur);
602    }
603 }
604 
GetShowFontChar(FontIndex)605 char *GetShowFontChar(FontIndex)
606    int FontIndex;
607 {
608    if (*fontFamilies[FontIndex].choice_char == '\0') {
609       if (canvasFontDoubleByte) {
610          int min_byte1=canvasFontPtr->min_byte1;
611          int max_byte1=canvasFontPtr->max_byte1;
612          int min_byte2=canvasFontPtr->min_char_or_byte2;
613          int max_byte2=canvasFontPtr->max_char_or_byte2;
614 
615          fontFamilies[FontIndex].choice_char[0] = ((min_byte1+max_byte1)>>1);
616          fontFamilies[FontIndex].choice_char[1] = ((min_byte2+max_byte2)>>1);
617          fontFamilies[FontIndex].choice_char[2] = '\0';
618          return fontFamilies[FontIndex].choice_char;
619       }
620       return NULL;
621    }
622    return fontFamilies[FontIndex].choice_char;
623 }
624 
625 static
RecordDoubleByteFontInfo(xfs,pszSection)626 void RecordDoubleByteFontInfo(xfs, pszSection)
627    XFontStruct *xfs;
628    char *pszSection;
629 {
630 #ifdef _TGIF_DBG /* debug, do not translate */
631    char szIniFile[MAXPATHLENGTH];
632 
633    sprintf(szIniFile, "%s%cfontinfo.ini", tgifDir, DIR_SEP);
634    tgWriteProfileString(pszSection, NULL, NULL, szIniFile);
635 
636    sprintf(gszMsgBox, "\\%03o", (int)(xfs->min_byte1));
637    tgWriteProfileString(pszSection, "min_byte1", gszMsgBox, szIniFile);
638    sprintf(gszMsgBox, "\\%03o", (int)(xfs->max_byte1));
639    tgWriteProfileString(pszSection, "max_byte1", gszMsgBox, szIniFile);
640    sprintf(gszMsgBox, "\\%03o", (int)(xfs->min_char_or_byte2));
641    tgWriteProfileString(pszSection, "min_byte2", gszMsgBox, szIniFile);
642    sprintf(gszMsgBox, "\\%03o", (int)(xfs->max_char_or_byte2));
643    tgWriteProfileString(pszSection, "max_byte2", gszMsgBox, szIniFile);
644    sprintf(gszMsgBox, "%1d", (int)(xfs->ascent));
645    tgWriteProfileString(pszSection, "ascent", gszMsgBox, szIniFile);
646    sprintf(gszMsgBox, "%1d", (int)(xfs->descent));
647    tgWriteProfileString(pszSection, "descent", gszMsgBox, szIniFile);
648 
649    tgWriteProfileString(NULL, NULL, NULL, szIniFile);
650 #endif /* _TGIF_DBG */
651 }
652 
653 #define X_FONT_PREFIX 0
654 #define X_FONT_SUFFIX 1
655 #define PS_FONT_NAME  2
656 
GetCurFontInfoStr(buf,buf_sz)657 void GetCurFontInfoStr(buf, buf_sz)
658    char* buf;
659    int buf_sz;
660 {
661    int font_index=curFont;
662    int style_index=curStyle;
663    int size=SzUnitToFontSize(curSzUnit);
664    int info_index=InfoIndex(font_index, style_index);
665 
666    if (strstr(fontInfoStr[info_index], "%d") != NULL) {
667       sprintf(gszAttemptedFontName, fontInfoStr[info_index], size);
668    } else {
669       sprintf(gszAttemptedFontName, "%s-%s-*-%1d-*-*-*-*-*-%s", fontNamePrefix,
670             fontInfoStr[info_index+X_FONT_PREFIX], size,
671             fontInfoStr[info_index+X_FONT_SUFFIX]);
672    }
673    UtilStrCpyN(buf, buf_sz, gszAttemptedFontName);
674 }
675 
LoadAFontByName(psz_font_name,double_byte,can_debug)676 XFontStruct *LoadAFontByName(psz_font_name, double_byte, can_debug)
677    char *psz_font_name;
678    int double_byte, can_debug;
679 {
680    XFontStruct *xfs=NULL;
681 
682    sprintf(gszMsgBox, TgLoadCachedString(CSTID_LOADING_FILE),
683          psz_font_name);
684    SetStringStatus(gszMsgBox);
685    xfs = XLoadQueryFont(mainDisplay, psz_font_name);
686    if (xfs != NULL && double_byte && can_debug &&
687          (xfs->min_byte1 != 0 || xfs->max_byte1 != 0)) {
688       RecordDoubleByteFontInfo(xfs, psz_font_name);
689       if ((xfs->min_byte1 & 0x80) != (xfs->max_byte1 & 0x80)) {
690          sprintf(gszMsgBox, TgLoadString(STID_TOOL_CANT_HANDLE_DB_FONT),
691                psz_font_name, (int)(xfs->min_byte1),
692                (int)(xfs->max_byte1), TOOL_NAME, authorEmailString);
693          fprintf(stderr, "%s\n", gszMsgBox);
694          MsgBox(gszMsgBox, TOOL_NAME, STOP_MB);
695       }
696    }
697    return xfs;
698 }
699 
700 static
LoadAFont(info_index,size,can_debug,pxfs,pn_vert)701 void LoadAFont(info_index, size, can_debug, pxfs, pn_vert)
702    int info_index, size, can_debug, *pn_vert;
703    XFontStruct **pxfs;
704 {
705    int watch_cursor=watchCursorOnMainWindow;
706    int font_index=InfoIndexToFontIndex(info_index);
707    int supposedly_double_byte=fontFamilies[font_index].double_byte;
708    XFontStruct *xfs=NULL;
709 
710    *pxfs = NULL;
711    *pn_vert = FALSE;
712 
713    if (!watch_cursor && mainWindow != None && !RedrawDuringScrolling()) {
714       SetWatchCursor(drawWindow);
715       SetWatchCursor(mainWindow);
716    }
717    if (strstr(fontInfoStr[info_index], "%d") != NULL) {
718       sprintf(gszAttemptedFontName, fontInfoStr[info_index], size);
719       if (UtilStrICmp(fontInfoStr[info_index+X_FONT_SUFFIX], "V") == 0) {
720          *pn_vert = TRUE;
721       }
722    } else {
723       sprintf(gszAttemptedFontName, "%s-%s-*-%1d-*-*-*-*-*-%s", fontNamePrefix,
724             fontInfoStr[info_index+X_FONT_PREFIX], size,
725             fontInfoStr[info_index+X_FONT_SUFFIX]);
726    }
727    xfs = LoadAFontByName(gszAttemptedFontName, supposedly_double_byte,
728          can_debug);
729    if (xfs != NULL && can_debug && debugScalableFonts) {
730       int i;
731 
732       for (i=0; i < (MAXFONTSIZES<<1)-1; i++) {
733          if (atoi(initSizeMenuStr[i]) == size) {
734             break;
735          }
736       }
737       if (i >= (MAXFONTSIZES<<1)-1) {
738          XFreeFont(mainDisplay, xfs);
739          xfs = NULL;
740       }
741    }
742    if (!watch_cursor && mainWindow != None && !RedrawDuringScrolling()) {
743       SetDefaultCursor(mainWindow);
744       ShowCursor();
745    }
746    *pxfs = xfs;
747 }
748 
749 static
FindFontInfo(font_index,style_index,sz_unit,must_find)750 struct FontSizeRec *FindFontInfo(font_index, style_index, sz_unit, must_find)
751    int font_index, style_index, sz_unit, must_find;
752 {
753    struct FontSizeRec *fs_ptr, *prev_fs=NULL, *new_fs_ptr;
754    int info_index, watch_cursor=watchCursorOnMainWindow, vert=FALSE;
755    XFontStruct *xfs=NULL;
756 
757    canvasFontIsFaked = FALSE;
758    *gszAttemptedFontName = '\0';
759    for (fs_ptr=fontFamilies[font_index].fr[style_index].next; fs_ptr != NULL;
760          fs_ptr=fs_ptr->next) {
761       if (fs_ptr->sz_unit == sz_unit) {
762          canvasFontIsFaked = fs_ptr->faked;
763          return (canvasFontIsFaked ?
764                &fontFamilies[font_index].fr[style_index] : fs_ptr);
765       }
766       if (fs_ptr->sz_unit > sz_unit) break;
767       prev_fs = fs_ptr;
768    }
769    info_index = InfoIndex(font_index, style_index);
770 
771    SaveStatusStrings();
772    LoadAFont(info_index, SzUnitToFontSize(sz_unit), TRUE, &xfs, &vert);
773 
774    if (xfs == NULL) {
775       if (must_find) return NULL;
776 
777       canvasFontIsFaked = TRUE;
778       xfs = fontFamilies[font_index].fr[style_index].xfs;
779       if (xfs == NULL) {
780          LoadAFont(info_index, defaultFontSize, FALSE, &xfs, &vert);
781 
782          fontFamilies[font_index].fr[style_index].xfs = xfs;
783          fontFamilies[font_index].fr[style_index].sz_unit =
784                FontSizeToSzUnit(defaultFontSize);
785          if (xfs != NULL && defaultCurFont == (-1) &&
786                !IsFontDoubleByte(font_index)) {
787             defaultCurFont = font_index;
788             defaultCurStyle = style_index;
789             defaultCurSzUnit = FontSizeToSzUnit(defaultFontSize);
790          }
791          if (xfs == NULL) {
792             if (allowFontFaceSubstitution) {
793                /*
794                 * Even for a double-byte font, substitute Courier font anyway!
795                 */
796                int default_info_index=(-1);
797                char failed_font_name[MAXSTRING];
798 
799                if (defaultCurFont == (-1)) {
800                   defaultCurFont = FONT_COU;
801                   defaultCurStyle = STYLE_NR;
802                   defaultCurSzUnit = FontSizeToSzUnit(14);
803                }
804                default_info_index = InfoIndex(defaultCurFont,defaultCurStyle);
805                LoadAFont(default_info_index, defaultFontSize, FALSE, &xfs,
806                      &vert);
807 
808                fontFamilies[font_index].fr[style_index].xfs = xfs;
809                fontFamilies[font_index].fr[style_index].sz_unit =
810                      defaultCurSzUnit;
811                if (xfs == NULL) {
812                   if (!watch_cursor && mainWindow!=None) {
813                      SetDefaultCursor(mainWindow);
814                      ShowCursor();
815                   }
816                   RestoreStatusStrings();
817                   return NULL;
818                }
819                GetCurFontInfoStr(failed_font_name, sizeof(failed_font_name));
820                sprintf(gszMsgBox, TgLoadString(STID_FAIL_LOAD_FONT_FONT_SUBS),
821                      gszAttemptedFontName,
822                      fontInfoStr[default_info_index+PS_FONT_NAME],
823                      SzUnitToFontSize(defaultCurSzUnit),
824                      fontInfoStr[info_index+PS_FONT_NAME],
825                      SzUnitToFontSize(sz_unit));
826                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
827 
828                actualCurFont = defaultCurFont;
829                actualCurStyle = defaultCurStyle;
830                actualCurSzUnit = defaultCurSzUnit;
831             }
832          } else if (changingFontSizeFromRead) {
833             sprintf(gszMsgBox, TgLoadString(STID_FONT_SUBSTITUTED),
834                   fontInfoStr[info_index+PS_FONT_NAME], defaultFontSize,
835                   fontInfoStr[info_index+PS_FONT_NAME],
836                   SzUnitToFontSize(sz_unit));
837             Msg(gszMsgBox);
838          }
839       }
840    } else if (defaultCurFont == (-1) && !IsFontDoubleByte(font_index)) {
841       defaultCurFont = font_index;
842       defaultCurStyle = style_index;
843       defaultCurSzUnit = sz_unit;
844    }
845    if (!watch_cursor && mainWindow!=None) {
846       SetDefaultCursor(mainWindow);
847       ShowCursor();
848    }
849    RestoreStatusStrings();
850    if (xfs == NULL) return NULL;
851 
852    new_fs_ptr = (struct FontSizeRec *)malloc(sizeof(struct FontSizeRec));
853    if (new_fs_ptr == NULL) FailAllocMessage();
854    memset(new_fs_ptr, 0, sizeof(struct FontSizeRec));
855    new_fs_ptr->next = fs_ptr;
856    new_fs_ptr->faked = canvasFontIsFaked;
857    new_fs_ptr->xfs = xfs;
858    new_fs_ptr->sz_unit = sz_unit;
859    new_fs_ptr->vert = vert;
860    if (prev_fs == NULL) {
861       fontFamilies[font_index].fr[style_index].next = new_fs_ptr;
862    } else {
863       prev_fs->next = new_fs_ptr;
864    }
865    return (canvasFontIsFaked ? &fontFamilies[font_index].fr[style_index]:
866          new_fs_ptr);
867 }
868 
GetPSFontStr(FontIndex,StyleIndex,FontStr)869 void GetPSFontStr(FontIndex, StyleIndex, FontStr)
870    int FontIndex, StyleIndex;
871    char *FontStr;
872 {
873    if (PRTGIF && !cmdLineOpenDisplay) {
874       if (FontIndex < MAXFONTS) {
875          sprintf(FontStr, "/%s",
876                initFontInfoStr[InfoIndex(FontIndex,StyleIndex)+PS_FONT_NAME]);
877       } else {
878          sprintf(FontStr, "/%s", fontFamilies[FontIndex].name_faked);
879       }
880    } else {
881       if (FontIndex < numFonts) {
882          sprintf(FontStr, "/%s",
883                fontInfoStr[InfoIndex(FontIndex,StyleIndex)+PS_FONT_NAME]);
884       } else {
885          sprintf(FontStr, "/%s", fontFamilies[FontIndex].name_faked);
886       }
887    }
888 }
889 
LoadASymbolFont(font_size)890 XFontStruct *LoadASymbolFont(font_size)
891    int font_size;
892 {
893    int info_index=InfoIndex(FONT_SYM, STYLE_NR), vert=FALSE;
894    XFontStruct *xfs=NULL;
895 
896    SaveStatusStrings();
897    LoadAFont(info_index, font_size, TRUE, &xfs, &vert);
898    RestoreStatusStrings();
899 
900    return xfs;
901 }
902 
903 static
LookupPSFontAliases(buf)904 char *LookupPSFontAliases(buf)
905    char *buf;
906 {
907    int i=0;
908 
909    for (i=0; i < gnNumPSFontAliases; i++) {
910       KeyValInfo *pKeyValue=(&gaPSFontAliases[i]);
911 
912       if (pKeyValue == NULL) return FALSE;
913 
914       if (pKeyValue != NULL && pKeyValue->key != NULL &&
915             strcmp(pKeyValue->key, buf) == 0) {
916          return pKeyValue->value;
917       }
918    }
919    return NULL;
920 }
921 
MapAliasedPSFontName(buf,buf_sz)922 void MapAliasedPSFontName(buf, buf_sz)
923    char *buf;
924    int buf_sz;
925 {
926    char *real_ps_font_name=NULL;
927 
928    if ((real_ps_font_name=LookupPSFontAliases(&buf[1])) != NULL) {
929       UtilStrCpyN(&buf[1], buf_sz-1, real_ps_font_name);
930    }
931 }
932 
SetTextExtentsInfo(pTextExtents)933 void SetTextExtentsInfo(pTextExtents)
934    TextExtentsInfo *pTextExtents;
935 {
936    if (pTextExtents->buf == NULL || pTextExtents->len == 0) {
937       pTextExtents->w = pTextExtents->lbearing = pTextExtents->rextra = 0;
938       pTextExtents->bbox_w = 0;
939    } else {
940       XCharStruct xcs;
941 
942       MyTextExtents(canvasFontPtr, pTextExtents->buf, pTextExtents->len, &xcs);
943       pTextExtents->w = xcs.width;
944       pTextExtents->lbearing = (xcs.lbearing >= 0 ? 0 : xcs.lbearing);
945       pTextExtents->rextra = xcs.rbearing - xcs.width;
946       pTextExtents->bbox_w = pTextExtents->w - pTextExtents->lbearing +
947             pTextExtents->rextra;
948    }
949    pTextExtents->bbox_h = canvasFontHeight;
950    pTextExtents->asc = canvasFontAsc;
951    pTextExtents->des = canvasFontDes;
952 }
953 
SegmentDoubleByteString(pszStr)954 struct StrRec *SegmentDoubleByteString(pszStr)
955    char *pszStr;
956 {
957    struct StrRec *pFirstStr=NULL, *pLastStr=NULL;
958    int nLen=strlen(pszStr), nIndex=0;
959 
960    if (nLen == 0) {
961       return NewStr();
962    }
963    while (nIndex < nLen) {
964       int nSubStrIndex=0, nDoubleByte;
965       char *psz=NULL, *pszStart=NULL, saved_ch='\0';
966       struct StrRec *pStr=NULL;
967 
968       pszStart = &pszStr[nIndex];
969       nDoubleByte = ((*pszStart) & 0x80);
970       if (nDoubleByte) {
971          int nOdd=FALSE;
972 
973          for (psz=pszStart, nSubStrIndex=0;
974                nIndex+nSubStrIndex < nLen &&
975                (nOdd || ((*psz)&0x80) == nDoubleByte);
976                psz++, nSubStrIndex++) {
977             nOdd = !nOdd;
978          }
979       } else {
980          for (psz=pszStart, nSubStrIndex=0;
981                nIndex+nSubStrIndex < nLen && ((*psz)&0x80) == 0;
982                psz++, nSubStrIndex++) {
983          }
984       }
985       pStr = NewStr();
986       saved_ch = (*psz);
987       *psz = '\0';
988       DynStrSet(&pStr->dyn_str, pszStart);
989       *psz = saved_ch;
990 
991       pStr->prev = pLastStr;
992       pStr->next = NULL;
993       if (pFirstStr == NULL) {
994          pFirstStr = pStr;
995       } else {
996          pLastStr->next = pStr;
997       }
998       pLastStr = pStr;
999 
1000       nIndex += nSubStrIndex;
1001    }
1002    return pFirstStr;
1003 }
1004 
1005 static char *gpszTmpStr=NULL;
1006 static XChar2b *gpszTmpStr16=NULL;
1007 static int gnTmpStrLen=0;
1008 
1009 static
AllocTmp16Strings(pszStr,nLen)1010 void AllocTmp16Strings(pszStr, nLen)
1011    char *pszStr;
1012    int nLen;
1013 {
1014    if (nLen > gnTmpStrLen) {
1015       char *psz=(char*)malloc(nLen+3);
1016       XChar2b *psz16=(XChar2b*)malloc((nLen+3)*sizeof(XChar2b));
1017 
1018       if (psz == NULL || psz16 == NULL) FailAllocMessage();
1019       if (gpszTmpStr != NULL) free(gpszTmpStr);
1020       if (gpszTmpStr16 != NULL) free(gpszTmpStr16);
1021       gpszTmpStr = psz;
1022       gpszTmpStr16 = psz16;
1023       gnTmpStrLen = nLen;
1024    }
1025    if (gpszTmpStr != NULL) *gpszTmpStr = '\0';
1026    if (gpszTmpStr16 != NULL) {
1027       gpszTmpStr16[0].byte1 = gpszTmpStr16[0].byte2 = (unsigned char)0;
1028    }
1029 }
1030 
MyTextExtents(xfs,pszStr,nLen,pxcs)1031 void MyTextExtents(xfs, pszStr, nLen, pxcs)
1032    XFontStruct *xfs;
1033    char *pszStr;
1034    int nLen;
1035    XCharStruct *pxcs;
1036    /* nLen does not include trailing '\0' */
1037 {
1038    int dir=0, asc=0, des=0;
1039 
1040    memset(pxcs, 0, sizeof(XCharStruct));
1041    if (canvasFontDoubleByte) {
1042       int nDoubleByte, nIndex=0;
1043       XCharStruct xcs;
1044 
1045       memset(&xcs, 0, sizeof(XCharStruct));
1046       AllocTmp16Strings(pszStr, nLen);
1047       while (nIndex < nLen) {
1048          int nSubStrIndex=0;
1049          char *psz=NULL, *pszStart=NULL;
1050 
1051          pszStart = &pszStr[nIndex];
1052          nDoubleByte = ((*pszStart) & 0x80);
1053          if (nDoubleByte) {
1054             int nDoubleByteIndex=0, nOdd=FALSE;
1055 
1056             for (psz=pszStart, nSubStrIndex=0;
1057                   nIndex+nSubStrIndex < nLen &&
1058                   (nOdd || ((*psz)&0x80) == nDoubleByte);
1059                   psz++, nSubStrIndex++) {
1060                if (nOdd) {
1061                   gpszTmpStr16[nDoubleByteIndex].byte2 = (unsigned char)(*psz) & 0x7f;
1062                   nDoubleByteIndex++;
1063                } else {
1064                   gpszTmpStr16[nDoubleByteIndex].byte1 = (unsigned char)(*psz) & 0x7f;
1065                }
1066                nOdd = !nOdd;
1067             }
1068             if (canvasFontDoubleByteModBytes) {
1069                int i;
1070 
1071                for (i=0; i < nDoubleByteIndex; i++) {
1072                   gpszTmpStr16[i].byte1 &= 0x7f;
1073                   gpszTmpStr16[i].byte2 &= 0x7f;
1074                }
1075             }
1076             XTextExtents16(xfs, gpszTmpStr16, nDoubleByteIndex, &dir, &asc,
1077                   &des, &xcs);
1078          } else {
1079             for (psz=pszStart, nSubStrIndex=0;
1080                   nIndex+nSubStrIndex < nLen && ((*psz)&0x80) == 0;
1081                   psz++, nSubStrIndex++) {
1082             }
1083             XTextExtents(xfs, pszStart, nSubStrIndex, &dir, &asc,
1084                   &des, &xcs);
1085          }
1086          if (pszStart == pszStr) {
1087             pxcs->lbearing = xcs.lbearing;
1088          }
1089          pxcs->width += xcs.width;
1090          pxcs->rbearing = xcs.rbearing-xcs.width;
1091 
1092          nIndex += nSubStrIndex;
1093       }
1094       pxcs->rbearing += pxcs->width;
1095    } else {
1096       XTextExtents(xfs, pszStr, nLen, &dir, &asc, &des, pxcs);
1097    }
1098 }
1099 
MyTextWidth(xfs,pszStr,nLen)1100 int MyTextWidth(xfs, pszStr, nLen)
1101    XFontStruct *xfs;
1102    char *pszStr;
1103    int nLen;
1104    /* nLen does not include trailing '\0' */
1105 {
1106    if (canvasFontDoubleByte) {
1107       int nDoubleByte, nIndex=0, nTotal=0;
1108 
1109       AllocTmp16Strings(pszStr, nLen);
1110       while (nIndex < nLen) {
1111          int nSubStrIndex=0;
1112          char *psz=NULL, *pszStart=NULL;
1113 
1114          pszStart = &pszStr[nIndex];
1115          nDoubleByte = ((*pszStart) & 0x80);
1116          if (nDoubleByte) {
1117             int nDoubleByteIndex=0, nOdd=FALSE;
1118 
1119             for (psz=pszStart, nSubStrIndex=0;
1120                   nIndex+nSubStrIndex < nLen &&
1121                   (nOdd || ((*psz)&0x80) == nDoubleByte);
1122                   psz++, nSubStrIndex++) {
1123                if (nOdd) {
1124                   gpszTmpStr16[nDoubleByteIndex].byte2 = (unsigned char)(*psz) & 0x7f;
1125                   nDoubleByteIndex++;
1126                } else {
1127                   gpszTmpStr16[nDoubleByteIndex].byte1 = (unsigned char)(*psz) & 0x7f;
1128                }
1129                nOdd = !nOdd;
1130             }
1131             nTotal += XTextWidth16(xfs, gpszTmpStr16, nDoubleByteIndex);
1132          } else {
1133             for (psz=pszStart, nSubStrIndex=0;
1134                   nIndex+nSubStrIndex < nLen && ((*psz)&0x80) == 0;
1135                   psz++, nSubStrIndex++) {
1136             }
1137             nTotal += XTextWidth(xfs, pszStart, nSubStrIndex);
1138          }
1139          nIndex += nSubStrIndex;
1140       }
1141       return nTotal;
1142    } else {
1143       return XTextWidth(xfs, pszStr, nLen);
1144    }
1145 }
1146 
MyDrawString(dpy,d,gc,nDepth,x,y,pszStr,nLen)1147 void MyDrawString(dpy, d, gc, nDepth, x, y, pszStr, nLen)
1148    Display *dpy;
1149    Drawable d;
1150    GC gc;
1151    int nDepth, x, y, nLen;
1152    char *pszStr;
1153    /* nLen does not include trailing '\0' */
1154 {
1155    if (canvasFontDoubleByte) {
1156       int nDoubleByte, nIndex=0, nTotal=0;
1157 
1158       AllocTmp16Strings(pszStr, nLen);
1159       while (nIndex < nLen) {
1160          int nSubStrIndex=0;
1161          char *psz=NULL, *pszStart=NULL;
1162 
1163          pszStart = &pszStr[nIndex];
1164          nDoubleByte = ((*pszStart) & 0x80);
1165          if (nDoubleByte) {
1166             int nDoubleByteIndex=0, nOdd=FALSE, w=0, i=0;
1167 
1168             for (psz=pszStart, nSubStrIndex=0;
1169                   nIndex+nSubStrIndex < nLen &&
1170                   (nOdd || ((*psz)&0x80) == nDoubleByte);
1171                   psz++, nSubStrIndex++) {
1172                if (nOdd) {
1173                   gpszTmpStr16[nDoubleByteIndex].byte2 = (unsigned char)(*psz) & 0x7f;
1174                   nDoubleByteIndex++;
1175                } else {
1176                   gpszTmpStr16[nDoubleByteIndex].byte1 = (unsigned char)(*psz) & 0x7f;
1177                }
1178                nOdd = !nOdd;
1179             }
1180             if (canvasFontDoubleByteModBytes) {
1181                for (i=0; i < nDoubleByteIndex; i++) {
1182                   gpszTmpStr16[i].byte1 &= 0x7f;
1183                   gpszTmpStr16[i].byte2 &= 0x7f;
1184                }
1185             }
1186             if (canvasFontDoubleByteVertical) {
1187                for (i=0; i < nDoubleByteIndex; i++) {
1188                   char buf[3];
1189                   Pixmap bitmap=None;
1190                   TextExtentsInfo stTextExtents;
1191 
1192                   w = XTextWidth16(canvasFontPtr, &gpszTmpStr16[i], 1);
1193                   buf[0] = pszStart[i<<1];
1194                   buf[1] = pszStart[(i<<1)+1];
1195                   buf[2] = '\0';
1196                   memset(&stTextExtents, 0, sizeof(TextExtentsInfo));
1197                   stTextExtents.buf = buf;
1198                   stTextExtents.len = 2;
1199                   bitmap = PaintVertChar(&stTextExtents, ROTATE270);
1200                   if (bitmap != None) {
1201                      XGCValues values;
1202 
1203                      values.clip_mask = bitmap;
1204                      values.clip_x_origin = x+nTotal;
1205                      values.clip_y_origin = y-canvasFontAsc;
1206                      XChangeGC(dpy, gc,
1207                            GCClipMask | GCClipXOrigin | GCClipYOrigin, &values);
1208 
1209                      XFillRectangle(dpy, d, gc, x+nTotal, y-canvasFontAsc,
1210                            stTextExtents.bbox_h, stTextExtents.bbox_w);
1211 
1212                      values.clip_mask = None;
1213                      values.clip_x_origin = 0;
1214                      values.clip_y_origin = 0;
1215                      XChangeGC(dpy, gc,
1216                            GCClipMask | GCClipXOrigin | GCClipYOrigin, &values);
1217                   }
1218                   nTotal += w;
1219                }
1220             } else {
1221                XDrawString16(dpy, d, gc, x+nTotal, y, gpszTmpStr16,
1222                      nDoubleByteIndex);
1223                w = XTextWidth16(canvasFontPtr, gpszTmpStr16, nDoubleByteIndex);
1224                nTotal += w;
1225             }
1226          } else {
1227             for (psz=pszStart, nSubStrIndex=0;
1228                   nIndex+nSubStrIndex < nLen && ((*psz)&0x80) == 0;
1229                   psz++, nSubStrIndex++) {
1230             }
1231             XDrawString(dpy, d, gc, x+nTotal, y, pszStart, nSubStrIndex);
1232             nTotal += XTextWidth(canvasFontPtr, pszStart, nSubStrIndex);
1233          }
1234          nIndex += nSubStrIndex;
1235       }
1236    } else {
1237       XDrawString(dpy, d, gc, x, y, pszStr, nLen);
1238    }
1239 }
1240 
1241 static Pixmap	vertFontBitmap=None, rotatedVertFontBitmap=None;
1242 static XImage	*rotatedVertFontImage=NULL;
1243 static int	vertFontBitmapW=0, vertFontBitmapH=0;
1244 
PaintVertChar(pTextExtents,nRotate)1245 Pixmap PaintVertChar(pTextExtents, nRotate)
1246    TextExtentsInfo *pTextExtents;
1247    int nRotate;
1248    /* Caller must not delete the returned pixmap! */
1249 {
1250    int w=0, lbearing=0, rextra=0, image_w=0, image_h=0;
1251    int r=0, dest_cols=0, dest_rows=0;
1252    int saved_db_vert=canvasFontDoubleByteVertical;
1253    XImage *src_image=NULL;
1254    XGCValues values;
1255 
1256    SetTextExtentsInfo(pTextExtents);
1257    w = pTextExtents->w;
1258    lbearing = pTextExtents->lbearing;
1259    rextra = pTextExtents->rextra;
1260    image_w = pTextExtents->bbox_w;
1261    image_h = pTextExtents->bbox_h;
1262 
1263    if (image_w > vertFontBitmapW || image_h > vertFontBitmapH) {
1264       int tmp_w, tmp_h;
1265 
1266       if (vertFontBitmap != None) XFreePixmap(mainDisplay, vertFontBitmap);
1267       if (rotatedVertFontBitmap != None) {
1268          XFreePixmap(mainDisplay, rotatedVertFontBitmap);
1269       }
1270       tmp_w = max(image_w, vertFontBitmapW);
1271       tmp_h = max(image_h, vertFontBitmapH);
1272       vertFontBitmap = XCreatePixmap(mainDisplay, mainWindow, tmp_w, tmp_h, 1);
1273       rotatedVertFontBitmap = XCreatePixmap(mainDisplay, mainWindow, tmp_h,
1274             tmp_w, 1);
1275       if (vertFontBitmap == None) {
1276          sprintf(gszMsgBox, TgLoadString(STID_CANNOT_ALLOC_PIXMAP_OF_SIZE),
1277                tmp_w, tmp_h);
1278          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1279          return FALSE;
1280       } else if (rotatedVertFontBitmap == None) {
1281          sprintf(gszMsgBox, TgLoadString(STID_CANNOT_ALLOC_PIXMAP_OF_SIZE),
1282                tmp_h, tmp_w);
1283          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1284          return FALSE;
1285       }
1286       vertFontBitmapW = tmp_w;
1287       vertFontBitmapH = tmp_h;
1288    }
1289    dest_cols = image_h;
1290    dest_rows = image_w;
1291 
1292    XSetForeground(mainDisplay, rotateGC, 0);
1293    XFillRectangle(mainDisplay, vertFontBitmap, rotateGC, 0, 0,
1294          vertFontBitmapW, vertFontBitmapH);
1295    XFillRectangle(mainDisplay, rotatedVertFontBitmap, rotateGC, 0, 0,
1296          image_h, image_w);
1297 
1298    values.foreground = 1;
1299    values.font = canvasFontPtr->fid;
1300    XChangeGC(mainDisplay, rotateGC, GCForeground | GCFont, &values);
1301    canvasFontDoubleByteVertical = FALSE;
1302    MyDrawString(mainDisplay, vertFontBitmap, rotateGC, 1, -lbearing,
1303          canvasFontAsc, pTextExtents->buf, pTextExtents->len);
1304    canvasFontDoubleByteVertical = saved_db_vert;
1305    src_image = XGetImage(mainDisplay, vertFontBitmap, 0, 0, image_w, image_h, 1,
1306          ZPixmap);
1307    if (src_image == NULL) {
1308       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_GET_IMAGE_OF_SIZE),
1309             image_w, image_h);
1310       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1311       return FALSE;
1312    }
1313    if (rotatedVertFontImage != NULL) XDestroyImage(rotatedVertFontImage);
1314    rotatedVertFontImage = XGetImage(mainDisplay, rotatedVertFontBitmap, 0, 0,
1315          dest_cols, dest_rows, 1, ZPixmap);
1316    if (rotatedVertFontImage == NULL) {
1317       XDestroyImage(src_image);
1318       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_GET_IMAGE_OF_SIZE),
1319             dest_cols, dest_rows);
1320       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1321       return FALSE;
1322    }
1323    switch (nRotate) {
1324    case ROTATE90:
1325       for (r=0; r < dest_rows; r++) {
1326          int c=0;
1327 
1328          for (c=0; c < dest_cols; c++) {
1329             int x=r;
1330             int y=image_h-c-1;
1331 
1332             if (XGetPixel(src_image, x, y)==1) {
1333                XPutPixel(rotatedVertFontImage, c, r, 1);
1334             }
1335          }
1336       }
1337       break;
1338    case ROTATE270:
1339       for (r=0; r < dest_rows; r++) {
1340          int c=0;
1341 
1342          for (c=0; c < dest_cols; c++) {
1343             int x=image_w-r-1;
1344             int y=c;
1345 
1346             if (XGetPixel(src_image, x, y)==1) {
1347                XPutPixel(rotatedVertFontImage, c, r, 1);
1348             }
1349          }
1350       }
1351       break;
1352    }
1353    XPutImage(mainDisplay, rotatedVertFontBitmap, rotateGC,
1354          rotatedVertFontImage, 0, 0, 0, 0, dest_cols, dest_rows);
1355    XDestroyImage(src_image);
1356 
1357    return rotatedVertFontBitmap;
1358 }
1359 
1360 static
CleanUpTmpStrings()1361 void CleanUpTmpStrings()
1362 {
1363    if (gpszTmpStr != NULL) free(gpszTmpStr);
1364    if (gpszTmpStr16 != NULL) free(gpszTmpStr16);
1365    gpszTmpStr = NULL;
1366    gpszTmpStr16 = NULL;
1367    gnTmpStrLen = 0;
1368 }
1369 
ValidCharCode(c_ptr)1370 int ValidCharCode(c_ptr)
1371    char *c_ptr;
1372 {
1373    int index=(int)(*c_ptr - '\200');
1374 
1375    if (*charCodeToName[index] == '\0' || *charCodeToName[index] == '8' ||
1376          *charCodeToName[index] == '\\') {
1377       return TRUE;
1378    }
1379    sprintf(gszMsgBox, TgLoadString(STID_UNRECOG_CHARCODE_DISCARD),
1380          (*c_ptr)&0xff);
1381    Msg(gszMsgBox);
1382    return FALSE;
1383 }
1384 
CharCodeTranslate(c_ptr)1385 char *CharCodeTranslate(c_ptr)
1386    char *c_ptr;
1387 {
1388    int index=(int)(*c_ptr - '\200');
1389 
1390    if (*charCodeToName[index] == '\\' || *charCodeToName[index] == '8') {
1391       return charCodeToName[index];
1392    }
1393    return NULL;
1394 }
1395 
1396 static int	*encodeFont=NULL;
1397 static short	**encodeCharFlags=NULL;
1398 static int	encodeCharFlagsAllocated=FALSE;
1399 static int	numEncodeCharFonts=0;
1400 
1401 static int	gnDontReencodeInitialized=FALSE;
1402 static char	*gpszDontReencode=NULL;
1403 
1404 static
CleanUpEncodeCharFonts()1405 void CleanUpEncodeCharFonts()
1406 {
1407    int i;
1408 
1409    if (encodeCharFlagsAllocated) {
1410       for (i = 0; i < numEncodeCharFonts*MAXFONTSTYLES; i++) {
1411          free(encodeCharFlags[i]);
1412       }
1413       free(encodeFont);
1414       free(encodeCharFlags);
1415       encodeCharFlagsAllocated = FALSE;
1416       numEncodeCharFonts = 0;
1417       encodeFont = NULL;
1418       encodeCharFlags = NULL;
1419    }
1420    *cmdLineDontReencode = '\0';
1421 }
1422 
1423 static
RemovePSFontNameVariations(ps_font_name_str)1424 void RemovePSFontNameVariations(ps_font_name_str)
1425    char *ps_font_name_str;
1426    /*
1427     * Get rid of the '-' as in 'ZapfChancery-MediumItalic'.
1428     * Also get rid of the '--' as in 'Helvetica-Narrow--Bold' and
1429     *       'Helvetica-Narrow--'.
1430     */
1431 {
1432    char *psz=NULL;
1433 
1434    if ((psz=strstr(ps_font_name_str, "--")) != NULL) {
1435       *psz = '\0';
1436    } else if ((psz=strchr(ps_font_name_str, '-')) != NULL) {
1437       *psz = '\0';
1438    }
1439 }
1440 
SaveDontReencode(FP)1441 void SaveDontReencode(FP)
1442    FILE *FP;
1443 {
1444    char *c_ptr=NULL;
1445 
1446    if (gpszDontReencode == NULL) return;
1447 
1448    if (fprintf(FP, "dont_reencode(\"") == EOF) {
1449       writeFileFailed = TRUE;
1450    }
1451    for (c_ptr=gpszDontReencode; *c_ptr != '\0'; c_ptr++) {
1452       if (fprintf(FP, "%s", c_ptr) == EOF) writeFileFailed = TRUE;
1453       c_ptr += strlen(c_ptr);
1454       if (c_ptr[1] != '\0') {
1455          if (fprintf(FP, ":") == EOF) writeFileFailed = TRUE;
1456       }
1457    }
1458    if (fprintf(FP, "\").\n") == EOF) writeFileFailed = TRUE;
1459 }
1460 
ReadDontReencode(buf)1461 int ReadDontReencode(buf)
1462    char *buf;
1463 {
1464    char *s=NULL, *c_ptr=NULL;
1465 
1466    if (!PRTGIF || cmdLineOpenDisplay) return TRUE;
1467 
1468 #ifndef _PRTGIF_USE_ISO_LATIN_1_ALWAYS
1469    s = FindChar((int)'(', buf);
1470    c_ptr = FindChar((int)'"', s);
1471    s = ReadString(c_ptr);
1472    *(--s) = '\0';
1473    InitDontReencode(c_ptr);
1474 #endif /* ~_PRTGIF_USE_ISO_LATIN_1_ALWAYS */
1475 
1476    return TRUE;
1477 }
1478 
SavePSFontAliases(FP)1479 void SavePSFontAliases(FP)
1480    FILE *FP;
1481 {
1482    int i=0, count=0, total=0;
1483 
1484    if (gnNumPSFontAliases == 0 || gaPSFontAliases == NULL) return;
1485 
1486    for (i=0; i < gnNumPSFontAliases; i++) {
1487       KeyValInfo *pKeyValue=(&gaPSFontAliases[i]);
1488 
1489       if (pKeyValue == NULL || pKeyValue->key == NULL ||
1490             pKeyValue->value == NULL) {
1491          continue;
1492       }
1493       count++;
1494    }
1495    if (count == 0) return;
1496 
1497    if (fprintf(FP, "ps_font_aliases([\n") == EOF) {
1498       writeFileFailed = TRUE;
1499    }
1500    for (i=0; i < gnNumPSFontAliases; i++) {
1501       KeyValInfo *pKeyValue=(&gaPSFontAliases[i]);
1502 
1503       if (pKeyValue == NULL || pKeyValue->key == NULL ||
1504             pKeyValue->value == NULL) {
1505          continue;
1506       }
1507       total++;
1508       if (fprintf(FP, "\t\"%s=%s\"", pKeyValue->key, pKeyValue->value) == EOF) {
1509          writeFileFailed = TRUE;
1510       }
1511       if (total != count) {
1512          if (fprintf(FP, ",\n") == EOF) writeFileFailed = TRUE;
1513       }
1514    }
1515    /*
1516     * For the next file version, the '\t' below should be removed.
1517     */
1518    if (fprintf(FP, "\n\t]).\n") == EOF) writeFileFailed = TRUE;
1519 }
1520 
SaveDoubleByteModBytes(FP)1521 void SaveDoubleByteModBytes(FP)
1522    FILE *FP;
1523    /* This function doesn't do anything.  May be there is no need for this. */
1524 {
1525    int i=0;
1526 
1527    for (i=0; i < numFonts; i++) {
1528       if (IsFontDoubleByte(i)) {
1529       }
1530    }
1531 }
1532 
SavePSFontNeedCharSubs(FP)1533 void SavePSFontNeedCharSubs(FP)
1534    FILE *FP;
1535 {
1536    int i=0, count=0, total=0;
1537 
1538    if (gnNumPSFontNeedCharSubs == 0 || gaPSFontNeedCharSubs == NULL) return;
1539 
1540    for (i=0; i < gnNumPSFontNeedCharSubs; i++) {
1541       KeyValInfo *pKeyValue=(&gaPSFontNeedCharSubs[i]);
1542 
1543       if (pKeyValue == NULL || pKeyValue->key == NULL ||
1544             pKeyValue->value == NULL) {
1545          continue;
1546       }
1547       count++;
1548    }
1549    if (count == 0) return;
1550 
1551    if (fprintf(FP, "ps_font_need_char_subs([\n") == EOF) {
1552       writeFileFailed = TRUE;
1553    }
1554    for (i=0; i < gnNumPSFontNeedCharSubs; i++) {
1555       KeyValInfo *pKeyValue=(&gaPSFontNeedCharSubs[i]);
1556 
1557       if (pKeyValue == NULL || pKeyValue->key == NULL ||
1558             pKeyValue->value == NULL) {
1559          continue;
1560       }
1561       total++;
1562       if (fprintf(FP, "\t\"%s=%s\"", pKeyValue->key, pKeyValue->value) == EOF) {
1563          writeFileFailed = TRUE;
1564       }
1565       if (total != count) {
1566          if (fprintf(FP, ",\n") == EOF) writeFileFailed = TRUE;
1567       }
1568    }
1569    /*
1570     * For the next file version, the '\t' below should be removed.
1571     */
1572    if (fprintf(FP, "\n\t]).\n") == EOF) writeFileFailed = TRUE;
1573 }
1574 
SavePSCharSubs(FP)1575 void SavePSCharSubs(FP)
1576    FILE *FP;
1577 {
1578    CVListElem *elem=NULL;
1579 
1580    for (elem=ListFirst(&psCharSubsList); elem != NULL;
1581          elem=ListNext(&psCharSubsList, elem)) {
1582       PSCharSubs *ppscs=(PSCharSubs*)elem->obj;
1583 
1584       if (ppscs != NULL && ppscs->token_name != NULL) {
1585          int i=0, first_one=TRUE;
1586 
1587          if (fprintf(FP, "ps_char_subs(\"%s\",[\n", ppscs->token_name) == EOF) {
1588             writeFileFailed = TRUE;
1589          }
1590          for (i=0; i < 128; i++) {
1591             char *ps_char_name=ppscs->ps_char_name[i];
1592 
1593             if (ps_char_name != NULL) {
1594                if (first_one) {
1595                   if (fprintf(FP, "\t\"8#%03o%s\"",
1596                         (i|0x080), ps_char_name) == EOF) {
1597                      writeFileFailed = TRUE;
1598                   }
1599                   first_one = FALSE;
1600                } else {
1601                   if (fprintf(FP, ",\n\t\"8#%03o%s\"",
1602                         (i|0x080), ps_char_name) == EOF) {
1603                      writeFileFailed = TRUE;
1604                   }
1605                }
1606             }
1607          }
1608          if (fprintf(FP, "\n\t]).\n") == EOF) writeFileFailed = TRUE;
1609       }
1610    }
1611 }
1612 
1613 static
ProcessAPSFontAlias(fake_font_name,real_font_name)1614 void ProcessAPSFontAlias(fake_font_name, real_font_name)
1615    char *fake_font_name, *real_font_name;
1616 {
1617    if (gaPSFontAliases == NULL) {
1618       gaPSFontAliases = (KeyValInfo*)malloc(sizeof(KeyValInfo));
1619    } else {
1620       gaPSFontAliases = (KeyValInfo*)realloc(gaPSFontAliases,
1621             (gnNumPSFontAliases+1)*sizeof(KeyValInfo));
1622    }
1623    if (gaPSFontAliases == NULL) FailAllocMessage();
1624    memset(&gaPSFontAliases[gnNumPSFontAliases], 0, sizeof(KeyValInfo));
1625 
1626    gaPSFontAliases[gnNumPSFontAliases].key =
1627          UtilStrDup(fake_font_name);
1628    gaPSFontAliases[gnNumPSFontAliases].value =
1629          UtilStrDup(&real_font_name[1]);
1630    if (gaPSFontAliases[gnNumPSFontAliases].key == NULL ||
1631          gaPSFontAliases[gnNumPSFontAliases].value == NULL) {
1632       FailAllocMessage();
1633    }
1634    *real_font_name = '=';
1635 
1636    UtilTrimBlanks(gaPSFontAliases[gnNumPSFontAliases].key);
1637    UtilTrimBlanks(gaPSFontAliases[gnNumPSFontAliases].value);
1638    gnNumPSFontAliases++;
1639 }
1640 
ReadPSFontAliases(FP,buf)1641 int ReadPSFontAliases(FP, buf)
1642    FILE *FP;
1643    char *buf;
1644 {
1645    char *line=NULL;
1646    int skip_processing=FALSE;
1647 
1648    if (!PRTGIF || cmdLineOpenDisplay) skip_processing = TRUE;
1649    if (gaPSFontAliases != NULL || gnNumPSFontAliases > 0) {
1650       skip_processing = TRUE;
1651    }
1652    while ((line=UtilGetALine(FP)) != NULL) {
1653       char *c_ptr=NULL, *fake_font_name=NULL, *real_font_name=NULL;
1654       char info[MAXSTRING];
1655 
1656       scanLineNum++;
1657       if (*line == ']' || (line[0] == '\t' && line[1] == ']')) {
1658          free(line);
1659          break;
1660       }
1661       if (!skip_processing) {
1662 #ifndef _PRTGIF_USE_ISO_LATIN_1_ALWAYS
1663          c_ptr = FindChar((int)'"', line);
1664          c_ptr = ParseStr(c_ptr, (int)'"', info, sizeof(info));
1665          fake_font_name = info;
1666          real_font_name = strchr(fake_font_name, '=');
1667          if (real_font_name == NULL || real_font_name[1] == '\0') {
1668             free(line);
1669             continue;
1670          }
1671          *real_font_name = '\0';
1672          ProcessAPSFontAlias(fake_font_name, real_font_name);
1673          *real_font_name = '=';
1674 #endif /* ~_PRTGIF_USE_ISO_LATIN_1_ALWAYS */
1675       }
1676       free(line);
1677    }
1678    return TRUE;
1679 }
1680 
1681 static
FreePSCharSubs(pppscs)1682 void FreePSCharSubs(pppscs)
1683    PSCharSubs **pppscs;
1684 {
1685    PSCharSubs *ppscs=(*pppscs);
1686 
1687    if (ppscs != NULL) {
1688       int i=0;
1689 
1690       UtilFree(ppscs->token_name);
1691       for (i=0; i < 128; i++) {
1692          if (ppscs->ps_char_name[i] != NULL) {
1693             free(ppscs->ps_char_name[i]);
1694          }
1695       }
1696       free(ppscs);
1697    }
1698    *pppscs = NULL;
1699 }
1700 
1701 static
ValidCharCodeSpec(psz_char_code,token_name,pn_char_code,resource_name)1702 int ValidCharCodeSpec(psz_char_code, token_name, pn_char_code, resource_name)
1703    char *psz_char_code, *token_name, *resource_name;
1704    int *pn_char_code;
1705 {
1706    int char_code=0;
1707 
1708    if (strncmp(psz_char_code, "8#", 2) == 0) {
1709       if (sscanf(&psz_char_code[2], "%o", &char_code) != 1) {
1710          if (resource_name == NULL) {
1711             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_PARSE_CHAR_CODE_FILE),
1712                   psz_char_code, token_name);
1713          } else {
1714             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_PARSE_CHAR_CODE_XDEF),
1715                   psz_char_code, token_name, TOOL_NAME, resource_name);
1716          }
1717          fprintf(stderr, "%s\n", gszMsgBox);
1718          return FALSE;
1719       }
1720    } else if (strncmp(psz_char_code, "0x", 2) == 0) {
1721       if (sscanf(&psz_char_code[2], "%x", &char_code) != 1) {
1722          if (resource_name == NULL) {
1723             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_PARSE_CHAR_CODE_FILE),
1724                   psz_char_code, token_name);
1725          } else {
1726             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_PARSE_CHAR_CODE_XDEF),
1727                   psz_char_code, token_name, TOOL_NAME, resource_name);
1728          }
1729          fprintf(stderr, "%s\n", gszMsgBox);
1730          return FALSE;
1731       }
1732    } else {
1733       if (sscanf(psz_char_code, "%d", &char_code) != 1) {
1734          if (resource_name == NULL) {
1735             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_PARSE_CHAR_CODE_FILE),
1736                   psz_char_code, token_name);
1737          } else {
1738             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_PARSE_CHAR_CODE_XDEF),
1739                   psz_char_code, token_name, TOOL_NAME, resource_name);
1740          }
1741          fprintf(stderr, "%s\n", gszMsgBox);
1742          return FALSE;
1743       }
1744    }
1745    if (char_code < 161 || char_code > 255) {
1746       if (resource_name == NULL) {
1747          sprintf(gszMsgBox, TgLoadString(STID_CHAR_CODE_OUT_OF_RANGE_FILE),
1748                psz_char_code, token_name);
1749       } else {
1750          sprintf(gszMsgBox, TgLoadString(STID_CHAR_CODE_OUT_OF_RANGE_XDEF),
1751                psz_char_code, token_name, TOOL_NAME, resource_name);
1752       }
1753       fprintf(stderr, "%s\n", gszMsgBox);
1754       return FALSE;
1755    }
1756    *pn_char_code = char_code;
1757 
1758    return TRUE;
1759 }
1760 
1761 static
ProcessCharSubs(ppscs,psz_char_code,ps_char_name,resource_name)1762 void ProcessCharSubs(ppscs, psz_char_code, ps_char_name, resource_name)
1763    PSCharSubs *ppscs;
1764    char *psz_char_code, *ps_char_name, *resource_name;
1765 {
1766    int char_code=0, len=strlen(ps_char_name)+1;
1767 
1768    if (!ValidCharCodeSpec(psz_char_code, ppscs->token_name, &char_code,
1769          resource_name)) {
1770       return;
1771    }
1772    if (ppscs->ps_char_name[char_code-128] != NULL) {
1773       if (resource_name == NULL) {
1774          sprintf(gszMsgBox, TgLoadString(STID_DUP_CHAR_CODE_FILE_IGNORED),
1775                char_code, char_code, TOOL_NAME, resource_name);
1776       } else {
1777          sprintf(gszMsgBox, TgLoadString(STID_DUP_CHAR_CODE_XDEF_IGNORED),
1778                char_code, char_code, TOOL_NAME, resource_name);
1779       }
1780       fprintf(stderr, "%s\n", gszMsgBox);
1781       return;
1782    }
1783    ppscs->ps_char_name[char_code-128] = (char*)malloc(len+1);
1784    if (ppscs->ps_char_name[char_code-128] == NULL) FailAllocMessage();
1785    sprintf(ppscs->ps_char_name[char_code-128], "/%s", ps_char_name);
1786 }
1787 
1788 static
ParsePSCharSubs(ppscs,c_ptr,resource_name)1789 int ParsePSCharSubs(ppscs, c_ptr, resource_name)
1790    PSCharSubs *ppscs;
1791    char *c_ptr, *resource_name;
1792 {
1793    char *buf=UtilStrDup(c_ptr), *buf1=NULL, *psz_state=NULL;
1794 
1795    if (buf == NULL) FailAllocMessage();
1796    for (buf1=UtilStrTok(buf, " ,\t\n\r", &psz_state); buf1 != NULL;
1797          buf1=UtilStrTok(NULL, " ,\t\n\r", &psz_state)) {
1798       char *ps_char_name=strchr(buf1, '/');
1799 
1800       if (ps_char_name == NULL) {
1801          fprintf(stderr, TgLoadString(STID_BAD_XDEF_CANT_FIND_TOKEN_SKIP), buf1,
1802                "'='", TOOL_NAME, resource_name);
1803          fprintf(stderr, "\n");
1804          continue;
1805       }
1806       if (ps_char_name[1] == '\0') {
1807          fprintf(stderr, TgLoadString(STID_BAD_XDEF_MISS_CHAR_NAME_SKIP),
1808                buf1, TOOL_NAME, resource_name);
1809          fprintf(stderr, "\n");
1810          continue;
1811       }
1812       *ps_char_name = '\0';
1813       ProcessCharSubs(ppscs, buf1, &ps_char_name[1], resource_name);
1814       *ps_char_name = '/';
1815    }
1816    UtilFree(buf);
1817 
1818    return TRUE;
1819 }
1820 
1821 static
FindPSFontNeedCharSubs(ps_font_name)1822 char *FindPSFontNeedCharSubs(ps_font_name)
1823    char *ps_font_name;
1824 {
1825    int i=0;
1826 
1827    for (i=0; i < gnNumPSFontNeedCharSubs; i++) {
1828       if (strcmp(ps_font_name, gaPSFontNeedCharSubs[i].key) == 0) {
1829          return gaPSFontNeedCharSubs[i].value;
1830       }
1831    }
1832    return NULL;
1833 }
1834 
1835 static
FindTokenInPSCharSubs(token_name)1836 PSCharSubs *FindTokenInPSCharSubs(token_name)
1837    char *token_name;
1838 {
1839    CVListElem *elem=NULL;
1840 
1841    for (elem=ListFirst(&psCharSubsList); elem != NULL;
1842          elem=ListNext(&psCharSubsList, elem)) {
1843       PSCharSubs *ppscs=(PSCharSubs*)elem->obj;
1844 
1845       if (ppscs != NULL && ppscs->token_name != NULL &&
1846             strcmp(ppscs->token_name, token_name) == 0) {
1847          return ppscs;
1848       }
1849    }
1850    return NULL;
1851 }
1852 
1853 static
FindPSCharSubs(ps_font_name)1854 PSCharSubs *FindPSCharSubs(ps_font_name)
1855    char *ps_font_name;
1856 {
1857    char *token_name=FindPSFontNeedCharSubs(ps_font_name);
1858 
1859    if (token_name == NULL) return NULL;
1860 
1861    return FindTokenInPSCharSubs(token_name);
1862 }
1863 
1864 static
ProcessPSCharSubs(font_name,token_name)1865 void ProcessPSCharSubs(font_name, token_name)
1866    char *font_name, *token_name;
1867 {
1868    if (gaPSFontNeedCharSubs == NULL) {
1869       gaPSFontNeedCharSubs = (KeyValInfo*)malloc(sizeof(KeyValInfo));
1870    } else {
1871       gaPSFontNeedCharSubs = (KeyValInfo*)realloc(gaPSFontNeedCharSubs,
1872             (gnNumPSFontNeedCharSubs+1)*sizeof(KeyValInfo));
1873    }
1874    if (gaPSFontNeedCharSubs == NULL) FailAllocMessage();
1875    memset(&gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs], 0,
1876          sizeof(KeyValInfo));
1877 
1878    gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs].key =
1879          UtilStrDup(font_name);
1880    gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs].value =
1881          UtilStrDup(token_name);
1882    if (gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs].key == NULL ||
1883          gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs].value == NULL) {
1884       FailAllocMessage();
1885    }
1886    UtilTrimBlanks(gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs].key);
1887    UtilTrimBlanks(gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs].value);
1888    gnNumPSFontNeedCharSubs++;
1889 
1890    if (FindTokenInPSCharSubs(token_name) == NULL) {
1891       if (mainDisplay != NULL) {
1892          char *c_ptr=NULL, buf[MAXSTRING];
1893 
1894          sprintf(buf, "PSCharSubs_%s", token_name);
1895          if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,buf)) == NULL) {
1896             sprintf(gszMsgBox, TgLoadString(STID_CANNOT_GET_X_DEFAULT),
1897                   TOOL_NAME, buf);
1898             fprintf(stderr, "%s\n", gszMsgBox);
1899          } else {
1900             PSCharSubs *ppscs=NULL;
1901 
1902             ppscs = (PSCharSubs*)malloc(sizeof(PSCharSubs));
1903             if (ppscs == NULL) FailAllocMessage();
1904             memset(ppscs, 0, sizeof(PSCharSubs));
1905             ppscs->token_name = UtilStrDup(token_name);
1906             if (ppscs->token_name == NULL) FailAllocMessage();
1907             if (ParsePSCharSubs(ppscs, c_ptr, buf)) {
1908                ListAppend(&psCharSubsList, ppscs);
1909             } else {
1910                FreePSCharSubs(&ppscs);
1911             }
1912          }
1913       } else {
1914          sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_PS_CHAR_SUBS_READ),
1915                token_name);
1916          fprintf(stderr, "%s\n", gszMsgBox);
1917       }
1918    }
1919 }
1920 
1921 static
CleanUpPSFontCharSubs()1922 void CleanUpPSFontCharSubs()
1923 {
1924    if (gnNumPSFontNeedCharSubs > 0) {
1925       CVListElem *elem=NULL;
1926 
1927       for (elem=ListFirst(&psCharSubsList); elem != NULL;
1928             elem=ListNext(&psCharSubsList, elem)) {
1929          PSCharSubs *ppscs=(PSCharSubs*)elem->obj;
1930 
1931          if (ppscs != NULL) {
1932             FreePSCharSubs(&ppscs);
1933          }
1934       }
1935       ListUnlinkAll(&psCharSubsList);
1936 
1937       while (gnNumPSFontNeedCharSubs-- > 0) {
1938          UtilFree(gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs].key);
1939          UtilFree(gaPSFontNeedCharSubs[gnNumPSFontNeedCharSubs].value);
1940       }
1941       free(gaPSFontNeedCharSubs);
1942    }
1943    gaPSFontNeedCharSubs = NULL;
1944    gnNumPSFontNeedCharSubs = 0;
1945 }
1946 
ReadPSFontNeedCharSubs(FP,buf)1947 int ReadPSFontNeedCharSubs(FP, buf)
1948    FILE *FP;
1949    char *buf;
1950 {
1951    char *line=NULL;
1952    int skip_processing=FALSE;
1953 
1954    if (!PRTGIF || cmdLineOpenDisplay) skip_processing = TRUE;
1955    if (gaPSFontNeedCharSubs != NULL || gnNumPSFontNeedCharSubs > 0) {
1956       skip_processing = TRUE;
1957    }
1958    while ((line=UtilGetALine(FP)) != NULL) {
1959       char *c_ptr=NULL, *font_name=NULL, *token_name=NULL;
1960       char info[MAXSTRING];
1961 
1962       scanLineNum++;
1963       if (*line == ']' || (line[0] == '\t' && line[1] == ']')) {
1964          free(line);
1965          break;
1966       }
1967       if (!skip_processing) {
1968 #ifndef _PRTGIF_USE_ISO_LATIN_1_ALWAYS
1969          c_ptr = FindChar((int)'"', line);
1970          c_ptr = ParseStr(c_ptr, (int)'"', info, sizeof(info));
1971          font_name = info;
1972          token_name = strchr(font_name, '=');
1973          if (token_name == NULL || token_name[1] == '\0') {
1974             free(line);
1975             continue;
1976          }
1977          *token_name = '\0';
1978          ProcessPSCharSubs(font_name, &token_name[1]);
1979          *token_name = '=';
1980 #endif /* ~_PRTGIF_USE_ISO_LATIN_1_ALWAYS */
1981       }
1982       free(line);
1983    }
1984    return TRUE;
1985 }
1986 
ReadPSCharSubs(FP,buf)1987 int ReadPSCharSubs(FP, buf)
1988    FILE *FP;
1989    char *buf;
1990 {
1991    char *line=NULL;
1992    int skip_processing=FALSE, ok=FALSE;
1993    PSCharSubs *ppscs=NULL;
1994 
1995    if (!PRTGIF || cmdLineOpenDisplay) skip_processing = TRUE;
1996    if (!skip_processing) {
1997       char *s=FindChar((int)'(', buf), *c_ptr=NULL;
1998 
1999       c_ptr = FindChar((int)'"', s);
2000       s = ReadString(c_ptr);
2001       *(--s) = '\0';
2002 
2003       if (FindTokenInPSCharSubs(c_ptr) != NULL) {
2004          sprintf(gszMsgBox, TgLoadString(STID_DUP_TOKEN_PS_CHAR_SUBS_READ),
2005                c_ptr);
2006          fprintf(stderr, "%s\n", gszMsgBox);
2007          skip_processing = TRUE;
2008       } else {
2009          ppscs = (PSCharSubs*)malloc(sizeof(PSCharSubs));
2010          if (ppscs == NULL) FailAllocMessage();
2011          memset(ppscs, 0, sizeof(PSCharSubs));
2012          ppscs->token_name = UtilStrDup(c_ptr);
2013          if (ppscs->token_name == NULL) FailAllocMessage();
2014          ok = TRUE;
2015       }
2016    }
2017    while ((line=UtilGetALine(FP)) != NULL) {
2018       char *c_ptr=NULL, *buf1=NULL, *ps_char_name=NULL;
2019       char info[MAXSTRING];
2020 
2021       scanLineNum++;
2022       if (*line == ']' || (line[0] == '\t' && line[1] == ']')) {
2023          free(line);
2024          break;
2025       }
2026       if (!skip_processing) {
2027 #ifndef _PRTGIF_USE_ISO_LATIN_1_ALWAYS
2028          c_ptr = FindChar((int)'"', line);
2029          c_ptr = ParseStr(c_ptr, (int)'"', info, sizeof(info));
2030          buf1 = info;
2031          ps_char_name = strchr(buf1, '/');
2032          if (ps_char_name == NULL || ps_char_name[1] == '\0') {
2033             free(line);
2034             continue;
2035          }
2036          *ps_char_name = '\0';
2037          ProcessCharSubs(ppscs, buf1, &ps_char_name[1], NULL);
2038          *ps_char_name = '/';
2039 #endif /* ~_PRTGIF_USE_ISO_LATIN_1_ALWAYS */
2040       }
2041       free(line);
2042    }
2043    if (ppscs != NULL) {
2044       if (ok) {
2045          ListAppend(&psCharSubsList, ppscs);
2046       } else {
2047          FreePSCharSubs(&ppscs);
2048       }
2049    }
2050    return TRUE;
2051 }
2052 
2053 static
DontReencodeInXDefOrCmdLine(pszFontName,nFontIndex,nFontStyle)2054 int DontReencodeInXDefOrCmdLine(pszFontName, nFontIndex, nFontStyle)
2055    char *pszFontName;
2056    int nFontIndex, nFontStyle;
2057 {
2058    char *c_ptr=NULL;
2059 
2060    if (gpszDontReencode != NULL) {
2061       char szFontStr[MAXSTRING];
2062 
2063       *szFontStr = '\0';
2064       if (pszFontName == NULL) {
2065          GetPSFontStr(nFontIndex, nFontStyle, szFontStr);
2066          if (strncmp(szFontStr, "/(", 2) == 0) {
2067             /* bitmapped PS font! */
2068             return FALSE;
2069          } else if (*szFontStr == '/') {
2070             *szFontStr = ' ';
2071          }
2072       } else {
2073          UtilStrCpyN(szFontStr, sizeof(szFontStr), pszFontName);
2074       }
2075       RemovePSFontNameVariations(szFontStr);
2076       UtilTrimBlanks(szFontStr);
2077       pszFontName = szFontStr;
2078 
2079       for (c_ptr=gpszDontReencode; *c_ptr != '\0'; c_ptr++) {
2080          if (UtilStrICmp(c_ptr, pszFontName) == 0) {
2081             return TRUE;
2082          }
2083          c_ptr += strlen(c_ptr);
2084       }
2085    }
2086    return FALSE;
2087 }
2088 
2089 static
UpdateEncodeCharInfo(nIndex,psz)2090 void UpdateEncodeCharInfo(nIndex, psz)
2091    int nIndex;
2092    char *psz;
2093 {
2094    int byte_index=(int)(((*psz) & 0x7f)>>3);
2095    short *flag_ptr=encodeCharFlags[nIndex];
2096 
2097    encodeFont[nIndex] = TRUE;
2098    flag_ptr[byte_index] |= (1<<((*psz) & 0x07));
2099 }
2100 
2101 static
PrepareStrSeg(pStrSeg)2102 void PrepareStrSeg(pStrSeg)
2103    StrSegInfo *pStrSeg;
2104 {
2105    char *c_ptr=NULL;
2106    int font_and_style_index=0;
2107 
2108    if (pStrSeg->double_byte) return;
2109 
2110    if (pStrSeg->font_name == NULL) {
2111       if (pStrSeg->font == FONT_SYM) {
2112          return;
2113       }
2114    } else if (strcmp(pStrSeg->font_name, "Symbol") == 0) {
2115       return;
2116    }
2117    if (DontReencodeInXDefOrCmdLine(pStrSeg->font_name, pStrSeg->font,
2118          pStrSeg->style)) {
2119       return;
2120    } else if (PRTGIF && !cmdLineOpenDisplay && pStrSeg->font < 0) {
2121       /*
2122        * Since pStrSeg->font is < 0, there's no way to call
2123        *       UpdateEncodeCharInfo()!  Therefore, font encoding is forced!
2124        */
2125       return;
2126    }
2127    font_and_style_index = pStrSeg->font*MAXFONTSTYLES + pStrSeg->style;
2128    for (c_ptr=pStrSeg->dyn_str.s; *c_ptr != '\0'; c_ptr++) {
2129       if (((*c_ptr)&0x80) && *charCodeToName[(int)(*c_ptr-'\200')]=='8') {
2130          UpdateEncodeCharInfo(font_and_style_index, c_ptr);
2131       }
2132    }
2133 }
2134 
2135 static
PrepareStrBlock(pStrBlock)2136 void PrepareStrBlock(pStrBlock)
2137    StrBlockInfo *pStrBlock;
2138 {
2139    switch (pStrBlock->type) {
2140    case SB_SIMPLE:
2141       PrepareStrSeg(pStrBlock->seg);
2142       break;
2143 
2144    case SB_CHAR_SPACE:
2145       break;
2146 
2147    case SB_SUPSUB_LEFT:
2148    case SB_SUPSUB_CENTER:
2149    case SB_SUPSUB_RIGHT:
2150       if (pStrBlock->sup != NULL) PrepareMiniLines(pStrBlock->sup);
2151       if (pStrBlock->sub != NULL) PrepareMiniLines(pStrBlock->sub);
2152       if (pStrBlock->type == SB_SUPSUB_CENTER) {
2153          PrepareStrSeg(pStrBlock->seg);
2154       }
2155       break;
2156    }
2157 }
2158 
2159 static
PrepareMiniLine(pMiniLine)2160 void PrepareMiniLine(pMiniLine)
2161    MiniLineInfo *pMiniLine;
2162 {
2163    StrBlockInfo *pStrBlock=NULL;
2164 
2165    for (pStrBlock=pMiniLine->first_block; pStrBlock != NULL;
2166          pStrBlock=pStrBlock->next) {
2167       PrepareStrBlock(pStrBlock);
2168    }
2169 }
2170 
PrepareMiniLines(minilines)2171 void PrepareMiniLines(minilines)
2172    MiniLinesInfo *minilines;
2173 {
2174    MiniLineInfo *pMiniLine=NULL;
2175 
2176    for (pMiniLine=minilines->first; pMiniLine != NULL;
2177          pMiniLine=pMiniLine->next) {
2178       PrepareMiniLine(pMiniLine);
2179    }
2180 }
2181 
2182 static
PrepareText(ObjPtr)2183 void PrepareText(ObjPtr)
2184    struct ObjRec *ObjPtr;
2185 {
2186    MiniLinesInfo *minilines=(&ObjPtr->detail.t->minilines);
2187 
2188    PrepareMiniLines(minilines);
2189 }
2190 
2191 static
PrepareObjFontInfo(ObjPtr)2192 void PrepareObjFontInfo(ObjPtr)
2193    struct ObjRec *ObjPtr;
2194 {
2195    struct ObjRec *obj_ptr;
2196    struct AttrRec *attr_ptr;
2197 
2198    for (obj_ptr=ObjPtr; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
2199       switch (obj_ptr->type) {
2200       case OBJ_TEXT: PrepareText(obj_ptr); break;
2201 
2202       case OBJ_GROUP:
2203       case OBJ_SYM:
2204       case OBJ_ICON: PrepareObjFontInfo(obj_ptr->detail.r->last); break;
2205 
2206       case OBJ_PIN:
2207          PrepareObjFontInfo(GetPinObj(obj_ptr)->detail.r->last);
2208          break;
2209       }
2210       for (attr_ptr=obj_ptr->lattr; attr_ptr!=NULL; attr_ptr=attr_ptr->prev) {
2211          PrepareText(attr_ptr->obj);
2212       }
2213    }
2214 }
2215 
PrepareEightBitFontInfo()2216 void PrepareEightBitFontInfo()
2217 {
2218    struct ObjRec *obj_ptr;
2219    struct AttrRec *attr_ptr;
2220    int j, i;
2221    short *flag_ptr;
2222    struct PageRec *page_ptr;
2223 
2224    if (encodeCharFlagsAllocated && numEncodeCharFonts < numFonts) {
2225       CleanUpEncodeCharFonts();
2226    }
2227    if (!encodeCharFlagsAllocated) {
2228       int font_count=0;
2229 
2230       font_count = ((PRTGIF && !cmdLineOpenDisplay) ?
2231             MAXFONTS+numFakedFonts : numFonts+numFakedFonts);
2232 
2233       encodeCharFlags =
2234             (short**)malloc(font_count*MAXFONTSTYLES*sizeof(short*));
2235       if (encodeCharFlags == NULL) FailAllocMessage();
2236       encodeFont = (int*)malloc(font_count*MAXFONTSTYLES*sizeof(int));
2237       if (encodeFont == NULL) FailAllocMessage();
2238       memset(encodeFont, 0, font_count*MAXFONTSTYLES*sizeof(int));
2239       for (i = 0; i < font_count*MAXFONTSTYLES; i++) {
2240          encodeCharFlags[i] = (short*)malloc(16*sizeof(short));
2241          if (encodeCharFlags[i] == NULL) FailAllocMessage();
2242          memset(encodeCharFlags[i], 0, 16*sizeof(short));
2243       }
2244       encodeCharFlagsAllocated = TRUE;
2245       numEncodeCharFonts = font_count;
2246    }
2247 
2248    for (i=0; i < numEncodeCharFonts*MAXFONTSTYLES; i++) {
2249       encodeFont[i] = FALSE;
2250       flag_ptr = encodeCharFlags[i];
2251       for (j=0; j < 16; j++) flag_ptr[j] = 0;
2252    }
2253    for (page_ptr=firstPage; page_ptr != NULL; page_ptr=page_ptr->next) {
2254       for (obj_ptr=page_ptr->bot; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
2255          switch (obj_ptr->type) {
2256          case OBJ_TEXT: PrepareText(obj_ptr); break;
2257 
2258          case OBJ_GROUP:
2259          case OBJ_SYM:
2260          case OBJ_ICON: PrepareObjFontInfo(obj_ptr->detail.r->last); break;
2261 
2262          case OBJ_PIN:
2263             PrepareObjFontInfo(GetPinObj(obj_ptr)->detail.r->last);
2264             break;
2265          }
2266          for (attr_ptr=obj_ptr->lattr; attr_ptr!=NULL;
2267                attr_ptr=attr_ptr->prev) {
2268             PrepareText(attr_ptr->obj);
2269          }
2270       }
2271    }
2272 }
2273 
NeedEncode(FontName,FontIndex,StyleIndex)2274 int NeedEncode(FontName, FontIndex, StyleIndex)
2275    char *FontName;
2276    int FontIndex, StyleIndex;
2277 {
2278    if (PRTGIF && !cmdLineOpenDisplay) {
2279       /* No need to do anything here because encodeFont[] takes care of it */
2280       if (FontIndex < 0) {
2281          /*
2282           * Since FontIndex is < 0, there's no way to compute an index into
2283           *       encodeFont[]!  Therefore, the decision to encode a font
2284           *       or not must be made here!  (By default, a font is encoded!)
2285           */
2286          return (FontName==NULL ? FALSE :
2287                !DontReencodeInXDefOrCmdLine(FontName, FontIndex, StyleIndex));
2288       }
2289    }
2290    if (FontIndex == FONT_SYM) {
2291       return FALSE;
2292    }
2293    return encodeFont[FontIndex*MAXFONTSTYLES+StyleIndex];
2294 }
2295 
GetFontIndex(FontStr,StyleIndex,MustFind)2296 int GetFontIndex(FontStr, StyleIndex, MustFind)
2297    char *FontStr;
2298    int StyleIndex, MustFind;
2299 {
2300    int i;
2301    int num_base_fonts=((PRTGIF && !cmdLineOpenDisplay) ? MAXFONTS : numFonts);
2302    char **base_font_info_str=((PRTGIF && !cmdLineOpenDisplay) ?
2303          initFontInfoStr : fontInfoStr);
2304 
2305    for (i=0; i < num_base_fonts; i++) {
2306       if (strcmp(
2307             base_font_info_str[(i*MAXFONTSTYLES+StyleIndex)*3+PS_FONT_NAME],
2308             FontStr) == 0) {
2309          return i;
2310       }
2311    }
2312    for ( ; i < num_base_fonts+numFakedFonts; i++) {
2313       if (strcmp(fontFamilies[i].name_faked, FontStr) == 0) {
2314          return i;
2315       }
2316    }
2317    if (MustFind) return INVALID;
2318 
2319    numFakedFonts++;
2320    if (fontFamilies == NULL) {
2321       fontFamilies = (struct FontFmlyRec *)malloc(
2322             (num_base_fonts+numFakedFonts)*sizeof(struct FontFmlyRec));
2323       if (fontFamilies == NULL) FailAllocMessage();
2324       memset(fontFamilies, 0,
2325             (num_base_fonts+numFakedFonts)*sizeof(struct FontFmlyRec));
2326    } else {
2327       fontFamilies = (struct FontFmlyRec *)realloc(fontFamilies,
2328             (num_base_fonts+numFakedFonts)*sizeof(struct FontFmlyRec));
2329       if (fontFamilies == NULL) FailAllocMessage();
2330       memset(&fontFamilies[num_base_fonts+numFakedFonts-1], 0,
2331             sizeof(struct FontFmlyRec));
2332    }
2333    fontFamilies[num_base_fonts+numFakedFonts-1].name_faked =
2334          (char*)malloc((strlen(FontStr)+1)*sizeof(char));
2335    if (fontFamilies[num_base_fonts+numFakedFonts-1].name_faked == NULL) {
2336       FailAllocMessage();
2337    }
2338    strcpy(fontFamilies[num_base_fonts+numFakedFonts-1].name_faked, FontStr);
2339    for (i=0; i < MAXFONTSTYLES; i++) {
2340       fontFamilies[num_base_fonts+numFakedFonts-1].fr[i].next = NULL;
2341       fontFamilies[num_base_fonts+numFakedFonts-1].fr[i].xfs = NULL;
2342    }
2343    return (num_base_fonts+numFakedFonts-1);
2344 }
2345 
GetFontAndStyle(FontStr,pnFont,pnStyle,MustFind)2346 int GetFontAndStyle(FontStr, pnFont, pnStyle, MustFind)
2347    char *FontStr;
2348    int *pnFont, *pnStyle, MustFind;
2349 {
2350    int font=0;
2351    int num_fonts=((PRTGIF && !cmdLineOpenDisplay) ? MAXFONTS : numFonts);
2352 
2353    for (font=0; font < num_fonts; font++) {
2354       int style=0;
2355 
2356       for (style=0; style < MAXFONTSTYLES; style++) {
2357          char font_str[MAXSTRING];
2358 
2359          GetPSFontStr(font, style, font_str);
2360          /* font_str[0] is '/' */
2361          if (UtilStrICmp(FontStr, &font_str[1]) == 0) {
2362             if (pnFont != NULL) *pnFont = font;
2363             if (pnStyle != NULL) *pnStyle = style;
2364             return TRUE;
2365          }
2366       }
2367    }
2368    if (MustFind) return FALSE;
2369 
2370    return TRUE;
2371 }
2372 
GetFontIndexFromPSFontAndStyle(font_str,style,pnDoubleByte,pnModified)2373 int GetFontIndexFromPSFontAndStyle(font_str, style, pnDoubleByte, pnModified)
2374    char *font_str;
2375    int style, *pnDoubleByte, *pnModified;
2376 {
2377    int len=strlen(font_str), font=FONT_TIM;
2378 
2379    if (pnModified != NULL) *pnModified = FALSE;
2380    if (len > 1 && *font_str == '\'' && font_str[len-1] == '\'') {
2381       char *psz1=(&font_str[1]), *psz2=NULL;
2382 
2383       font_str[len-1] = '\0';
2384       psz2 = font_str;
2385       while (*psz1 != '\0') *psz2++ = *psz1++;
2386       *psz2 = '\0';
2387    }
2388    font = GetFontIndex(font_str, style, (!PRTGIF || cmdLineOpenDisplay));
2389    if (font == INVALID && (!PRTGIF || cmdLineOpenDisplay)) {
2390       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_FIND_FONT_USE_ALT),
2391             font_str, "Times");
2392       Msg(gszMsgBox);
2393       if (pnModified != NULL) *pnModified = TRUE;
2394       font = FONT_TIM;
2395       if (pnDoubleByte != NULL && *pnDoubleByte) {
2396          /*
2397           * font would have been the double-byte font.
2398           * But since it can't be found and Times is used, it should
2399           *     not be double-byte any more.
2400           */
2401          *pnDoubleByte = FALSE;
2402       }
2403    }
2404    return font;
2405 }
2406 
CleanUpDontReencode()2407 void CleanUpDontReencode()
2408 {
2409    if (gpszDontReencode != NULL) {
2410       UtilFree(gpszDontReencode);
2411       gpszDontReencode = NULL;
2412    }
2413    gnDontReencodeInitialized = FALSE;
2414 }
2415 
InitDontReencode(buf)2416 void InitDontReencode(buf)
2417    char *buf;
2418 {
2419    char *c_ptr=NULL, *pszDontReencode=NULL;
2420 
2421    if (buf == NULL && gnDontReencodeInitialized) return;
2422 
2423    if (buf == NULL) {
2424       gnDontReencodeInitialized = TRUE;
2425    }
2426    if (buf != NULL) {
2427       if (gpszDontReencode != NULL) {
2428          /* if it is already initialized, don't parse the content of buf */
2429          return;
2430       }
2431       if ((pszDontReencode=UtilStrDup(buf)) == NULL) FailAllocMessage();
2432       UtilTrimBlanks(pszDontReencode);
2433    } else if (PRTGIF && !cmdLineOpenDisplay) {
2434       if (*cmdLineDontReencode != '\0') {
2435          UtilTrimBlanks(cmdLineDontReencode);
2436          if ((pszDontReencode=UtilStrDup(cmdLineDontReencode)) == NULL) {
2437             FailAllocMessage();
2438          }
2439 #ifdef _DONT_REENCODE
2440       } else {
2441          if ((pszDontReencode=UtilStrDup(_DONT_REENCODE)) == NULL) {
2442             FailAllocMessage();
2443          }
2444          UtilTrimBlanks(pszDontReencode);
2445 #endif /* _DONT_REENCODE */
2446       }
2447    } else {
2448       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
2449             "DontReencode")) != NULL) {
2450          if ((pszDontReencode=UtilStrDup(c_ptr)) == NULL) FailAllocMessage();
2451          UtilTrimBlanks(pszDontReencode);
2452 #ifdef _DONT_REENCODE
2453       } else {
2454          if ((pszDontReencode=UtilStrDup(_DONT_REENCODE)) == NULL) {
2455             FailAllocMessage();
2456          }
2457          UtilTrimBlanks(pszDontReencode);
2458 #endif /* _DONT_REENCODE */
2459       }
2460       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
2461             "AdditionalDontReencode")) != NULL) {
2462          while (*c_ptr == ':') c_ptr++;
2463          if (pszDontReencode == NULL) {
2464             if ((pszDontReencode=UtilStrDup(c_ptr)) == NULL) FailAllocMessage();
2465          } else {
2466             int len=strlen(pszDontReencode);
2467             char *psz=(char*)malloc(sizeof(char)*(len+2+strlen(c_ptr)));
2468 
2469             if (psz == NULL) FailAllocMessage();
2470             sprintf(psz, "%s:%s", pszDontReencode, c_ptr);
2471             UtilFree(pszDontReencode);
2472             pszDontReencode = psz;
2473          }
2474          UtilTrimBlanks(pszDontReencode);
2475       }
2476    }
2477    if (pszDontReencode != NULL && *pszDontReencode != '\0') {
2478       char *c_ptr1=NULL;
2479 
2480       gpszDontReencode = (char*)malloc(strlen(pszDontReencode)+2);
2481       if (gpszDontReencode == NULL) FailAllocMessage();
2482       for (c_ptr1=gpszDontReencode, c_ptr=strtok(pszDontReencode,
2483             " ,:;\t\n\r"); c_ptr != NULL;
2484             c_ptr=strtok(NULL, " ,:;\t\n\r")) {
2485          strcpy(c_ptr1, c_ptr);
2486          c_ptr1 += strlen(c_ptr)+1;
2487       }
2488       *c_ptr1 = '\0';
2489    }
2490    UtilFree(pszDontReencode);
2491 }
2492 
InitPSFontCharSubs()2493 void InitPSFontCharSubs()
2494 {
2495    char *c_ptr=NULL;
2496 
2497    gaPSFontNeedCharSubs = NULL;
2498    gnNumPSFontNeedCharSubs = 0;
2499    CVListInit(&psCharSubsList);
2500 
2501    if (mainDisplay == NULL) return;
2502 
2503    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"PSFontNeedCharSubs")) !=
2504          NULL) {
2505       char *buf=UtilStrDup(c_ptr), *buf1=NULL, *psz_state=NULL;
2506 
2507       if (buf == NULL) FailAllocMessage();
2508       for (buf1=UtilStrTok(buf, " ,\t\n\r", &psz_state); buf1 != NULL;
2509             buf1=UtilStrTok(NULL, " ,\t\n\r", &psz_state)) {
2510          char *token_name=strchr(buf1, '=');
2511 
2512          if (token_name == NULL) {
2513             fprintf(stderr, TgLoadString(STID_BAD_XDEF_CANT_FIND_EQ_SKIP), buf1,
2514                   TOOL_NAME, "PSFontNeedCharSubs");
2515             fprintf(stderr, "\n");
2516             continue;
2517          }
2518          if (token_name[1] == '\0') {
2519             fprintf(stderr, TgLoadString(STID_BAD_XDEF_MISS_TOKEN_NAME_SKIP),
2520                   buf1, TOOL_NAME, "PSFontNeedCharSubs");
2521             fprintf(stderr, "\n");
2522             continue;
2523          }
2524          *token_name = '\0';
2525          if (LookupPSFontAliases(buf1) == NULL) {
2526             fprintf(stderr, TgLoadString(STID_BAD_FAKE_FONT_NAME_NO_ALIAS),
2527                   TOOL_NAME, "PSFontNeedCharSubs", buf1, TOOL_NAME,
2528                   "PSFontAliases");
2529             fprintf(stderr, "\n");
2530             *token_name = '=';
2531             continue;
2532          }
2533          ProcessPSCharSubs(buf1, &token_name[1]);
2534          *token_name = '=';
2535       }
2536       UtilFree(buf);
2537    }
2538 }
2539 
PrTgifInitBaseFonts()2540 void PrTgifInitBaseFonts()
2541 {
2542    int i;
2543 
2544    if (fontFamilies != NULL) return;
2545 
2546    fontFamilies = (struct FontFmlyRec *)malloc(
2547          MAXFONTS*sizeof(struct FontFmlyRec));
2548    if (fontFamilies == NULL) FailAllocMessage();
2549    memset(fontFamilies, 0, MAXFONTS*sizeof(struct FontFmlyRec));
2550    for (i=0; i < MAXFONTS; i++) {
2551       int j;
2552 
2553       fontFamilies[i].name_faked = NULL;
2554       fontFamilies[i].bitmapped_ps_font = FALSE;
2555       *fontFamilies[i].choice_char = '\0';
2556       for (j=0; j < MAXFONTSTYLES; j++) {
2557          fontFamilies[i].fr[j].next = NULL;
2558          fontFamilies[i].fr[j].xfs = NULL;
2559       }
2560    }
2561 }
2562 
GetCurSzUnit()2563 int GetCurSzUnit()
2564 {
2565    if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
2566       return curRealSzUnit;
2567    } else {
2568       return curSzUnit;
2569    }
2570 }
2571 
PutCurSzUnit(sz_unit)2572 void PutCurSzUnit(sz_unit)
2573    int sz_unit;
2574 {
2575    if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
2576       curRealSzUnit = sz_unit;
2577    } else {
2578       curSzUnit = sz_unit;
2579    }
2580 }
2581 
GetCurFontMsg(buf,pStrSeg)2582 void GetCurFontMsg(buf, pStrSeg)
2583    char *buf;
2584    StrSegInfo *pStrSeg;
2585 {
2586    char font_str[MAXSTRING];
2587 
2588    GetPSFontStr(curFont, curStyle, font_str);
2589 
2590    if (pStrSeg != NULL && editTextSize != 0) {
2591       if (showFontSizeInPoints) {
2592          sprintf(buf, "%s-%1dpt (%s %1dpt)",
2593                &font_str[1], SzUnitToPointSize(pStrSeg->real_sz_unit),
2594                TgLoadCachedString(CSTID_EDIT_TEXT_SIZE_SUBSTR),
2595                SzUnitToPointSize(curSzUnit));
2596       } else {
2597          sprintf(buf, "%s-%1d (%s %1d)",
2598                &font_str[1], SzUnitToFontSize(pStrSeg->real_sz_unit),
2599                TgLoadCachedString(CSTID_EDIT_TEXT_SIZE_SUBSTR),
2600                SzUnitToFontSize(curSzUnit));
2601       }
2602    } else {
2603       if (showFontSizeInPoints) {
2604          sprintf(buf, "%s-%1dpt", &font_str[1], SzUnitToPointSize(curSzUnit));
2605       } else {
2606          sprintf(buf, "%s-%1d", &font_str[1], SzUnitToFontSize(curSzUnit));
2607       }
2608    }
2609 }
2610 
CurFontMsg(nShowInMsgWindow,nShowInStatusWindow,pStrSeg)2611 void CurFontMsg(nShowInMsgWindow, nShowInStatusWindow, pStrSeg)
2612    int nShowInMsgWindow, nShowInStatusWindow;
2613    StrSegInfo *pStrSeg;
2614 {
2615    char buf[MAXSTRING];
2616 
2617    GetCurFontMsg(buf, pStrSeg);
2618 
2619    if (nShowInMsgWindow) Msg(buf);
2620    if (nShowInStatusWindow) SetStringStatus(buf);
2621 }
2622 
DumpReEncodeVector(FP,vec_prefix,vec_suffix,flag_ptr)2623 void DumpReEncodeVector(FP, vec_prefix, vec_suffix, flag_ptr)
2624    FILE *FP;
2625    char *vec_prefix, *vec_suffix;
2626    short *flag_ptr;
2627 {
2628    int j=0;
2629    PSCharSubs *ppscs=FindPSCharSubs(&vec_prefix[1]);
2630 
2631    fprintf(FP, "%s%s%s [\n",
2632          ((vec_prefix != NULL && *vec_prefix == '/') ? "" : "/"),
2633          vec_prefix, vec_suffix);
2634    for (j=0; j < 16; j++) {
2635       short flag=0;
2636 
2637       if (flag_ptr != NULL) {
2638          flag = *flag_ptr++;
2639       } else {
2640          /* dump the whole vector if flag_ptr is NULL */
2641          flag = 0xff;
2642       }
2643       if ((flag & 0xff) != 0) {
2644          int k=0;
2645 
2646          for (k=0; k < 8; k++) {
2647             if (flag & (1<<k)) {
2648                char *spec=charCodeToName[(j<<3)+k];
2649 
2650                if (spec && *spec && *spec != 'x') {
2651                   int index=((j<<3)+k);
2652 
2653                   /* avoid writing blank lines and "x" */
2654                   if (ppscs != NULL && ppscs->ps_char_name[index] != NULL) {
2655                      fprintf(FP, " 8#%03o %s\n", (index|0x080),
2656                            ppscs->ps_char_name[index]);
2657                   } else {
2658                      fprintf(FP, " %s\n", spec);
2659                   }
2660                }
2661             }
2662          }
2663       }
2664    }
2665    fprintf(FP, " ] def\n");
2666 }
2667 
DumpEightBitFontInfo(FP)2668 void DumpEightBitFontInfo(FP)
2669    FILE *FP;
2670 {
2671    int font_index=0, style_index=0, font_count=0;
2672 
2673    font_count = ((PRTGIF && !cmdLineOpenDisplay) ? MAXFONTS+numFakedFonts :
2674          numFonts+numFakedFonts);
2675 
2676    for (font_index=0; font_index < font_count; font_index++) {
2677       for (style_index=0; style_index < MAXFONTSTYLES; style_index++) {
2678          if (NeedEncode(NULL, font_index, style_index)) {
2679             char font_str[MAXSTRING];
2680 
2681             *font_str = '\0';
2682             GetPSFontStr(font_index, style_index, font_str);
2683             if (strncmp(font_str, "/(", 2) == 0) {
2684                /* bitmapped PS font! */
2685             } else {
2686                char real_font_str[MAXSTRING];
2687 
2688                DumpReEncodeVector(FP, font_str, "-vec",
2689                      encodeCharFlags[font_index*MAXFONTSTYLES+style_index]);
2690 
2691                strcpy(real_font_str, font_str);
2692                MapAliasedPSFontName(real_font_str, sizeof(real_font_str));
2693                fprintf(FP, "%s %s-8 %s-vec tgifReEncodeSmall\n\n",
2694                      real_font_str, font_str, &font_str[1]);
2695                if (preDumpSetup) PSUseReencode(font_str);
2696             }
2697          }
2698       }
2699    }
2700 }
2701 
2702 static int fontSize75[]={ 8, 10, 12, 14, 18, 24 };
2703 static int fontSize100[]={ 11, 14, 17, 20, 25, 34 };
2704 
GetCompatibleSize(font_dpi,font_size)2705 int GetCompatibleSize(font_dpi, font_size)
2706    int font_dpi, font_size;
2707 {
2708    switch (font_dpi) {
2709    case FONT_DPI_75: return fontSize75[font_size];
2710    case FONT_DPI_100: return fontSize100[font_size];
2711    }
2712    return INVALID;
2713 }
2714 
SetCanvasFont()2715 int SetCanvasFont()
2716    /*
2717     * Use curFont, curStyle, and curSzUnit to setup canvasFontPtr,
2718     *       canvasFontDoubleByte, metrics related to the font, etc.
2719     * Returns TRUE to mean this font should be ``read-only''.
2720     */
2721 {
2722    struct FontSizeRec *fs_ptr=NULL;
2723    int vert=FALSE, rc=TRUE;
2724 
2725    if (mainDisplay == NULL) return TRUE;
2726 
2727    actualCurFont = curFont;
2728    actualCurStyle = curStyle;
2729    actualCurSzUnit = curSzUnit;
2730    fs_ptr = FindFontInfo(curFont, curStyle, curSzUnit, FALSE);
2731 
2732    if (allowFontFaceSubstitution && fs_ptr == NULL) {
2733 #ifdef _TGIF_DBG /* debug, do not translate */
2734       TgAssert(FALSE, "Font substitution detected in SetCanvasFont()", NULL);
2735 #endif /* _TGIF_DBG */
2736       actualCurFont = defaultCurFont;
2737       actualCurStyle = defaultCurStyle;
2738       actualCurSzUnit = defaultCurSzUnit;
2739       fs_ptr = FindFontInfo(defaultCurFont, defaultCurStyle,
2740             defaultCurSzUnit, FALSE);
2741    }
2742    if (!allowFontFaceSubstitution && fs_ptr == NULL) {
2743       canvasFontSize = INVALID;
2744       return TRUE;
2745    }
2746    if (fs_ptr == NULL) {
2747       char buf[MAXSTRING];
2748 
2749       GetCurFontMsg(buf, NULL);
2750       fprintf(stderr, TgLoadString(STID_CANT_FIND_FONT_USE_ALT),
2751             buf, defaultFontName);
2752       fprintf(stderr, "\n");
2753       canvasFontPtr = defaultFontPtr;
2754       canvasFontSize = INVALID;
2755    } else {
2756       canvasFontPtr = fs_ptr->xfs;
2757       canvasFontSize = SzUnitToFontSize(fs_ptr->sz_unit);
2758       vert = fs_ptr->vert;
2759       rc = FALSE;
2760    }
2761    canvasFontAsc = canvasFontPtr->max_bounds.ascent;
2762    canvasFontDes = canvasFontPtr->max_bounds.descent;
2763    canvasFontDirection = canvasFontPtr->direction;
2764    /*
2765     * Need to fix this.
2766     */
2767    canvasFontDontReencode = FALSE;
2768 
2769    /*
2770     * The following does not seem to work any more because of UTF-8 fonts
2771     *     such as the ones that are iso10646-1 encoded.
2772     * canvasFontDoubleByte = (canvasFontPtr->min_byte1 != 0 ||
2773     *       canvasFontPtr->max_byte1 != 0);
2774     */
2775    canvasFontDoubleByte = (canvasFontPtr->min_byte1 != 0);
2776    if (canvasFontDoubleByte) {
2777       canvasFontDoubleByteModBytes = ((canvasFontPtr->min_byte1 & 0x80) == 0);
2778       canvasFontDoubleByteVertical = vert;
2779    } else {
2780       canvasFontDoubleByteModBytes = FALSE;
2781    }
2782    canvasFontHeight = canvasFontAsc + canvasFontDes;
2783    XSetFont(mainDisplay, drawGC, canvasFontPtr->fid);
2784 
2785    textCursorH = canvasFontHeight;
2786 
2787    return rc;
2788 }
2789 
CurFontCheck()2790 int CurFontCheck()
2791 {
2792    changingFontSizeFromRead = FALSE;
2793    allowFontFaceSubstitution = FALSE;
2794    SetCanvasFont();
2795    allowFontFaceSubstitution = TRUE;
2796    changingFontSizeFromRead = TRUE;
2797 
2798    return (SzUnitToFontSize(curSzUnit) == canvasFontSize);
2799 }
2800 
TrySetCanvasFont(font,style,size,must_find_requested,pnGotRequested)2801 int TrySetCanvasFont(font, style, size, must_find_requested, pnGotRequested)
2802    int font, style, size, must_find_requested, *pnGotRequested;
2803    /*
2804     * if size is not available, try all sizes in fontSzUnits[]
2805     */
2806 {
2807    int i, last=0, saved_size=size, saved_sz_unit=curSzUnit, sz_unit=0;
2808 
2809    if (pnGotRequested != NULL) *pnGotRequested = FALSE;
2810 
2811    curFont = font;
2812    curStyle = style;
2813 
2814    sz_unit = FontSizeToSzUnit(size);
2815 
2816    curSzUnit = sz_unit;
2817    SetCanvasFont();
2818    if (canvasFontSize != INVALID) {
2819       if (SzUnitToFontSize(curSzUnit) != canvasFontSize) {
2820          if (must_find_requested) {
2821             curSzUnit = saved_sz_unit;
2822             SetCanvasFont();
2823             return FALSE;
2824          }
2825          SetFileModified(TRUE);
2826          curSzUnit = FontSizeToSzUnit(canvasFontSize);
2827       }
2828       if (pnGotRequested != NULL) {
2829          *pnGotRequested = (canvasFontSize==saved_size);
2830       }
2831       return TRUE;
2832    }
2833    if (must_find_requested) {
2834       curSzUnit = saved_sz_unit;
2835       SetCanvasFont();
2836       return FALSE;
2837    }
2838    /* now try to find something close to the requested font */
2839    for (i=0; i < numFontSizes; i++) {
2840       int size1=SzUnitToFontSize(fontSzUnits[i]);
2841 
2842       if (size1 >= saved_size) {
2843          break;
2844       }
2845    }
2846    if (i == numFontSizes) {
2847       return FALSE;
2848    }
2849    last = i;
2850    for (i=0; i < last; i++) {
2851       curSzUnit = fontSzUnits[i];
2852       SetCanvasFont();
2853       if (canvasFontSize != INVALID) {
2854          if (SzUnitToFontSize(curSzUnit) != canvasFontSize) {
2855             SetFileModified(TRUE);
2856             curSzUnit = FontSizeToSzUnit(canvasFontSize);
2857          }
2858          if (pnGotRequested != NULL) {
2859             *pnGotRequested = (canvasFontSize==saved_size);
2860          }
2861          return TRUE;
2862       }
2863    }
2864    if (SzUnitToFontSize(fontSzUnits[last]) == saved_size) {
2865       last++;
2866    }
2867    for (i=last; i < numFontSizes; i++) {
2868       curSzUnit = fontSzUnits[i];
2869       SetCanvasFont();
2870       if (canvasFontSize != INVALID) {
2871          if (SzUnitToFontSize(curSzUnit) != canvasFontSize) {
2872             SetFileModified(TRUE);
2873             curSzUnit = FontSizeToSzUnit(canvasFontSize);
2874          }
2875          if (pnGotRequested != NULL) {
2876             *pnGotRequested = (canvasFontSize==saved_size);
2877          }
2878          return TRUE;
2879       }
2880    }
2881    curSzUnit = saved_sz_unit;
2882    SetCanvasFont();
2883 
2884    return FALSE;
2885 }
2886 
ObjFontInfoToCurFontInfo(TextPtr)2887 void ObjFontInfoToCurFontInfo(TextPtr)
2888    struct TextRec *TextPtr;
2889 {
2890    textJust = TextPtr->minilines.just;
2891    textVSpace = TextPtr->minilines.v_space;
2892    curUnderlineYOffset = TextPtr->underline_y_offset;
2893    curOverlineYOffset = TextPtr->overline_y_offset;
2894 }
2895 
StrSegInfoToCurFontInfo(pStrSeg)2896 void StrSegInfoToCurFontInfo(pStrSeg)
2897    StrSegInfo *pStrSeg;
2898 {
2899    curFont = pStrSeg->font;
2900    curStyle = pStrSeg->style;
2901    curSzUnit = pStrSeg->sz_unit;
2902    curUnderlineOn = pStrSeg->underline_on;
2903    curOverlineOn = pStrSeg->overline_on;
2904 }
2905 
2906 struct TmpFontFmlyRec {
2907    char				**font_strings;
2908    int				double_byte;
2909    struct TmpFontFmlyRec	*next, *prev;
2910 };
2911 
2912 static
SetupFontInfoStr(num_new_fonts,first_fmly)2913 void SetupFontInfoStr(num_new_fonts, first_fmly)
2914    int num_new_fonts;
2915    struct TmpFontFmlyRec *first_fmly;
2916 {
2917    struct TmpFontFmlyRec *fmly_ptr=NULL, *next_fmly=NULL;
2918    int index=0, fmly_index=0;
2919 
2920    numFonts = MAXFONTS+num_new_fonts;
2921    fontFamilies = (struct FontFmlyRec *)malloc(
2922          numFonts*sizeof(struct FontFmlyRec));
2923    if (fontFamilies == NULL) FailAllocMessage();
2924    memset(fontFamilies, 0, numFonts*sizeof(struct FontFmlyRec));
2925 
2926    fontInfoStr =
2927          (char**)malloc(numFonts*MAXFONTSTYLES*3*sizeof(char*));
2928    fontMenuStr = (char**)malloc(numFonts*sizeof(char*));
2929    if (fontInfoStr == NULL || fontMenuStr == NULL) FailAllocMessage();
2930 
2931    memset(fontInfoStr, 0, numFonts*MAXFONTSTYLES*3*sizeof(char*));
2932    memset(fontMenuStr, 0, numFonts*sizeof(char*));
2933 
2934    index = MAXFONTS*MAXFONTSTYLES*3;
2935    for (fmly_ptr=first_fmly, fmly_index=MAXFONTS; fmly_ptr != NULL;
2936          fmly_ptr=next_fmly, fmly_index++) {
2937       char *c_ptr=NULL, font_name[MAXSTRING], choice_char[3];
2938       int i=0, j=0, bitmapped_ps_font=FALSE;
2939       char *ps_font_name=fmly_ptr->font_strings[PS_FONT_NAME];
2940       int font_name_len=strlen(ps_font_name);
2941 
2942       *choice_char = '\0';
2943       next_fmly = fmly_ptr->next;
2944       if (*ps_font_name == '(' &&
2945             ps_font_name[font_name_len-1] == ')') {
2946          strcpy(font_name, &ps_font_name[1]);
2947          font_name[font_name_len-2] = '\0';
2948          strcpy(ps_font_name, font_name);
2949          RemovePSFontNameVariations(font_name);
2950          bitmapped_ps_font = TRUE;
2951       } else {
2952          strcpy(font_name, ps_font_name);
2953          RemovePSFontNameVariations(font_name);
2954       }
2955       for (i=0, j=0; i<MAXFONTSTYLES; i++, j+=3) {
2956          char *psz=fmly_ptr->font_strings[j+PS_FONT_NAME];
2957          int len=strlen(psz);
2958 
2959          if (len > 0 && *psz == '(' && psz[len-1] == ')') {
2960             strcpy(gszMsgBox, &psz[1]);
2961             gszMsgBox[len-2] = '\0';
2962             strcpy(psz, gszMsgBox);
2963          }
2964       }
2965       fontMenuStr[fmly_index] =
2966             (char*)malloc((strlen(font_name)+3)*sizeof(char));
2967       if (fontMenuStr[fmly_index] == NULL) FailAllocMessage();
2968       strcpy(fontMenuStr[fmly_index], font_name);
2969       if (strstr(fmly_ptr->font_strings[X_FONT_PREFIX], "%d") != NULL &&
2970             UtilStrICmp(fmly_ptr->font_strings[X_FONT_SUFFIX], "V") == 0) {
2971          strcat(fontMenuStr[fmly_index], "-V");
2972       }
2973       for (i=0, j=0; i<MAXFONTSTYLES; i++) {
2974          if (UtilStrICmp(fmly_ptr->font_strings[j+X_FONT_SUFFIX], "V") == 0) {
2975             fontFamilies[fmly_index].fr[i].vert = TRUE;
2976          }
2977          fontInfoStr[index++] = fmly_ptr->font_strings[j++];
2978          fontInfoStr[index++] = fmly_ptr->font_strings[j++];
2979          fontInfoStr[index++] = fmly_ptr->font_strings[j++];
2980       }
2981       fontFamilies[fmly_index].double_byte = fmly_ptr->double_byte;
2982       free(fmly_ptr->font_strings);
2983       free(fmly_ptr);
2984       fontFamilies[fmly_index].fr[STYLE_NR].next =
2985             fontFamilies[fmly_index].fr[STYLE_BR].next =
2986             fontFamilies[fmly_index].fr[STYLE_NI].next =
2987             fontFamilies[fmly_index].fr[STYLE_BI].next = NULL;
2988       fontFamilies[fmly_index].fr[STYLE_NR].xfs =
2989             fontFamilies[fmly_index].fr[STYLE_BR].xfs =
2990             fontFamilies[fmly_index].fr[STYLE_NI].xfs =
2991             fontFamilies[fmly_index].fr[STYLE_BI].xfs = NULL;
2992       fontFamilies[fmly_index].bitmapped_ps_font = bitmapped_ps_font;
2993       *fontFamilies[fmly_index].choice_char = '\0';
2994       sprintf(gszMsgBox, "%sShowFontChar", font_name);
2995       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,gszMsgBox)) != NULL) {
2996          int len=0;
2997 
2998          UtilStrCpyN(gszMsgBox, sizeof(gszMsgBox), c_ptr);
2999          UtilTrimBlanks(gszMsgBox);
3000          len = strlen(gszMsgBox);
3001          if (len > 0) {
3002             if (((*gszMsgBox) & 0x80) == 0) {
3003                if (gszMsgBox[len-1] == '"') gszMsgBox[--len] = '\0';
3004                gszMsgBox[len++] = '"';
3005                gszMsgBox[len] = '\0';
3006                c_ptr = ReadString(gszMsgBox);
3007                if (c_ptr != gszMsgBox) c_ptr--;
3008                *c_ptr = '\0';
3009             }
3010             strcpy(fontFamilies[fmly_index].choice_char, gszMsgBox);
3011          }
3012       }
3013       if (fontFamilies[fmly_index].double_byte) {
3014          char resource_name[MAXSTRING];
3015          int count=0;
3016 
3017          sprintf(resource_name, "%sConvFromUTF8", font_name);
3018          if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,resource_name)) != NULL) {
3019             UtilStrCpyN(gszMsgBox, sizeof(gszMsgBox), c_ptr);
3020             UtilTrimBlanks(gszMsgBox);
3021             if (*gszMsgBox != '\0') {
3022                for (count=0, c_ptr=strstr(gszMsgBox,"%s"); c_ptr!=NULL;
3023                      c_ptr=strstr(++c_ptr,"%s")) {
3024                   count++;
3025                }
3026                if (count > 1) {
3027                   fprintf(stderr, TgLoadString(STID_INVALID_XDEF), TOOL_NAME,
3028                         resource_name, gszMsgBox);
3029                   fprintf(stderr, "\n");
3030                } else {
3031                   fontFamilies[fmly_index].conv_from_utf8_cmd =
3032                         UtilStrDup(gszMsgBox);
3033                   if (fontFamilies[fmly_index].conv_from_utf8_cmd == NULL) {
3034                      FailAllocMessage();
3035                   }
3036                }
3037             }
3038          }
3039          sprintf(resource_name, "%sConvToUTF8", font_name);
3040          if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,resource_name)) != NULL) {
3041             UtilStrCpyN(gszMsgBox, sizeof(gszMsgBox), c_ptr);
3042             UtilTrimBlanks(gszMsgBox);
3043             if (*gszMsgBox != '\0') {
3044                for (count=0, c_ptr=strstr(gszMsgBox,"%s"); c_ptr!=NULL;
3045                      c_ptr=strstr(++c_ptr,"%s")) {
3046                   count++;
3047                }
3048                if (count > 1) {
3049                   fprintf(stderr, TgLoadString(STID_INVALID_XDEF), TOOL_NAME,
3050                         resource_name, gszMsgBox);
3051                   fprintf(stderr, "\n");
3052                } else {
3053                   fontFamilies[fmly_index].conv_to_utf8_cmd =
3054                         UtilStrDup(gszMsgBox);
3055                   if (fontFamilies[fmly_index].conv_to_utf8_cmd == NULL) {
3056                      FailAllocMessage();
3057                   }
3058                }
3059             }
3060          }
3061       }
3062    }
3063 }
3064 
3065 static
CleanUpPSFontAliases()3066 void CleanUpPSFontAliases()
3067 {
3068    if (gnNumPSFontAliases > 0) {
3069       while (gnNumPSFontAliases-- > 0) {
3070          UtilFree(gaPSFontAliases[gnNumPSFontAliases].key);
3071          UtilFree(gaPSFontAliases[gnNumPSFontAliases].value);
3072       }
3073       free(gaPSFontAliases);
3074    }
3075    gaPSFontAliases = NULL;
3076    gnNumPSFontAliases = 0;
3077 }
3078 
3079 static
InitPSFontAliases()3080 void InitPSFontAliases()
3081 {
3082    char *c_ptr=NULL;
3083 
3084    gaPSFontAliases = NULL;
3085    gnNumPSFontAliases = 0;
3086 
3087    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"PSFontAliases")) != NULL) {
3088       char *buf=UtilStrDup(c_ptr), *fake_font_name=NULL;
3089 
3090       if (buf == NULL) FailAllocMessage();
3091       for (fake_font_name=strtok(buf, ",\t\n\r"); fake_font_name != NULL;
3092             fake_font_name=strtok(NULL, ",\t\n\r")) {
3093          char *real_font_name=strchr(fake_font_name, '=');
3094 
3095          if (real_font_name == NULL) {
3096             fprintf(stderr, TgLoadString(STID_BAD_XDEF_CANT_FIND_EQ_SKIP),
3097                   fake_font_name, TOOL_NAME, "PSFontAliases");
3098             fprintf(stderr, "\n");
3099             continue;
3100          }
3101          *real_font_name = '\0';
3102          if (real_font_name[1] == '\0') {
3103             *real_font_name = '=';
3104             fprintf(stderr, TgLoadString(STID_BAD_XDEF_MISS_FONT_NAME_SKIP),
3105                   fake_font_name, TOOL_NAME, "PSFontAliases");
3106             fprintf(stderr, "\n");
3107             continue;
3108          }
3109          ProcessAPSFontAlias(fake_font_name, real_font_name);
3110          *real_font_name = '=';
3111       }
3112       UtilFree(buf);
3113    }
3114 }
3115 
3116 static
InitAdditionalFonts()3117 void InitAdditionalFonts()
3118 {
3119    int i, j, len, fmly_index, style_index, num_new_fonts=0;
3120    int got_double_fonts=FALSE;
3121    char *c_ptr=NULL, *buf=NULL;
3122    struct TmpFontFmlyRec *first_fmly=NULL, *last_fmly=NULL;
3123 
3124    fontFamilies = NULL;
3125    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"AdditionalFonts")) != NULL) {
3126       char *font_ptr=NULL;
3127 
3128       len = strlen(c_ptr);
3129       buf = (char*)malloc((len+1)*sizeof(char));
3130       if (buf == NULL) FailAllocMessage();
3131       strcpy(buf, c_ptr);
3132       for (font_ptr=buf; *font_ptr != '\0' &&
3133             strchr(" ,\t\n\r",*font_ptr) != NULL; font_ptr++) {
3134       }
3135       if (font_ptr != NULL && *font_ptr != '\0') {
3136          int ok=TRUE, index=0, font_exists=FALSE;
3137          char **font_strings=NULL;
3138          struct TmpFontFmlyRec *fmly_ptr=NULL;
3139 
3140          while (ok && font_ptr != NULL && *font_ptr != '\0') {
3141             font_strings = (char**)malloc((MAXFONTSTYLES*3)*sizeof(char*));
3142             if (font_strings == NULL) FailAllocMessage();
3143             memset(font_strings, 0, (MAXFONTSTYLES*3)*sizeof(char*));
3144             for (i=0, index=0; i<MAXFONTSTYLES; i++) {
3145                char *rgstry=NULL, *ps_name=NULL, *dup_ptr;
3146 
3147                dup_ptr = (font_ptr == NULL ? NULL : UtilStrDup(font_ptr));
3148                if ((font_ptr=strtok(font_ptr,",\t\n\r")) != NULL &&
3149                      (rgstry=strtok(NULL,",\t\n\r")) != NULL &&
3150                      (ps_name=strtok(NULL," ,\t\n\r")) != NULL &&
3151                      (font_exists=DoesFontExist(font_ptr,FALSE)) != FALSE) {
3152                   font_strings[index] = (char*)malloc(MAXSTRING*sizeof(char));
3153                   if (font_strings[index] == NULL) FailAllocMessage();
3154                   strcpy(font_strings[index], font_ptr);
3155                   UtilTrimBlanks(font_strings[index++]);
3156                   font_strings[index] = (char*)malloc(MAXSTRING*sizeof(char));
3157                   if (font_strings[index] == NULL) FailAllocMessage();
3158                   strcpy(font_strings[index], rgstry);
3159                   UtilTrimBlanks(font_strings[index++]);
3160                   font_strings[index] = (char*)malloc(MAXSTRING*sizeof(char));
3161                   if (font_strings[index] == NULL) FailAllocMessage();
3162                   strcpy(font_strings[index], ps_name);
3163                   UtilTrimBlanks(font_strings[index++]);
3164                   for (font_ptr=(&ps_name[strlen(ps_name)+1]);
3165                         *font_ptr != '\0' &&
3166                         strchr(" ,\t\n\r",*font_ptr) != NULL; font_ptr++) {
3167                   }
3168                } else {
3169                   int dup_len=(dup_ptr == NULL ? 0 : strlen(dup_ptr));
3170 
3171                   if (dup_len > 128) {
3172                      strcpy(&dup_ptr[128-3], "...");
3173                   }
3174                   ok = FALSE;
3175                   *gszMsgBox = '\0';
3176                   if (dup_ptr == NULL) {
3177                      sprintf(gszMsgBox,
3178                            TgLoadString(STID_MISS_FONT_SPEC_IN_XDEF),
3179                            TOOL_NAME, "AdditionalFonts");
3180                   } else if (font_ptr == NULL) {
3181                      sprintf(gszMsgBox,
3182                            TgLoadString(STID_INVALID_X_FONT_INFO_IN_XDEF),
3183                            TOOL_NAME, "AdditionalFonts", dup_ptr);
3184                   } else if (rgstry == NULL) {
3185                      sprintf(gszMsgBox,
3186                            TgLoadString(STID_INVALID_X_REG_INFO_IN_XDEF),
3187                            TOOL_NAME, "AdditionalFonts", dup_ptr);
3188                   } else if (ps_name == NULL) {
3189                      sprintf(gszMsgBox,
3190                            TgLoadString(STID_INVALID_PS_INFO_IN_XDEF),
3191                            TOOL_NAME, "AdditionalFonts", dup_ptr);
3192                   } else if (!font_exists) {
3193                      ok = TRUE;
3194                      if (reportMissingFonts) {
3195                         sprintf(gszMsgBox,
3196                               TgLoadCachedString(CSTID_NO_SUCH_FONT), font_ptr);
3197                      }
3198                      for (font_ptr=(&ps_name[strlen(ps_name)+1]);
3199                            *font_ptr != '\0' &&
3200                            strchr(" ,\t\n\r",*font_ptr) != NULL; font_ptr++) {
3201                      }
3202                   }
3203                   if (*gszMsgBox != '\0') {
3204                      fprintf(stderr, "%s\n", gszMsgBox);
3205                   }
3206                }
3207                if (dup_ptr != NULL) free(dup_ptr);
3208                if (!ok) break;
3209             }
3210             if (ok && font_exists) {
3211                num_new_fonts++;
3212                fmly_ptr = (struct TmpFontFmlyRec *)malloc(
3213                      sizeof(struct TmpFontFmlyRec));
3214                if (fmly_ptr == NULL) FailAllocMessage();
3215                memset(fmly_ptr, 0, sizeof(struct TmpFontFmlyRec));
3216                fmly_ptr->next = NULL;
3217                fmly_ptr->prev = last_fmly;
3218                fmly_ptr->font_strings = font_strings;
3219                if (last_fmly == NULL) {
3220                   first_fmly = fmly_ptr;
3221                } else {
3222                   last_fmly->next = fmly_ptr;
3223                }
3224                last_fmly = fmly_ptr;
3225             } else if (!font_exists) {
3226                if (font_strings != NULL) {
3227                   for (i=0; i<MAXFONTSTYLES*3; i++) {
3228                      UtilFree(font_strings[i]);
3229                   }
3230                   free(font_strings);
3231                }
3232             }
3233             if (font_ptr-buf >= len) break;
3234          }
3235       }
3236       free(buf);
3237    }
3238    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"SquareDoubleByteFonts")) !=
3239          NULL) {
3240       char *font_ptr=NULL;
3241 
3242       len = strlen(c_ptr);
3243       buf = (char*)malloc((len+1)*sizeof(char));
3244       if (buf == NULL) FailAllocMessage();
3245       strcpy(buf, c_ptr);
3246       for (font_ptr=buf; *font_ptr != '\0' &&
3247             strchr(" ,\t\n\r",*font_ptr) != NULL; font_ptr++) {
3248       }
3249       if (font_ptr != NULL && *font_ptr != '\0') {
3250          int ok=TRUE, index=0, font_exists=FALSE;
3251          char **font_strings=NULL;
3252          struct TmpFontFmlyRec *fmly_ptr=NULL;
3253 
3254          while (ok && font_ptr != NULL && *font_ptr != '\0') {
3255             font_strings = (char**)malloc((MAXFONTSTYLES*3)*sizeof(char *));
3256             if (font_strings == NULL) FailAllocMessage();
3257             memset(font_strings, 0, (MAXFONTSTYLES*3)*sizeof(char*));
3258             for (i=0, index=0; i<MAXFONTSTYLES; i++) {
3259                char *rgstry=NULL, *ps_name=NULL, *dup_ptr;
3260 
3261                dup_ptr = (font_ptr == NULL ? NULL : UtilStrDup(font_ptr));
3262                if ((font_ptr=strtok(font_ptr,",\t\n\r")) != NULL &&
3263                      (rgstry=strtok(NULL,",\t\n\r")) != NULL &&
3264                      (ps_name=strtok(NULL," ,\t\n\r")) != NULL &&
3265                      (font_exists=DoesFontExist(font_ptr,TRUE)) != FALSE) {
3266                   font_strings[index] = (char*)malloc(MAXSTRING*sizeof(char));
3267                   if (font_strings[index] == NULL) FailAllocMessage();
3268                   strcpy(font_strings[index], font_ptr);
3269                   UtilTrimBlanks(font_strings[index++]);
3270                   font_strings[index] = (char*)malloc(MAXSTRING*sizeof(char));
3271                   if (font_strings[index] == NULL) FailAllocMessage();
3272                   strcpy(font_strings[index], rgstry);
3273                   UtilTrimBlanks(font_strings[index++]);
3274                   font_strings[index] = (char*)malloc(MAXSTRING*sizeof(char));
3275                   if (font_strings[index] == NULL) FailAllocMessage();
3276                   strcpy(font_strings[index], ps_name);
3277                   UtilTrimBlanks(font_strings[index++]);
3278                   for (font_ptr=(&ps_name[strlen(ps_name)+1]);
3279                         *font_ptr != '\0' &&
3280                         strchr(" ,\t\n\r",*font_ptr) != NULL; font_ptr++) {
3281                   }
3282                } else {
3283                   int dup_len=(dup_ptr == NULL ? 0 : strlen(dup_ptr));
3284 
3285                   if (dup_len > 128) {
3286                      strcpy(&dup_ptr[128-3], "...");
3287                   }
3288                   ok = FALSE;
3289                   *gszMsgBox = '\0';
3290                   if (dup_ptr == NULL) {
3291                      sprintf(gszMsgBox,
3292                            TgLoadString(STID_MISS_FONT_SPEC_IN_XDEF),
3293                            TOOL_NAME, "SquareDoubleByteFonts", dup_ptr);
3294                   } else if (font_ptr == NULL) {
3295                      sprintf(gszMsgBox,
3296                            TgLoadString(STID_INVALID_X_FONT_INFO_IN_XDEF),
3297                            TOOL_NAME, "SquareDoubleByteFonts", dup_ptr);
3298                   } else if (rgstry == NULL) {
3299                      sprintf(gszMsgBox,
3300                            TgLoadString(STID_INVALID_X_REG_INFO_IN_XDEF),
3301                            TOOL_NAME, "SquareDoubleByteFonts", dup_ptr);
3302                   } else if (ps_name == NULL) {
3303                      sprintf(gszMsgBox,
3304                            TgLoadString(STID_INVALID_PS_INFO_IN_XDEF),
3305                            TOOL_NAME, "SquareDoubleByteFonts", dup_ptr);
3306                   } else if (!font_exists) {
3307                      ok = TRUE;
3308                      if (reportMissingFonts) {
3309                         sprintf(gszMsgBox,
3310                               TgLoadCachedString(CSTID_NO_SUCH_FONT), font_ptr);
3311                      }
3312                      for (font_ptr=(&ps_name[strlen(ps_name)+1]);
3313                            *font_ptr != '\0' &&
3314                            strchr(" ,\t\n\r",*font_ptr) != NULL; font_ptr++) {
3315                      }
3316                   }
3317                   if (*gszMsgBox != '\0') {
3318                      fprintf(stderr, "%s\n", gszMsgBox);
3319                   }
3320                }
3321                if (dup_ptr != NULL) free(dup_ptr);
3322                if (!ok) break;
3323             }
3324             if (ok && font_exists) {
3325                num_new_fonts++;
3326                fmly_ptr = (struct TmpFontFmlyRec *)malloc(
3327                      sizeof(struct TmpFontFmlyRec));
3328                if (fmly_ptr == NULL) FailAllocMessage();
3329                memset(fmly_ptr, 0, sizeof(struct TmpFontFmlyRec));
3330                fmly_ptr->next = NULL;
3331                fmly_ptr->prev = last_fmly;
3332                fmly_ptr->font_strings = font_strings;
3333                fmly_ptr->double_byte = TRUE;
3334                if (last_fmly == NULL) {
3335                   first_fmly = fmly_ptr;
3336                } else {
3337                   last_fmly->next = fmly_ptr;
3338                }
3339                last_fmly = fmly_ptr;
3340             } else if (!font_exists) {
3341                if (font_strings != NULL) {
3342                   for (i=0; i<MAXFONTSTYLES*3; i++) {
3343                      UtilFree(font_strings[i]);
3344                   }
3345                   free(font_strings);
3346                }
3347             }
3348             if (font_ptr-buf >= len) break;
3349          }
3350       }
3351       free(buf);
3352       got_double_fonts = TRUE;
3353    }
3354    if (num_new_fonts > 0 && first_fmly != NULL) {
3355       /* setup fontInfoStr[] */
3356       SetupFontInfoStr(num_new_fonts, first_fmly);
3357    }
3358    if (fontFamilies == NULL) {
3359       fontFamilies =
3360             (struct FontFmlyRec *)malloc(numFonts*sizeof(struct FontFmlyRec));
3361       if (fontFamilies == NULL) FailAllocMessage();
3362       memset(fontFamilies, 0, numFonts*sizeof(struct FontFmlyRec));
3363       fontInfoStr = (char**)malloc(numFonts*MAXFONTSTYLES*3*sizeof(char*));
3364       fontMenuStr = (char**)malloc(numFonts*sizeof(char*));
3365       if (fontInfoStr == NULL || fontMenuStr == NULL) FailAllocMessage();
3366       memset(fontInfoStr, 0, numFonts*MAXFONTSTYLES*3*sizeof(char*));
3367       memset(fontMenuStr, 0, numFonts*sizeof(char*));
3368    }
3369    altFontInfoStr = (char**)malloc(MAXFONTS*MAXFONTSTYLES*3*sizeof(char*));
3370    if (altFontInfoStr == NULL) FailAllocMessage();
3371    for (j=0; j<MAXFONTS*MAXFONTSTYLES*3; j++) altFontInfoStr[j] = NULL;
3372    i = 0;
3373    fmly_index = 0;
3374    for (fmly_index=0; fmly_index < MAXFONTS; fmly_index++) {
3375       char s[MAXSTRING];
3376       int bitmapped_ps_font=FALSE;
3377       int font_name_len=strlen(initFontInfoStr[i+PS_FONT_NAME]);
3378 
3379       if (*initFontInfoStr[i+PS_FONT_NAME] == '(' &&
3380             initFontInfoStr[i+PS_FONT_NAME][font_name_len-1] == ')') {
3381          /*
3382           * This shouldn't happen because none of the initFontInfoStr
3383           *      should have the bitmapped_ps_font!
3384           */
3385          strcpy(s, &(initFontInfoStr[i+PS_FONT_NAME])[1]);
3386          s[font_name_len-2] = '\0';
3387          strcpy(initFontInfoStr[i+PS_FONT_NAME], s);
3388          RemovePSFontNameVariations(s);
3389          bitmapped_ps_font = TRUE;
3390       } else {
3391          strcpy(s, initFontInfoStr[i+PS_FONT_NAME]);
3392          RemovePSFontNameVariations(s);
3393       }
3394       fontMenuStr[fmly_index] = (char*)malloc((strlen(s)+1)*sizeof(char));
3395       if (fontMenuStr[fmly_index] == NULL) FailAllocMessage();
3396       strcpy(fontMenuStr[fmly_index], s );
3397       for (style_index=0; style_index < MAXFONTSTYLES; style_index++) {
3398          if (hasAlternateDefaultFonts && (c_ptr=XGetDefault(mainDisplay,
3399                TOOL_NAME, initFontInfoStr[i+PS_FONT_NAME])) != NULL) {
3400             char *ps_font_name=strchr(c_ptr, ',');
3401 
3402             if (ps_font_name != NULL) *ps_font_name++ = '\0';
3403 
3404             if (strstr(c_ptr, "%d") != NULL) {
3405                altFontInfoStr[i] = UtilStrDup(c_ptr);
3406                if (altFontInfoStr[i] == NULL) FailAllocMessage();
3407                fontInfoStr[i] = altFontInfoStr[i];
3408             } else {
3409                fprintf(stderr, TgLoadString(STID_ERR_PROCESS_FONT_USE_ALT),
3410                      TOOL_NAME, initFontInfoStr[i+PS_FONT_NAME], c_ptr,
3411                      fontNamePrefix, initFontInfoStr[i],
3412                      initFontInfoStr[i+X_FONT_SUFFIX]);
3413                fprintf(stderr, "\n");
3414                fontInfoStr[i] = initFontInfoStr[i];
3415             }
3416             i++;
3417             fontInfoStr[i] = initFontInfoStr[i];
3418             i++;
3419             if (ps_font_name != NULL) {
3420                altFontInfoStr[i] = UtilStrDup(ps_font_name);
3421                if (altFontInfoStr[i] == NULL) FailAllocMessage();
3422                fontInfoStr[i] = altFontInfoStr[i];
3423             } else {
3424                fontInfoStr[i] = initFontInfoStr[i];
3425             }
3426             i++;
3427          } else {
3428             fontInfoStr[i] = initFontInfoStr[i]; i++;
3429             if (fmly_index == FONT_TIM || fmly_index == FONT_COU ||
3430                   fmly_index == FONT_HEL || fmly_index == FONT_CEN) {
3431                fontInfoStr[i] = defaultLatin1FontCharEncoding; i++;
3432             } else {
3433                fontInfoStr[i] = initFontInfoStr[i]; i++;
3434             }
3435             fontInfoStr[i] = initFontInfoStr[i]; i++;
3436          }
3437       }
3438       fontFamilies[fmly_index].fr[STYLE_NR].next =
3439             fontFamilies[fmly_index].fr[STYLE_BR].next =
3440             fontFamilies[fmly_index].fr[STYLE_NI].next =
3441             fontFamilies[fmly_index].fr[STYLE_BI].next = NULL;
3442       fontFamilies[fmly_index].fr[STYLE_NR].xfs =
3443             fontFamilies[fmly_index].fr[STYLE_BR].xfs =
3444             fontFamilies[fmly_index].fr[STYLE_NI].xfs =
3445             fontFamilies[fmly_index].fr[STYLE_BI].xfs = NULL;
3446       fontFamilies[fmly_index].bitmapped_ps_font = bitmapped_ps_font;
3447       *fontFamilies[fmly_index].choice_char = '\0';
3448    }
3449    defaultSingleByteFont = FONT_TIM;
3450    if (got_double_fonts) {
3451       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"DefaultSingleByteFont")) !=
3452             NULL) {
3453          for (i=0; i < numFonts; i++) {
3454             if (UtilStrICmp(c_ptr, fontMenuStr[i]) == 0) {
3455                if (IsFontDoubleByte(i)) {
3456                   fprintf(stderr,
3457                         TgLoadString(STID_INVALID_SB_FONT_USE_DB_FONT),
3458                         TOOL_NAME, "DefaultSingleByteFont", c_ptr);
3459                   fprintf(stderr, "\n");
3460                } else {
3461                   defaultSingleByteFont = i;
3462                }
3463                break;
3464             }
3465          }
3466       }
3467    }
3468 }
3469 
3470 /* do not translate -- program constants */
3471 static char *gaszFontStyles[]={ "Roman", "Bold", "Italic", "BoldItalic", NULL };
3472 static char *gaszFontJusts[]={ "Left", "Center", "Right", NULL };
3473 
3474 #ifndef _NO_LOCALE_SUPPORT
3475 #ifdef ENABLE_NLS
3476 static
InitABasicFontSet(pFontSet,ppszFontSetName,opt_name,pnFontWidth,pnFontAsc,pnFontDes,pnFontHeight,def_font_name)3477 void InitABasicFontSet(pFontSet, ppszFontSetName, opt_name, pnFontWidth,
3478       pnFontAsc, pnFontDes, pnFontHeight, def_font_name)
3479    XFontSet *pFontSet;
3480    char **ppszFontSetName, *opt_name, *def_font_name;
3481    int *pnFontWidth, *pnFontAsc, *pnFontDes, *pnFontHeight;
3482 {
3483    char *c_ptr=NULL;
3484 
3485    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, opt_name)) != NULL) {
3486       if (UtilStrICmp(c_ptr, "none") == 0) {
3487          /* don't attempt to call XCreateFontSet() */
3488       } else {
3489          char **missing_charsets=NULL, *default_string=NULL;
3490          int num_missing_charsets=0;
3491          XFontSet xfset=NULL;
3492 
3493          *ppszFontSetName = UtilStrDup(c_ptr);
3494          if (*ppszFontSetName == NULL) FailAllocMessage();
3495          xfset = XCreateFontSet(mainDisplay, *ppszFontSetName,
3496                &missing_charsets, &num_missing_charsets, &default_string);
3497          if (xfset == NULL) {
3498             fprintf(stderr, TgLoadString(STID_CANNOT_LOAD_FONTSET),
3499                   TOOL_NAME, opt_name, *ppszFontSetName);
3500             fprintf(stderr, "\n");
3501             if (*ppszFontSetName != NULL) free(*ppszFontSetName);
3502             *ppszFontSetName = NULL;
3503          } else {
3504             *pFontSet = xfset;
3505          }
3506       }
3507    } else {
3508       char **missing_charsets=NULL, *default_string=NULL;
3509       int num_missing_charsets=0;
3510       char *fn1=def_font_name;
3511       char *fn2="-*-*-medium-r-*--12-*-*-*-*-*-*-*";
3512       int sz=strlen(fn1)+strlen(fn2)+1;
3513       XFontSet xfset=NULL;
3514 
3515       memset(&xfset, 0, sizeof(XFontSet));
3516 
3517       *ppszFontSetName = (char*)malloc((sz+1)*sizeof(char));
3518       if (*ppszFontSetName == NULL) FailAllocMessage();
3519       sprintf(*ppszFontSetName, "%s,%s", fn1, fn2);
3520       xfset = XCreateFontSet(mainDisplay, *ppszFontSetName,
3521             &missing_charsets, &num_missing_charsets, &default_string);
3522       if (xfset == NULL) {
3523          fprintf(stderr, TgLoadString(STID_CANNOT_LOAD_FONTSET),
3524                TOOL_NAME, opt_name, *ppszFontSetName);
3525          fprintf(stderr, "\n");
3526          if (*ppszFontSetName != NULL) free(*ppszFontSetName);
3527          *ppszFontSetName = NULL;
3528       } else {
3529          *pFontSet = xfset;
3530       }
3531    }
3532    if (*pFontSet != NULL) {
3533       XFontStruct **xfset_list=NULL;
3534       char **font_name_list=NULL;
3535       int n=0;
3536 
3537       n = XFontsOfFontSet(*pFontSet, &xfset_list, &font_name_list);
3538       /* do not translate -- the string is used to measure things */
3539       *pnFontWidth = XmbTextEscapement(*pFontSet, "x", 1);
3540       *pnFontAsc = (*xfset_list)->max_bounds.ascent;
3541       *pnFontDes = (*xfset_list)->max_bounds.descent;
3542       *pnFontHeight = menuFontAsc + menuFontDes;
3543    }
3544 }
3545 #endif /* ENABLE_NLS */
3546 #endif /* ~_NO_LOCALE_SUPPORT */
3547 
3548 static
InitABasicFontPtr(ppFontPtr,ppszFontName,opt_name,def_font_name,pnFontWidth,pnFontAsc,pnFontDes,pnFontHeight,pnFoundInXDefault,msg_font_name)3549 void InitABasicFontPtr(ppFontPtr, ppszFontName, opt_name, def_font_name,
3550       pnFontWidth, pnFontAsc, pnFontDes, pnFontHeight, pnFoundInXDefault,
3551       msg_font_name)
3552    XFontStruct **ppFontPtr;
3553    char **ppszFontName, *opt_name, *def_font_name, *msg_font_name;
3554    int *pnFontWidth, *pnFontAsc, *pnFontDes, *pnFontHeight, *pnFoundInXDefault;
3555 {
3556    XFontStruct *xfs=NULL;
3557    char *c_ptr=NULL;
3558 
3559    *ppFontPtr = NULL;
3560 
3561    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, opt_name)) != NULL) {
3562       /* First try to see if the default is overridden by an X default */
3563       *ppszFontName = UtilStrDup(c_ptr);
3564       if (*ppszFontName == NULL) FailAllocMessage();
3565       xfs = XLoadQueryFont(mainDisplay, *ppszFontName);
3566       if (xfs == NULL) {
3567          fprintf(stderr, TgLoadString(STID_CANNOT_LOAD_FONT),
3568                TOOL_NAME, opt_name, *ppszFontName);
3569          fprintf(stderr, "\n");
3570          if (*ppszFontName != NULL) free(*ppszFontName);
3571          *ppszFontName = NULL;
3572       } else {
3573          *ppFontPtr = xfs;
3574          if (pnFoundInXDefault != NULL && msg_font_name == NULL) {
3575             *pnFoundInXDefault = TRUE;
3576          }
3577       }
3578    } else {
3579       /* Not in X default, now try the default value */
3580       *ppszFontName = UtilStrDup(def_font_name);
3581       if (*ppszFontName == NULL) FailAllocMessage();
3582       xfs = XLoadQueryFont(mainDisplay, *ppszFontName);
3583       if (xfs == NULL) {
3584          if (*ppszFontName != NULL) free(*ppszFontName);
3585          *ppszFontName = NULL;
3586       } else {
3587          *ppFontPtr = xfs;
3588       }
3589    }
3590    if (*ppszFontName == NULL && pnFoundInXDefault != NULL &&
3591          (*pnFoundInXDefault) && msg_font_name != NULL) {
3592       /*
3593        * If it's not in X default and the default value does not work,
3594        *         if MsgFont is valid (from a previous call to this function
3595        *         with opt_name being "MsgFont", use it!
3596        */
3597       *ppszFontName = UtilStrDup(msg_font_name);
3598       if (*ppszFontName == NULL) FailAllocMessage();
3599       xfs = XLoadQueryFont(mainDisplay, *ppszFontName);
3600       if (xfs == NULL) {
3601          fprintf(stderr, TgLoadString(STID_CANNOT_LOAD_FONT),
3602                TOOL_NAME, opt_name, *ppszFontName);
3603          fprintf(stderr, "\n");
3604          if (*ppszFontName != NULL) free(*ppszFontName);
3605          *ppszFontName = NULL;
3606       } else {
3607          *ppFontPtr = xfs;
3608       }
3609    }
3610    if (*ppFontPtr != NULL) {
3611       /* do not translate -- the string is used to measure things */
3612       *pnFontWidth = XTextWidth(*ppFontPtr, "x", 1);
3613       *pnFontAsc = (*ppFontPtr)->max_bounds.ascent;
3614       *pnFontDes = (*ppFontPtr)->max_bounds.descent;
3615       *pnFontHeight = menuFontAsc + menuFontDes;
3616    }
3617 }
3618 
3619 static
InitFontSetsAndBasicFonts()3620 void InitFontSetsAndBasicFonts()
3621 {
3622    int user_msg_font=FALSE;
3623 
3624    boldMsgFontDoubleByte = FALSE;
3625 #ifndef _NO_LOCALE_SUPPORT
3626 #ifdef ENABLE_NLS
3627    if (boldMsgFontSet != NULL) {
3628       char *c_ptr=NULL;
3629 
3630       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"BoldMsgFontDoubleByte")) !=
3631             NULL && UtilStrICmp(c_ptr, "true") == 0) {
3632          boldMsgFontDoubleByte = TRUE;
3633       }
3634    }
3635 #endif /* ENABLE_NLS */
3636 #endif /* ~_NO_LOCALE_SUPPORT */
3637 
3638    menuFontSet = NULL;
3639 #ifndef _NO_LOCALE_SUPPORT
3640 #ifdef ENABLE_NLS
3641    InitABasicFontSet(&menuFontSet, &menuFontSetName, "MenuFontSet",
3642          &menuFontWidth, &menuFontAsc, &menuFontDes, &menuFontHeight,
3643          "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*");
3644 #endif /* ENABLE_NLS */
3645 #endif /* ~_NO_LOCALE_SUPPORT */
3646    if (menuFontSet == NULL) {
3647       menuFontPtr = NULL;
3648       InitABasicFontPtr(&menuFontPtr, &menuFontName, "MenuFont",
3649             "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*", &menuFontWidth,
3650             &menuFontAsc, &menuFontDes, &menuFontHeight, NULL, NULL);
3651    }
3652    msgFontSet = NULL;
3653 #ifndef _NO_LOCALE_SUPPORT
3654 #ifdef ENABLE_NLS
3655    InitABasicFontSet(&msgFontSet, &msgFontSetName, "MsgFontSet",
3656          &msgFontWidth, &msgFontAsc, &msgFontDes, &msgFontHeight,
3657          "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*");
3658 #endif /* ENABLE_NLS */
3659 #endif /* ~_NO_LOCALE_SUPPORT */
3660    if (msgFontSet == NULL) {
3661       msgFontPtr = NULL;
3662       InitABasicFontPtr(&msgFontPtr, &msgFontName, "MsgFont",
3663             "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*", &msgFontWidth,
3664             &msgFontAsc, &msgFontDes, &msgFontHeight, &user_msg_font, NULL);
3665    }
3666    boldMsgFontSet = NULL;
3667 #ifndef _NO_LOCALE_SUPPORT
3668 #ifdef ENABLE_NLS
3669    InitABasicFontSet(&boldMsgFontSet, &boldMsgFontSetName, "BoldMsgFontSet",
3670          &boldMsgFontWidth, &boldMsgFontAsc, &boldMsgFontDes,
3671          &boldMsgFontHeight, "-*-helvetica-bold-r-normal--12-*-*-*-*-*-*-*");
3672 #endif /* ENABLE_NLS */
3673 #endif /* ~_NO_LOCALE_SUPPORT */
3674    if (boldMsgFontSet == NULL) {
3675       boldMsgFontPtr = NULL;
3676       InitABasicFontPtr(&boldMsgFontPtr, &boldMsgFontName, "BoldMsgFont",
3677             "-*-helvetica-bold-r-normal--12-*-*-*-*-*-*-*", &boldMsgFontWidth,
3678             &boldMsgFontAsc, &boldMsgFontDes, &boldMsgFontHeight,
3679             &user_msg_font, msgFontName);
3680    }
3681    italicMsgFontSet = NULL;
3682 #ifndef _NO_LOCALE_SUPPORT
3683 #ifdef ENABLE_NLS
3684    InitABasicFontSet(&italicMsgFontSet, &italicMsgFontSetName,
3685          "ItalicMsgFontSet", &italicMsgFontWidth, &italicMsgFontAsc,
3686          &italicMsgFontDes, &italicMsgFontHeight,
3687          "-*-helvetica-medium-o-normal--12-*-*-*-*-*-*-*");
3688 #endif /* ENABLE_NLS */
3689 #endif /* ~_NO_LOCALE_SUPPORT */
3690    if (italicMsgFontSet == NULL) {
3691       italicMsgFontPtr = NULL;
3692       InitABasicFontPtr(&italicMsgFontPtr, &italicMsgFontName, "ItalicMsgFont",
3693             "-*-helvetica-medium-o-normal--12-*-*-*-*-*-*-*",
3694             &italicMsgFontWidth, &italicMsgFontAsc, &italicMsgFontDes,
3695             &italicMsgFontHeight, &user_msg_font, msgFontName);
3696    }
3697    boldItalicMsgFontSet = NULL;
3698 #ifndef _NO_LOCALE_SUPPORT
3699 #ifdef ENABLE_NLS
3700    InitABasicFontSet(&boldItalicMsgFontSet, &boldItalicMsgFontSetName,
3701          "BoldItalicMsgFontSet", &boldItalicMsgFontWidth, &boldItalicMsgFontAsc,
3702          &boldItalicMsgFontDes, &boldItalicMsgFontHeight,
3703          "-*-helvetica-bold-o-normal--12-*-*-*-*-*-*-*");
3704 #endif /* ENABLE_NLS */
3705 #endif /* ~_NO_LOCALE_SUPPORT */
3706    if (boldItalicMsgFontSet == NULL) {
3707       boldItalicMsgFontPtr = NULL;
3708       InitABasicFontPtr(&boldItalicMsgFontPtr, &boldItalicMsgFontName,
3709             "BoldItalicMsgFont", "-*-helvetica-bold-o-normal--12-*-*-*-*-*-*-*",
3710             &boldItalicMsgFontWidth, &boldItalicMsgFontAsc,
3711             &boldItalicMsgFontDes, &boldItalicMsgFontHeight, &user_msg_font,
3712             msgFontName);
3713    }
3714 }
3715 
InitFonts()3716 void InitFonts()
3717 {
3718    int i=0, ruler_font_size=0;
3719    char *c_ptr=NULL, *buf=NULL, buf1[MAXSTRING];
3720    struct FontSizeRec *fs_ptr=NULL;
3721    XFontStruct *xfs=NULL;
3722 
3723    memset(&gstSavedFontInfo, 0, sizeof(struct PushedFontRec));
3724 
3725    rotatedVertFontImage = NULL;
3726    vertFontBitmap = rotatedVertFontBitmap = None;
3727    vertFontBitmapW = vertFontBitmapH = 0;
3728 
3729    debugScalableFonts = FALSE;
3730    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"DebugScalableFonts")) !=
3731          NULL && UtilStrICmp(c_ptr, "true") == 0) {
3732       debugScalableFonts = TRUE;
3733    }
3734    defaultFontSize = DEFAULT_FONT_SIZE;
3735    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"DefaultFontSize")) != NULL) {
3736       if ((defaultFontSize=atoi(c_ptr)) <= 0) {
3737          defaultFontSize = DEFAULT_FONT_SIZE;
3738          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
3739                TOOL_NAME, "DefaultFontSize", c_ptr, DEFAULT_FONT_SIZE);
3740          fprintf(stderr, "\n");
3741       }
3742    }
3743    strcpy(fontNamePrefix, "-*");
3744    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"FontNamePrefix")) != NULL) {
3745       strcpy(fontNamePrefix, c_ptr);
3746    }
3747    strcpy(defaultLatin1FontCharEncoding, "iso8859-1");
3748    if ((c_ptr=
3749          XGetDefault(mainDisplay,TOOL_NAME,"DefaultLatin1FontCharEncoding")) !=
3750          NULL) {
3751       strcpy(defaultLatin1FontCharEncoding, c_ptr);
3752    }
3753    showFontSizeInPoints = FALSE;
3754    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ShowFontSizeInPoints")) !=
3755          NULL && UtilStrICmp(c_ptr, "true") == 0) {
3756       showFontSizeInPoints = TRUE;
3757    }
3758    fontSzUnits = NULL;
3759    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"FontSizes")) != NULL) {
3760       char *size_ptr;
3761       int allocated=50, ok=TRUE;
3762 
3763       numFontSizes = 0;
3764       fontSzUnits = (int*)malloc(allocated*sizeof(int));
3765       if (fontSzUnits == NULL) FailAllocMessage();
3766       sizeMenuStr = (char**)malloc(allocated*sizeof(char*));
3767       if (sizeMenuStr == NULL) FailAllocMessage();
3768       buf = UtilStrDup(c_ptr);
3769       if (buf == NULL) FailAllocMessage();
3770       if ((size_ptr=strtok(buf," ,\t\n\r")) != NULL) {
3771          while (ok && size_ptr != NULL) {
3772             int size=0, sz_unit=0;
3773             char *psz=NULL, saved_ch='\0';
3774 
3775             UtilStrLower(size_ptr);
3776             /* do not translate -- program constants */
3777             if ((psz=strstr(size_ptr, "pt")) != NULL) {
3778                saved_ch = *psz;
3779                *psz = '\0';
3780                size = atoi(size_ptr);
3781                sz_unit = PointSizeToSzUnit(size);
3782                *psz = saved_ch;
3783             } else {
3784                size = atoi(size_ptr);
3785                sz_unit = FontSizeToSzUnit(size);
3786             }
3787             if (size <= 0 || size>=1000) {
3788                ok = FALSE;
3789                break;
3790             }
3791             if (numFontSizes >= allocated) {
3792                allocated += 50;
3793                fontSzUnits = (int*)realloc(fontSzUnits, allocated*sizeof(int));
3794                sizeMenuStr = (char**)realloc(sizeMenuStr,
3795                      allocated*sizeof(char*));
3796             }
3797             sizeMenuStr[numFontSizes] = (char*)malloc(40*sizeof(char));
3798             if (sizeMenuStr[numFontSizes] == NULL) FailAllocMessage();
3799             if (showFontSizeInPoints) {
3800                sprintf(sizeMenuStr[numFontSizes], "%3d pts",
3801                      SzUnitToPointSize(sz_unit));
3802             } else {
3803                sprintf(sizeMenuStr[numFontSizes], "%3d",
3804                      SzUnitToFontSize(sz_unit));
3805             }
3806             fontSzUnits[numFontSizes++] = sz_unit;
3807             size_ptr = strtok(NULL, " ,\t\n\r");
3808          }
3809       }
3810       UtilFree(buf);
3811       if (!ok || numFontSizes <= 0) {
3812          for (i=0; i < numFontSizes; i++) free(sizeMenuStr[i]);
3813          free(sizeMenuStr);
3814          sizeMenuStr = NULL;
3815          free(fontSzUnits);
3816          fontSzUnits = NULL;
3817          numFontSizes = 0;
3818          fprintf(stderr, TgLoadString(STID_ERR_PROCESS_SIZE_USE_DEF_SIZE),
3819                TOOL_NAME, "FontSizes");
3820          fprintf(stderr, "\n");
3821       }
3822    }
3823    if (fontSzUnits == NULL) {
3824       numFontSizes = (MAXFONTSIZES<<1)-1;
3825       fontSzUnits = (int*)malloc(numFontSizes*sizeof(int));
3826       if (fontSzUnits == NULL) FailAllocMessage();
3827       sizeMenuStr = (char**)malloc(numFontSizes*sizeof(char*));
3828       if (sizeMenuStr == NULL) FailAllocMessage();
3829       for (i=0; i<numFontSizes; i++) {
3830          char *psz=initSizeMenuStr[i];
3831 
3832          fontSzUnits[i] = FontSizeToSzUnit(atoi(psz));
3833          sizeMenuStr[i] = (char*)malloc(40*sizeof(char));
3834          if (sizeMenuStr[i] == NULL) FailAllocMessage();
3835          if (showFontSizeInPoints) {
3836             sprintf(sizeMenuStr[i], "%3d pts",
3837                   SzUnitToPointSize(FontSizeToSzUnit(atoi(psz))));
3838          } else {
3839             strcpy(sizeMenuStr[i], psz);
3840          }
3841       }
3842    }
3843    hasAlternateDefaultFonts = FALSE;
3844    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"HasAlternateDefaultFonts")) !=
3845          NULL && UtilStrICmp(c_ptr, "true") == 0) {
3846       hasAlternateDefaultFonts = TRUE;
3847    }
3848 #ifdef _TGIF_DBG
3849    reportMissingFonts = TRUE;
3850    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ReportMissingFonts")) !=
3851          NULL && UtilStrICmp(c_ptr, "false") == 0) {
3852       reportMissingFonts = FALSE;
3853    }
3854 #else /* ~ _TGIF_DBG */
3855    reportMissingFonts = FALSE;
3856    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ReportMissingFonts")) !=
3857          NULL && UtilStrICmp(c_ptr, "true") == 0) {
3858       reportMissingFonts = TRUE;
3859    }
3860 #endif /* _TGIF_DBG */
3861    InitDontReencode(NULL);
3862    InitAdditionalFonts();
3863    InitPSFontAliases();
3864    InitPSFontCharSubs();
3865 
3866    curFont = FONT_COU;
3867    curStyle = STYLE_NR;
3868    curSzUnit = FontSizeToSzUnit(14);
3869 
3870    ruler_font_size = 10;
3871    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "RulerFontSize")) != NULL) {
3872       ruler_font_size = atoi(c_ptr);
3873       if (ruler_font_size <= 0) {
3874          ruler_font_size = defaultFontSize;
3875          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
3876                TOOL_NAME, "RulerFontSize", c_ptr, ruler_font_size);
3877          fprintf(stderr, "\n");
3878       }
3879    }
3880    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "InitialFontDPI")) != NULL) {
3881       fprintf(stderr, TgLoadString(STID_OBSOLETE_XDEF_USE_ALT),
3882             TOOL_NAME, "InitialFontDPI", TOOL_NAME, "InitialFontSize");
3883       fprintf(stderr, "\n");
3884    }
3885    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MsgFontSizeIndex")) != NULL) {
3886       fprintf(stderr, TgLoadString(STID_OBSOLETE_XDEF_USE_ALT),
3887             TOOL_NAME, "MsgFontSizeIndex", TOOL_NAME, "MsgFontSize");
3888       fprintf(stderr, "\n");
3889    }
3890    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "MsgFontSize")) != NULL) {
3891       UtilStrCpyN(buf1, sizeof(buf1), c_ptr);
3892       curSzUnit = FontSizeToSzUnit(atoi(buf1));
3893       if (curSzUnit <= 0) {
3894          curSzUnit = FontSizeToSzUnit(defaultFontSize);
3895          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
3896                TOOL_NAME, "MsgFontSize", buf1, defaultFontSize);
3897          fprintf(stderr, "\n");
3898       }
3899    }
3900    defaultFontPtr = NULL;
3901    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "DefFixedWidthFont")) !=
3902          NULL) {
3903       defaultFontName = UtilStrDup(c_ptr);
3904       if (defaultFontName == NULL) FailAllocMessage();
3905       xfs = XLoadQueryFont(mainDisplay, defaultFontName);
3906       if (xfs == NULL) {
3907          fprintf(stderr, TgLoadString(STID_CANNOT_LOAD_FONT),
3908                TOOL_NAME, "DefFixedWidthFont", defaultFontName);
3909          fprintf(stderr, "\n");
3910          if (defaultFontName != NULL) free(defaultFontName);
3911          defaultFontName = NULL;
3912          defaultFontPtr = NULL;
3913       } else {
3914          defaultFontPtr = xfs;
3915          defaultFontWidth = defaultFontPtr->max_bounds.width;
3916          defaultFontAsc = defaultFontPtr->max_bounds.ascent;
3917          defaultFontDes = defaultFontPtr->max_bounds.descent;
3918          defaultFontHeight = defaultFontAsc + defaultFontDes;
3919       }
3920    }
3921    if (defaultFontPtr == NULL) {
3922       fs_ptr = FindFontInfo(curFont, curStyle, curSzUnit, TRUE);
3923       if (fs_ptr == NULL) {
3924          sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_DEF_MSG_FONT_ABORT),
3925                gszAttemptedFontName);
3926          Error("OpenFont()", gszMsgBox);
3927       }
3928       defaultFontPtr = fs_ptr->xfs;
3929       defaultFontWidth = defaultFontPtr->max_bounds.width;
3930       defaultFontAsc = defaultFontPtr->max_bounds.ascent;
3931       defaultFontDes = defaultFontPtr->max_bounds.descent;
3932       defaultFontHeight = defaultFontAsc + defaultFontDes;
3933    }
3934    if (defaultFontWidth < 1 || defaultFontHeight < 1) {
3935       fprintf(stderr, TgLoadString(STID_WARN_VERY_SMALL_DEF_FONT),
3936             defaultFontWidth, defaultFontHeight);
3937       fprintf(stderr, "\n");
3938       defaultFontWidth = 9;
3939       defaultFontHeight = 14;
3940    }
3941    rulerFontPtr = NULL;
3942    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "DefFixedWidthRulerFont")) !=
3943          NULL) {
3944       rulerFontName = UtilStrDup(c_ptr);
3945       if (rulerFontName == NULL) FailAllocMessage();
3946       xfs = XLoadQueryFont(mainDisplay, rulerFontName);
3947       if (xfs == NULL) {
3948          fprintf(stderr, TgLoadString(STID_CANNOT_LOAD_FONT),
3949                TOOL_NAME, "DefFixedWidthRulerFont", rulerFontName);
3950          fprintf(stderr, "\n");
3951          if (rulerFontName != NULL) free(rulerFontName);
3952          rulerFontName = NULL;
3953          rulerFontPtr = NULL;
3954       } else {
3955          rulerFontPtr = xfs;
3956          rulerFontWidth = rulerFontPtr->max_bounds.width;
3957          rulerFontAsc = rulerFontPtr->max_bounds.ascent;
3958          rulerFontDes = rulerFontPtr->max_bounds.descent;
3959          rulerFontHeight = rulerFontAsc + rulerFontDes;
3960       }
3961    }
3962    if (rulerFontPtr == NULL) {
3963       fs_ptr = FindFontInfo(curFont, curStyle,
3964             FontSizeToSzUnit(ruler_font_size), TRUE);
3965       if (fs_ptr == NULL) {
3966          sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_RULER_FONT_ABORT),
3967                gszAttemptedFontName);
3968          Error("OpenFont()", gszMsgBox);
3969       }
3970       rulerFontPtr = fs_ptr->xfs;
3971       rulerFontWidth = rulerFontPtr->max_bounds.width;
3972       rulerFontAsc = rulerFontPtr->max_bounds.ascent;
3973       rulerFontDes = rulerFontPtr->max_bounds.descent;
3974       rulerFontHeight = rulerFontAsc + rulerFontDes;
3975    }
3976    if (rulerFontWidth < 1 || rulerFontHeight < 1) {
3977       fprintf(stderr, TgLoadString(STID_WARN_VERY_SMALL_RULER_FONT),
3978             rulerFontWidth, rulerFontHeight);
3979       fprintf(stderr, "\n");
3980       rulerFontWidth = 7;
3981       rulerFontHeight = 12;
3982    }
3983    InitFontSetsAndBasicFonts();
3984 
3985    initialFont = curFont;
3986    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "InitialFont")) != NULL) {
3987       for (i = 0; i < numFonts; i++) {
3988          if (strcmp(c_ptr, fontMenuStr[i]) == 0) {
3989             break;
3990          }
3991       }
3992       if (i != numFonts) {
3993          initialFont = curFont = i;
3994       } else {
3995          fprintf(stderr, TgLoadString(STID_CANNOT_SET_INITIAL_FONT_TO), c_ptr);
3996          fprintf(stderr, "\n");
3997       }
3998    }
3999    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"InitialFontStyle")) != NULL) {
4000       for (i = 0; i < MAXFONTSTYLES; i++) {
4001          if (UtilStrICmp(c_ptr, gaszFontStyles[i]) == 0) {
4002             curStyle = i;
4003             break;
4004          }
4005       }
4006       if (i == MAXFONTSTYLES) {
4007          fprintf(stderr, TgLoadString(STID_CANT_SET_INIT_FONTSTYLE_ALT),
4008                c_ptr, "Roman");
4009          fprintf(stderr, "\n");
4010       }
4011    }
4012    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "InitialFontJust")) != NULL) {
4013       for (i = 0; i < MAXJUSTS; i++) {
4014          if (UtilStrICmp(c_ptr, gaszFontJusts[i]) == 0) {
4015             textJust = i;
4016             break;
4017          }
4018       }
4019       if (i == MAXJUSTS) {
4020          fprintf(stderr, TgLoadString(STID_CANT_SET_INIT_FONTJUST_ALT),
4021                c_ptr, "Left");
4022          fprintf(stderr, "\n");
4023       }
4024    }
4025    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"InitialFontSizeIndex")) !=
4026          NULL) {
4027       fprintf(stderr, TgLoadString(STID_OBSOLETE_XDEF_USE_ALT),
4028             TOOL_NAME, "InitialFontSizeIndex", TOOL_NAME, "InitialFontSize");
4029       fprintf(stderr, "\n");
4030    }
4031    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"InitialFontSize")) != NULL) {
4032       UtilStrCpyN(buf1, sizeof(buf1), c_ptr);
4033       UtilStrLower(buf1);
4034       if ((c_ptr=strstr(buf1, "pt")) != NULL) {
4035          char saved_ch=(*c_ptr);
4036 
4037          *c_ptr = '\0';
4038          curSzUnit = PointSizeToSzUnit(atoi(buf1));
4039          *c_ptr = saved_ch;
4040       } else {
4041          curSzUnit = FontSizeToSzUnit(atoi(buf1));
4042       }
4043       if (curSzUnit <= 0) {
4044          curSzUnit = FontSizeToSzUnit(defaultFontSize);
4045          fprintf(stderr, TgLoadString(STID_CANT_SET_INIT_FONTSIZE_ALT),
4046                buf1, defaultFontSize);
4047          fprintf(stderr, "\n");
4048       }
4049    }
4050    curUnderlineOn = FALSE;
4051    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"InitialUnderlineOn"))!=NULL &&
4052          UtilStrICmp(c_ptr, "true") == 0) {
4053       curUnderlineOn = TRUE;
4054    }
4055    curUnderlineYOffset = 2;
4056    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
4057          "InitialUnderlineAmount")) != NULL) {
4058       curUnderlineYOffset = atoi(c_ptr);
4059    }
4060    curOverlineOn = FALSE;
4061    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"InitialOverlineOn"))!=NULL &&
4062          UtilStrICmp(c_ptr, "true") == 0) {
4063       curOverlineOn = TRUE;
4064    }
4065    curOverlineYOffset = (-1);
4066    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
4067          "InitialOverlineAmount")) != NULL) {
4068       curOverlineYOffset = atoi(c_ptr);
4069    }
4070    changePropertiesOfAttrs = FALSE;
4071    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
4072          "ChangePropertiesOfAttrs")) != NULL &&
4073          UtilStrICmp(c_ptr, "true") == 0) {
4074       changePropertiesOfAttrs = TRUE;
4075    }
4076    if (FindFontInfo(curFont, curStyle, curSzUnit, TRUE) == NULL) {
4077       sprintf(gszMsgBox, TgLoadString(STID_CANT_LOAD_INITIAL_FONT),
4078             gszAttemptedFontName, TOOL_NAME, TOOL_NAME, TOOL_NAME);
4079       fprintf(stderr, "%s\n", gszMsgBox);
4080    }
4081 }
4082 
SaveCurFont()4083 void SaveCurFont()
4084 {
4085    gstSavedFontInfo.font = curFont;
4086    gstSavedFontInfo.sz_unit = curSzUnit;
4087    gstSavedFontInfo.style = curStyle;
4088    gstSavedFontInfo.double_byte = canvasFontDoubleByte;
4089    gstSavedFontInfo.double_byte_mod_bytes = canvasFontDoubleByteModBytes;
4090    gstSavedFontInfo.double_byte_vertical = canvasFontDoubleByteVertical;
4091    gstSavedFontInfo.just = textJust;
4092    gstSavedFontInfo.pen = penPat;
4093    gstSavedFontInfo.fill = objFill;
4094    gstSavedFontInfo.trans_pat = transPat;
4095    gstSavedFontInfo.v_space = textVSpace;
4096    gstSavedFontInfo.underline_on = curUnderlineOn;
4097    gstSavedFontInfo.underline_y_offset = curUnderlineYOffset;
4098    gstSavedFontInfo.overline_on = curOverlineOn;
4099    gstSavedFontInfo.overline_y_offset = curOverlineYOffset;
4100 }
4101 
RestoreCurFont()4102 void RestoreCurFont()
4103 {
4104    curFont = gstSavedFontInfo.font;
4105    curSzUnit = gstSavedFontInfo.sz_unit;
4106    curStyle = gstSavedFontInfo.style;
4107    canvasFontDoubleByte = gstSavedFontInfo.double_byte;
4108    canvasFontDoubleByteModBytes = gstSavedFontInfo.double_byte_mod_bytes;
4109    canvasFontDoubleByteVertical = gstSavedFontInfo.double_byte_vertical;
4110    textJust = gstSavedFontInfo.just;
4111    penPat = gstSavedFontInfo.pen;
4112    objFill = gstSavedFontInfo.fill;
4113    transPat = gstSavedFontInfo.trans_pat;
4114    textVSpace = gstSavedFontInfo.v_space;
4115    curUnderlineOn = gstSavedFontInfo.underline_on;
4116    curUnderlineYOffset = gstSavedFontInfo.underline_y_offset;
4117    curOverlineOn = gstSavedFontInfo.overline_on;
4118    curOverlineYOffset = gstSavedFontInfo.overline_y_offset;
4119 
4120    if (!PRTGIF) SetCanvasFont();
4121 }
4122 
4123 static struct PushedFontRec *topPushedFontStk=NULL;
4124 
GetTopFontStk()4125 struct PushedFontRec *GetTopFontStk()
4126 {
4127    return topPushedFontStk;
4128 }
4129 
PushCurFont()4130 struct PushedFontRec *PushCurFont()
4131 {
4132    struct PushedFontRec *pushed_font_ptr=(struct PushedFontRec *)malloc(
4133          sizeof(struct PushedFontRec));
4134 
4135    if (pushed_font_ptr == NULL) FailAllocMessage();
4136 
4137    memset(pushed_font_ptr, 0, sizeof(struct PushedFontRec));
4138    pushed_font_ptr->next = topPushedFontStk;
4139    pushed_font_ptr->font = curFont;
4140    pushed_font_ptr->sz_unit = curSzUnit;
4141    pushed_font_ptr->style = curStyle;
4142    pushed_font_ptr->just = textJust;
4143    pushed_font_ptr->pen = penPat;
4144    pushed_font_ptr->fill = objFill;
4145    pushed_font_ptr->trans_pat = transPat;
4146    pushed_font_ptr->v_space = textVSpace;
4147    pushed_font_ptr->color = colorIndex;
4148    pushed_font_ptr->underline_on = curUnderlineOn;
4149    pushed_font_ptr->underline_y_offset = curUnderlineYOffset;
4150    pushed_font_ptr->overline_on = curOverlineOn;
4151    pushed_font_ptr->overline_y_offset = curOverlineYOffset;
4152    pushed_font_ptr->double_byte = canvasFontDoubleByte;
4153    pushed_font_ptr->double_byte_mod_bytes = canvasFontDoubleByteModBytes;
4154    pushed_font_ptr->double_byte_vertical = canvasFontDoubleByteVertical;
4155    topPushedFontStk = pushed_font_ptr;
4156 
4157    return topPushedFontStk;
4158 }
4159 
PopCurFont()4160 void PopCurFont()
4161 {
4162    struct PushedFontRec *pushed_font_ptr=NULL;
4163 
4164    if (topPushedFontStk == NULL) {
4165       /* debug, do not translate */
4166       FatalUnexpectedError("Empty stack in PopCurFont().", NULL);
4167       return;
4168    }
4169    pushed_font_ptr = topPushedFontStk->next;
4170 
4171    curFont = topPushedFontStk->font;
4172    curSzUnit = topPushedFontStk->sz_unit;
4173    curStyle = topPushedFontStk->style;
4174    textJust = topPushedFontStk->just;
4175    penPat = topPushedFontStk->pen;
4176    objFill = topPushedFontStk->fill;
4177    transPat = topPushedFontStk->trans_pat;
4178    textVSpace = topPushedFontStk->v_space;
4179    colorIndex = topPushedFontStk->color;
4180    curUnderlineOn = topPushedFontStk->underline_on;
4181    curUnderlineYOffset = topPushedFontStk->underline_y_offset;
4182    curOverlineOn = topPushedFontStk->overline_on;
4183    curOverlineYOffset = topPushedFontStk->overline_y_offset;
4184    canvasFontDoubleByte = topPushedFontStk->double_byte;
4185    canvasFontDoubleByteModBytes = topPushedFontStk->double_byte_mod_bytes;
4186    canvasFontDoubleByteVertical = topPushedFontStk->double_byte_vertical;
4187 
4188    free(topPushedFontStk);
4189    topPushedFontStk = pushed_font_ptr;
4190 
4191    if (!PRTGIF) SetCanvasFont();
4192 }
4193 
SetPushedFontValue(which,value)4194 void SetPushedFontValue(which, value)
4195    int which, value;
4196 {
4197    if (topPushedFontStk == NULL) {
4198       if (!editingText) {
4199          /* NewCurText() doesn't call PushCurFont() */
4200          return;
4201       }
4202       /* debug, do not translate */
4203       FatalUnexpectedError("Empty stack in SetPushedFontValue().", NULL);
4204       return;
4205    }
4206    switch(which) {
4207    case PUSH_FONT: topPushedFontStk->font = value; break;
4208    case PUSH_SZ_UNIT: topPushedFontStk->sz_unit = value; break;
4209    case PUSH_STYLE: topPushedFontStk->style = value; break;
4210    case PUSH_JUST: topPushedFontStk->just = value; break;
4211    case PUSH_PEN: topPushedFontStk->pen = value; break;
4212    case PUSH_FILL: topPushedFontStk->fill = value; break;
4213    case PUSH_TRANSPAT: topPushedFontStk->trans_pat = value; break;
4214    case PUSH_VSPACE: topPushedFontStk->v_space = value; break;
4215    case PUSH_COLORINDEX: topPushedFontStk->color = value; break;
4216    case PUSH_UNDERLINE_ON: topPushedFontStk->underline_on = value; break;
4217    case PUSH_UNDERLINE_Y_OFFSET:
4218       topPushedFontStk->underline_y_offset = value;
4219       break;
4220    case PUSH_OVERLINE_ON: topPushedFontStk->overline_on = value; break;
4221    case PUSH_OVERLINE_Y_OFFSET:
4222       topPushedFontStk->overline_y_offset = value;
4223       break;
4224    case PUSH_DOUBLEBYTE: topPushedFontStk->double_byte = value; break;
4225    }
4226 }
4227 
4228 static
AdjTransformedTextBBox(ObjPtr)4229 int AdjTransformedTextBBox(ObjPtr)
4230    struct ObjRec *ObjPtr;
4231    /* a transformed text object has just changed it's font */
4232    /*      property, so its bounding box needs to be adjusted */
4233    /* returns FALSE if font size is invalid and the text will be read_only */
4234    /* returns INVALID if font size is invalid and the text will be read_only */
4235 {
4236    struct XfrmMtrxRec *ctm=ObjPtr->ctm;
4237 
4238    if (ctm == NULL) {
4239       if (UpdTextBBox(ObjPtr)) {
4240          return TRUE;
4241       } else {
4242          return INVALID;
4243       }
4244    }
4245    ObjPtr->ctm = NULL;
4246    if (!UpdTextBBox(ObjPtr)) {
4247       ObjPtr->ctm = ctm;
4248       return FALSE;
4249    }
4250    SetCTM(ObjPtr, ctm);
4251    UpdTextBBox(ObjPtr);
4252    AdjObjSplineVs(ObjPtr);
4253    AdjObjBBox(ObjPtr);
4254    return TRUE;
4255 }
4256 
4257 static
ChangeStrSegFontProp(pStrSeg,which,value)4258 int ChangeStrSegFontProp(pStrSeg, which, value)
4259    StrSegInfo *pStrSeg;
4260    int which, value;
4261 {
4262    int changed=FALSE, font=0, style=0, sz_unit=0, double_byte=FALSE;
4263 
4264    font = pStrSeg->font;
4265    style = pStrSeg->style;
4266    sz_unit = pStrSeg->sz_unit;
4267 
4268    switch (which) {
4269    case PUSH_STYLE:
4270       style = value;
4271       if (pStrSeg->style == style) return FALSE;
4272       break;
4273    case PUSH_SZ_UNIT:
4274       sz_unit = value;
4275       if (pStrSeg->sz_unit == sz_unit) return FALSE;
4276       break;
4277    case PUSH_FONT:
4278       font = value;
4279       if (pStrSeg->font == font) return FALSE;
4280       double_byte = IsFontDoubleByte(font);
4281       if (pStrSeg->double_byte != double_byte) {
4282          return FALSE;
4283       }
4284       break;
4285    case PUSH_UNDERLINE_ON:
4286       if (pStrSeg->underline_on == value) return FALSE;
4287       pStrSeg->underline_on = value;
4288       return TRUE;
4289    case PUSH_OVERLINE_ON:
4290       if (pStrSeg->overline_on == value) return FALSE;
4291       pStrSeg->overline_on = value;
4292       return TRUE;
4293    }
4294    if (FindFontInfo(font, style, sz_unit, TRUE) != NULL) {
4295       switch (which) {
4296       case PUSH_STYLE: pStrSeg->style = style; break;
4297       case PUSH_SZ_UNIT: pStrSeg->sz_unit = sz_unit; break;
4298       case PUSH_FONT:
4299          pStrSeg->font = font;
4300          pStrSeg->double_byte = double_byte;
4301          if (double_byte) {
4302             pStrSeg->double_byte_vertical =
4303                   IsDoubleByteFontVertical(font, style);
4304          } else {
4305             pStrSeg->double_byte_vertical = FALSE;
4306          }
4307          break;
4308       }
4309       changed = TRUE;
4310    }
4311    return changed;
4312 }
4313 
4314 static
ChangeStrBlockFontProp(pStrBlock,which,value)4315 int ChangeStrBlockFontProp(pStrBlock, which, value)
4316    StrBlockInfo *pStrBlock;
4317    int which, value;
4318 {
4319    int changed=FALSE;
4320 
4321    switch (pStrBlock->type) {
4322    case SB_SIMPLE:
4323       return ChangeStrSegFontProp(pStrBlock->seg, which, value);
4324       break;
4325 
4326    case SB_CHAR_SPACE: break;
4327 
4328    case SB_SUPSUB_LEFT:
4329    case SB_SUPSUB_CENTER:
4330    case SB_SUPSUB_RIGHT:
4331       if (pStrBlock->sup != NULL) {
4332          if (ChangeMiniLinesFontProp(pStrBlock->sup, which, value)) {
4333             changed = TRUE;
4334          }
4335       }
4336       if (pStrBlock->sub != NULL) {
4337          if (ChangeMiniLinesFontProp(pStrBlock->sub, which, value)) {
4338             changed = TRUE;
4339          }
4340       }
4341       if (pStrBlock->type == SB_SUPSUB_CENTER) {
4342          /* pStrBlock->seg better not be NULL or it will crash */
4343          if (ChangeStrSegFontProp(pStrBlock->seg, which, value)) {
4344             changed = TRUE;
4345          }
4346       }
4347       break;
4348    }
4349    return changed;
4350 }
4351 
4352 static
ChangeMiniLineFontProp(pMiniLine,which,value)4353 int ChangeMiniLineFontProp(pMiniLine, which, value)
4354    MiniLineInfo *pMiniLine;
4355    int which, value;
4356 {
4357    int changed=FALSE;
4358    StrBlockInfo *pStrBlock=NULL;
4359 
4360    for (pStrBlock=pMiniLine->first_block; pStrBlock != NULL;
4361          pStrBlock=pStrBlock->next) {
4362       if (ChangeStrBlockFontProp(pStrBlock, which, value)) {
4363          changed = TRUE;
4364       }
4365    }
4366    return changed;
4367 }
4368 
ChangeMiniLinesFontProp(minilines,which,value)4369 int ChangeMiniLinesFontProp(minilines, which, value)
4370    MiniLinesInfo *minilines;
4371    int which, value;
4372 {
4373    int changed=FALSE;
4374    MiniLineInfo *pMiniLine=NULL;
4375 
4376    for (pMiniLine=minilines->first; pMiniLine != NULL;
4377          pMiniLine=pMiniLine->next) {
4378       if (ChangeMiniLineFontProp(pMiniLine, which, value)) {
4379          changed = TRUE;
4380       }
4381    }
4382    return changed;
4383 }
4384 
4385 static
ChangeTextFontProp(text_ptr,which,value)4386 int ChangeTextFontProp(text_ptr, which, value)
4387    struct TextRec *text_ptr;
4388    int which, value;
4389 {
4390    if (which == PUSH_UNDERLINE_Y_OFFSET) {
4391       if (text_ptr->underline_y_offset == value) return FALSE;
4392 
4393       text_ptr->underline_y_offset = value;
4394       return TRUE;
4395    }
4396    if (which == PUSH_OVERLINE_Y_OFFSET) {
4397       if (text_ptr->overline_y_offset == value) return FALSE;
4398 
4399       text_ptr->overline_y_offset = value;
4400       return TRUE;
4401    }
4402    return ChangeMiniLinesFontProp(&text_ptr->minilines, which, value);
4403 }
4404 
ChangeObjTextStyle(ObjPtr,StyleIndex)4405 int ChangeObjTextStyle(ObjPtr, StyleIndex)
4406    struct ObjRec *ObjPtr;
4407    int StyleIndex;
4408 {
4409    struct ObjRec *obj_ptr;
4410    int changed=FALSE, obj_changed;
4411 
4412    switch (ObjPtr->type) {
4413    case OBJ_TEXT:
4414       if (ChangeTextFontProp(ObjPtr->detail.t, PUSH_STYLE, StyleIndex)) {
4415          InvalidateTextCache(ObjPtr->detail.t);
4416          UpdTextBBox(ObjPtr);
4417          AdjObjBBox(ObjPtr);
4418          changed = TRUE;
4419       }
4420       break;
4421 
4422    case OBJ_GROUP:
4423    case OBJ_SYM:
4424       obj_changed = FALSE;
4425       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
4426             obj_ptr=obj_ptr->prev) {
4427          if (ChangeObjTextStyle(obj_ptr, StyleIndex)) {
4428             obj_changed = TRUE;
4429          }
4430       }
4431       if (obj_changed) {
4432          changed = TRUE;
4433          AdjObjBBox(ObjPtr);
4434       }
4435       break;
4436    }
4437    if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
4438       struct AttrRec *attr_ptr=ObjPtr->fattr;
4439 
4440       obj_changed = FALSE;
4441       for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
4442          if (ChangeObjTextStyle(attr_ptr->obj, StyleIndex)) {
4443             obj_changed = TRUE;
4444          }
4445       }
4446       if (obj_changed) {
4447          changed = TRUE;
4448          AdjObjBBox(ObjPtr);
4449       }
4450    }
4451    return changed;
4452 }
4453 
ChangeFontStyle(StyleIndex)4454 void ChangeFontStyle(StyleIndex)
4455    int StyleIndex;
4456 {
4457    struct SelRec *sel_ptr;
4458    int ltx, lty, rbx, rby, changed=FALSE, saved_style=curStyle;
4459 
4460    if (StyleIndex == INVALID) return;
4461 
4462    if (topSel == NULL || stickyMenuSelection) {
4463       int saved_sz_unit=curSzUnit;
4464 
4465       if (!(curChoice == DRAWTEXT && textCursorShown)) {
4466          TieLooseEnds();
4467       }
4468       curStyle = StyleIndex;
4469       if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
4470          curSzUnit = GetCurSzUnit();
4471       }
4472       allowFontFaceSubstitution = FALSE;
4473       SetCanvasFont();
4474       allowFontFaceSubstitution = TRUE;
4475       if (canvasFontSize == INVALID) {
4476          char buf[MAXSTRING];
4477 
4478          GetCurFontMsg(buf, NULL);
4479          curStyle = saved_style;
4480          if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
4481             curSzUnit = saved_sz_unit;
4482          }
4483          SetCanvasFont();
4484          sprintf(gszMsgBox, TgLoadString(STID_FONT_NOT_AVAILABLE), buf);
4485          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4486       } else if (SzUnitToFontSize(curSzUnit) != canvasFontSize) {
4487          if (showFontSizeInPoints) {
4488             sprintf(gszMsgBox, TgLoadString(STID_CANT_CHANGE_SIZEPT_TO_USE_ALT),
4489                   SzUnitToPointSize(curSzUnit),
4490                   SzUnitToPointSize(FontSizeToSzUnit(canvasFontSize)));
4491          } else {
4492             sprintf(gszMsgBox, TgLoadString(STID_CANT_CHANGE_SIZE_TO_USE_ALT),
4493                   SzUnitToFontSize(curSzUnit), canvasFontSize);
4494          }
4495          curSzUnit = FontSizeToSzUnit(canvasFontSize);
4496          if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
4497             PutCurSzUnit(curSzUnit);
4498          }
4499          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4500       } else if (curChoice == DRAWTEXT && textCursorShown &&
4501             editTextSize != 0) {
4502          PutCurSzUnit(curSzUnit);
4503       }
4504       if (curChoice == DRAWTEXT && textCursorShown) {
4505          if (ChangeEditTextProperty(PROP_MASK_TEXT_STYLE, StyleIndex)) {
4506             curTextModified = TRUE;
4507             UpdCurTextBBox();
4508             RedrawCurText();
4509             SetFileModified(TRUE);
4510             if (cycleThroughChoice) {
4511                SetPushedFontValue(PUSH_STYLE, curStyle);
4512             }
4513          }
4514       } else {
4515          textCursorShown = FALSE;
4516       }
4517       ShowCurFont();
4518       ShowTextSize();
4519       UpdatePinnedMenu(MENU_STYLE);
4520       if (topSel == NULL) return;
4521    }
4522    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
4523 
4524    HighLightReverse();
4525    StartCompositeCmd();
4526    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
4527       PrepareToReplaceAnObj(sel_ptr->obj);
4528       if (ChangeObjTextStyle(sel_ptr->obj, StyleIndex)) {
4529          changed = TRUE;
4530          RecordReplaceAnObj(sel_ptr->obj);
4531       } else {
4532          AbortPrepareCmd(CMD_REPLACE);
4533       }
4534    }
4535    EndCompositeCmd();
4536 
4537    if (changed) {
4538       UpdSelBBox();
4539       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
4540             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
4541             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
4542             selRbY+GRID_ABS_SIZE(1));
4543       SetFileModified(TRUE);
4544    }
4545    HighLightForward();
4546 }
4547 
ChangeObjTextJust(ObjPtr,JustIndex)4548 int ChangeObjTextJust(ObjPtr, JustIndex)
4549    struct ObjRec *ObjPtr;
4550    int JustIndex;
4551 {
4552    struct ObjRec *obj_ptr;
4553    int changed=FALSE, obj_changed;
4554 
4555    switch (ObjPtr->type) {
4556    case OBJ_TEXT:
4557       if (ObjPtr->detail.t->minilines.just != JustIndex) {
4558          ObjPtr->detail.t->minilines.just = JustIndex;
4559          UpdTextBBox(ObjPtr);
4560 
4561          if (ObjPtr->detail.t->cached_bitmap != None) {
4562             XFreePixmap(mainDisplay,ObjPtr->detail.t->cached_bitmap);
4563          }
4564          ObjPtr->detail.t->cached_zoom = 0;
4565          ObjPtr->detail.t->cached_bitmap = None;
4566 
4567          AdjObjSplineVs(ObjPtr);
4568          changed = TRUE;
4569       }
4570       break;
4571 
4572    case OBJ_GROUP:
4573    case OBJ_SYM:
4574       obj_changed = FALSE;
4575       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
4576             obj_ptr=obj_ptr->prev) {
4577          if (ChangeObjTextJust(obj_ptr, JustIndex)) {
4578             obj_changed = TRUE;
4579          }
4580       }
4581       if (obj_changed) {
4582          changed = TRUE;
4583          AdjObjBBox(ObjPtr);
4584       }
4585       break;
4586    }
4587    if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
4588       struct AttrRec *attr_ptr=ObjPtr->fattr;
4589 
4590       obj_changed = FALSE;
4591       for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
4592          if (ChangeObjTextJust(attr_ptr->obj, JustIndex)) {
4593             obj_changed = TRUE;
4594          }
4595       }
4596       if (obj_changed) {
4597          changed = TRUE;
4598          AdjObjBBox(ObjPtr);
4599       }
4600    }
4601    return changed;
4602 }
4603 
ChangeFontJust(JustIndex)4604 void ChangeFontJust(JustIndex)
4605    int JustIndex;
4606 {
4607    struct SelRec *sel_ptr;
4608    int ltx, lty, rbx, rby, changed=FALSE;
4609 
4610    if (JustIndex == INVALID) return;
4611 
4612    if (topSel == NULL || stickyMenuSelection) {
4613       if (!(curChoice == DRAWTEXT && textCursorShown)) {
4614          TieLooseEnds();
4615       }
4616       textJust = JustIndex;
4617       ShowJust();
4618       UpdatePinnedMenu(MENU_STYLE);
4619       if (curChoice == DRAWTEXT && textCursorShown) {
4620          if (ChangeObjTextJust(curTextObj, JustIndex)) {
4621             curTextModified = TRUE;
4622             UpdCurTextBBox();
4623             SetFileModified(TRUE);
4624             ClearAndRedrawDrawWindow();
4625             if (cycleThroughChoice) {
4626                SetPushedFontValue(PUSH_JUST, textJust);
4627             }
4628          }
4629       } else {
4630          textCursorShown = FALSE;
4631       }
4632       if (topSel == NULL) return;
4633    }
4634    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
4635 
4636    HighLightReverse();
4637    StartCompositeCmd();
4638    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
4639       PrepareToReplaceAnObj(sel_ptr->obj);
4640       if (ChangeObjTextJust(sel_ptr->obj, JustIndex)) {
4641          changed = TRUE;
4642          RecordReplaceAnObj(sel_ptr->obj);
4643       } else {
4644          AbortPrepareCmd(CMD_REPLACE);
4645       }
4646    }
4647    EndCompositeCmd();
4648 
4649    if (changed) {
4650       UpdSelBBox();
4651       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
4652             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
4653             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
4654             selRbY+GRID_ABS_SIZE(1));
4655       SetFileModified(TRUE);
4656    }
4657    HighLightForward();
4658 }
4659 
ChangeObjTextUnderline(ObjPtr,UnderlineIndex)4660 int ChangeObjTextUnderline(ObjPtr, UnderlineIndex)
4661    struct ObjRec *ObjPtr;
4662    int UnderlineIndex;
4663 {
4664    struct ObjRec *obj_ptr;
4665    int changed=FALSE, obj_changed=FALSE;
4666 
4667    switch (ObjPtr->type) {
4668    case OBJ_TEXT:
4669       if (ChangeTextFontProp(ObjPtr->detail.t, PUSH_UNDERLINE_ON,
4670             UnderlineIndex)) {
4671          InvalidateTextCache(ObjPtr->detail.t);
4672          UpdTextBBox(ObjPtr);
4673          AdjObjBBox(ObjPtr);
4674          changed = TRUE;
4675       }
4676       break;
4677 
4678    case OBJ_GROUP:
4679    case OBJ_SYM:
4680       obj_changed = FALSE;
4681       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
4682             obj_ptr=obj_ptr->prev) {
4683          if (ChangeObjTextUnderline(obj_ptr, UnderlineIndex)) {
4684             obj_changed = TRUE;
4685          }
4686       }
4687       if (obj_changed) {
4688          changed = TRUE;
4689          AdjObjBBox(ObjPtr);
4690       }
4691       break;
4692    }
4693    if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
4694       struct AttrRec *attr_ptr=ObjPtr->fattr;
4695 
4696       obj_changed = FALSE;
4697       for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
4698          if (ChangeObjTextUnderline(attr_ptr->obj, UnderlineIndex)) {
4699             obj_changed = TRUE;
4700          }
4701       }
4702       if (obj_changed) {
4703          changed = TRUE;
4704          AdjObjBBox(ObjPtr);
4705       }
4706    }
4707    return changed;
4708 }
4709 
ChangeFontUnderline(UnderlineIndex)4710 void ChangeFontUnderline(UnderlineIndex)
4711    int UnderlineIndex;
4712 {
4713    struct SelRec *sel_ptr;
4714    int ltx, lty, rbx, rby, changed=FALSE;
4715 
4716    if (UnderlineIndex == INVALID) return;
4717 
4718    if (topSel == NULL || stickyMenuSelection) {
4719       if (!(curChoice == DRAWTEXT && textCursorShown)) {
4720          TieLooseEnds();
4721       }
4722       curUnderlineOn = UnderlineIndex;
4723       if (curChoice == DRAWTEXT && textCursorShown) {
4724          if (ChangeEditTextProperty(PROP_MASK_UNDERLINE_ON,
4725                UnderlineIndex)) {
4726             curTextModified = TRUE;
4727             UpdCurTextBBox();
4728             RedrawCurText();
4729             SetFileModified(TRUE);
4730             if (cycleThroughChoice) {
4731                SetPushedFontValue(PUSH_UNDERLINE_ON, curUnderlineOn);
4732             }
4733          }
4734       } else {
4735          textCursorShown = FALSE;
4736       }
4737       ShowCurFont();
4738       UpdatePinnedMenu(MENU_STYLE);
4739       if (topSel == NULL) return;
4740    }
4741    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
4742 
4743    HighLightReverse();
4744    StartCompositeCmd();
4745    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
4746       PrepareToReplaceAnObj(sel_ptr->obj);
4747       if (ChangeObjTextUnderline(sel_ptr->obj, UnderlineIndex)) {
4748          changed = TRUE;
4749          RecordReplaceAnObj(sel_ptr->obj);
4750       } else {
4751          AbortPrepareCmd(CMD_REPLACE);
4752       }
4753    }
4754    EndCompositeCmd();
4755 
4756    if (changed) {
4757       UpdSelBBox();
4758       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
4759             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
4760             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
4761             selRbY+GRID_ABS_SIZE(1));
4762       SetFileModified(TRUE);
4763    }
4764    HighLightForward();
4765 }
4766 
ChangeObjTextOverline(ObjPtr,OverlineIndex)4767 int ChangeObjTextOverline(ObjPtr, OverlineIndex)
4768    struct ObjRec *ObjPtr;
4769    int OverlineIndex;
4770 {
4771    struct ObjRec *obj_ptr;
4772    int changed=FALSE, obj_changed=FALSE;
4773 
4774    switch (ObjPtr->type) {
4775    case OBJ_TEXT:
4776       if (ChangeTextFontProp(ObjPtr->detail.t, PUSH_OVERLINE_ON,
4777             OverlineIndex)) {
4778          InvalidateTextCache(ObjPtr->detail.t);
4779          UpdTextBBox(ObjPtr);
4780          AdjObjBBox(ObjPtr);
4781          changed = TRUE;
4782       }
4783       break;
4784 
4785    case OBJ_GROUP:
4786    case OBJ_SYM:
4787       obj_changed = FALSE;
4788       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
4789             obj_ptr=obj_ptr->prev) {
4790          if (ChangeObjTextOverline(obj_ptr, OverlineIndex)) {
4791             obj_changed = TRUE;
4792          }
4793       }
4794       if (obj_changed) {
4795          changed = TRUE;
4796          AdjObjBBox(ObjPtr);
4797       }
4798       break;
4799    }
4800    if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
4801       struct AttrRec *attr_ptr=ObjPtr->fattr;
4802 
4803       obj_changed = FALSE;
4804       for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
4805          if (ChangeObjTextOverline(attr_ptr->obj, OverlineIndex)) {
4806             obj_changed = TRUE;
4807          }
4808       }
4809       if (obj_changed) {
4810          changed = TRUE;
4811          AdjObjBBox(ObjPtr);
4812       }
4813    }
4814    return changed;
4815 }
4816 
ChangeFontOverline(OverlineIndex)4817 void ChangeFontOverline(OverlineIndex)
4818    int OverlineIndex;
4819 {
4820    struct SelRec *sel_ptr;
4821    int ltx, lty, rbx, rby, changed=FALSE;
4822 
4823    if (OverlineIndex == INVALID) return;
4824 
4825    if (topSel == NULL || stickyMenuSelection) {
4826       if (!(curChoice == DRAWTEXT && textCursorShown)) {
4827          TieLooseEnds();
4828       }
4829       curOverlineOn = OverlineIndex;
4830       if (curChoice == DRAWTEXT && textCursorShown) {
4831          if (ChangeEditTextProperty(PROP_MASK_OVERLINE_ON,
4832                OverlineIndex)) {
4833             curTextModified = TRUE;
4834             UpdCurTextBBox();
4835             RedrawCurText();
4836             SetFileModified(TRUE);
4837             if (cycleThroughChoice) {
4838                SetPushedFontValue(PUSH_OVERLINE_ON, curOverlineOn);
4839             }
4840          }
4841       } else {
4842          textCursorShown = FALSE;
4843       }
4844       ShowCurFont();
4845       UpdatePinnedMenu(MENU_STYLE);
4846       if (topSel == NULL) return;
4847    }
4848    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
4849 
4850    HighLightReverse();
4851    StartCompositeCmd();
4852    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
4853       PrepareToReplaceAnObj(sel_ptr->obj);
4854       if (ChangeObjTextOverline(sel_ptr->obj, OverlineIndex)) {
4855          changed = TRUE;
4856          RecordReplaceAnObj(sel_ptr->obj);
4857       } else {
4858          AbortPrepareCmd(CMD_REPLACE);
4859       }
4860    }
4861    EndCompositeCmd();
4862 
4863    if (changed) {
4864       UpdSelBBox();
4865       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
4866             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
4867             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
4868             selRbY+GRID_ABS_SIZE(1));
4869       SetFileModified(TRUE);
4870    }
4871    HighLightForward();
4872 }
4873 
RefreshFontStyleMenu(menu)4874 int RefreshFontStyleMenu(menu)
4875    TgMenu *menu;
4876 {
4877    int i, rc=TRUE, num_items=menu->num_items;
4878    TgMenuItem *menuitems=menu->menuitems;
4879 
4880    for (i=0; i < num_items; i++) {
4881       TgMenuItem *menu_item=(&menuitems[i]);
4882       TgMenuItem stMenuItem;
4883 
4884       memset(&stMenuItem, 0, sizeof(TgMenuItem));
4885       stMenuItem.state = TGBS_NORMAL;
4886       if (i < MAXFONTSTYLES) {
4887          stMenuItem.checked = (i == curStyle);
4888          if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_RADIO,
4889                &stMenuItem)) {
4890             rc = FALSE;
4891          }
4892       } else if (i > MAXFONTSTYLES && i < MAXFONTSTYLES+MAXJUSTS+1) {
4893          stMenuItem.checked = (i-MAXFONTSTYLES-1 == textJust);
4894          if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_RADIO,
4895                &stMenuItem)) {
4896             rc = FALSE;
4897          }
4898       } else if (i > MAXFONTSTYLES+MAXJUSTS+1 &&
4899             i < MAXFONTSTYLES+MAXJUSTS+4) {
4900          stMenuItem.checked = (i-MAXFONTSTYLES-MAXJUSTS-2 == curUnderlineOn);
4901          if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_RADIO,
4902                &stMenuItem)) {
4903             rc = FALSE;
4904          }
4905       } else if (i > MAXFONTSTYLES+MAXJUSTS+4) {
4906          stMenuItem.checked = (i-MAXFONTSTYLES-MAXJUSTS-5 == curOverlineOn);
4907          if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_RADIO,
4908                &stMenuItem)) {
4909             rc = FALSE;
4910          }
4911       }
4912    }
4913    return rc;
4914 }
4915 
CreateFontStyleMenu(parent_menu,x,y,menu_info,status_str_xlated)4916 TgMenu *CreateFontStyleMenu(parent_menu, x, y, menu_info, status_str_xlated)
4917    TgMenu *parent_menu;
4918    int x, y;
4919    TgMenuInfo *menu_info;
4920    int status_str_xlated; /* ignored, always 0 */
4921 {
4922    TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
4923 
4924    if (menu != NULL) {
4925       menu->track_menubar = TRUE;
4926       if (!RefreshFontStyleMenu(menu)) {
4927          return TgDestroyMenu(menu, TRUE);
4928       }
4929       menu->refresh_proc = ((RefreshMenuFunc*)RefreshFontStyleMenu);
4930    }
4931    return menu;
4932 }
4933 
StyleMenu(X,Y,TrackMenubar)4934 int StyleMenu(X, Y, TrackMenubar)
4935    int X, Y, TrackMenubar;
4936 {
4937    int rc=INVALID;
4938    TgMenu *menu=(fontStyleMenuInfo.create_proc)(NULL, X, Y, &fontStyleMenuInfo,
4939          INVALID);
4940 
4941    activeMenu = MENU_STYLE;
4942    if (menu != NULL) {
4943       menu->track_menubar = TrackMenubar;
4944 
4945       rc = TgMenuLoop(menu);
4946       TgDestroyMenu(menu, TRUE);
4947    }
4948    return rc;
4949 }
4950 
GetSizeMenuIndex()4951 int GetSizeMenuIndex()
4952 {
4953    int i=0, sz_unit=GetCurSzUnit();
4954 
4955    for (i=0; i < numFontSizes; i++) {
4956       if (fontSzUnits[i] == sz_unit) {
4957          return i;
4958       }
4959    }
4960    return INVALID;
4961 }
4962 
ChangeObjTextSzUnit(ObjPtr,SzUnit)4963 int ChangeObjTextSzUnit(ObjPtr, SzUnit)
4964    struct ObjRec *ObjPtr;
4965    int SzUnit;
4966 {
4967    struct ObjRec *obj_ptr;
4968    int changed=FALSE, obj_changed;
4969 
4970    switch (ObjPtr->type) {
4971    case OBJ_TEXT:
4972       if (ChangeTextFontProp(ObjPtr->detail.t, PUSH_SZ_UNIT, SzUnit)) {
4973          InvalidateTextCache(ObjPtr->detail.t);
4974          UpdTextBBox(ObjPtr);
4975          AdjObjBBox(ObjPtr);
4976          changed = TRUE;
4977       }
4978       break;
4979 
4980    case OBJ_GROUP:
4981    case OBJ_SYM:
4982       obj_changed = FALSE;
4983       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
4984             obj_ptr=obj_ptr->prev) {
4985          if (ChangeObjTextSzUnit(obj_ptr, SzUnit)) {
4986             obj_changed = TRUE;
4987          }
4988       }
4989       if (obj_changed) {
4990          changed = TRUE;
4991          AdjObjBBox(ObjPtr);
4992       }
4993       break;
4994    }
4995    if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
4996       struct AttrRec *attr_ptr=ObjPtr->fattr;
4997 
4998       obj_changed = FALSE;
4999       for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
5000          if (ChangeObjTextSzUnit(attr_ptr->obj, SzUnit)) {
5001             obj_changed = TRUE;
5002          }
5003       }
5004       if (obj_changed) {
5005          changed = TRUE;
5006          AdjObjBBox(ObjPtr);
5007       }
5008    }
5009    return changed;
5010 }
5011 
ChangeFontSize(SizeIndex)5012 void ChangeFontSize(SizeIndex)
5013    int SizeIndex;
5014 {
5015    struct SelRec *sel_ptr;
5016    int ltx, lty, rbx, rby;
5017    int changed=FALSE;
5018    int saved_sz_unit=curSzUnit;
5019 
5020    if (SizeIndex == INVALID) return;
5021 
5022    if (topSel == NULL || stickyMenuSelection) {
5023       if (!(curChoice == DRAWTEXT && textCursorShown)) {
5024          TieLooseEnds();
5025       }
5026       curSzUnit = fontSzUnits[SizeIndex];
5027       changingFontSizeFromRead = FALSE;
5028       allowFontFaceSubstitution = FALSE;
5029       SetCanvasFont();
5030       allowFontFaceSubstitution = TRUE;
5031       changingFontSizeFromRead = TRUE;
5032       if (canvasFontSize == INVALID) {
5033          char buf[MAXSTRING];
5034 
5035          GetCurFontMsg(buf, NULL);
5036          curSzUnit = saved_sz_unit;
5037          SizeIndex = GetSizeMenuIndex();
5038          SetCanvasFont();
5039          sprintf(gszMsgBox, TgLoadString(STID_FONT_NOT_AVAILABLE), buf);
5040          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5041       } else if (SzUnitToFontSize(curSzUnit) != canvasFontSize) {
5042          if (showFontSizeInPoints) {
5043             sprintf(gszMsgBox, TgLoadString(STID_CANT_CHANGE_SIZEPT_TO_USE_ALT),
5044                   SzUnitToPointSize(curSzUnit),
5045                   SzUnitToPointSize(FontSizeToSzUnit(canvasFontSize)));
5046          } else {
5047             sprintf(gszMsgBox, TgLoadString(STID_CANT_CHANGE_SIZE_TO_USE_ALT),
5048                   SzUnitToFontSize(curSzUnit), canvasFontSize);
5049          }
5050          curSzUnit = FontSizeToSzUnit(canvasFontSize);
5051          SizeIndex = GetSizeMenuIndex();
5052          if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
5053             PutCurSzUnit(curSzUnit);
5054          }
5055          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5056       } else if (curChoice == DRAWTEXT && textCursorShown &&
5057             editTextSize != 0) {
5058          PutCurSzUnit(curSzUnit);
5059       }
5060       if (curChoice == DRAWTEXT && textCursorShown) {
5061          if (ChangeEditTextProperty(PROP_MASK_TEXT_SZ_UNIT,
5062                fontSzUnits[SizeIndex])) {
5063             curTextModified = TRUE;
5064             UpdCurTextBBox();
5065             RedrawCurText();
5066             SetFileModified(TRUE);
5067             if (cycleThroughChoice) {
5068                SetPushedFontValue(PUSH_SZ_UNIT, GetCurSzUnit());
5069             }
5070          }
5071       } else {
5072          textCursorShown = FALSE;
5073       }
5074       ShowCurFont();
5075       ShowTextSize();
5076       UpdatePinnedMenu(MENU_SIZE);
5077       if (topSel == NULL) return;
5078    }
5079    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
5080 
5081    HighLightReverse();
5082    StartCompositeCmd();
5083    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
5084       PrepareToReplaceAnObj(sel_ptr->obj);
5085       if (ChangeObjTextSzUnit(sel_ptr->obj, fontSzUnits[SizeIndex])) {
5086          changed = TRUE;
5087          RecordReplaceAnObj(sel_ptr->obj);
5088       } else {
5089          AbortPrepareCmd(CMD_REPLACE);
5090       }
5091    }
5092    EndCompositeCmd();
5093 
5094    if (changed) {
5095       UpdSelBBox();
5096       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
5097             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
5098             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
5099             selRbY+GRID_ABS_SIZE(1));
5100       SetFileModified(TRUE);
5101    }
5102    HighLightForward();
5103 }
5104 
RefreshFontSizeMenu(menu)5105 int RefreshFontSizeMenu(menu)
5106    TgMenu *menu;
5107 {
5108    int i, num_items=menu->num_items, sz_unit=GetCurSzUnit();
5109    TgMenuItem *menuitems=menu->menuitems;
5110 
5111    for (i=0; i < num_items; i++) {
5112       TgMenuItem *menu_item=(&menuitems[i]);
5113       TgMenuItem stMenuItem;
5114 
5115       memset(&stMenuItem, 0, sizeof(TgMenuItem));
5116       stMenuItem.state = TGBS_NORMAL;
5117       stMenuItem.checked = (fontSzUnits[i] == sz_unit);
5118       if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_RADIO,
5119             &stMenuItem)) {
5120          return FALSE;
5121       }
5122    }
5123    return TRUE;
5124 }
5125 
CreateFontSizeMenu(parent_menu,x,y,menu_info,status_str_xlated)5126 TgMenu *CreateFontSizeMenu(parent_menu, x, y, menu_info, status_str_xlated)
5127    TgMenu *parent_menu;
5128    int x, y;
5129    TgMenuInfo *menu_info;
5130    int status_str_xlated; /* ignored, always 0 */
5131 {
5132    int i=0;
5133    TgMenu *menu=NULL;
5134    TgMenuInfo stMenuInfo;
5135    TgMenuItemInfo *item_info=NULL;
5136 
5137    memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
5138    stMenuInfo.items = (TgMenuItemInfo*)malloc(
5139          (numFontSizes+1)*sizeof(TgMenuItemInfo));
5140    if (stMenuInfo.items == NULL) FailAllocMessage();
5141    memset(stMenuInfo.items, 0, (numFontSizes+1)*sizeof(TgMenuItemInfo));
5142    for (item_info=stMenuInfo.items, i=0; i < numFontSizes; item_info++, i++) {
5143       item_info->menu_str = UtilStrDup(sizeMenuStr[i]);
5144       if (item_info->menu_str == NULL) FailAllocMessage();
5145       item_info->shortcut_str = NULL;
5146       if (showFontSizeInPoints) {
5147          sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_FONT_SIZE_TO_PT),
5148                SzUnitToPointSize(fontSzUnits[i]));
5149       } else {
5150          sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_FONT_SIZE_TO),
5151                SzUnitToFontSize(fontSzUnits[i]));
5152       }
5153       item_info->status_str = UtilStrDup(gszMsgBox);
5154       if (item_info->status_str == NULL) FailAllocMessage();
5155       item_info->submenu_info = NULL;
5156       item_info->cmdid = CMDID_CHANGEALLSELFONTSIZE;
5157    }
5158    stMenuInfo.items[numFontSizes].cmdid = INVALID;
5159    stMenuInfo.type |= TGMUTYPE_CANSCROLL;
5160 
5161    /* the status_str has been translated in TgLoadCachedString() */
5162    menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
5163    for (item_info=stMenuInfo.items, i=0; i < numFontSizes; item_info++, i++) {
5164       UtilFree(item_info->status_str);
5165    }
5166    memset(stMenuInfo.items, 0, (numFontSizes+1)*sizeof(TgMenuItemInfo));
5167    free(stMenuInfo.items);
5168    stMenuInfo.items = NULL;
5169    if (menu != NULL) {
5170       for (i=0; i < numFontSizes; i++) {
5171          menu->menuitems[i].menu_str_allocated = TRUE;
5172       }
5173       if (!RefreshFontSizeMenu(menu)) {
5174          return TgDestroyMenu(menu, TRUE);
5175       }
5176       for (i=0; i < numFontSizes; i++) {
5177          if (TgIsMenuItemRadio(menu, i)) {
5178             SetScrollableMenuFirstIndex(menu, i);
5179             break;
5180          }
5181       }
5182       menu->refresh_proc = ((RefreshMenuFunc*)RefreshFontSizeMenu);
5183    }
5184    return menu;
5185 }
5186 
SizeMenu(X,Y,TrackMenubar)5187 int SizeMenu(X, Y, TrackMenubar)
5188    int X, Y, TrackMenubar;
5189 {
5190    int rc=INVALID;
5191    TgMenu *menu=(fontSizeMenuInfo.create_proc)(NULL, X, Y, &fontSizeMenuInfo,
5192          INVALID);
5193 
5194    activeMenu = MENU_SIZE;
5195    if (menu != NULL) {
5196       menu->track_menubar = TrackMenubar;
5197 
5198       rc = TgMenuLoop(menu);
5199       TgDestroyMenu(menu, TRUE);
5200    }
5201    return rc;
5202 }
5203 
ChangeObjTextFont(ObjPtr,FontIndex)5204 int ChangeObjTextFont(ObjPtr, FontIndex)
5205    struct ObjRec *ObjPtr;
5206    int FontIndex;
5207 {
5208    struct ObjRec *obj_ptr;
5209    int changed=FALSE, obj_changed=FALSE;
5210 
5211    switch (ObjPtr->type) {
5212    case OBJ_TEXT:
5213       if (ChangeTextFontProp(ObjPtr->detail.t, PUSH_FONT, FontIndex)) {
5214          InvalidateTextCache(ObjPtr->detail.t);
5215          UpdTextBBox(ObjPtr);
5216          AdjObjBBox(ObjPtr);
5217          changed = TRUE;
5218       }
5219       break;
5220 
5221    case OBJ_GROUP:
5222    case OBJ_SYM:
5223       obj_changed = FALSE;
5224       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
5225             obj_ptr=obj_ptr->prev) {
5226          if (ChangeObjTextFont(obj_ptr, FontIndex)) {
5227             obj_changed = TRUE;
5228          }
5229       }
5230       if (obj_changed) {
5231          changed = TRUE;
5232          AdjObjBBox(ObjPtr);
5233       }
5234       break;
5235    }
5236    if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
5237       struct AttrRec *attr_ptr=ObjPtr->fattr;
5238 
5239       obj_changed = FALSE;
5240       for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
5241          if (ChangeObjTextFont(attr_ptr->obj, FontIndex)) {
5242             obj_changed = TRUE;
5243          }
5244       }
5245       if (obj_changed) {
5246          changed = TRUE;
5247          AdjObjBBox(ObjPtr);
5248       }
5249    }
5250    return changed;
5251 }
5252 
ChangeFont(FontIndex,ForceNewChoice)5253 int ChangeFont(FontIndex, ForceNewChoice)
5254    int FontIndex, ForceNewChoice;
5255 {
5256    struct SelRec *sel_ptr=NULL;
5257    int ltx, lty, rbx, rby, changed=FALSE, saved_font=curFont, rc=TRUE;
5258 
5259    if (FontIndex == INVALID) return FALSE;
5260 
5261    if (topSel == NULL || stickyMenuSelection || ForceNewChoice) {
5262       int saved_sz_unit=curSzUnit;
5263 
5264       if (!(curChoice == DRAWTEXT && textCursorShown)) {
5265          TieLooseEnds();
5266       }
5267       curFont = FontIndex;
5268       if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
5269          curSzUnit = GetCurSzUnit();
5270       }
5271       allowFontFaceSubstitution = FALSE;
5272       SetCanvasFont();
5273       allowFontFaceSubstitution = TRUE;
5274       if (canvasFontSize == INVALID) {
5275          char buf[MAXSTRING];
5276 
5277          GetCurFontMsg(buf, NULL);
5278          curFont = FontIndex = saved_font;
5279          if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
5280             curSzUnit = saved_sz_unit;
5281          }
5282          SetCanvasFont();
5283          sprintf(gszMsgBox, TgLoadString(STID_FONT_NOT_AVAILABLE), buf);
5284          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5285          rc = FALSE;
5286       } else if (SzUnitToFontSize(curSzUnit) != canvasFontSize) {
5287          if (showFontSizeInPoints) {
5288             sprintf(gszMsgBox, TgLoadString(STID_CANT_CHANGE_SIZEPT_TO_USE_ALT),
5289                   SzUnitToPointSize(curSzUnit),
5290                   SzUnitToPointSize(FontSizeToSzUnit(canvasFontSize)));
5291          } else {
5292             sprintf(gszMsgBox, TgLoadString(STID_CANT_CHANGE_SIZE_TO_USE_ALT),
5293                   SzUnitToFontSize(curSzUnit), canvasFontSize);
5294          }
5295          curSzUnit = FontSizeToSzUnit(canvasFontSize);
5296          if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
5297             PutCurSzUnit(curSzUnit);
5298          }
5299          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5300       } else if (curChoice == DRAWTEXT && textCursorShown &&
5301             editTextSize != 0) {
5302          PutCurSzUnit(curSzUnit);
5303       }
5304       if (curChoice == DRAWTEXT && textCursorShown) {
5305          if (ChangeEditTextProperty(PROP_MASK_TEXT_FONT, FontIndex)) {
5306             curTextModified = TRUE;
5307             UpdCurTextBBox();
5308             RedrawCurText();
5309             SetFileModified(TRUE);
5310             if (cycleThroughChoice) {
5311                SetPushedFontValue(PUSH_FONT, curFont);
5312             }
5313          }
5314       } else {
5315          textCursorShown = FALSE;
5316       }
5317       ShowCurFont();
5318       ShowTextSize();
5319       UpdatePinnedMenu(MENU_FONT);
5320       if (topSel == NULL) return rc;
5321    }
5322    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
5323 
5324    HighLightReverse();
5325    StartCompositeCmd();
5326    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
5327       PrepareToReplaceAnObj(sel_ptr->obj);
5328       if (ChangeObjTextFont(sel_ptr->obj, FontIndex)) {
5329          changed = TRUE;
5330          RecordReplaceAnObj(sel_ptr->obj);
5331       } else {
5332          AbortPrepareCmd(CMD_REPLACE);
5333       }
5334    }
5335    EndCompositeCmd();
5336 
5337    if (changed) {
5338       UpdSelBBox();
5339       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
5340             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
5341             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
5342             selRbY+GRID_ABS_SIZE(1));
5343       SetFileModified(TRUE);
5344    }
5345    HighLightForward();
5346 
5347    return rc;
5348 }
5349 
RefreshFontMenu(menu)5350 int RefreshFontMenu(menu)
5351    TgMenu *menu;
5352 {
5353    int i, num_items=menu->num_items;
5354    TgMenuItem *menuitems=menu->menuitems;
5355 
5356    for (i=0; i < num_items; i++) {
5357       TgMenuItem *menu_item=(&menuitems[i]);
5358       TgMenuItem stMenuItem;
5359 
5360       memset(&stMenuItem, 0, sizeof(TgMenuItem));
5361       stMenuItem.state = TGBS_NORMAL;
5362       stMenuItem.checked = (i == curFont);
5363       TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_RADIO,
5364             &stMenuItem);
5365    }
5366    return TRUE;
5367 }
5368 
CreateFontMenu(parent_menu,x,y,menu_info,status_str_xlated)5369 TgMenu *CreateFontMenu(parent_menu, x, y, menu_info, status_str_xlated)
5370    TgMenu *parent_menu;
5371    int x, y;
5372    TgMenuInfo *menu_info;
5373    int status_str_xlated; /* ignored, always 0 */
5374 {
5375    int i=0;
5376    TgMenu *menu=NULL;
5377    TgMenuInfo stMenuInfo;
5378    TgMenuItemInfo *item_info=NULL;
5379 
5380    memcpy(&stMenuInfo, menu_info, sizeof(TgMenuInfo));
5381    stMenuInfo.items = (TgMenuItemInfo*)malloc(
5382          (numFonts+1)*sizeof(TgMenuItemInfo));
5383    if (stMenuInfo.items == NULL) FailAllocMessage();
5384    memset(stMenuInfo.items, 0, (numFonts+1)*sizeof(TgMenuItemInfo));
5385    for (item_info=stMenuInfo.items, i=0; i < numFonts; item_info++, i++) {
5386       item_info->menu_str = UtilStrDup(fontMenuStr[i]);
5387       if (item_info->menu_str == NULL) FailAllocMessage();
5388       item_info->shortcut_str = NULL;
5389       sprintf(gszMsgBox, TgLoadCachedString(CSTID_SET_FONT_TO), fontMenuStr[i]);
5390       item_info->status_str = UtilStrDup(gszMsgBox);
5391       if (item_info->status_str == NULL) FailAllocMessage();
5392       item_info->submenu_info = NULL;
5393       item_info->cmdid = CMDID_CHANGEALLSELFONT;
5394    }
5395    stMenuInfo.items[numFonts].cmdid = INVALID;
5396    stMenuInfo.type |= TGMUTYPE_CANSCROLL;
5397 
5398    /* the status_str has been translated in TgLoadCachedString() */
5399    menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
5400    for (item_info=stMenuInfo.items, i=0; i < numFonts; item_info++, i++) {
5401       UtilFree(item_info->status_str);
5402    }
5403    memset(stMenuInfo.items, 0, (numFonts+1)*sizeof(TgMenuItemInfo));
5404    free(stMenuInfo.items);
5405    stMenuInfo.items = NULL;
5406    if (menu != NULL) {
5407       TgMenuItem *menu_item=NULL;
5408       TgMenuItem stMenuItem;
5409 
5410       menu->track_menubar = TRUE;
5411       menu_item = (&menu->menuitems[curFont]);
5412 
5413       memset(&stMenuItem, 0, sizeof(TgMenuItem));
5414       stMenuItem.checked = TRUE;
5415       if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_RADIO, &stMenuItem)) {
5416          return TgDestroyMenu(menu, TRUE);
5417       }
5418       for (i=0; i < numFonts; i++) {
5419          menu->menuitems[i].menu_str_allocated = TRUE;
5420       }
5421       SetScrollableMenuFirstIndex(menu, curFont);
5422       menu->refresh_proc = ((RefreshMenuFunc*)RefreshFontMenu);
5423    }
5424    return menu;
5425 }
5426 
FontMenu(X,Y,TrackMenubar)5427 int FontMenu(X, Y, TrackMenubar)
5428    int X, Y, TrackMenubar;
5429 {
5430    int rc=INVALID;
5431    TgMenu *menu=(fontMenuInfo.create_proc)(NULL, X, Y, &fontMenuInfo, INVALID);
5432 
5433    activeMenu = MENU_FONT;
5434    if (menu != NULL) {
5435       menu->track_menubar = TrackMenubar;
5436 
5437       rc = TgMenuLoop(menu);
5438       TgDestroyMenu(menu, TRUE);
5439    }
5440    return rc;
5441 }
5442 
ChangeObjVSpace(ObjPtr,VSpace)5443 int ChangeObjVSpace(ObjPtr, VSpace)
5444    struct ObjRec *ObjPtr;
5445    int VSpace;
5446 {
5447    struct ObjRec *obj_ptr;
5448    int changed=FALSE, obj_changed;
5449    int saved_v_space;
5450 
5451    switch (ObjPtr->type) {
5452    case OBJ_TEXT:
5453       if (ObjPtr->detail.t->minilines.v_space != VSpace) {
5454          saved_v_space = ObjPtr->detail.t->minilines.v_space;
5455          ObjPtr->detail.t->minilines.v_space = VSpace;
5456          if (AdjTransformedTextBBox(ObjPtr) == FALSE) {
5457             Msg(TgLoadString(STID_INVALID_VSPACE_NOT_CHANGED));
5458             ObjPtr->detail.t->minilines.v_space = saved_v_space;
5459             UpdTextBBox(ObjPtr);
5460          } else {
5461             if (ObjPtr->detail.t->cached_bitmap != None) {
5462                XFreePixmap(mainDisplay,ObjPtr->detail.t->cached_bitmap);
5463             }
5464             ObjPtr->detail.t->cached_zoom = 0;
5465             ObjPtr->detail.t->cached_bitmap = None;
5466 
5467             AdjObjBBox(ObjPtr);
5468             changed = TRUE;
5469          }
5470       }
5471       break;
5472 
5473    case OBJ_GROUP:
5474    case OBJ_SYM:
5475       obj_changed = FALSE;
5476       for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
5477             obj_ptr=obj_ptr->prev) {
5478          if (ChangeObjVSpace(obj_ptr, VSpace)) {
5479             obj_changed = TRUE;
5480          }
5481       }
5482       if (obj_changed) {
5483          changed = TRUE;
5484          AdjObjBBox(ObjPtr);
5485       }
5486       break;
5487    }
5488    if (changePropertiesOfAttrs && ObjPtr->type != OBJ_TEXT) {
5489       struct AttrRec *attr_ptr=ObjPtr->fattr;
5490 
5491       obj_changed = FALSE;
5492       for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
5493          if (ChangeObjVSpace(attr_ptr->obj, VSpace)) {
5494             obj_changed = TRUE;
5495          }
5496       }
5497       if (obj_changed) {
5498          changed = TRUE;
5499          AdjObjBBox(ObjPtr);
5500       }
5501    }
5502    return changed;
5503 }
5504 
ChangeVSpace(VSpace)5505 void ChangeVSpace(VSpace)
5506    int VSpace;
5507 {
5508    struct SelRec *sel_ptr;
5509    int ltx, lty, rbx, rby, changed=FALSE;
5510 
5511    if (topSel == NULL || stickyMenuSelection) {
5512       if (!(curChoice == DRAWTEXT && textCursorShown)) {
5513          TieLooseEnds();
5514       }
5515       if (textCursorH+textVSpace <= 0) {
5516          Msg(TgLoadString(STID_VSPACE_TOO_SMALL_NOT_CHANGED));
5517       } else {
5518          textVSpace = VSpace;
5519          SetCanvasFont();
5520          ShowTextVSpace();
5521       }
5522       if (curChoice == DRAWTEXT && textCursorShown) {
5523          if (ChangeObjVSpace(curTextObj, VSpace)) {
5524             curTextModified = TRUE;
5525             UpdCurTextBBox();
5526             RedrawCurText();
5527             SetFileModified(TRUE);
5528             if (cycleThroughChoice) {
5529                SetPushedFontValue(PUSH_VSPACE, textVSpace);
5530             }
5531          }
5532       } else {
5533          textCursorShown = FALSE;
5534       }
5535       if (topSel == NULL) return;
5536    }
5537    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
5538 
5539    HighLightReverse();
5540    StartCompositeCmd();
5541    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
5542       PrepareToReplaceAnObj(sel_ptr->obj);
5543       if (ChangeObjVSpace(sel_ptr->obj, VSpace)) {
5544          changed = TRUE;
5545          RecordReplaceAnObj(sel_ptr->obj);
5546       } else {
5547          AbortPrepareCmd(CMD_REPLACE);
5548       }
5549    }
5550    EndCompositeCmd();
5551 
5552    if (changed) {
5553       UpdSelBBox();
5554       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
5555             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
5556             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
5557             selRbY+GRID_ABS_SIZE(1));
5558       SetFileModified(TRUE);
5559    }
5560    HighLightForward();
5561 }
5562 
ChangeAllSelRealSzUnit(sz_unit,HighLight)5563 void ChangeAllSelRealSzUnit(sz_unit, HighLight)
5564    int sz_unit, HighLight;
5565 {
5566    struct SelRec *sel_ptr=NULL;
5567    int changed=FALSE;
5568 
5569    if (topSel == NULL) {
5570       MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
5571       return;
5572    }
5573    if (HighLight) HighLightReverse();
5574    StartCompositeCmd();
5575    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
5576       PrepareToReplaceAnObj(sel_ptr->obj);
5577       if (ChangeObjTextSzUnit(sel_ptr->obj, sz_unit)) {
5578          changed = TRUE;
5579          RecordReplaceAnObj(sel_ptr->obj);
5580       } else {
5581          AbortPrepareCmd(CMD_REPLACE);
5582       }
5583    }
5584    EndCompositeCmd();
5585 
5586    if (changed) {
5587       int ltx=selLtX, lty=selLtY, rbx=selRbX, rby=selRbY;
5588 
5589       SetFileModified(TRUE);
5590       UpdSelBBox();
5591       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
5592             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
5593             selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
5594             selRbY+GRID_ABS_SIZE(1));
5595    }
5596    if (HighLight) HighLightForward();
5597 }
5598 
SetSelFontSize(pszBuf)5599 void SetSelFontSize(pszBuf)
5600    char *pszBuf;
5601 {
5602    char *psz=NULL, spec[MAXSTRING+1], spec_copy[MAXSTRING+1];
5603    int sz_unit=(-1), font_size=(-1), point_size=(-1);
5604 
5605    if (topSel == NULL) {
5606       int size=0;
5607 
5608       if (pszBuf != NULL && sscanf(pszBuf, "%d", &size) == 1) {
5609          int i, sz_unit=FontSizeToSzUnit(size);
5610 
5611          for (i=0; i<numFontSizes; i++) {
5612             if (fontSzUnits[i] == sz_unit) {
5613                ChangeFontSize(i);
5614                return;
5615             }
5616          }
5617       } else if (curChoice == DRAWTEXT && textCursorShown) {
5618          /* will call ChangeEditTextProperty() to handle this */
5619       } else {
5620          MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
5621          return;
5622       }
5623    }
5624    *spec = '\0';
5625    if (pszBuf != NULL) {
5626       UtilStrCpyN(spec, sizeof(spec), pszBuf);
5627    } else {
5628       if (showFontSizeInPoints) {
5629          Dialog(TgLoadString(STID_ENTER_POINT_SIZE),
5630                TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL), spec);
5631       } else {
5632          Dialog(TgLoadString(STID_ENTER_FONT_SIZE),
5633                TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL), spec);
5634       }
5635    }
5636    UtilTrimBlanks(spec);
5637    if (*spec == '\0') return;
5638    strcpy(spec_copy, spec);
5639    UtilStrUpper(spec_copy);
5640    /* do not translate -- program constants */
5641    if ((psz=strstr(spec_copy, "point")) != NULL ||
5642          (psz=strstr(spec_copy, "pt")) != NULL) {
5643       *psz = '\0';
5644       point_size = atoi(spec_copy);
5645       sz_unit = PointSizeToSzUnit(point_size);
5646    } else if (showFontSizeInPoints) {
5647       point_size = atoi(spec);
5648       sz_unit = PointSizeToSzUnit(point_size);
5649    } else {
5650       font_size = atoi(spec);
5651       sz_unit = FontSizeToSzUnit(font_size);
5652    }
5653    if (sz_unit <= 0) {
5654       sprintf(gszMsgBox, TgLoadString(STID_FONT_SIZE_TOO_SMALL), spec);
5655       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5656       return;
5657    }
5658    if (topSel == NULL && curChoice == DRAWTEXT && textCursorShown) {
5659       if (ChangeEditTextProperty(PROP_MASK_TEXT_SZ_UNIT, sz_unit)) {
5660          curTextModified = TRUE;
5661          UpdCurTextBBox();
5662          RedrawCurText();
5663          SetFileModified(TRUE);
5664          if (cycleThroughChoice) {
5665             SetPushedFontValue(PUSH_SZ_UNIT, GetCurSzUnit());
5666          }
5667       }
5668       ShowCurFont();
5669       ShowTextSize();
5670       UpdatePinnedMenu(MENU_SIZE);
5671    } else {
5672       ChangeAllSelRealSzUnit(sz_unit, TRUE);
5673    }
5674 }
5675 
CleanUpFonts()5676 void CleanUpFonts()
5677 {
5678    int i;
5679    int fmly_index, style_index;
5680    struct FontSizeRec *fs_ptr, *next_fs;
5681 
5682    CleanUpPSFontCharSubs();
5683    CleanUpDontReencode();
5684    if (vertFontBitmap != None) XFreePixmap(mainDisplay, vertFontBitmap);
5685    if (rotatedVertFontBitmap != None) {
5686       XFreePixmap(mainDisplay, rotatedVertFontBitmap);
5687    }
5688    if (rotatedVertFontImage != NULL) XDestroyImage(rotatedVertFontImage);
5689    rotatedVertFontImage = NULL;
5690    vertFontBitmap = rotatedVertFontBitmap = None;
5691    vertFontBitmapW = vertFontBitmapH = 0;
5692 
5693    if (sizeMenuStr != NULL) {
5694       for (i=0; i<numFontSizes; i++) {
5695          UtilFree(sizeMenuStr[i]);
5696       }
5697       free(sizeMenuStr);
5698       sizeMenuStr = NULL;
5699    }
5700    if (fontSzUnits != NULL) {
5701       free(fontSzUnits);
5702       fontSzUnits = NULL;
5703    }
5704    numFontSizes = 0;
5705 
5706    CleanUpPSFontAliases();
5707    CleanUpTmpStrings();
5708    CleanUpEncodeCharFonts();
5709 
5710    if (fontFamilies != NULL) {
5711       for (fmly_index=0; fmly_index<numFonts; fmly_index++) {
5712          for (style_index=0; style_index<MAXFONTSTYLES; style_index++) {
5713             if (fontFamilies[fmly_index].fr[style_index].xfs != NULL) {
5714                XFreeFont(mainDisplay,
5715                      fontFamilies[fmly_index].fr[style_index].xfs);
5716             }
5717             for (fs_ptr=fontFamilies[fmly_index].fr[style_index].next;
5718                   fs_ptr != NULL; fs_ptr = next_fs) {
5719                next_fs = fs_ptr->next;
5720                if (fs_ptr->xfs != NULL && !fs_ptr->faked) {
5721                   XFreeFont(mainDisplay, fs_ptr->xfs);
5722                }
5723                free(fs_ptr);
5724             }
5725          }
5726          UtilFree(fontFamilies[fmly_index].conv_from_utf8_cmd);
5727          UtilFree(fontFamilies[fmly_index].conv_to_utf8_cmd);
5728       }
5729       for (fmly_index=0; fmly_index<numFakedFonts; fmly_index++) {
5730          free(fontFamilies[fmly_index+numFonts].name_faked);
5731       }
5732       free(fontFamilies);
5733       fontFamilies = NULL;
5734    }
5735    if (fontInfoStr != NULL) {
5736       for (i=MAXFONTS*MAXFONTSTYLES*3; i<numFonts*MAXFONTSTYLES*3; i++) {
5737          free(fontInfoStr[i]);
5738       }
5739       free(fontInfoStr);
5740       fontInfoStr = NULL;
5741    }
5742    if (altFontInfoStr) {
5743       for (i=0; i<MAXFONTS*MAXFONTSTYLES*3; i++) {
5744          if (altFontInfoStr[i] != NULL) {
5745             free(altFontInfoStr[i]);
5746          }
5747       }
5748       free(altFontInfoStr);
5749       altFontInfoStr = NULL;
5750    }
5751    if (fontMenuStr != NULL) {
5752       for (fmly_index=0; fmly_index<numFonts; fmly_index++) {
5753          UtilFree(fontMenuStr[fmly_index]);
5754       }
5755       free(fontMenuStr);
5756       fontMenuStr = NULL;
5757    }
5758    numFonts = MAXFONTS;
5759    numFakedFonts = 0;
5760 
5761 #ifdef ENABLE_NLS
5762    if (menuFontSet != NULL) XFreeFontSet(mainDisplay, menuFontSet);
5763    if (msgFontSet != NULL) XFreeFontSet(mainDisplay, msgFontSet);
5764    if (boldMsgFontSet != NULL) XFreeFontSet(mainDisplay, boldMsgFontSet);
5765    if (italicMsgFontSet != NULL) XFreeFontSet(mainDisplay, italicMsgFontSet);
5766    if (boldItalicMsgFontSet != NULL) {
5767       XFreeFontSet(mainDisplay, boldItalicMsgFontSet);
5768    }
5769 #endif /* ENABLE_NLS */
5770    menuFontSet = msgFontSet = boldMsgFontSet = italicMsgFontSet =
5771          boldItalicMsgFontSet = NULL;
5772 
5773    if (menuFontPtr != NULL) XFreeFont(mainDisplay, menuFontPtr);
5774    if (msgFontPtr != NULL) XFreeFont(mainDisplay, msgFontPtr);
5775    if (boldMsgFontPtr != NULL) XFreeFont(mainDisplay, boldMsgFontPtr);
5776    if (italicMsgFontPtr != NULL) XFreeFont(mainDisplay, italicMsgFontPtr);
5777    if (boldItalicMsgFontPtr != NULL) {
5778       XFreeFont(mainDisplay, boldItalicMsgFontPtr);
5779    }
5780    menuFontPtr = msgFontPtr = boldMsgFontPtr = italicMsgFontPtr =
5781          boldItalicMsgFontPtr = NULL;
5782 
5783    if (rulerFontName != NULL) free(rulerFontName);
5784    if (defaultFontName != NULL) free(defaultFontName);
5785    rulerFontName = defaultFontName = NULL;
5786 
5787    if (menuFontName != NULL) free(menuFontName);
5788    if (msgFontName != NULL) free(msgFontName);
5789    if (boldMsgFontName != NULL) free(boldMsgFontName);
5790    if (italicMsgFontName != NULL) free(italicMsgFontName);
5791    if (boldItalicMsgFontName != NULL) free(boldItalicMsgFontName);
5792    menuFontName = msgFontName = boldMsgFontName = italicMsgFontName =
5793          boldItalicMsgFontName = NULL;
5794 
5795    if (menuFontSetName != NULL) free(menuFontSetName);
5796    if (msgFontSetName != NULL) free(msgFontSetName);
5797    if (boldMsgFontSetName != NULL) free(boldMsgFontSetName);
5798    if (italicMsgFontSetName != NULL) free(italicMsgFontSetName);
5799    if (boldItalicMsgFontSetName != NULL) free(boldItalicMsgFontSetName);
5800    menuFontSetName = msgFontSetName = boldMsgFontSetName =
5801          italicMsgFontSetName = boldItalicMsgFontSetName = NULL;
5802 }
5803 
VerifyCompatibleFontIndex(font_index)5804 void VerifyCompatibleFontIndex(font_index)
5805    int *font_index;
5806    /* should only call this function if fileVersion <= 29 */
5807 {
5808    if (*font_index >= MAXFONTS) *font_index = defaultCurFont;
5809 }
5810 
5811 static
GetFontStr(FontIndex,StyleIndex,FontStr)5812 void GetFontStr(FontIndex, StyleIndex, FontStr)
5813    int FontIndex, StyleIndex;
5814    char *FontStr;
5815 {
5816    char font_str[MAXSTRING];
5817 
5818    *font_str = '\0';
5819    GetPSFontStr(FontIndex, StyleIndex, font_str);
5820    /* font_str[0] is '/' now */
5821    strcpy(FontStr, &font_str[1]);
5822 }
5823 
GetCompatibleFontName(old_font_index,style,font_str)5824 void GetCompatibleFontName(old_font_index, style, font_str)
5825    int old_font_index, style;
5826    char *font_str;
5827 {
5828    int i;
5829    int cSingle=0;
5830    int cDouble=0;
5831    int cpSingle=INVALID;
5832    int cpDouble=INVALID;
5833    int old_font_single=(old_font_index % 1000);
5834    int old_font_double=((old_font_index / 1000) - 1);
5835    int num_fonts=((PRTGIF && !cmdLineOpenDisplay) ? MAXFONTS+numFakedFonts:
5836          numFonts+numFakedFonts);
5837 
5838    for (i=0; i < num_fonts; i++) {
5839       if (!IsFontDoubleByte(i)) {
5840          if (cSingle == old_font_single) cpSingle = i;
5841          cSingle++;
5842       } else {
5843          if (cDouble == old_font_double) cpDouble = i;
5844          cDouble++;
5845       }
5846    }
5847    if (cpSingle != INVALID) {
5848       GetFontStr(cpSingle, style, font_str);
5849    } else {
5850       GetFontStr(defaultCurFont, style, font_str);
5851       sprintf(gszMsgBox, TgLoadString(STID_FONT_SUB_NO_SUCH_FONT_USR_DEF),
5852             font_str, old_font_single);
5853       if (PRTGIF) {
5854          fprintf(stderr, "%s\n", gszMsgBox);
5855       } else {
5856          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5857       }
5858    }
5859    if (cpDouble != INVALID) {
5860       strcat(font_str, "%");
5861       GetFontStr(cpDouble, style, font_str+strlen(font_str));
5862    } else if (old_font_double >=0) {
5863       sprintf(gszMsgBox, TgLoadString(STID_NO_KANJI_FONT_GIVEN_NUMBER),
5864             old_font_double);
5865       if (PRTGIF) {
5866          fprintf(stderr, "%s\n", gszMsgBox);
5867       } else {
5868          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5869       }
5870    }
5871 }
5872 
5873 /* The following procedure is used to generate pdrawFontAsc[] and */
5874 /*    pDrawFontDes[], to be used in ``prtgif.c''.  It is supposed */
5875 /*    to be called within dbx and not tgif.                       */
5876 
5877 /*
5878  * static
5879  * void GenerateFontInfo()
5880  * {
5881  *    register int i, j, num_rows;
5882  *
5883  *    for (i = 0; i < FONTTABLESIZE; i++)
5884  *       if (!myFontInfo[i].valid)
5885  *       {
5886  *          if ((myFontInfo[i].xfs =
5887  *                XLoadQueryFont(mainDisplay, fontNameStr[i])) == NULL)
5888  *          {
5889  *             printf("Cannot open %s.  Abort.\n\n", fontNameStr[i]);
5890  *             exit(-1);
5891  *          }
5892  *          myFontInfo[i].valid = TRUE;
5893  *       }
5894  *
5895  *    num_rows = FONTTABLESIZE / MAXFONTSIZES;
5896  *    printf("short\tpDrawFontAsc[] =\n{\n");
5897  *    for (i = 0; i < num_rows; i++)
5898  *    {
5899  *       printf("   ");
5900  *       for (j = 0; j < MAXFONTSIZES; j++)
5901  *          if (i == num_rows-1 && j == MAXFONTSIZES-1)
5902  *             printf("%2d ",
5903  *                   (myFontInfo[i*MAXFONTSIZES+j].xfs)->max_bounds.ascent);
5904  *          else
5905  *             printf("%2d, ",
5906  *                   (myFontInfo[i*MAXFONTSIZES+j].xfs)->max_bounds.ascent);
5907  *       printf("\n");
5908  *    }
5909  *    printf("};\n\n");
5910  *
5911  *    printf("short\tpDrawFontDes[] =\n{\n");
5912  *    for (i = 0; i < num_rows; i++)
5913  *    {
5914  *       printf("   ");
5915  *       for (j = 0; j < MAXFONTSIZES; j++)
5916  *          if (i == num_rows-1 && j == MAXFONTSIZES-1)
5917  *             printf("%2d ",
5918  *                   (myFontInfo[i*MAXFONTSIZES+j].xfs)->max_bounds.descent);
5919  *          else
5920  *             printf("%2d, ",
5921  *                   (myFontInfo[i*MAXFONTSIZES+j].xfs)->max_bounds.descent);
5922  *       printf("\n");
5923  *    }
5924  *    printf("};\n");
5925  * }
5926  */
5927