1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #include "mc_font.h"
4
5 #include <stdio.h>
6 #include <ctype.h>
7 #include <pobl/bl_str.h> /* strdup */
8 #include <pobl/bl_mem.h> /* free */
9 #include <pobl/bl_debug.h>
10 #include <glib.h>
11 #include <c_intl.h>
12
13 #if defined(GDK_WINDOWING_X11) && !GTK_CHECK_VERSION(2, 90, 0)
14 #include "gtkxlfdsel.c"
15 #endif
16
17 #include "mc_combo.h"
18 #include "mc_flags.h"
19 #include "mc_radio.h"
20 #include "mc_char_encoding.h"
21 #include "mc_color.h"
22 #include "mc_unicode_areas.h"
23
24 #if 0
25 #define __DEBUG
26 #endif
27
28 typedef struct cs_info {
29 char *cs;
30
31 /*
32 * Default font encoding name.
33 * This used only if xcore font is used.
34 *
35 * !! Notice !!
36 * The last element must be NULL.
37 * (Conforming to the specification of 'charsets' argument of
38 * gtk_xlfd_selection_dialog_set_filter()).
39 */
40 char *encoding_names[3];
41
42 } cs_info_t;
43
44 /* --- static variables --- */
45
46 /*
47 * Combination of x_font_config.c:cs_table and x_font.c:cs_info_table
48 */
49 static cs_info_t cs_info_table[] = {
50 { "DEFAULT", { NULL, NULL, NULL, }, },
51
52 /*
53 * UNICODE => ISO10646_UCS4_1 or U+XXXX-XXXX in get_correct_cs().
54 */
55 { "UNICODE", { "iso10646-1", NULL, NULL, }, },
56 { "UNICODE (Full Width)", { "iso10646-1", NULL, NULL, }, },
57 { "UNICODE (Emoji)", { "iso10646-1", NULL, NULL, }, },
58 { "UNICODE (Hankaku Kana)", { "iso10646-1", NULL, NULL, }, },
59 { "UNICODE (Hebrew)", { "iso10646-1", NULL, NULL, }, },
60 { "UNICODE (Arabic)", { "iso10646-1", NULL, NULL, }, },
61 { "UNICODE (Hindi)", { "iso10646-1", NULL, NULL, }, },
62 { "UNICODE (Bengali)", { "iso10646-1", NULL, NULL, }, },
63 { "UNICODE (Punjabi)", { "iso10646-1", NULL, NULL, }, },
64 { "UNICODE (Gujarati)", { "iso10646-1", NULL, NULL, }, },
65 { "UNICODE (Oriya)", { "iso10646-1", NULL, NULL, }, },
66 { "UNICODE (Tamil)", { "iso10646-1", NULL, NULL, }, },
67 { "UNICODE (Telugu)", { "iso10646-1", NULL, NULL, }, },
68 { "UNICODE (Kannada)", { "iso10646-1", NULL, NULL, }, },
69 { "UNICODE (Malayalam)", { "iso10646-1", NULL, NULL, }, },
70
71 { "DEC_SPECIAL", { "iso8859-1", NULL, NULL, }, },
72 { "ISO8859_1", { "iso8859-1", NULL, NULL, }, },
73 { "ISO8859_2", { "iso8859-2", NULL, NULL, }, },
74 { "ISO8859_3", { "iso8859-3", NULL, NULL, }, },
75 { "ISO8859_4", { "iso8859-4", NULL, NULL, }, },
76 { "ISO8859_5", { "iso8859-5", NULL, NULL, }, },
77 { "ISO8859_6", { "iso8859-6", NULL, NULL, }, },
78 { "ISO8859_7", { "iso8859-7", NULL, NULL, }, },
79 { "ISO8859_8", { "iso8859-8", NULL, NULL, }, },
80 { "ISO8859_9", { "iso8859-9", NULL, NULL, }, },
81 { "ISO8859_10", { "iso8859-10", NULL, NULL, }, },
82 { "TIS620", { "tis620.2533-1", "tis620.2529-1", NULL, }, },
83 { "ISO8859_13", { "iso8859-13", NULL, NULL, }, },
84 { "ISO8859_14", { "iso8859-14", NULL, NULL, }, },
85 { "ISO8859_15", { "iso8859-15", NULL, NULL, }, },
86 { "ISO8859_16", { "iso8859-16", NULL, NULL, }, },
87
88 /*
89 * XXX
90 * The encoding of TCVN font is iso8859-1, and its font family is .VnTime or
91 * .VnTimeH... How to deal with it ?
92 */
93 { "TCVN5712", { NULL, NULL, NULL, }, },
94
95 { "ISCII_ASSAMESE", { NULL, NULL, NULL, }, },
96 { "ISCII_BENGALI", { NULL, NULL, NULL, }, },
97 { "ISCII_GUJARATI", { NULL, NULL, NULL, }, },
98 { "ISCII_HINDI", { NULL, NULL, NULL, }, },
99 { "ISCII_KANNADA", { NULL, NULL, NULL, }, },
100 { "ISCII_MALAYALAM", { NULL, NULL, NULL, }, },
101 { "ISCII_ORIYA", { NULL, NULL, NULL, }, },
102 { "ISCII_PUNJABI", { NULL, NULL, NULL, }, },
103 { "ISCII_TAMIL", { NULL, NULL, NULL, }, },
104 { "ISCII_TELUGU", { NULL, NULL, NULL, }, },
105 { "VISCII", { "viscii-1", NULL, NULL, }, },
106 { "KOI8_R", { "koi8-r", NULL, NULL, }, },
107 { "KOI8_U", { "koi8-u", NULL, NULL, }, },
108
109 #if 0
110 /*
111 * XXX
112 * KOI8_T, GEORGIAN_PS and CP125X charset can be shown by unicode font only.
113 */
114 { "KOI8_T", { NULL, NULL, NULL, }, },
115 { "GEORGIAN_PS", { NULL, NULL, NULL, }, },
116 #endif
117 #ifdef USE_WIN32GUI
118 { "CP1250", { NULL, NULL, NULL, }, },
119 { "CP1251", { NULL, NULL, NULL, }, },
120 { "CP1252", { NULL, NULL, NULL, }, },
121 { "CP1253", { NULL, NULL, NULL, }, },
122 { "CP1254", { NULL, NULL, NULL, }, },
123 { "CP1255", { NULL, NULL, NULL, }, },
124 { "CP1256", { NULL, NULL, NULL, }, },
125 { "CP1257", { NULL, NULL, NULL, }, },
126 { "CP1258", { NULL, NULL, NULL, }, },
127 { "CP874", { NULL, NULL, NULL, }, },
128 #endif
129
130 { "JISX0201_KATA", { "jisx0201.1976-0", NULL, NULL, }, },
131 { "JISX0201_ROMAN", { "jisx0201.1976-0", NULL, NULL, }, },
132 { "JISX0208_1978", { "jisx0208.1978-0", "jisx0208.1983-0", NULL, }, },
133 { "JISX0208_1983", { "jisx0208.1983-0", "jisx0208.1990-0", NULL, }, },
134 { "JISX0208_1990", { "jisx0208.1990-0", "jisx0208.1983-0", NULL, }, },
135 { "JISX0212_1990", { "jisx0212.1990-0", NULL, NULL, }, },
136 { "JISX0213_2000_1", { "jisx0213.2000-1", "jisx0208.1983-0", NULL, }, },
137 { "JISX0213_2000_2", { "jisx0213.2000-2", NULL, NULL, }, },
138 { "KSX1001_1997", { "ksc5601.1987-0", "ksx1001.1997-0", NULL, }, },
139
140 #if 0
141 /*
142 * XXX
143 * UHC and JOHAB fonts are not used at the present time.
144 * see vt_vt100_parser.c:vt_parse_vt100_sequence().
145 */
146 { "UHC", { NULL, NULL, NULL, }, },
147 { "JOHAB", { "johabsh-1", /* "johabs-1" , */ "johab-1", NULL, }, },
148 #endif
149
150 { "GB2312_80", { "gb2312.1980-0", NULL, NULL, }, },
151 { "GBK", { "gbk-0", NULL, NULL, }, },
152 { "BIG5", { "big5.eten-0", "big5.hku-0", NULL, }, },
153 { "HKSCS", { "big5hkscs-0", "big5-0", NULL, }, },
154 { "CNS11643_1992_1", { "cns11643.1992-1", "cns11643.1992.1-0", NULL, }, },
155 { "CNS11643_1992_2", { "cns11643.1992-2", "cns11643.1992.2-0", NULL, }, },
156 { "CNS11643_1992_3", { "cns11643.1992-3", "cns11643.1992.3-0", NULL, }, },
157 { "CNS11643_1992_4", { "cns11643.1992-4", "cns11643.1992.4-0", NULL, }, },
158 { "CNS11643_1992_5", { "cns11643.1992-5", "cns11643.1992.5-0", NULL, }, },
159 { "CNS11643_1992_6", { "cns11643.1992-6", "cns11643.1992.6-0", NULL, }, },
160 { "CNS11643_1992_7", { "cns11643.1992-7", "cns11643.1992.7-0", NULL, }, },
161 };
162
163 static char *new_fontsize = NULL;
164 static char *old_fontsize = NULL;
165 static int is_fontsize_changed;
166
167 static char *new_fontname_list[sizeof(cs_info_table) / sizeof(cs_info_table[0])];
168 static int dont_change_new_fontname_list = 0;
169 static int selected_cs = 0; /* 0 = DEFAULT */
170 static GtkWidget *fontcs_entry;
171 static GtkWidget *fontname_entry;
172 static GtkWidget *select_font_button;
173 static GtkWidget *xft_flag;
174 static GtkWidget *cairo_flag;
175 static GtkWidget *aa_flag;
176 static GtkWidget *vcol_flag;
177 static int dont_change_type_engine;
178 static GtkWidget *noconv_areas_button;
179 static char *noconv_areas;
180
181 /* --- static functions --- */
182
reset_fontname_list(void)183 static void reset_fontname_list(void) {
184 int count;
185
186 for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) {
187 free(new_fontname_list[count]);
188 new_fontname_list[count] = NULL;
189 }
190 }
191
192 /*
193 * If you use functions in mc_io.c, use this function instead of direct
194 * access to cs_info_t::cs.
195 */
get_correct_cs(int idx)196 static const char *get_correct_cs(int idx) {
197 const char *unicode_names[] = {
198 "ISO10646_UCS4_1", "ISO10646_UCS4_1_FULLWIDTH", "U+1F000-1F77F", /* Emoji */
199 "U+FF61-FF9F", /* Hankaku Kana */
200 "U+0590-05FF", /* Hebrew */
201 "U+0600-06FF", /* Arabic */
202 "U+0900-097F", /* Hindi */
203 "U+0980-09FF", /* Bengali */
204 "U+0A00-0A7F", /* Punjabi */
205 "U+0A80-0AFF", /* Gujarati */
206 "U+0B00-0B7F", /* Oriya */
207 "U+0B80-0BFF", /* Tamil */
208 "U+0C00-0C7F", /* Telugu */
209 "U+0C80-0CFF", /* Kannada */
210 "U+0D00-0D7F", /* Malayalam */
211 };
212
213 if (idx < 0) {
214 return NULL;
215 } else if (1 <= idx && idx <= 15) {
216 return unicode_names[idx - 1];
217 } else if (idx < sizeof(cs_info_table) / sizeof(cs_info_table[0])) {
218 return cs_info_table[idx].cs;
219 } else {
220 return NULL;
221 }
222 }
223
get_font_file(void)224 static char *get_font_file(void) {
225 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xft_flag)) ||
226 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cairo_flag)) ||
227 mc_get_flag_value("use_aafont")) {
228 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vcol_flag))) {
229 return "vaafont";
230 } else if (mc_radio_get_value(MC_RADIO_VERTICAL_MODE)) {
231 return "taafont";
232 } else {
233 return "aafont";
234 }
235 } else {
236 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vcol_flag))) {
237 return "vfont";
238 } else if (mc_radio_get_value(MC_RADIO_VERTICAL_MODE)) {
239 return "tfont";
240 } else {
241 return "font";
242 }
243 }
244 }
245
aa_flag_checked(GtkWidget * widget,gpointer data)246 static gint aa_flag_checked(GtkWidget *widget, gpointer data) {
247 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
248 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xft_flag)) &&
249 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cairo_flag))) {
250 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xft_flag), 1);
251
252 reset_fontname_list();
253 gtk_entry_set_text(
254 GTK_ENTRY(fontname_entry),
255 g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL,
256 NULL, NULL));
257 }
258 }
259
260 return 1;
261 }
262
xft_flag_checked(GtkWidget * widget,gpointer data)263 static gint xft_flag_checked(GtkWidget *widget, gpointer data) {
264 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) &&
265 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cairo_flag))) {
266 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(aa_flag), 0);
267 } else if (!dont_change_type_engine) {
268 dont_change_type_engine = 1;
269 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cairo_flag), 0);
270 dont_change_type_engine = 0;
271 }
272
273 reset_fontname_list();
274 gtk_entry_set_text(
275 GTK_ENTRY(fontname_entry),
276 g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL,
277 NULL, NULL));
278
279 return 1;
280 }
281
cairo_flag_checked(GtkWidget * widget,gpointer data)282 static gint cairo_flag_checked(GtkWidget *widget, gpointer data) {
283 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) &&
284 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xft_flag))) {
285 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(aa_flag), 0);
286 } else if (!dont_change_type_engine) {
287 dont_change_type_engine = 1;
288 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xft_flag), 0);
289 dont_change_type_engine = 0;
290 }
291
292 reset_fontname_list();
293 gtk_entry_set_text(
294 GTK_ENTRY(fontname_entry),
295 g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL,
296 NULL, NULL));
297
298 return 1;
299 }
300
vcol_flag_checked(GtkWidget * widget,gpointer data)301 static gint vcol_flag_checked(GtkWidget *widget, gpointer data) {
302 reset_fontname_list();
303 gtk_entry_set_text(
304 GTK_ENTRY(fontname_entry),
305 g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL,
306 NULL, NULL));
307
308 return 1;
309 }
310
vertical_mode_changed(void)311 static void vertical_mode_changed(void) {
312 reset_fontname_list();
313 gtk_entry_set_text(
314 GTK_ENTRY(fontname_entry),
315 g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL,
316 NULL, NULL));
317
318 if (mc_radio_get_value(MC_RADIO_VERTICAL_MODE)) {
319 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vcol_flag), 0);
320 gtk_widget_set_sensitive(vcol_flag, 0);
321 } else {
322 gtk_widget_set_sensitive(vcol_flag, 1);
323 }
324 }
325
fontsize_selected(GtkWidget * widget,gpointer data)326 static gint fontsize_selected(GtkWidget *widget, gpointer data) {
327 g_free(new_fontsize);
328 new_fontsize = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1);
329
330 #ifdef __DEBUG
331 bl_debug_printf(BL_DEBUG_TAG " %s font size is selected.\n", new_fontsize);
332 #endif
333
334 return 1;
335 }
336
specify_width(GtkWidget * widget,int flag)337 static void specify_width(GtkWidget *widget, int flag) {
338 gchar *fontname;
339
340 if (((fontname = new_fontname_list[selected_cs]) ||
341 (fontname = gtk_entry_get_text(GTK_ENTRY(fontname_entry)))) &&
342 *fontname) {
343 gchar *p;
344 int percent;
345 size_t len;
346
347 if (!(p = strrchr(fontname, ':')) || (percent = atoi(p + 1)) == 0) {
348 if (flag == 0) {
349 return;
350 }
351
352 len = strlen(fontname);
353 percent = (flag < 0 ? 100 : 110);
354 } else {
355 len = p - fontname;
356
357 if (flag == 0) {
358 percent = 0;
359 } else {
360 percent += (flag < 0 ? -10 : 10);
361
362 if (percent <= 0 || 200 < percent) {
363 return;
364 }
365 }
366 }
367
368 if ((p = malloc(len + 5))) {
369 strncpy(p, fontname, len);
370 if (percent == 0) {
371 p[len] = '\0';
372 } else {
373 sprintf(p + len, ":%d", percent);
374 }
375 free(new_fontname_list[selected_cs]);
376 new_fontname_list[selected_cs] = p;
377
378 dont_change_new_fontname_list = 1;
379 gtk_entry_set_text(GTK_ENTRY(fontname_entry), p);
380 dont_change_new_fontname_list = 0;
381 }
382 }
383 }
384
widen_width(GtkWidget * widget,gpointer data)385 static void widen_width(GtkWidget *widget, gpointer data) { specify_width(widget, 1); }
386
narrow_width(GtkWidget * widget,gpointer data)387 static void narrow_width(GtkWidget *widget, gpointer data) { specify_width(widget, -1); }
388
default_width(GtkWidget * widget,gpointer data)389 static void default_width(GtkWidget *widget, gpointer data) { specify_width(widget, 0); }
390
fontcs_changed(void)391 static void fontcs_changed(void) {
392 dont_change_new_fontname_list = 1;
393
394 if (new_fontname_list[selected_cs]) {
395 gtk_entry_set_text(GTK_ENTRY(fontname_entry), new_fontname_list[selected_cs]);
396 } else {
397 gtk_entry_set_text(
398 GTK_ENTRY(fontname_entry),
399 g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL,
400 NULL, NULL));
401 }
402
403 dont_change_new_fontname_list = 0;
404 }
405
406 /* compare two encoding names, returns non-zero if equal
407 */
compare(const char * e1,const char * e2)408 static int compare(const char *e1, const char *e2) {
409 while (1) {
410 /* ')' is for "auto (currently EUC-JP)" */
411 if (*e1 == '-' || *e1 == '_' || *e1 == ')') {
412 e1++;
413 continue;
414 }
415 if (*e2 == '-' || *e2 == '_' || *e2 == ')') {
416 e2++;
417 continue;
418 }
419 if ((*e1 == 0 || *e1 == ' ') && (*e2 == 0 || *e2 == ' ')) {
420 return 1;
421 }
422 if (toupper(*e1) != toupper(*e2)) {
423 return 0;
424 }
425 e1++;
426 e2++;
427 }
428 }
429
fontcs_map(GtkWidget * widget,gpointer data)430 static void fontcs_map(GtkWidget *widget, gpointer data) {
431 char *encoding;
432 int count;
433
434 encoding = mc_get_char_encoding();
435
436 if ((strstr(encoding, "UTF") && mc_radio_get_value(MC_RADIO_FONT_POLICY) != 2) ||
437 mc_radio_get_value(MC_RADIO_FONT_POLICY) == 1) {
438 if (selected_cs == 1) {
439 return;
440 }
441
442 selected_cs = 1; /* UNICODE */
443 } else {
444 for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) {
445 if (strcmp(cs_info_table[count].cs, "JISX0201_KATA") == 0) {
446 break;
447 } else if (compare(encoding, cs_info_table[count].cs)) {
448 if (selected_cs == count) {
449 return;
450 }
451
452 selected_cs = count;
453
454 goto update_cs;
455 }
456 }
457
458 if (selected_cs == 0) {
459 return;
460 }
461
462 selected_cs = 0; /* DEFAULT */
463 }
464
465 update_cs:
466 gtk_entry_set_text(GTK_ENTRY(widget), cs_info_table[selected_cs].cs);
467 fontcs_changed();
468 }
469
font_policy_changed(void)470 static void font_policy_changed(void) {
471 fontcs_map(fontcs_entry, NULL);
472
473 if (noconv_areas_button) {
474 gtk_widget_set_sensitive(noconv_areas_button, (mc_radio_get_value(MC_RADIO_FONT_POLICY) == 2));
475 }
476 }
477
fontcs_selected(GtkWidget * widget,gpointer data)478 static gint fontcs_selected(GtkWidget *widget, gpointer data) {
479 const char *cs;
480 int count;
481
482 cs = gtk_entry_get_text(GTK_ENTRY(widget));
483
484 for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) {
485 if (strcmp(cs, cs_info_table[count].cs) == 0) {
486 if (selected_cs != count) {
487 #if 0
488 bl_debug_printf("Before: cs %s fontname %s => ", cs_info_table[selected_cs].cs,
489 new_fontname_list[selected_cs]);
490 #endif
491
492 selected_cs = count;
493
494 fontcs_changed();
495
496 #if 0
497 bl_debug_printf("After: cs %s fontname %s\n", cs, new_fontname_list[selected_cs]);
498 #endif
499
500 return 1;
501 }
502 }
503 }
504
505 return 0;
506 }
507
508 #if defined(GDK_WINDOWING_X11) && !GTK_CHECK_VERSION(2, 90, 0)
509
get_xlfd_font_name(gpointer dialog)510 static gchar *get_xlfd_font_name(gpointer dialog) {
511 char *name;
512
513 name = gtk_xlfd_selection_dialog_get_font_name(GTK_XLFD_SELECTION_DIALOG(dialog));
514 if (selected_cs == 0 && name && *name) /* DEFAULT */
515 {
516 /*
517 * Removing font encoding such as "iso8859-1".
518 */
519
520 char *p;
521
522 if ((p = strrchr(name, '-'))) {
523 *p = '\0';
524 if ((p = strrchr(name, '-'))) {
525 *(p + 1) = '\0';
526 }
527 }
528 }
529
530 return name;
531 }
532
ok_pressed(GtkWidget * widget,gpointer dialog)533 static void ok_pressed(GtkWidget *widget, gpointer dialog) {
534 gchar *name;
535
536 name = get_xlfd_font_name(dialog);
537 gtk_entry_set_text(GTK_ENTRY(fontname_entry), name);
538 g_free(name);
539
540 gtk_widget_destroy(GTK_WIDGET(dialog));
541 }
542
apply_pressed(GtkWidget * widget,gpointer dialog)543 static void apply_pressed(GtkWidget *widget, gpointer dialog) {
544 gchar *name;
545
546 name = get_xlfd_font_name(dialog);
547 gtk_entry_set_text(GTK_ENTRY(fontname_entry), name);
548 g_free(name);
549 }
550
cancel_pressed(GtkWidget * widget,gpointer dialog)551 static void cancel_pressed(GtkWidget *widget, gpointer dialog) {
552 gtk_widget_destroy(GTK_WIDGET(dialog));
553 }
554
set_current_font_name(GtkWidget * dialog)555 static int set_current_font_name(GtkWidget *dialog) {
556 const gchar *font_name;
557
558 font_name = gtk_entry_get_text(GTK_ENTRY(fontname_entry));
559 if (font_name && *font_name) {
560 char *p;
561
562 /*
563 * Modify DEFAULT font name. "-*-...-*-" => "-*-...-*-*-*"
564 */
565 if (selected_cs == 0 && (p = alloca(strlen(font_name) + 4))) {
566 sprintf(p, "%s*-*", font_name);
567 font_name = p;
568 }
569
570 return gtk_xlfd_selection_dialog_set_font_name(GTK_XLFD_SELECTION_DIALOG(dialog), font_name);
571 } else {
572 return 0;
573 }
574 }
575
select_xlfd_font(GtkWidget * widget,gpointer label)576 static void select_xlfd_font(GtkWidget *widget, gpointer label) {
577 GtkWidget *dialog;
578
579 dialog = gtk_xlfd_selection_dialog_new("Select Font");
580 if (!set_current_font_name(dialog)) {
581 char *encoding;
582 char *font_name;
583 char format[] = "-misc-fixed-medium-*-normal-*-%s-*-*-*-*-*-%s";
584
585 if ((encoding = cs_info_table[selected_cs].encoding_names[0]) == NULL) {
586 encoding = "*-*";
587 }
588
589 if ((font_name = alloca(sizeof(format) + strlen(new_fontsize) + strlen(encoding)))) {
590 sprintf(font_name, format, new_fontsize, encoding);
591
592 gtk_xlfd_selection_dialog_set_font_name(GTK_XLFD_SELECTION_DIALOG(dialog), font_name);
593 }
594 }
595
596 if (cs_info_table[selected_cs].encoding_names[0]) {
597 gtk_xlfd_selection_dialog_set_filter(GTK_XLFD_SELECTION_DIALOG(dialog), GTK_XLFD_FILTER_USER,
598 GTK_XLFD_ALL, NULL, NULL, NULL, NULL, NULL,
599 cs_info_table[selected_cs].encoding_names);
600 }
601
602 g_signal_connect(GTK_XLFD_SELECTION_DIALOG(dialog)->ok_button, "clicked", G_CALLBACK(ok_pressed),
603 dialog);
604 g_signal_connect(GTK_XLFD_SELECTION_DIALOG(dialog)->apply_button, "clicked",
605 G_CALLBACK(apply_pressed), dialog);
606 g_signal_connect(GTK_XLFD_SELECTION_DIALOG(dialog)->cancel_button, "clicked",
607 G_CALLBACK(cancel_pressed), dialog);
608
609 gtk_widget_show_all(dialog);
610 }
611
612 #endif
613
my_gtk_font_selection_dialog_get_font_name(GtkFontSelectionDialog * dialog)614 static char *my_gtk_font_selection_dialog_get_font_name(GtkFontSelectionDialog *dialog) {
615 char *str;
616 int count;
617 char *p;
618 char *dup_str;
619
620 str = gtk_font_selection_dialog_get_font_name(dialog);
621
622 if ((dup_str = malloc(strlen(str) * 2 + 1)) == NULL) {
623 free(str);
624
625 return NULL;
626 }
627
628 /* Escape '-' in Xft. */
629 count = 0;
630 p = str;
631 while (*p) {
632 #ifndef USE_WIN32GUI
633 if (*p == '-') {
634 dup_str[count++] = '\\';
635 }
636 #endif
637
638 dup_str[count++] = *(p++);
639 }
640
641 dup_str[count] = '\0';
642
643 g_free(str);
644
645 return dup_str;
646 }
647
get_gtk_font_name(const char * font_name)648 static char *get_gtk_font_name(const char *font_name) {
649 int count;
650 char *str;
651
652 if ((str = malloc(strlen(font_name) + 1)) == NULL) {
653 return NULL;
654 }
655
656 count = 0;
657 while (*font_name && *font_name != '-') {
658 if (*font_name == '\\') {
659 font_name++;
660 }
661
662 str[count++] = *(font_name++);
663 }
664
665 str[count] = '\0';
666
667 return str;
668 }
669
fontname_entry_edit(GtkWidget * widget,gpointer p)670 static void fontname_entry_edit(GtkWidget *widget, gpointer p) {
671 /* In case fontname is editted in text entry widget. */
672
673 if (!dont_change_new_fontname_list) {
674 const char *name;
675
676 if (!(name = gtk_entry_get_text(GTK_ENTRY(fontname_entry)))) {
677 if (new_fontname_list[selected_cs]) {
678 /*
679 * Font name for selected_cs was specfied, but now
680 * font name for selected_cs is cleared.
681 */
682 name = "";
683 }
684 }
685
686 if (name) {
687 free(new_fontname_list[selected_cs]);
688 new_fontname_list[selected_cs] = strdup(name);
689 }
690 }
691 }
692
select_fc_font(GtkWidget * widget,gpointer p)693 static void select_fc_font(GtkWidget *widget, gpointer p) {
694 GtkWidget *dialog;
695 char *font_name;
696 GtkResponseType result;
697
698 dialog = gtk_font_selection_dialog_new("Select Font");
699
700 font_name = get_gtk_font_name(gtk_entry_get_text(GTK_ENTRY(fontname_entry)));
701 if (!font_name || !*font_name ||
702 !gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), font_name)) {
703 free(font_name);
704
705 if ((font_name = malloc(6 + strlen(new_fontsize))) == NULL) {
706 return;
707 }
708
709 sprintf(font_name, "Sans %s", new_fontsize);
710
711 gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), font_name);
712 }
713
714 free(font_name);
715
716 result = gtk_dialog_run(GTK_DIALOG(dialog));
717 if (result == GTK_RESPONSE_OK) {
718 gtk_entry_set_text(GTK_ENTRY(fontname_entry), my_gtk_font_selection_dialog_get_font_name(
719 GTK_FONT_SELECTION_DIALOG(dialog)));
720 }
721
722 gtk_widget_destroy(dialog);
723 }
724
select_font(GtkWidget * widget,gpointer p)725 static void select_font(GtkWidget *widget, gpointer p) {
726 #if defined(GDK_WINDOWING_X11) && !GTK_CHECK_VERSION(2, 90, 0)
727 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xft_flag)) &&
728 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cairo_flag)) &&
729 strcmp(mc_get_gui(), "xlib") == 0) {
730 select_xlfd_font(widget, p);
731 } else
732 #endif
733 {
734 select_fc_font(widget, p);
735 }
736 }
737
edit_noconv_areas(GtkWidget * widget,gpointer data)738 static void edit_noconv_areas(GtkWidget *widget, gpointer data) {
739 char *cur_areas;
740 char *new_areas;
741
742 if (noconv_areas) {
743 cur_areas = strdup(noconv_areas);
744 } else {
745 cur_areas = mc_get_str_value("unicode_noconv_areas");
746 }
747
748 if ((new_areas = mc_get_unicode_areas(cur_areas)) &&
749 bl_compare_str(noconv_areas, new_areas) != 0) {
750 free(noconv_areas);
751 noconv_areas = new_areas;
752 }
753
754 free(cur_areas);
755 }
756
757 /* --- global functions --- */
758
mc_font_config_widget_new(void)759 GtkWidget *mc_font_config_widget_new(void) {
760 GtkWidget *vbox;
761 GtkWidget *hbox;
762 GtkWidget *fgcolor;
763 GtkWidget *combo;
764 GtkWidget *entry;
765 GtkWidget *radio;
766 GtkWidget *label;
767 GtkWidget *button;
768 char *fontlist[] = {
769 "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18",
770 "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30",
771 };
772 char **cslist;
773
774 new_fontsize = strdup(old_fontsize = mc_get_str_value("fontsize"));
775 is_fontsize_changed = 0;
776
777 vbox = gtk_vbox_new(FALSE, 0);
778
779 hbox = gtk_hbox_new(FALSE, 0);
780 gtk_widget_show(hbox);
781 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
782
783 combo =
784 mc_combo_new_with_width(_("Font size (pixels)"), fontlist,
785 sizeof(fontlist) / sizeof(fontlist[0]), new_fontsize, 1, 30, &entry);
786 g_signal_connect(entry, "changed", G_CALLBACK(fontsize_selected), NULL);
787 gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0);
788 #if GTK_CHECK_VERSION(2, 12, 0)
789 gtk_widget_set_tooltip_text(combo,
790 "If you change fonts from \"Select\" button, "
791 "it is not recommended to change font size here.");
792 #endif
793
794 fgcolor = mc_color_config_widget_new(MC_COLOR_FG);
795 gtk_widget_show(fgcolor);
796 gtk_box_pack_start(GTK_BOX(hbox), fgcolor, FALSE, FALSE, 5);
797
798 hbox = gtk_hbox_new(FALSE, 0);
799 gtk_widget_show(hbox);
800
801 xft_flag = mc_flag_config_widget_new(MC_FLAG_XFT);
802 gtk_widget_show(xft_flag);
803 gtk_box_pack_start(GTK_BOX(hbox), xft_flag, FALSE, FALSE, 0);
804 g_signal_connect(xft_flag, "toggled", G_CALLBACK(xft_flag_checked), NULL);
805 if (strcmp(mc_get_gui(), "xlib") != 0) {
806 gtk_widget_set_sensitive(xft_flag, 0);
807 }
808
809 cairo_flag = mc_flag_config_widget_new(MC_FLAG_CAIRO);
810 gtk_widget_show(cairo_flag);
811 gtk_box_pack_start(GTK_BOX(hbox), cairo_flag, FALSE, FALSE, 0);
812 g_signal_connect(cairo_flag, "toggled", G_CALLBACK(cairo_flag_checked), NULL);
813 if (strcmp(mc_get_gui(), "xlib") != 0) {
814 gtk_widget_set_sensitive(cairo_flag, 0);
815 }
816
817 aa_flag = mc_flag_config_widget_new(MC_FLAG_AA);
818 gtk_widget_show(aa_flag);
819 gtk_box_pack_start(GTK_BOX(hbox), aa_flag, FALSE, FALSE, 0);
820 g_signal_connect(aa_flag, "toggled", G_CALLBACK(aa_flag_checked), NULL);
821
822 vcol_flag = mc_flag_config_widget_new(MC_FLAG_VCOL);
823 gtk_widget_show(vcol_flag);
824 gtk_box_pack_start(GTK_BOX(hbox), vcol_flag, FALSE, FALSE, 0);
825 g_signal_connect(vcol_flag, "toggled", G_CALLBACK(vcol_flag_checked), NULL);
826 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
827
828 radio = mc_radio_config_widget_new(MC_RADIO_VERTICAL_MODE);
829 gtk_widget_show(radio);
830 gtk_box_pack_start(GTK_BOX(vbox), radio, FALSE, FALSE, 0);
831 mc_radio_set_callback(MC_RADIO_VERTICAL_MODE, vertical_mode_changed);
832 if (mc_radio_get_value(MC_RADIO_VERTICAL_MODE)) {
833 gtk_widget_set_sensitive(vcol_flag, 0);
834 }
835
836 hbox = gtk_hbox_new(FALSE, 0);
837 gtk_widget_show(hbox);
838
839 if ((cslist = alloca(sizeof(char*) * sizeof(cs_info_table) / sizeof(cs_info_table[0])))) {
840 int count;
841
842 for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) {
843 cslist[count] = cs_info_table[count].cs;
844 }
845
846 combo = mc_combo_new_with_width(_("Font name"), cslist, count, cslist[selected_cs], 1, 90,
847 &fontcs_entry);
848 g_signal_connect(fontcs_entry, "changed", G_CALLBACK(fontcs_selected), NULL);
849 g_signal_connect(fontcs_entry, "map", G_CALLBACK(fontcs_map), NULL);
850 gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0);
851 }
852
853 fontname_entry = gtk_entry_new();
854 gtk_entry_set_text(
855 GTK_ENTRY(fontname_entry),
856 g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL,
857 NULL, NULL));
858 gtk_widget_show(fontname_entry);
859 gtk_box_pack_start(GTK_BOX(hbox), fontname_entry, TRUE, TRUE, 1);
860 g_signal_connect(fontname_entry, "changed", G_CALLBACK(fontname_entry_edit), NULL);
861
862 select_font_button = gtk_button_new_with_label(_("Select"));
863 gtk_widget_show(select_font_button);
864 gtk_box_pack_start(GTK_BOX(hbox), select_font_button, FALSE, FALSE, 1);
865 g_signal_connect(select_font_button, "clicked", G_CALLBACK(select_font), NULL);
866
867 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
868
869 hbox = gtk_hbox_new(FALSE, 0);
870 gtk_widget_show(hbox);
871
872 label = gtk_label_new(_("Font width"));
873 gtk_widget_show(label);
874 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
875
876 button = gtk_button_new_with_label(_("Narrow"));
877 gtk_widget_show(button);
878 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
879 g_signal_connect(button, "clicked", G_CALLBACK(narrow_width), NULL);
880
881 button = gtk_button_new_with_label(_("Widen"));
882 gtk_widget_show(button);
883 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
884 g_signal_connect(button, "clicked", G_CALLBACK(widen_width), NULL);
885
886 button = gtk_button_new_with_label(_("Default"));
887 gtk_widget_show(button);
888 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
889 g_signal_connect(button, "clicked", G_CALLBACK(default_width), NULL);
890
891 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
892
893 radio = mc_radio_config_widget_new(MC_RADIO_FONT_POLICY);
894 gtk_widget_show(radio);
895 gtk_box_pack_start(GTK_BOX(vbox), radio, FALSE, FALSE, 0);
896 mc_radio_set_callback(MC_RADIO_FONT_POLICY, font_policy_changed);
897
898 hbox = gtk_hbox_new(FALSE, 0);
899 gtk_widget_show(hbox);
900
901 label = gtk_label_new(_("Unicode areas you won't convert to other charsets"));
902 gtk_widget_show(label);
903 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
904 noconv_areas_button = gtk_button_new_with_label(_(" Edit "));
905 gtk_widget_show(noconv_areas_button);
906 gtk_box_pack_start(GTK_BOX(hbox), noconv_areas_button, FALSE, FALSE, 0);
907 g_signal_connect(noconv_areas_button, "clicked", G_CALLBACK(edit_noconv_areas), NULL);
908 if (mc_radio_get_value(MC_RADIO_FONT_POLICY) != 2) {
909 gtk_widget_set_sensitive(noconv_areas_button, 0);
910 }
911
912 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
913
914 radio = mc_radio_config_widget_new(MC_RADIO_BOX_DRAWING);
915 gtk_widget_show(radio);
916 gtk_box_pack_start(GTK_BOX(vbox), radio, FALSE, FALSE, 0);
917
918 return vbox;
919 }
920
mc_update_font_misc(void)921 void mc_update_font_misc(void) {
922 if (strcmp(new_fontsize, old_fontsize)) is_fontsize_changed = 1;
923
924 if (is_fontsize_changed) {
925 mc_set_str_value("fontsize", new_fontsize);
926 free(old_fontsize);
927 old_fontsize = strdup(new_fontsize);
928 }
929
930 /*
931 * MC_FLAG_{XFT|CAIRO} should be updated last because MC_FLAG_{XFT|CAIRO} are
932 * invalid in some environments.
933 */
934 mc_update_flag_mode(MC_FLAG_AA);
935 mc_update_radio(MC_RADIO_VERTICAL_MODE);
936 /* vcol is forcibly disabled in vertical mode, so update after vertical mode.
937 */
938 mc_update_flag_mode(MC_FLAG_VCOL);
939 mc_update_flag_mode(MC_FLAG_XFT);
940 mc_update_flag_mode(MC_FLAG_CAIRO);
941 mc_update_radio(MC_RADIO_BOX_DRAWING);
942 mc_update_radio(MC_RADIO_FONT_POLICY);
943
944 if (noconv_areas) {
945 mc_set_str_value("unicode_noconv_areas", noconv_areas);
946 }
947 }
948
mc_update_font_name(mc_io_t io)949 void mc_update_font_name(mc_io_t io) {
950 size_t count;
951
952 for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) {
953 if (new_fontname_list[count]) {
954 mc_set_font_name(io, get_font_file(), get_correct_cs(count), new_fontname_list[count]);
955
956 if (count == 6) {
957 /* Arabic Supplement */
958 mc_set_font_name(io, get_font_file(), "U+0750-77F", new_fontname_list[count]);
959 /* Arabic Extended-A */
960 mc_set_font_name(io, get_font_file(), "U+08A0-8FF", new_fontname_list[count]);
961 /* Arabic Presentation Forms-A */
962 mc_set_font_name(io, get_font_file(), "U+FB50-FDFF", new_fontname_list[count]);
963 /* Arabic Presentation Forms-B */
964 mc_set_font_name(io, get_font_file(), "U+FE70-FEFF", new_fontname_list[count]);
965 /* Arabic Mathematical Alphabetic Symbols */
966 mc_set_font_name(io, get_font_file(), "U+1EE00-1EEFF", new_fontname_list[count]);
967 }
968 }
969 }
970 }
971