1 /*
2 * $LynxId: UCAuto.c,v 1.51 2013/05/04 13:14:39 tom Exp $
3 *
4 * This file contains code for changing the Linux console mode.
5 * Currently some names for font files are hardwired in here.
6 * You have to change this code if it needs accommodation for your
7 * system (or get the required files...).
8 *
9 * Depending on the Display Character Set switched to, and the previous
10 * one as far as it is known, system("setfont ...") and/or output of
11 * escape sequences to switch console mode are done. Curses will be
12 * temporarily suspended while that happens.
13 *
14 * NOTE that the setfont calls will also affect all other virtual consoles.
15 *
16 * Any ideas how to do this for other systems?
17 */
18
19 #include <HTUtils.h>
20 #include <LYUtils.h>
21
22 #include <UCMap.h>
23 #include <UCDefs.h>
24 #include <UCAuto.h>
25 #include <LYGlobalDefs.h>
26 #include <LYStrings.h>
27 #include <LYClean.h>
28 #include <LYLeaks.h>
29 #include <LYCharSets.h>
30
31 #ifdef EXP_CHARTRANS_AUTOSWITCH
32
33 #include <HTFile.h>
34 #include <www_wait.h>
35
36 #ifdef LINUX
37 #include <sysexits.h> /* EX_DATAERR, etc. */
38 #endif
39
40 # ifdef CAN_SWITCH_DISPLAY_CHARSET
41 char *charset_switch_rules;
42 char *charsets_directory;
43 int auto_other_display_charset = -1;
44 int codepages[2];
45 int real_charsets[2] =
46 {-1, -1}; /* Non "auto-" charsets for the cps */
47 int switch_display_charsets;
48
49 # endif
50
51 #ifdef HAVE_USE_LEGACY_CODING
52 static int original_coding = 0;
53 #endif
54
55 # ifdef __EMX__
56 /* If we "just include" <os2.h>, BOOLEAN conflicts. */
57 # define BOOLEAN OS2_BOOLEAN /* This file doesn't use it, conflicts */
58 # define INCL_VIO /* I want some Vio functions.. */
59 # define INCL_DOSPROCESS /* TIB PIB. */
60 # define INCL_DOSNLS /* DosQueryCp. */
61 # include <os2.h> /* Misc stuff.. */
62 # include <os2thunk.h> /* 32 bit to 16 bit pointer conv */
63 # endif
64
65 #ifdef LINUX
66 typedef enum {
67 Is_Unset,
68 Is_Set,
69 Dunno,
70 Dont_Care
71 } TGen_state_t;
72
73 /*
74 * List the states the console has been set to via SCS (select character-set).
75 */
76 typedef enum {
77 GN_Blat1, /* Latin-1 */
78 GN_Ucp437, /* PC -> PC */
79 GN_Kuser, /* user-defined */
80 GN_dunno,
81 GN_dontCare
82 } TTransT_t;
83
84 static char *T_font_fn = NULL; /* font filename */
85 static char *T_umap_fn = NULL; /* unicode-map filename */
86
87 #define NOOUTPUT "2>/dev/null >/dev/null"
88
89 /*
90 * Return the configured path of the setfont/consolechars program.
91 */
GetSetfontPath(void)92 static const char *GetSetfontPath(void)
93 {
94 return HTGetProgramPath(ppSETFONT);
95 }
96
97 /*
98 * setfont and consolechars have different options and available data.
99 */
isSetFont(void)100 static BOOL isSetFont(void)
101 {
102 const char *program = GetSetfontPath();
103 const char *slash = strrchr(program, '/');
104 const char *leaf = (slash ? slash + 1 : program);
105
106 return (BOOL) !strcmp(leaf, "setfont");
107 }
108
109 /*
110 * Here are the differences in options which affect lynx:
111 */
112 #define setfont_u() (isSetFont() ? "-u " : "--sfm ")
113 #define setfont_o() (isSetFont() ? "-o " : "--old-font-raw ")
114 #define setfont_ou() (isSetFont() ? "-ou " : "--old-sfm ")
115 #define console_font() (isSetFont() ? "" : "--font ")
116
117 /*
118 * call_setfont - execute "setfont" command via system()
119 * returns: 0 ok (as far as we know)
120 * -1 error (assume font and umap are not loaded)
121 * 1 error with umap (assume font loaded but umap empty)
122 */
call_setfont(const char * font,const char * fnsuffix,const char * umap)123 static int call_setfont(const char *font,
124 const char *fnsuffix,
125 const char *umap)
126 {
127 const char *program = GetSetfontPath();
128 char *T_setfont_cmd = NULL;
129 int rv;
130
131 /*
132 * console-data package has only a few unicode maps.
133 */
134 if (!isSetFont())
135 umap = 0;
136
137 if ((font && T_font_fn && !strcmp(font, T_font_fn))
138 && (umap && T_umap_fn && !strcmp(umap, T_umap_fn))) {
139 /*
140 * No need to repeat.
141 */
142 return 0;
143 }
144 if (font)
145 StrAllocCopy(T_font_fn, font);
146 if (umap)
147 StrAllocCopy(T_umap_fn, umap);
148
149 if (!*fnsuffix)
150 fnsuffix = "";
151
152 if (non_empty(umap) && non_empty(font)) {
153 HTSprintf0(&T_setfont_cmd, "%s %s%s%s %s%s %s",
154 program,
155 console_font(), font, fnsuffix,
156 setfont_u(), umap,
157 NOOUTPUT);
158 } else if (non_empty(font)) {
159 HTSprintf0(&T_setfont_cmd, "%s %s%s%s %s",
160 program,
161 console_font(), font, fnsuffix,
162 NOOUTPUT);
163 } else if (non_empty(umap)) {
164 HTSprintf0(&T_setfont_cmd, "%s %s%s %s",
165 program,
166 setfont_u(), umap,
167 NOOUTPUT);
168 }
169
170 if (T_setfont_cmd) {
171 CTRACE((tfp, "Changing font: '%s'\n", T_setfont_cmd));
172 rv = LYSystem(T_setfont_cmd);
173 FREE(T_setfont_cmd);
174 if (rv) {
175 CTRACE((tfp, "call_setfont: system returned %d (0x%x)!\n",
176 rv, rv));
177 if (rv == -1 || WIFSIGNALED(rv) || !WIFEXITED(rv)) {
178 return -1;
179 } else if ((WEXITSTATUS(rv) == EX_DATAERR ||
180 WEXITSTATUS(rv) == EX_NOINPUT) &&
181 non_empty(umap)) {
182 /*
183 * Check if the font was loaded ok but something was wrong with
184 * the umap file.
185 */
186 return 1;
187 } else {
188 return -1;
189 }
190 }
191 }
192 return 0;
193 }
194
write_esc(const char * p)195 static void write_esc(const char *p)
196 {
197 int fd = open("/dev/tty", O_WRONLY);
198
199 if (fd >= 0) {
200 IGNORE_RC(write(fd, p, strlen(p)));
201 close(fd);
202 }
203 }
204
nonempty_file(const char * p)205 static int nonempty_file(const char *p)
206 {
207 struct stat sb;
208
209 return (stat(p, &sb) == 0 &&
210 S_ISREG(sb.st_mode) &&
211 (sb.st_size != 0));
212 }
213
on_console(void)214 static BOOL on_console(void)
215 {
216 if ((x_display != NULL) ||
217 LYgetXDisplay() != NULL) {
218 /*
219 * We won't do anything in an xterm. Better that way...
220 */
221 return FALSE;
222 }
223 return TRUE;
224 }
225
226 /*
227 * This is the thing that actually gets called from display_page().
228 */
UCChangeTerminalCodepage(int newcs,LYUCcharset * p)229 void UCChangeTerminalCodepage(int newcs,
230 LYUCcharset *p)
231 {
232 const char *program = GetSetfontPath();
233 static int lastcs = -1;
234 static const char *lastname = NULL;
235 static TTransT_t lastTransT = GN_dunno;
236 static TGen_state_t lastUtf = Dunno;
237 static TGen_state_t lastHasUmap = Dunno;
238
239 static char *old_font = NULL;
240 static char *old_umap = NULL;
241
242 const char *name;
243 TTransT_t TransT = GN_dunno;
244 TGen_state_t Utf = Dunno;
245 TGen_state_t HasUmap = Dunno;
246
247 char *tmpbuf1 = NULL;
248 char *tmpbuf2 = NULL;
249 int status = 0;
250
251 if (!on_console())
252 return;
253
254 #ifdef HAVE_USE_LEGACY_CODING
255 if (newcs < 0) {
256 use_legacy_coding(original_coding);
257 } else {
258 original_coding = use_legacy_coding(2);
259 }
260 #endif
261
262 /*
263 * Restore the original character set.
264 */
265 if (newcs < 0 || p == 0) {
266 if (non_empty(old_font) &&
267 non_empty(old_umap)) {
268
269 if (nonempty_file(old_font)) {
270 if (nonempty_file(old_umap)) {
271 HTSprintf0(&tmpbuf1, "%s %s%s %s%s %s",
272 program,
273 console_font(), old_font,
274 setfont_u(), old_umap,
275 NOOUTPUT);
276 } else {
277 HTSprintf0(&tmpbuf1, "%s %s%s %s",
278 program,
279 console_font(), old_font,
280 NOOUTPUT);
281 }
282 CTRACE((tfp, "Restoring font: '%s'\n", tmpbuf1));
283 status = LYSystem(tmpbuf1);
284 if (status != 0) {
285 CTRACE((tfp, "...system returned %d (0x%x)\n", status, status));
286 }
287 FREE(tmpbuf1);
288 }
289 }
290 if (newcs < 0 && p == 0) {
291 if (old_font) {
292 (void) LYRemoveTemp(old_font);
293 FREE(old_font);
294 }
295 if (old_umap) {
296 (void) LYRemoveTemp(old_umap);
297 FREE(old_umap);
298 }
299 if (status == 0) {
300 FREE(T_font_fn);
301 FREE(T_umap_fn);
302 }
303 }
304 return;
305 } else if (lastcs < 0 && old_umap == 0 && old_font == 0) {
306 FILE *fp1;
307 FILE *fp2 = NULL;
308
309 if ((old_font = typecallocn(char, LY_MAXPATH)) != 0)
310 old_umap = typecallocn(char, LY_MAXPATH);
311
312 if (old_font == NULL)
313 outofmem(__FILE__, "UCChangeTerminalCodepage");
314
315 assert(old_font != NULL);
316
317 if ((fp1 = LYOpenTemp(old_font, ".fnt", BIN_W)) != 0)
318 fp2 = LYOpenTemp(old_umap, ".uni", BIN_W);
319
320 if (fp1 && fp2) {
321 size_t nlen;
322 int rv;
323
324 HTSprintf0(&tmpbuf1, "%s %s%s %s%s %s",
325 program,
326 setfont_o(), old_font,
327 setfont_ou(), old_umap,
328 NOOUTPUT);
329
330 CTRACE((tfp, "Saving font: '%s'\n", tmpbuf1));
331 rv = LYSystem(tmpbuf1);
332 if (rv != 0) {
333 CTRACE((tfp, "...system returned %d (0x%x)\n", rv, rv));
334 }
335 FREE(tmpbuf1);
336 LYCloseTempFP(fp1);
337 LYCloseTempFP(fp2);
338
339 /* free up a few bytes */
340 if ((nlen = strlen(old_font) + 1) < LY_MAXPATH)
341 old_font = typeRealloc(char, old_font, nlen);
342
343 if ((nlen = strlen(old_umap) + 1) < LY_MAXPATH)
344 old_umap = typeRealloc(char, old_umap, nlen);
345 } else {
346 if (fp1)
347 (void) LYRemoveTemp(old_font);
348 FREE(old_font);
349 FREE(old_umap);
350 }
351 }
352
353 name = p->MIMEname;
354
355 /*
356 * Font sizes are currently hardwired here.
357 */
358 #define SUFF1 ".f16"
359 #define SUFF2 "-16.psf"
360 #define SUFF3 "-8x16"
361 #define SUFF4 "8x16"
362 #define SUFF5 ".cp -16"
363 #define SUFF6 "_8x16"
364
365 /* NOTE: `!!umap not in kbd!!' comments below means that the *.uni file
366 * is not found in kbd package. Reference Debian Package: kbd-data,
367 * Version: 0.96a-14. They should be located elsewhere or generated.
368 * Also some cpNNN fonts used below are not in the kbd-data. - kw
369 */
370
371 if (!StrNCmp(name, "iso-8859-1", 10) &&
372 (!name[10] || !isdigit(UCH(name[10])))) {
373 if ((lastHasUmap == Is_Set) && !strcmp(lastname, "cp850")) {
374 /*
375 * cp850 already contains all latin1 characters.
376 */
377 if (lastTransT != GN_Blat1) {
378 TransT = GN_Blat1;
379 }
380 } else {
381 /*
382 * "setfont lat1u-16.psf -u lat1u.uni"
383 */
384 status = call_setfont("lat1u", SUFF2, "lat1u.uni");
385 HasUmap = Is_Set;
386 if (lastTransT != GN_Blat1) {
387 TransT = GN_Blat1;
388 }
389 }
390 Utf = Is_Unset;
391 } else if (!strcmp(name, "iso-8859-2")) {
392 /*
393 * "setfont iso02.f16 -u iso02.uni"
394 */
395 status = call_setfont("iso02", SUFF1, "iso02.uni");
396 TransT = GN_Kuser;
397 HasUmap = Is_Set;
398 Utf = Is_Unset;
399 } else if (!strcmp(name, "iso-8859-15")) {
400 /*
401 * "setfont lat0-16.psf"
402 */
403 status = call_setfont("lat0", SUFF2, NULL);
404 TransT = GN_Blat1; /* bogus! */
405 HasUmap = Dunno; /* distributed lat0 files have bogus map data! */
406 Utf = Is_Unset;
407 } else if (!StrNCmp(name, "iso-8859-", 9)) {
408 if (strlen(name) <= 10 || !isdigit(UCH(name[10])))
409 HTSprintf0(&tmpbuf1, "iso0%s", &name[9]);
410 else
411 HTSprintf0(&tmpbuf1, "iso%s", &name[9]);
412 HTSprintf0(&tmpbuf2, "%s.uni", tmpbuf1);
413 /*
414 * "setfont iso0N.f16 -u iso0N.uni"
415 */
416 status = call_setfont(tmpbuf1, SUFF1, tmpbuf2);
417 FREE(tmpbuf1);
418 FREE(tmpbuf2);
419 TransT = GN_Kuser;
420 HasUmap = Is_Set;
421 Utf = Is_Unset;
422 } else if (!strcmp(name, "koi8-r")) {
423 /*
424 * "setfont koi8-8x16"
425 * !!umap not in kbd!!
426 */
427 status = call_setfont("koi8", SUFF3, "koi8r.uni");
428 TransT = GN_Kuser;
429 HasUmap = Is_Set;
430 Utf = Is_Unset;
431 } else if (!strcmp(name, "koi8-u")) {
432 /*
433 * "setfont koi8u_8x16"
434 * !!umap not in kbd!!
435 */
436 status = call_setfont("koi8u", SUFF6, "koi8u.uni");
437 TransT = GN_Kuser;
438 HasUmap = Is_Set;
439 Utf = Is_Unset;
440 } else if (!strcmp(name, "cp437")) {
441 /*
442 * "setfont default8x16 -u cp437.uni"
443 */
444 status = call_setfont("default", SUFF4, "cp437.uni");
445 if (lastTransT == GN_Kuser || lastTransT == GN_Ucp437)
446 TransT = GN_dontCare;
447 else
448 TransT = GN_Ucp437;
449 HasUmap = Is_Set;
450 Utf = Is_Unset;
451 } else if (!strcmp(name, "cp850")) {
452 /*
453 * "setfont cp850-8x16 -u cp850.uni"
454 * !!umap not in kbd!!
455 */
456 status = call_setfont("cp850", SUFF3, "cp850.uni");
457 TransT = GN_Kuser;
458 HasUmap = Is_Set;
459 Utf = Is_Unset;
460 } else if (!strcmp(name, "cp866") ||
461 !strcmp(name, "cp852") ||
462 !strcmp(name, "cp862")) { /* MS-Kermit has these files */
463 HTSprintf0(&tmpbuf2, "%s.uni", name);
464 /*
465 * "setfont cpNNN.f16"
466 * !!umap not in kbd!!
467 */
468 status = call_setfont(name, SUFF1, tmpbuf2);
469 FREE(tmpbuf2);
470 TransT = GN_Kuser;
471 HasUmap = Is_Set;
472 Utf = Is_Unset;
473 } else if (!strcmp(name, "cp737")) {
474 /*
475 * "setfont cp737.cp"
476 * !!umap not in kbd!!
477 */
478 if (isSetFont()) {
479 status = call_setfont("737", SUFF5, "cp737.uni");
480 } else {
481 status = call_setfont("greek", "", "cp737.uni");
482 }
483 TransT = GN_Kuser;
484 HasUmap = Is_Set;
485 Utf = Is_Unset;
486 } else if (!strcmp(name, "cp857")) {
487 status = call_setfont("cp857", SUFF3, "cp857.uni");
488 TransT = GN_Kuser;
489 HasUmap = Is_Set;
490 Utf = Is_Unset;
491 } else if (!strcmp(name, "x-transparent")) {
492 Utf = Dont_Care;
493 } else if (!strcmp(name, "us-ascii")) {
494 Utf = Dont_Care;
495 } else if (!StrNCmp(name, "mnem", 4)) {
496 Utf = Dont_Care;
497 }
498
499 if (status == 1)
500 HasUmap = Is_Unset;
501 else if (status < 0) {
502 if (HasUmap == Is_Set)
503 HasUmap = Dunno;
504 name = "unknown-8bit";
505 }
506
507 if (TransT != lastTransT) {
508 if (TransT == GN_Blat1) {
509 /*
510 * Switch Linux console to lat1 table.
511 */
512 write_esc("\033(B");
513 } else if (TransT == GN_Ucp437) {
514 /*
515 * Switch Linux console to 437 table?
516 */
517 write_esc("\033(U");
518 } else if (TransT == GN_Kuser) {
519 /*
520 * Switch Linux console to user table.
521 */
522 write_esc("\033(K");
523 }
524 if (TransT != GN_dunno && TransT != GN_dontCare) {
525 lastTransT = TransT;
526 }
527 }
528
529 if (HasUmap != Dont_Care && HasUmap != Dunno)
530 lastHasUmap = HasUmap;
531
532 if (p->enc == UCT_ENC_UTF8) {
533 if (lastUtf != Is_Set) {
534 Utf = Is_Set;
535 /*
536 * Turn Linux console UTF8 mode ON.
537 */
538 write_esc("\033%G");
539 lastUtf = Utf;
540 }
541 return;
542 } else if (lastUtf == Is_Set && Utf != Dont_Care) {
543 Utf = Is_Unset;
544 /*
545 * Turn Linux console UTF8 mode OFF.
546 */
547 write_esc("\033%@");
548 lastUtf = Utf;
549 }
550
551 if (Utf != Dont_Care && Utf != Dunno)
552 lastUtf = Utf;
553
554 lastcs = newcs;
555 lastname = name;
556 }
557
558 #else /* Not LINUX: */
559 /*
560 * This is the thing that actually gets called from display_page().
561 */
UCChangeTerminalCodepage(int newcs,LYUCcharset * p)562 void UCChangeTerminalCodepage(int newcs,
563 LYUCcharset *p)
564 {
565 #ifdef __EMX__
566 int res = 0;
567
568 #ifdef HAVE_USE_LEGACY_CODING
569 if (newcs < 0) {
570 use_legacy_coding(original_coding);
571 } else {
572 original_coding = use_legacy_coding(2);
573 }
574 #endif
575
576 if (newcs < 0)
577 newcs = auto_display_charset;
578 res = Switch_Display_Charset(newcs, SWITCH_DISPLAY_CHARSET_REALLY);
579 CTRACE((tfp,
580 "UCChangeTerminalCodepage: Switch_Display_Charset(%d) returned %d\n",
581 newcs, res));
582 #else
583 CTRACE((tfp, "UCChangeTerminalCodepage: Called, but not implemented!"));
584 #endif
585 }
586 #endif /* LINUX */
587
588 #ifdef CAN_SWITCH_DISPLAY_CHARSET
589
Find_Best_Display_Charset(int ord)590 int Find_Best_Display_Charset(int ord)
591 {
592 const char *name = LYCharSet_UC[ord].MIMEname;
593 char *s = charset_switch_rules, *r;
594 char buf[160];
595 static int lowercase;
596 int n = strlen(name), source = 1;
597
598 if (!s || !n)
599 return ord;
600 if (!lowercase++)
601 LYLowerCase(charset_switch_rules);
602 while (1) {
603 while (*s && strchr(" \t,", *s))
604 s++; /* Go to start of a name or ':' */
605 if (!*s && source)
606 return ord; /* OK to find nothing */
607 if (!*s) {
608 sprintf(buf,
609 gettext("No destination for '%.80s' in CHARSET_SWITCH_RULES"),
610 name);
611 HTInfoMsg(buf);
612 return ord;
613 }
614 if (*s == ':') {
615 /* Before the replacement name */
616 while (*s && strchr(" \t:", *s))
617 s++; /* Go to the replacement */
618 /* At start of the replacement name */
619 r = s;
620 while (*s && !strchr(" \t,:", *s))
621 s++; /* Skip the replacement */
622 if (source)
623 continue;
624 break;
625 }
626 /* At start of the source name */
627 if (source && !strnicmp(name, s, n) && strchr(" \t,", s[n])) { /* Found! */
628 source = 0;
629 s += n;
630 continue; /* Look for the replacement */
631 }
632 while (*s && !strchr(" \t,:", *s))
633 s++; /* Skip the other source names */
634 }
635 /* Here r point to the replacement, s to the end of the replacement. */
636 if (s >= r + sizeof(buf)) {
637 HTInfoMsg(gettext("Charset name in CHARSET_SWITCH_RULES too long"));
638 return ord;
639 }
640 LYStrNCpy(buf, r, s - r);
641 n = UCGetLYhndl_byMIME(buf);
642 if (n < 0) {
643 sprintf(buf,
644 gettext("Unknown charset name '%.*s' in CHARSET_SWITCH_RULES"),
645 s - r, r);
646 HTInfoMsg(buf);
647 return ord;
648 }
649 return n;
650 }
651
652 # ifdef __EMX__
653 /* Switch display for the best fit for LYCharSet_UC[ord].
654 If really is MAYBE, the switch is tentative only, another switch may happen
655 before the actual display.
656
657 Returns the charset we switched to. */
_Switch_Display_Charset(int ord,enum switch_display_charset_t really)658 static int _Switch_Display_Charset(int ord, enum switch_display_charset_t really)
659 {
660 const char *name;
661 unsigned short cp;
662 static int font_loaded_for = -1, old_h, old_w;
663 int rc, ord1;
664 UCHAR msgbuf[MAXPATHLEN + 80];
665
666 CTRACE((tfp, "_Switch_Display_Charset(cp=%d, really=%d).\n", ord, really));
667 /* Do not trust current_char_set unless REALLY, we fake it if MAYBE! */
668 if (ord == current_char_set && really == SWITCH_DISPLAY_CHARSET_MAYBE)
669 return ord;
670 if (ord == auto_other_display_charset
671 || ord == auto_display_charset || ord == font_loaded_for) {
672 if (really == SWITCH_DISPLAY_CHARSET_MAYBE)
673 return ord; /* Report success, to avoid flicker, switch later */
674 } else /* Currently supports only koi8-r to cp866 translation */
675 ord = Find_Best_Display_Charset(ord);
676
677 /* Ignore sizechange unless the font is loaded */
678 if (ord != font_loaded_for && really == SWITCH_DISPLAY_CHARSET_RESIZE)
679 return ord;
680
681 if (ord == real_charsets[0] || ord == real_charsets[1]) {
682 ord1 = (ord == real_charsets[1]
683 ? auto_other_display_charset : auto_display_charset);
684 if (really == SWITCH_DISPLAY_CHARSET_MAYBE)
685 return ord; /* Can switch later, report success to avoid flicker */
686 } else
687 ord1 = ord;
688 if (ord == current_char_set && really == SWITCH_DISPLAY_CHARSET_MAYBE)
689 return ord;
690
691 name = LYCharSet_UC[ord1].MIMEname;
692 if (ord1 == auto_other_display_charset || ord1 == auto_display_charset) {
693 retry:
694 rc = VioSetCp(0, codepages[ord1 == auto_other_display_charset], 0);
695 if (rc == 0)
696 goto report;
697 err:
698 sprintf(msgbuf, gettext("Can't change to '%s': err=%#x=%d"), name, rc, rc);
699 HTInfoMsg(msgbuf);
700 return -1;
701 }
702
703 /* Not a "prepared" codepage. Need to load the user font. */
704 if (charsets_directory) {
705 TIB *tib; /* Can't load font in a windowed-VIO */
706 PIB *pib;
707 VIOFONTINFO f[2];
708 VIOFONTINFO *font;
709 UCHAR b[1 << 17];
710 UCHAR *buf = b;
711 UCHAR fnamebuf[MAXPATHLEN];
712 FILE *file;
713 APIRET rc;
714 long i, j;
715
716 /* 0 means a FS protected-mode session */
717 if (font_loaded_for == -1 /* Did not try it yet */
718 && (DosGetInfoBlocks(&tib, &pib) || pib->pib_ultype != 0)) {
719 ord = ord1 = auto_display_charset;
720 goto retry;
721 }
722 /* Should not cross 64K boundaries: */
723 font = f;
724 if (((((ULONG) (char *) f) + sizeof(*font)) & 0xFFFF) < sizeof(*font))
725 font++;
726 if (((ULONG) buf) & 0xFFFF)
727 buf += 0x10000 - (((ULONG) buf) & 0xFFFF);
728 font->cb = sizeof(*font); /* How large is this structure */
729 font->type = 0; /* Not the BIOS, the loaded font. */
730 font->cbData = 65535; /* How large is my buffer? */
731 font->pbData = _emx_32to16(buf); /* Wants an 16:16 pointer */
732
733 rc = VioGetFont(font, 0); /* Retrieve data for current font */
734 if (rc) {
735 sprintf(msgbuf,
736 gettext("Can't fetch current font info: err=%#x=%d"), rc, rc);
737 HTInfoMsg(msgbuf);
738 ord = ord1 = auto_display_charset;
739 goto retry;
740 }
741 if (ord1 == font_loaded_for
742 && old_h == font->cyCell && old_w == font->cxCell) {
743 /* The same as the previous font */
744 if ((rc = VioSetCp(0, -1, 0))) /* -1: User font */
745 goto err;
746 goto report;
747 }
748 sprintf(fnamebuf, "%s/%dx%d/%s.fnt",
749 charsets_directory, font->cyCell, font->cxCell, name);
750 file = fopen(fnamebuf, BIN_R);
751 if (!file) {
752 sprintf(msgbuf, gettext("Can't open font file '%s'"), fnamebuf);
753 HTInfoMsg(msgbuf);
754 ord = ord1 = auto_display_charset;
755 goto retry;
756 }
757 i = ftell(file);
758 fseek(file, 0, SEEK_END);
759 if (ftell(file) - i != font->cbData) {
760 fclose(file);
761 sprintf(msgbuf, gettext("Mismatch of size of font file '%s'"), fnamebuf);
762 HTAlert(msgbuf);
763 ord = ord1 = auto_display_charset;
764 goto retry;
765 }
766 fseek(file, i, SEEK_SET);
767 fread(buf, 1, font->cbData, file);
768 fclose(file);
769 rc = VioSetFont(font, 0); /* Put it all back.. */
770 if (rc) {
771 sprintf(msgbuf, gettext("Can't set font: err=%#x=%d"), rc, rc);
772 HTInfoMsg(msgbuf);
773 ord = ord1 = auto_display_charset;
774 font_loaded_for = -1;
775 goto retry;
776 }
777 font_loaded_for = ord1;
778 old_h = font->cyCell;
779 old_w = font->cxCell;
780 } else {
781 ord = ord1 = auto_display_charset;
782 goto retry;
783 }
784 report:
785 CTRACE((tfp, "Display font set to '%s'.\n", name));
786 return ord;
787 }
788 # endif /* __EMX__ */
789
Switch_Display_Charset(const int ord,const enum switch_display_charset_t really)790 int Switch_Display_Charset(const int ord, const enum switch_display_charset_t really)
791 {
792 int prev = current_char_set;
793 int res;
794 static int repeated;
795
796 if (!switch_display_charsets)
797 return 0;
798 res = _Switch_Display_Charset(ord, really);
799 if (res < 0 || prev == res) /* No change */
800 return 0;
801 /* Register the change */
802 current_char_set = res;
803 HTMLUseCharacterSet(current_char_set);
804 return 1;
805 }
806 #endif /* CAN_SWITCH_DISPLAY_CHARSET */
807
808 #else /* EXP_CHARTRANS_AUTOSWITCH not defined: */
809 /*
810 * This is the thing that actually gets called from display_page().
811 */
UCChangeTerminalCodepage(int newcs GCC_UNUSED,LYUCcharset * p GCC_UNUSED)812 void UCChangeTerminalCodepage(int newcs GCC_UNUSED,
813 LYUCcharset *p GCC_UNUSED)
814 {
815 CTRACE((tfp, "UCChangeTerminalCodepage: Called, but not implemented!"));
816 }
817 #endif /* EXP_CHARTRANS_AUTOSWITCH */
818