1 /*
2 * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "gbdfed.h"
24 #include "labcon.h"
25
26 #ifdef HAVE_XLIB
27 #include <gdk/gdkx.h>
28 #endif
29
30 /*
31 * These are formats that can appear in the editor for importing/loading and
32 * exporting fonts.
33 */
34 #define BDF_FORMAT 1
35 #define CONSOLE_FORMAT 2
36 #define PKGF_FORMAT 3
37 #define FNT_FORMAT 4
38 #define HBF_FORMAT 5
39 #define OTF_FORMAT 6
40 #define HEX_FORMAT 7
41 #define PSF_FORMAT 8
42 #define PSFUNI_FORMAT 9
43
44 /*
45 * An array of filters used for the open/import and save dialogs.
46 */
47 static GtkFileFilter *filename_filters[10];
48
49 /*
50 * This variable is used to track whether the save dialog has been closed
51 * so the guifile_save_as_wait() routine knows when to return to the main
52 * application.
53 */
54 static gboolean save_dialog_done;
55
56 #ifdef HAVE_FREETYPE
57
58 #include FT_GLYPH_H
59 #include FT_SFNT_NAMES_H
60 #include FT_TRUETYPE_TABLES_H
61
62 /*
63 * Globals used for FreeType.
64 */
65 static FT_Library library;
66 static FT_Face face;
67
68 /*
69 * Globals used for importing OpenType fonts.
70 */
71 static gboolean ftinit = FALSE;
72 static gboolean otf_collection;
73 static gboolean otf_face_open;
74 static gint otf_select_done = 0;
75 static gchar *otf_fullpath;
76
77 /*
78 * These are the widgets that will be needed for importing OpenType fonts.
79 */
80 static GtkWidget *otf_dialog;
81 static GtkWidget *otf_faces;
82 static GtkWidget *otf_platforms;
83 static GtkWidget *otf_encodings;
84 static GtkWidget *otf_point_size;
85 static GtkWidget *otf_hres;
86 static GtkWidget *otf_vres;
87
88 /*
89 * List of platform IDs seen that is used when platforms are selected
90 * from OpenType fonts.
91 */
92 static gint16 platforms[32];
93 static gint nplatforms;
94
95 /*
96 * List of encoding IDs seen that is used when encodings are selected
97 * from OpenType fonts.
98 */
99 static gint16 encodings[34];
100 static gint nencodings;
101
102 /*
103 * Variables to hold the selected platform and encoding ID's.
104 */
105 static gint16 otf_pid_pos;
106 static gint16 otf_eid_pos;
107
108 #endif /* HAVE_FREETYPE */
109
110 #ifdef HAVE_XLIB
111
112 /*
113 * These are for importing fonts from the X server.
114 */
115 #define _XSRV_MAX_FONTS 32767
116 #define _XSRV_DEFAULT_FILTER "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
117
118 static GtkWidget *xsrv_dialog;
119 static GtkWidget *xsrv_filter_text;
120 static GtkWidget *xsrv_selection_text;
121 static GtkWidget *xsrv_font_list;
122 static GtkWidget *xsrv_import;
123
124 /*
125 * Because the grab dialog is shared amongst the editors, this tracks which
126 * editor has control of the font list.
127 */
128 static guint xsrv_active_editor;
129
130 #endif /* HAVE_XLIB */
131
132 /*
133 * Widgets for dealing with exporting PSF fonts.
134 */
135 static GtkWidget *psf_export_frame;
136 static GtkWidget *psf_export_options;
137
138 /*
139 * Widgets for selecting fonts from a Windows font archive.
140 */
141 static GtkWidget *fnt_dialog;
142 static GtkWidget *fnt_font_list;
143 static GtkWidget *fnt_load_button;
144
145 /*
146 * This is a list of Windows fonts that have been selected. It assumes that
147 * the font file will never contain more than 32 fonts.
148 */
149 static gint fnt_selected[32];
150 static gint fnt_selected_count;
151
152 /*
153 * A structure used to pass data to the load and cancel callbacks when dealing
154 * with FON/FNT fonts.
155 */
156 typedef struct {
157 gchar *file;
158 gchar *dir;
159 gchar *dot;
160 bdffnt_font_t font;
161 } _bdffnt_callback_data_t;
162
163 /*
164 * This is used in a couple of cases to point at the active editor.
165 */
166 static gbdfed_editor_t *active_editor;
167
168 static void
make_file_chooser_filters(void)169 make_file_chooser_filters(void)
170 {
171 int i;
172
173 if (filename_filters[0] != NULL)
174 return;
175
176 filename_filters[BDF_FORMAT] = gtk_file_filter_new();
177 gtk_file_filter_add_pattern(filename_filters[BDF_FORMAT],
178 "*.[Bb][Dd][Ff]");
179
180 filename_filters[CONSOLE_FORMAT] = gtk_file_filter_new();
181 gtk_file_filter_add_pattern(filename_filters[CONSOLE_FORMAT], "*");
182
183 filename_filters[PKGF_FORMAT] = gtk_file_filter_new();
184 gtk_file_filter_add_pattern(filename_filters[PKGF_FORMAT],
185 "*[PpGg][KkFf]");
186
187 filename_filters[FNT_FORMAT] = gtk_file_filter_new();
188 gtk_file_filter_add_pattern(filename_filters[FNT_FORMAT],
189 "*.[FfEeDd][OoNnXxLl][NnTtEeLl]");
190
191 filename_filters[HEX_FORMAT] = gtk_file_filter_new();
192 gtk_file_filter_add_pattern(filename_filters[HEX_FORMAT],
193 "*.[Hh][Ee][Xx]");
194
195 filename_filters[PSF_FORMAT] = gtk_file_filter_new();
196 gtk_file_filter_add_pattern(filename_filters[PSF_FORMAT],
197 "*.[Ps][Ss][Ff]*");
198
199 /*
200 * This one is basically for exporting unimap files that belong to PSF
201 * fonts.
202 */
203 filename_filters[PSFUNI_FORMAT] = gtk_file_filter_new();
204 gtk_file_filter_add_pattern(filename_filters[PSFUNI_FORMAT],
205 "*.[Uu][Nn][Ii]");
206
207 #ifdef HAVE_HBF
208 filename_filters[HBF_FORMAT] = gtk_file_filter_new();
209 gtk_file_filter_add_pattern(filename_filters[HBF_FORMAT],
210 "*.[Hh][Bb][Ff]");
211 #endif
212
213 #ifdef HAVE_FREETYPE
214 filename_filters[OTF_FORMAT] = gtk_file_filter_new();
215 gtk_file_filter_add_pattern(filename_filters[OTF_FORMAT],
216 "*.[OoTt][Tt][FfCcEe]");
217 #endif /* HAVE_FREETYPE */
218
219 filename_filters[0] = (GtkFileFilter *) 1;
220
221 /*
222 * Add a reference to all the filters so they don't cause a delayed crash
223 * when popping up the import dialog multiple times.
224 */
225 for (i = 1; i < 10; i++) {
226 if (filename_filters[i] != NULL)
227 g_object_ref(filename_filters[i]);
228 }
229 }
230
231 static gboolean
export_font(gchar * filename,gbdfed_editor_t * ed,gboolean copy_filename)232 export_font(gchar *filename, gbdfed_editor_t *ed, gboolean copy_filename)
233 {
234 FILE *out;
235 bdf_font_t *font;
236 gboolean local_font = FALSE;
237 bdf_property_t vanity;
238 FontgridSelectionInfo sinfo;
239
240 font = fontgrid_get_font(FONTGRID(ed->fgrid));
241
242 /*
243 * First, attempt to make a backup if they are specified.
244 */
245 if (options.backups) {
246 out = fopen(filename, "rb");
247 if (out != 0) {
248 fclose(out);
249
250 /*
251 * Attempt to make a backup.
252 */
253 sprintf(buffer2, "%s.bak", filename);
254
255 /*
256 * %PLATFORM_CHECK%
257 *
258 * Don't return here because we want to save the font even if a
259 * backup can't be made.
260 */
261 if (rename(filename, buffer2))
262 guiutil_error_message(ed->shell,
263 "Backups: Unable to make a backup.");
264 }
265 }
266
267 /*
268 * Try to open the file for writing. Only PSF needs binary.
269 */
270 out = (ed->export_format != PSF_FORMAT) ?
271 fopen(filename, "w") : fopen(filename, "wb");
272
273 if (out == 0) {
274 if (ed->export_format == BDF_FORMAT)
275 sprintf(buffer2, "Save Font: Unable to write to %s.", filename);
276 else
277 sprintf(buffer2, "Export Font: Unable to write to %s.", filename);
278 guiutil_error_message(ed->shell, buffer2);
279 return FALSE;
280 }
281
282 switch (ed->export_format) {
283 case BDF_FORMAT:
284 if (!font) {
285 /*
286 * We need to create a font with the default options so it
287 * can be written out as a skeleton.
288 */
289 font = bdf_new_font("unnamed",
290 options.font_opts.point_size,
291 options.font_opts.resolution_x,
292 options.font_opts.resolution_y,
293 options.font_opts.font_spacing,
294 options.font_opts.bits_per_pixel);
295 local_font = TRUE;
296 }
297
298 /*
299 * Add a custom property if the font has been
300 */
301 if (font->modified || local_font == TRUE) {
302 sprintf(buffer2, "Edited with gbdfed %s.", GBDFED_VERSION);
303 vanity.name = "_GBDFED_INFO";
304 vanity.format = BDF_ATOM;
305 vanity.value.atom = buffer2;
306 bdf_add_font_property(font, &vanity);
307 }
308 bdf_save_font(out, font, &options.font_opts, 0, 0);
309 if (local_font == TRUE)
310 bdf_free_font(font);
311 break;
312 case HEX_FORMAT:
313 bdf_export_hex(out, font, &options.font_opts, 0, 0);
314 break;
315 case PSF_FORMAT:
316 sinfo.start = sinfo.end = 0;
317 (void) fontgrid_has_selection(FONTGRID(ed->fgrid), &sinfo);
318 if (sinfo.start == sinfo.end) {
319 sinfo.start = font->glyphs[0].encoding;
320 sinfo.end = font->glyphs[font->glyphs_used - 1].encoding;
321 }
322 switch (bdf_export_psf(out, font, &options.font_opts,
323 sinfo.start, sinfo.end)) {
324 case BDF_OK:
325 buffer1[0] = 0;
326 break;
327 case BDF_BAD_RANGE:
328 sprintf(buffer1, "Export PSF: Invalid range %d-%d.\n",
329 sinfo.start, sinfo.end);
330 break;
331 case BDF_PSF_CORRUPT_UTF8:
332 strcpy(buffer1,
333 "Export PSF: Bad UTF-8 encountered in the mappings.");
334 break;
335 }
336 if (buffer1[0] != 0)
337 /*
338 * Something went wrong during the PSF export.
339 */
340 guiutil_error_message(ed->shell, buffer1);
341 }
342
343 fclose(out);
344
345 /*
346 * The rest of this only applies to BDF fonts and not PSF or HEX fonts.
347 * PSF and HEX fonts have their own extensions in the save dialog, but
348 * that does not affect the actual file name in the editor.
349 */
350 if (ed->export_format == BDF_FORMAT) {
351
352 /*
353 * Copy the path and filename into the editor if specified.
354 */
355 if (copy_filename) {
356 if (ed->path)
357 g_free(ed->path);
358 if (ed->file)
359 g_free(ed->file);
360 ed->path = ed->file = 0;
361 ed->file = g_path_get_basename(filename);
362 ed->path = g_path_get_dirname(filename);
363 }
364
365 /*
366 * Mark the font as being unmodified.
367 */
368 fontgrid_set_font_modified(FONTGRID(ed->fgrid), FALSE);
369
370 /*
371 * Update the window title accordingly.
372 */
373 if (ed->file)
374 sprintf(buffer1, "%s - %s", g_get_prgname(), ed->file);
375 else
376 sprintf(buffer1, "%s - (unnamed%d)", g_get_prgname(), ed->id);
377
378 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
379
380 /*
381 * Since the font was saved as BDF, it is no longer marked as being
382 * imported.
383 */
384 ed->imported = FALSE;
385 }
386
387 return TRUE;
388 }
389
390 static void
really_save_font(guint ed_id)391 really_save_font(guint ed_id)
392 {
393 gbdfed_editor_t *ed = editors + ed_id;
394 gchar *fname;
395 FILE *have;
396 #if (GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 10)
397 GtkRecentManager *recent;
398 #endif
399
400 fname = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ed->save_dialog));
401
402 have = fopen(fname, "rb");
403 if (have != 0) {
404 fclose(have);
405
406 /*
407 * Check to see if the user wishes to overwrite the existing font.
408 */
409 sprintf(buffer2, "Save Font: %s exists.\nDo you wish to overwrite?",
410 fname);
411 if (guiutil_yes_or_no(ed->shell, buffer2, TRUE) == FALSE) {
412 g_free(fname);
413 return;
414 }
415 }
416
417 /*
418 * If the write was successful, hide the dialog.
419 */
420 if (export_font(fname, ed, TRUE)) {
421 save_dialog_done = TRUE;
422 gtk_widget_hide(ed->save_dialog);
423 #if (GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 10)
424 recent = gtk_recent_manager_get_default();
425 sprintf(buffer1, "file://%s", fname);
426 if (gtk_recent_manager_has_item(recent,
427 (const gchar *) buffer1) == FALSE)
428 gtk_recent_manager_add_item(recent,
429 (const gchar *) buffer1);
430 #endif
431 }
432 g_free(fname);
433 }
434
435 /*
436 * This callback routine handles errors and updating the progress bar if
437 * one is being used.
438 */
439 static void
handle_import_messages(bdf_callback_struct_t * call_data,void * client_data)440 handle_import_messages(bdf_callback_struct_t *call_data, void *client_data)
441 {
442 if (call_data->reason == BDF_ERROR) {
443 sprintf(buffer1, "Import Font:%d: error: See the font messages.",
444 call_data->errlineno);
445 guiutil_error_message(GTK_WIDGET(client_data), buffer1);
446 }
447 }
448
449 /**************************************************************************
450 *
451 * BDF section.
452 *
453 **************************************************************************/
454
455 static void
load_bdf_font(gbdfed_editor_t * ed,const gchar * fullpath,const gchar * dir,const gchar * file)456 load_bdf_font(gbdfed_editor_t *ed, const gchar *fullpath, const gchar *dir,
457 const gchar *file)
458 {
459 FILE *in;
460 bdf_font_t *font;
461
462 /*
463 * Check to see if the file can be opened.
464 */
465 if ((in = fopen(fullpath, "rb")) == 0) {
466 sprintf(buffer1, "Import Font: Unable to open %s.", file);
467 guiutil_error_message(ed->shell, buffer1);
468 return;
469 }
470
471 guiutil_busy_cursor(ed->shell, TRUE);
472 if (ed->open_dialog != NULL)
473 guiutil_busy_cursor(ed->open_dialog, TRUE);
474
475 font = bdf_load_font(in, &options.font_opts,
476 handle_import_messages, (void *) ed->shell);
477
478 guiutil_busy_cursor(ed->shell, FALSE);
479 if (ed->open_dialog != NULL)
480 guiutil_busy_cursor(ed->open_dialog, FALSE);
481
482 if (font == 0) {
483 fclose(in);
484 sprintf(buffer1, "Import Font: Unable to load %s.", file);
485 guiutil_error_message(ed->shell, buffer1);
486 return;
487 }
488
489 fclose(in);
490 if (ed->open_dialog != NULL)
491 gtk_widget_hide(ed->open_dialog);
492
493 /*
494 * Delete the file and path names so they can be updated.
495 */
496 if (ed->file != 0)
497 g_free(ed->file);
498 if (ed->path != 0)
499 g_free(ed->path);
500
501 ed->file = ed->path = 0;
502
503 ed->file = strdup(file);
504 ed->path = strdup(dir);
505
506 /*
507 * Update the window title.
508 */
509 if (font->modified)
510 sprintf(buffer1, "%s - %s [modified]", g_get_prgname(), ed->file);
511 else
512 sprintf(buffer1, "%s - %s", g_get_prgname(), ed->file);
513
514 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
515
516 /*
517 * Tell the glyphtest widget to remove references to the current font if
518 * it has any, and redraw.
519 */
520 if (glyphtest != 0)
521 glyphtest_remove_font(GLYPHTEST(glyphtest),
522 fontgrid_get_font(FONTGRID(ed->fgrid)));
523
524 fontgrid_set_font(FONTGRID(ed->fgrid), font, -1);
525
526 /*
527 * Finally, update the font name field.
528 */
529 gtk_entry_set_text(GTK_ENTRY(ed->fontname),
530 fontgrid_get_font_name(FONTGRID(ed->fgrid)));
531
532 /*
533 * Make sure the imported flag is cleared in this case.
534 */
535 ed->imported = FALSE;
536 }
537
538 /**************************************************************************
539 *
540 * Console section.
541 *
542 **************************************************************************/
543
544 static void
load_console_font(gbdfed_editor_t * ed,gchar * fullpath,gchar * dot,gchar * dir,gchar * file)545 load_console_font(gbdfed_editor_t *ed, gchar *fullpath, gchar *dot,
546 gchar *dir, gchar *file)
547 {
548 FILE *in;
549 gbdfed_editor_t *ep;
550 gint i, j, nfonts, len;
551 gchar *np;
552 bdf_font_t *fonts[3];
553
554 /*
555 * Check to see if the file can be opened.
556 */
557 if ((in = fopen(fullpath, "rb")) == 0) {
558 sprintf(buffer1, "Import Font: Unable to open %s.", fullpath);
559 guiutil_error_message(ed->shell, buffer1);
560 return;
561 }
562
563 guiutil_busy_cursor(ed->shell, TRUE);
564 guiutil_busy_cursor(ed->open_dialog, TRUE);
565
566 i = bdf_load_console_font(in, &options.font_opts, 0, 0, fonts, &nfonts);
567
568 guiutil_busy_cursor(ed->shell, FALSE);
569 guiutil_busy_cursor(ed->open_dialog, FALSE);
570
571 fclose(in);
572
573 if (i != BDF_OK) {
574 /*
575 * Free up any font structures that happened to be loaded.
576 */
577 for (j = 0; j < nfonts; j++)
578 bdf_free_font(fonts[j]);
579
580 sprintf(buffer1, "Import Font: %s not a console font.", fullpath);
581 guiutil_error_message(ed->shell, buffer1);
582 return;
583 }
584
585 gtk_widget_hide(ed->open_dialog);
586
587 /*
588 * Handle creation of the editors. In the case of some console fonts,
589 * there are three different sizes contained in the font.
590 */
591 for (i = 0; i < nfonts; i++) {
592 if (i)
593 ep = editors + gbdfed_make_editor(0, FALSE);
594 else {
595 ep = ed;
596
597 /*
598 * Erase the existing file and directory name in the "root"
599 * editor.
600 */
601 if (ep->file)
602 g_free(ep->file);
603 if (ep->path)
604 g_free(ep->path);
605 ep->file = ep->path = 0;
606
607 /*
608 * Tell the glyphtest widget to remove references to the current
609 * font, if it has any, and redraw.
610 */
611 if (glyphtest != 0)
612 glyphtest_remove_font(GLYPHTEST(glyphtest),
613 fontgrid_get_font(FONTGRID(ep->fgrid)));
614 }
615
616 /*
617 * Make an XLFD name for the font using the filename. Run through the
618 * file name and change all occurences of '-' to '_' to avoid problems
619 * with '-' being the XLFD field separator.
620 */
621 for (j = 0, np = file; np < dot; np++, j++)
622 buffer2[j] = (*np != '-') ? *np : '_';
623 buffer2[j] = 0;
624
625 fonts[i]->name =
626 bdf_make_xlfd_name(fonts[i], "Unknown", buffer2);
627 bdf_update_properties_from_name(fonts[i]);
628
629 len = (gint) (dot - file);
630
631 /*
632 * Create the default name for the font file.
633 */
634 if (nfonts == 3) {
635 switch (i) {
636 case 0:
637 sprintf(buffer1, "%.*s-16.bdf", len, file);
638 break;
639 case 1:
640 sprintf(buffer1, "%.*s-14.bdf", len, file);
641 break;
642 case 2:
643 sprintf(buffer1, "%.*s-08.bdf", len, file);
644 break;
645 }
646 } else
647 sprintf(buffer1, "%.*s.bdf", len, file);
648
649 /*
650 * Set the filename for the editor.
651 */
652 ep->file = strdup(buffer1);
653 ep->path = strdup(dir);
654
655 /*
656 * Set the new editor title.
657 */
658 sprintf(buffer1, "%s - %s [modified]", g_get_prgname(), ep->file);
659 gtk_window_set_title(GTK_WINDOW(ep->shell), buffer1);
660
661 /*
662 * Change the font in the editor.
663 */
664 fontgrid_set_font(FONTGRID(ep->fgrid), fonts[i], -1);
665
666 /*
667 * Indicate the font was imported.
668 */
669 ed->imported = TRUE;
670
671 /*
672 * Update the XLFD name.
673 */
674 gtk_entry_set_text(GTK_ENTRY(ep->fontname),
675 fontgrid_get_font_name(FONTGRID(ep->fgrid)));
676 }
677 }
678
679 /**************************************************************************
680 *
681 * PK/GF section.
682 *
683 **************************************************************************/
684
685 static void
load_pkgf_font(gbdfed_editor_t * ed,gchar * fullpath,gchar * dot,gchar * dir,gchar * file)686 load_pkgf_font(gbdfed_editor_t *ed, gchar *fullpath, gchar *dot,
687 gchar *dir, gchar *file)
688 {
689 FILE *in;
690 gint i;
691 gchar *np;
692 bdf_font_t *font;
693
694 /*
695 * Check to see if the file can be opened.
696 */
697 if ((in = fopen(fullpath, "rb")) == 0) {
698 sprintf(buffer1, "Import Font: Unable to open %s.", file);
699 guiutil_error_message(ed->shell, buffer1);
700 return;
701 }
702
703 guiutil_busy_cursor(ed->shell, TRUE);
704 guiutil_busy_cursor(ed->open_dialog, TRUE);
705
706 i = bdf_load_mf_font(in, &options.font_opts, 0, 0, &font);
707
708 guiutil_busy_cursor(ed->shell, FALSE);
709 guiutil_busy_cursor(ed->open_dialog, FALSE);
710
711 fclose(in);
712
713 if (i != BDF_OK) {
714 sprintf(buffer1, "Import Font: %s not a PK or GF font.", fullpath);
715 guiutil_error_message(ed->shell, buffer1);
716 return;
717 }
718
719 gtk_widget_hide(ed->open_dialog);
720
721 /*
722 * Make an XLFD name for the font using the filename. Run through the
723 * file name and change all occurences of '-' to '_' to avoid problems
724 * with '-' being the XLFD field separator.
725 */
726 for (i = 0, np = file; np < dot; np++, i++)
727 buffer2[i] = (*np != '-') ? *np : '_';
728 buffer2[i] = 0;
729
730 font->name = bdf_make_xlfd_name(font, "Unknown", buffer2);
731 bdf_update_properties_from_name(font);
732
733 /*
734 * Now set up a file name.
735 */
736 sprintf(buffer1, "%.*s.bdf", (int) (dot - file), file);
737
738 /*
739 * Delete the file and path names so they can be updated.
740 */
741 if (ed->file != 0)
742 g_free(ed->file);
743 if (ed->path != 0)
744 g_free(ed->path);
745
746 ed->file = strdup(buffer1);
747 ed->path = strdup(dir);
748
749 /*
750 * Update the window title.
751 */
752 sprintf(buffer1, "%s - %s [modified]", g_get_prgname(), ed->file);
753 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
754
755 /*
756 * Tell the glyphtest widget to remove references to the current font if
757 * it has any, and redraw.
758 */
759 if (glyphtest != 0)
760 glyphtest_remove_font(GLYPHTEST(glyphtest),
761 fontgrid_get_font(FONTGRID(ed->fgrid)));
762
763 fontgrid_set_font(FONTGRID(ed->fgrid), font, -1);
764
765 /*
766 * Indicate the font was imported.
767 */
768 ed->imported = TRUE;
769
770 /*
771 * Finally, update the font name field.
772 */
773 gtk_entry_set_text(GTK_ENTRY(ed->fontname),
774 fontgrid_get_font_name(FONTGRID(ed->fgrid)));
775 }
776
777 /**************************************************************************
778 *
779 * FNT section.
780 *
781 **************************************************************************/
782
783 /*
784 * Toggles the "Ok" button on or off depending if there was a selection or
785 * not.
786 */
787 static void
fnt_check_load_button(GtkWidget * w,gpointer data)788 fnt_check_load_button(GtkWidget *w, gpointer data)
789 {
790 GtkTreeSelection *sel = GTK_TREE_SELECTION(data);
791
792 if (gtk_tree_selection_count_selected_rows(sel) == 0)
793 gtk_widget_set_sensitive(fnt_load_button, FALSE);
794 else
795 gtk_widget_set_sensitive(fnt_load_button, TRUE);
796 }
797
798 static void
fnt_unselect_all(GtkWidget * w,gpointer data)799 fnt_unselect_all(GtkWidget *w, gpointer data)
800 {
801 GtkTreeSelection *sel = GTK_TREE_SELECTION(data);
802
803 gtk_tree_selection_unselect_all(sel);
804
805 /*
806 * Disable the Ok button since everything is unselected.
807 */
808 gtk_widget_set_sensitive(fnt_load_button, FALSE);
809 }
810
811 static void
fnt_select_all(GtkWidget * w,gpointer data)812 fnt_select_all(GtkWidget *w, gpointer data)
813 {
814 GtkTreeSelection *sel = GTK_TREE_SELECTION(data);
815
816 gtk_tree_selection_select_all(sel);
817
818 /*
819 * Enable the Ok button since everything is unselected.
820 */
821 gtk_widget_set_sensitive(fnt_load_button, TRUE);
822 }
823
824 static void
fnt_foreach_selected(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)825 fnt_foreach_selected(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
826 gpointer data)
827 {
828 gint *id;
829
830 id = gtk_tree_path_get_indices(path);
831 fnt_selected[fnt_selected_count++] = *id;
832 }
833
834 static void
fnt_load_selected_fonts(GtkWidget * w,gpointer data)835 fnt_load_selected_fonts(GtkWidget *w, gpointer data)
836 {
837 gbdfed_editor_t *ep, *ed = editors + GPOINTER_TO_UINT(data);
838 GtkTreeSelection *sel =
839 gtk_tree_view_get_selection(GTK_TREE_VIEW(fnt_font_list));
840 gint i, nfonts;
841 gboolean loaded;
842 bdf_font_t **fonts;
843 _bdffnt_callback_data_t *cdata;
844
845 fnt_selected_count = 0;
846
847 if ((cdata = g_object_get_data(G_OBJECT(w),
848 "bdffnt_callback_data")) == NULL) {
849 /*
850 * Big problem. Should never happen.
851 */
852 guiutil_error_message(editors[0].shell,
853 "BIG PROBLEM PASSING OPEN FON/FNT FONT!!!!");
854 return;
855 }
856
857 /*
858 * This collects all the selected indices from the list and puts them in
859 * the global fnt_selected array.
860 */
861 gtk_tree_selection_selected_foreach(sel, fnt_foreach_selected, NULL);
862
863 /*
864 * CHANGE - maybe.
865 */
866 if (fnt_selected_count == 0)
867 return;
868
869 /*
870 * Hide the dialog that allowed selection of the fonts in the file.
871 */
872 gtk_widget_hide(fnt_dialog);
873
874 guiutil_busy_cursor(ed->shell, TRUE);
875 guiutil_busy_cursor(ed->open_dialog, TRUE);
876
877 fonts = (bdf_font_t **)
878 g_malloc(sizeof(bdf_font_t *) * fnt_selected_count);
879 for (loaded = TRUE, nfonts = 0;
880 nfonts < fnt_selected_count && loaded == TRUE;
881 nfonts++) {
882 /*
883 * If the current font can't be loaded, then assume the rest are
884 * not available either.
885 */
886 if (bdffnt_load_font(cdata->font, fnt_selected[nfonts],
887 0, 0, &fonts[nfonts]) != 0) {
888 /*
889 * It is easier to get the font name from the font than it is
890 * from the list store.
891 */
892 (void) bdffnt_get_facename(cdata->font, fnt_selected[nfonts], 0,
893 (unsigned char *) buffer1);
894 sprintf(buffer2, "Import Font: Unable to load %s from %s.",
895 buffer1, cdata->file);
896 guiutil_error_message(ed->shell, buffer2);
897
898 guiutil_busy_cursor(ed->shell, FALSE);
899 guiutil_busy_cursor(ed->open_dialog, FALSE);
900
901 loaded = FALSE;
902 }
903 }
904
905 guiutil_busy_cursor(ed->shell, FALSE);
906 guiutil_busy_cursor(ed->open_dialog, FALSE);
907
908 /*
909 * If no fonts were loaded, then simply return with the open dialog still
910 * up, giving the user a chance to load another font.
911 */
912 if (nfonts == 0) {
913 g_free(fonts);
914 return;
915 }
916
917 /*
918 * Hide the open dialog.
919 */
920 gtk_widget_hide(ed->open_dialog);
921
922 /*
923 * Create the editors for the fonts that did get loaded.
924 */
925 for (i = 0; i < nfonts; i++) {
926 if (i)
927 ep = editors + gbdfed_make_editor(0, FALSE);
928 else {
929 ep = ed;
930
931 /*
932 * Erase the existing file and directory name in the "root"
933 * editor.
934 */
935 if (ep->file)
936 g_free(ep->file);
937 if (ep->path)
938 g_free(ep->path);
939 ep->file = ep->path = 0;
940
941 /*
942 * Tell the glyphtest widget to remove references to the current
943 * font, if it has any, and redraw.
944 */
945 if (glyphtest != 0)
946 glyphtest_remove_font(GLYPHTEST(glyphtest),
947 fontgrid_get_font(FONTGRID(ep->fgrid)));
948 }
949
950 /*
951 * Make the BDF file name for the font.
952 */
953 sprintf(buffer1, "%.*s%d.bdf", (int) (cdata->dot - cdata->file),
954 cdata->file, fonts[i]->point_size);
955
956 ep->file = strdup(buffer1);
957 ep->path = strdup(cdata->dir);
958
959 /*
960 * Set the new editor title.
961 */
962 sprintf(buffer1, "%s - %s [modified]", g_get_prgname(), ep->file);
963 gtk_window_set_title(GTK_WINDOW(ep->shell), buffer1);
964
965 /*
966 * Change the font in the editor.
967 */
968 fontgrid_set_font(FONTGRID(ep->fgrid), fonts[i], -1);
969
970 /*
971 * Indicate the font was imported.
972 */
973 ep->imported = TRUE;
974
975 /*
976 * Update the XLFD name.
977 */
978 gtk_entry_set_text(GTK_ENTRY(ep->fontname),
979 fontgrid_get_font_name(FONTGRID(ep->fgrid)));
980 }
981
982 g_free(cdata->file);
983 g_free(cdata->dir);
984 bdffnt_close_font(cdata->font);
985
986 g_free(fonts);
987 }
988
989 static void
fnt_cancel(GtkWidget * w,gpointer data)990 fnt_cancel(GtkWidget *w, gpointer data)
991 {
992 _bdffnt_callback_data_t *cdata;
993
994 /*
995 * If the load callback stole the data already, this will be NULL.
996 */
997 if ((cdata = g_object_get_data(G_OBJECT(w),
998 "bdffnt_callback_data")) == NULL) {
999 /*
1000 * Big problem. Should never happen.
1001 */
1002 guiutil_error_message(editors[0].shell,
1003 "BIG PROBLEM PASSING OPEN FON/FNT FONT!!!!");
1004 return;
1005 }
1006
1007 g_free(cdata->file);
1008 g_free(cdata->dir);
1009 bdffnt_close_font(cdata->font);
1010
1011 gtk_widget_hide(fnt_dialog);
1012 }
1013
1014 static void
fnt_row_activate(GtkTreeView * view,GtkTreePath * path,GtkTreeViewColumn * col,gpointer data)1015 fnt_row_activate(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col,
1016 gpointer data)
1017 {
1018 fnt_load_selected_fonts(GTK_WIDGET(view), data);
1019 }
1020
1021 static void
load_windows_font(gbdfed_editor_t * ed,gchar * fullpath,gchar * dot,gchar * dir,gchar * file)1022 load_windows_font(gbdfed_editor_t *ed, gchar *fullpath, gchar *dot,
1023 gchar *dir, gchar *file)
1024 {
1025 gint i, nfonts;
1026 bdffnt_font_t fnt;
1027 bdf_font_t *font;
1028 _bdffnt_callback_data_t *cdata;
1029 GtkWidget *button, *vbox, *hbox, *swin;
1030 GtkListStore *store;
1031 GtkTreeViewColumn *column;
1032 GtkCellRenderer *cell_renderer;
1033 GtkTreeSelection *sel;
1034 GtkTreePath *tpath;
1035 GtkTreeIter iter;
1036
1037 if (bdffnt_open_font(fullpath, &fnt) <= 0) {
1038 sprintf(buffer1, "Import Font: Unable to open %s.", file);
1039 guiutil_error_message(ed->shell, buffer1);
1040 g_free(dir);
1041 return;
1042 }
1043
1044 nfonts = bdffnt_font_count(fnt);
1045
1046 if (nfonts == 1) {
1047 guiutil_busy_cursor(ed->shell, TRUE);
1048 guiutil_busy_cursor(ed->open_dialog, TRUE);
1049
1050 if (bdffnt_load_font(fnt, 0, 0, 0, &font) != 0) {
1051 sprintf(buffer1, "Import Font: Unable to load %s.", file);
1052 guiutil_error_message(ed->shell, buffer1);
1053 g_free(dir);
1054
1055 guiutil_busy_cursor(ed->shell, FALSE);
1056 guiutil_busy_cursor(ed->open_dialog, FALSE);
1057
1058 return;
1059 }
1060
1061 guiutil_busy_cursor(ed->shell, FALSE);
1062 guiutil_busy_cursor(ed->open_dialog, FALSE);
1063
1064 gtk_widget_hide(ed->open_dialog);
1065
1066 /*
1067 * Now set up a file name.
1068 */
1069 sprintf(buffer1, "%.*s.bdf", (int) (dot - file), file);
1070
1071 /*
1072 * Delete the file and path names so they can be updated.
1073 */
1074 if (ed->file != 0)
1075 g_free(ed->file);
1076 if (ed->path != 0)
1077 g_free(ed->path);
1078
1079 ed->file = strdup(buffer1);
1080 ed->path = strdup(dir);
1081
1082 /*
1083 * Update the window title.
1084 */
1085 sprintf(buffer1, "%s - %s [modified]", g_get_prgname(), ed->file);
1086 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
1087
1088 /*
1089 * Tell the glyphtest widget to remove references to the current font
1090 * if it has any, and redraw.
1091 */
1092 if (glyphtest != 0)
1093 glyphtest_remove_font(GLYPHTEST(glyphtest),
1094 fontgrid_get_font(FONTGRID(ed->fgrid)));
1095
1096 fontgrid_set_font(FONTGRID(ed->fgrid), font, -1);
1097
1098 /*
1099 * Indicate the font was imported.
1100 */
1101 ed->imported = TRUE;
1102
1103 /*
1104 * Finally, update the font name field.
1105 */
1106 gtk_entry_set_text(GTK_ENTRY(ed->fontname),
1107 fontgrid_get_font_name(FONTGRID(ed->fgrid)));
1108 return;
1109 }
1110
1111 /*
1112 * More than one font was found. Present the dialog to choose the fonts.
1113 */
1114 if (fnt_dialog == 0) {
1115 /*
1116 * Create a structure that will hold data needed by a couple callback
1117 * routines.
1118 */
1119 cdata = g_malloc(sizeof(_bdffnt_callback_data_t));
1120 cdata->file = strdup(file);
1121 cdata->dir = strdup(dir);
1122 cdata->dot = cdata->file + (dot - file);
1123 cdata->font = fnt;
1124
1125 fnt_dialog = gtk_dialog_new();
1126 gtk_window_set_title(GTK_WINDOW(fnt_dialog), "Windows Font Selection");
1127
1128 g_object_set_data(G_OBJECT(fnt_dialog), "bdffnt_callback_data",
1129 (gpointer) cdata);
1130
1131 (void) g_signal_connect(G_OBJECT(fnt_dialog), "delete_event",
1132 G_CALLBACK(fnt_cancel), 0);
1133
1134 vbox = GTK_DIALOG(fnt_dialog)->vbox;
1135 hbox = GTK_DIALOG(fnt_dialog)->action_area;
1136
1137 swin = gtk_scrolled_window_new(0, 0);
1138 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
1139 GTK_POLICY_AUTOMATIC,
1140 GTK_POLICY_ALWAYS);
1141
1142 store = gtk_list_store_new(1, G_TYPE_STRING);
1143 fnt_font_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1144 g_object_unref(store);
1145
1146 g_object_set_data(G_OBJECT(fnt_font_list), "bdffnt_callback_data",
1147 (gpointer) cdata);
1148
1149 gtk_widget_set_size_request(fnt_font_list, -1, 160);
1150
1151 cell_renderer = gtk_cell_renderer_text_new();
1152 column = gtk_tree_view_column_new_with_attributes("Fonts: 0",
1153 cell_renderer,
1154 "text", 0,
1155 NULL);
1156
1157 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1158 gtk_tree_view_append_column(GTK_TREE_VIEW(fnt_font_list), column);
1159 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(fnt_font_list));
1160
1161 (void) g_signal_connect(G_OBJECT(sel), "changed",
1162 G_CALLBACK(fnt_check_load_button),
1163 (gpointer) sel);
1164
1165 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
1166
1167 (void) g_signal_connect(G_OBJECT(fnt_font_list), "row_activated",
1168 G_CALLBACK(fnt_row_activate),
1169 GUINT_TO_POINTER(ed->id));
1170
1171 gtk_container_add(GTK_CONTAINER(swin), fnt_font_list);
1172
1173 gtk_box_pack_start(GTK_BOX(vbox), swin, FALSE, FALSE, 0);
1174
1175 button = gtk_button_new_with_label("Select All");
1176
1177 (void) g_signal_connect(G_OBJECT(button), "clicked",
1178 G_CALLBACK(fnt_select_all),
1179 (gpointer) sel);
1180
1181 gtk_container_add(GTK_CONTAINER(hbox), button);
1182
1183 button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
1184
1185 (void) g_signal_connect(G_OBJECT(button), "clicked",
1186 G_CALLBACK(fnt_unselect_all),
1187 (gpointer) sel);
1188
1189 gtk_container_add(GTK_CONTAINER(hbox), button);
1190
1191 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1192
1193 (void) g_signal_connect(G_OBJECT(button), "clicked",
1194 G_CALLBACK(fnt_cancel),
1195 GUINT_TO_POINTER(ed->id));
1196
1197 gtk_container_add(GTK_CONTAINER(hbox), button);
1198
1199 fnt_load_button = gtk_button_new_from_stock(GTK_STOCK_OK);
1200
1201 /*
1202 * Here we store a bunch of data to the buttons that are necessary to
1203 * load FON/FNT fonts in the callback.
1204 */
1205 g_object_set_data(G_OBJECT(fnt_load_button), "bdffnt_callback_data",
1206 (gpointer) cdata);
1207 g_object_set_data(G_OBJECT(button), "bdffnt_callback_data",
1208 (gpointer) cdata);
1209
1210 (void) g_signal_connect(G_OBJECT(fnt_load_button), "clicked",
1211 G_CALLBACK(fnt_load_selected_fonts),
1212 GUINT_TO_POINTER(ed->id));
1213
1214 gtk_container_add(GTK_CONTAINER(hbox), fnt_load_button);
1215
1216 gtk_widget_show_all(vbox);
1217 gtk_widget_show_all(hbox);
1218 } else {
1219 /*
1220 * Fill the CDATA item in with the latest info.
1221 */
1222 cdata = g_object_get_data(G_OBJECT(fnt_load_button),
1223 "bdffnt_callback_data");
1224 cdata->file = strdup(file);
1225 cdata->dir = strdup(dir);
1226 cdata->dot = cdata->file + (dot - file);
1227 cdata->font = fnt;
1228 }
1229
1230 store =
1231 GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(fnt_font_list)));
1232 column = gtk_tree_view_get_column(GTK_TREE_VIEW(fnt_font_list), 0);
1233 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(fnt_font_list));
1234
1235 /*
1236 * Set the number of fonts.
1237 */
1238 sprintf(buffer1, "Fonts: %d", nfonts);
1239 gtk_tree_view_column_set_title(column, buffer1);
1240
1241 /*
1242 * Clear the list and add the font names.
1243 */
1244 gtk_list_store_clear(store);
1245 for (i = 0; i < nfonts; i++) {
1246 (void) bdffnt_get_facename(fnt, i, 0, (unsigned char *) buffer1);
1247 gtk_list_store_append(store, &iter);
1248 gtk_list_store_set(store, &iter, 0, buffer1, -1);
1249 }
1250
1251 /*
1252 * Force the first one to be selected by default.
1253 */
1254 tpath = gtk_tree_path_new_from_indices(0, -1);
1255 gtk_tree_selection_select_path(sel, tpath);
1256
1257 /*
1258 * Show the dialog and wait until the selection is done.
1259 */
1260 guiutil_show_dialog_centered(fnt_dialog, ed->shell);
1261
1262 /*
1263 * Force the user to interact with this dialog before doing anything else.
1264 */
1265 gtk_window_set_modal(GTK_WINDOW(fnt_dialog), TRUE);
1266 }
1267
1268 /**************************************************************************
1269 *
1270 * OTF section.
1271 *
1272 **************************************************************************/
1273
1274 #ifdef HAVE_FREETYPE
1275
1276 static void
choose_otf_encoding(GtkTreeSelection * selection,gpointer data)1277 choose_otf_encoding(GtkTreeSelection *selection, gpointer data)
1278 {
1279 gint *rows;
1280 GtkTreeModel *model;
1281 GtkTreeIter iter;
1282 GtkTreePath *tpath;
1283
1284 /*
1285 * Get the row of the current selection.
1286 */
1287 if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
1288 return;
1289 tpath = gtk_tree_model_get_path(model, &iter);
1290 rows = gtk_tree_path_get_indices(tpath);
1291 otf_eid_pos = (gint16) rows[0];
1292 }
1293
1294 static void
choose_otf_platform(GtkTreeSelection * selection,gpointer data)1295 choose_otf_platform(GtkTreeSelection *selection, gpointer data)
1296 {
1297 gchar *name;
1298 gint i, ncmaps, sel, *rows;
1299 gint16 pid, eid, lasteid;
1300 GtkTreeModel *model;
1301 GtkListStore *store;
1302 GtkTreeIter iter;
1303 GtkTreePath *tpath;
1304 GtkTreeView *tview;
1305
1306 /*
1307 * Get the row of the current selection.
1308 */
1309 if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
1310 return;
1311 tpath = gtk_tree_model_get_path(model, &iter);
1312 rows = gtk_tree_path_get_indices(tpath);
1313 otf_pid_pos = (gint16) rows[0];
1314
1315 /*
1316 * Clear the encoding list.
1317 */
1318 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(otf_encodings)));
1319 gtk_list_store_clear(store);
1320
1321 /*
1322 * Collect the list of encoding IDs and put their names in the encoding
1323 * list.
1324 */
1325 nencodings = 0;
1326 ncmaps = face->num_charmaps;
1327 for (lasteid = -1, sel = i = 0; i < ncmaps; i++) {
1328 pid = face->charmaps[i]->platform_id;
1329 eid = face->charmaps[i]->encoding_id;
1330 if (pid == platforms[otf_pid_pos] && eid != lasteid) {
1331 name = bdfotf_encoding_name(pid, eid);
1332 if (strcmp(name, "ISO10646") == 0)
1333 sel = nencodings;
1334 gtk_list_store_append(store, &iter);
1335 gtk_list_store_set(store, &iter, 0, name, -1);
1336 encodings[nencodings++] = eid;
1337 lasteid = eid;
1338 }
1339 }
1340
1341 /*
1342 * Default the selection to the ISO10646 encoding.
1343 */
1344 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(otf_encodings));
1345 tpath = gtk_tree_path_new_from_indices(sel, -1);
1346 gtk_tree_selection_select_path(selection, tpath);
1347
1348 /*
1349 * Make sure the encoding is made visible.
1350 */
1351 tview = gtk_tree_selection_get_tree_view(selection);
1352 gtk_tree_view_scroll_to_cell(tview, tpath, NULL, TRUE, 0.5, 0.5);
1353 }
1354
1355 static void
choose_otf(GtkTreeSelection * selection,gpointer data)1356 choose_otf(GtkTreeSelection *selection, gpointer data)
1357 {
1358 gchar *name;
1359 gint i, ncmaps, sel, row, *rows;
1360 gint16 pid, eid, lastpid;
1361 GtkTreeModel *model;
1362 GtkListStore *store;
1363 GtkTreeIter iter;
1364 GtkTreePath *tpath;
1365 GtkTreeView *tview;
1366 GValue val;
1367
1368 /*
1369 * This is called after the list is cleared as well, so return if there is
1370 * no selection.
1371 */
1372 if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
1373 return;
1374
1375 /*
1376 * Get the name of the face currently selected and it's index. This is
1377 * way more complicated than it should be.
1378 */
1379 (void) memset((char *) &val, 0, sizeof(GValue));
1380 tpath = gtk_tree_model_get_path(model, &iter);
1381 rows = gtk_tree_path_get_indices(tpath);
1382 row = rows[0];
1383
1384 /*
1385 * Clear the platform list before trying to open the new face.
1386 */
1387 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(otf_platforms)));
1388 gtk_list_store_clear(store);
1389
1390 if (otf_collection) {
1391 if (otf_face_open)
1392 FT_Done_Face(face);
1393 if (FT_New_Face(library, otf_fullpath, row, &face)) {
1394 otf_face_open = FALSE;
1395 gtk_tree_selection_get_selected(selection, &model, &iter);
1396 gtk_tree_model_get_value(model, &iter, 0, &val);
1397 name = (gchar *) g_value_get_string(&val);
1398 sprintf(buffer1,
1399 "Import Font: Unable to open OpenType collection %s.",
1400 name);
1401 g_value_unset(&val);
1402 guiutil_error_message(active_editor->shell, buffer1);
1403 return;
1404 }
1405 otf_face_open = TRUE;
1406 }
1407
1408 /*
1409 * Collect the list of platform IDs and put their names in the platform
1410 * list.
1411 */
1412 nplatforms = 0;
1413 ncmaps = face->num_charmaps;
1414 for (lastpid = -1, sel = i = 0; i < ncmaps; i++) {
1415 pid = face->charmaps[i]->platform_id;
1416 eid = face->charmaps[i]->encoding_id;
1417 if (pid != lastpid) {
1418 /*
1419 * Add the platform name to the list. If the name happens to be
1420 * Microsoft, select it as the default.
1421 */
1422 name = bdfotf_platform_name(pid);
1423 if (strcmp(name, "Microsoft") == 0)
1424 sel = nplatforms;
1425 gtk_list_store_append(store, &iter);
1426 gtk_list_store_set(store, &iter, 0, name, -1);
1427 platforms[nplatforms++] = pid;
1428 lastpid = pid;
1429 }
1430 }
1431
1432 /*
1433 * Select the default platform, which is hard-coded to be Microsoft at the
1434 * moment.
1435 */
1436 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(otf_platforms));
1437 tpath = gtk_tree_path_new_from_indices(sel, -1);
1438 gtk_tree_selection_select_path(selection, tpath);
1439
1440 /*
1441 * Make sure the platform is made visible.
1442 */
1443 tview = gtk_tree_selection_get_tree_view(selection);
1444 gtk_tree_view_scroll_to_cell(tview, tpath, NULL, TRUE, 0.5, 0.5);
1445 }
1446
1447 static void
otf_dialog_done(GtkWidget * w,gpointer data)1448 otf_dialog_done(GtkWidget *w, gpointer data)
1449 {
1450 otf_select_done = GPOINTER_TO_INT(data);
1451 gtk_widget_hide(otf_dialog);
1452 }
1453
1454 static void
otf_reset_metrics(GtkWidget * w,gpointer data)1455 otf_reset_metrics(GtkWidget *w, gpointer data)
1456 {
1457 gtk_spin_button_set_value(GTK_SPIN_BUTTON(otf_point_size),
1458 (gfloat) options.font_opts.point_size);
1459 gtk_spin_button_set_value(GTK_SPIN_BUTTON(otf_hres),
1460 (gfloat) options.font_opts.resolution_x);
1461 gtk_spin_button_set_value(GTK_SPIN_BUTTON(otf_vres),
1462 (gfloat) options.font_opts.resolution_y);
1463 }
1464
1465 /*
1466 * Synchronize the vertical resolution with the horizontal resolution.
1467 */
1468 static void
otf_sync_res(GtkWidget * w,GdkEventFocus * ev,gpointer data)1469 otf_sync_res(GtkWidget *w, GdkEventFocus *ev, gpointer data)
1470 {
1471 gfloat v;
1472 GtkSpinButton *b;
1473
1474 b = GTK_SPIN_BUTTON(data);
1475 v = (gfloat) gtk_spin_button_get_value(b);
1476
1477 if (v != (gfloat) gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)))
1478 gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), v);
1479 }
1480
1481 static void
make_otf_import_dialog(void)1482 make_otf_import_dialog(void)
1483 {
1484 GtkWidget *label, *vbox, *hbox, *button, *table, *swin;
1485 GtkAdjustment *adj;
1486 GtkListStore *store;
1487 GtkTreeViewColumn *column;
1488 GtkCellRenderer *cell_renderer;
1489 GtkTreeSelection *sel;
1490 GList *fchain;
1491
1492 otf_dialog = gtk_dialog_new();
1493 gtk_window_set_title(GTK_WINDOW(otf_dialog), "OpenType Selection");
1494
1495 (void) g_signal_connect(G_OBJECT(otf_dialog), "delete_event",
1496 G_CALLBACK(gtk_widget_hide), 0);
1497
1498 vbox = GTK_DIALOG(otf_dialog)->vbox;
1499
1500 swin = gtk_scrolled_window_new(0, 0);
1501 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
1502 GTK_POLICY_AUTOMATIC,
1503 GTK_POLICY_ALWAYS);
1504
1505 store = gtk_list_store_new(1, G_TYPE_STRING);
1506 otf_faces = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1507 g_object_unref(store);
1508
1509 cell_renderer = gtk_cell_renderer_text_new();
1510 column = gtk_tree_view_column_new_with_attributes ("Faces",
1511 cell_renderer,
1512 "text", 0,
1513 NULL);
1514
1515 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1516 gtk_tree_view_append_column (GTK_TREE_VIEW(otf_faces), column);
1517
1518 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(otf_faces));
1519 gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
1520
1521 (void) g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(choose_otf),
1522 NULL);
1523
1524 /*
1525 * Set the size of the list explicitly to make enough space for
1526 * approximately five entries.
1527 */
1528 gtk_widget_set_size_request(otf_faces, -1, 100);
1529
1530 gtk_container_add(GTK_CONTAINER(swin), otf_faces);
1531
1532 gtk_box_pack_start(GTK_BOX(vbox), swin, TRUE, TRUE, 0);
1533
1534 /*
1535 * Create a table to hold the other two lists.
1536 */
1537 table = gtk_table_new(1, 2, TRUE);
1538
1539 swin = gtk_scrolled_window_new(0, 0);
1540 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
1541 GTK_POLICY_AUTOMATIC,
1542 GTK_POLICY_ALWAYS);
1543
1544 store = gtk_list_store_new(1, G_TYPE_STRING);
1545 otf_platforms = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1546 g_object_unref(store);
1547
1548 cell_renderer = gtk_cell_renderer_text_new();
1549 column = gtk_tree_view_column_new_with_attributes("Platforms",
1550 cell_renderer,
1551 "text", 0,
1552 NULL);
1553
1554 gtk_widget_set_size_request(otf_platforms, 200, 70);
1555
1556 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1557 gtk_tree_view_append_column(GTK_TREE_VIEW(otf_platforms), column);
1558
1559 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(otf_platforms));
1560 gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
1561
1562 (void) g_signal_connect(G_OBJECT(sel), "changed",
1563 G_CALLBACK(choose_otf_platform), NULL);
1564
1565 gtk_container_add(GTK_CONTAINER(swin), otf_platforms);
1566
1567 /*
1568 * Attach the platform list to the table.
1569 */
1570 gtk_table_attach(GTK_TABLE(table), swin, 0, 1, 0, 1,
1571 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
1572
1573 swin = gtk_scrolled_window_new(0, 0);
1574 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
1575 GTK_POLICY_AUTOMATIC,
1576 GTK_POLICY_ALWAYS);
1577
1578 store = gtk_list_store_new(1, G_TYPE_STRING);
1579 otf_encodings = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1580 g_object_unref(store);
1581
1582 cell_renderer = gtk_cell_renderer_text_new();
1583 column = gtk_tree_view_column_new_with_attributes("Encodings",
1584 cell_renderer,
1585 "text", 0,
1586 NULL);
1587
1588 gtk_widget_set_size_request(otf_encodings, 200, 70);
1589
1590 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1591 gtk_tree_view_append_column(GTK_TREE_VIEW(otf_encodings), column);
1592
1593 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(otf_encodings));
1594 gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
1595
1596 (void) g_signal_connect(G_OBJECT(sel), "changed",
1597 G_CALLBACK(choose_otf_encoding), NULL);
1598
1599 gtk_container_add(GTK_CONTAINER(swin), otf_encodings);
1600
1601 /*
1602 * Attach the encodings list to the table.
1603 */
1604 gtk_table_attach(GTK_TABLE(table), swin, 1, 2, 0, 1,
1605 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
1606
1607 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
1608
1609 /*
1610 * Make a table that will contain the point size and resolution
1611 * spin buttons.
1612 */
1613 table = gtk_table_new(3, 3, FALSE);
1614
1615 /*
1616 * Make the spin button labels.
1617 */
1618 label = gtk_label_new("Point Size:");
1619 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
1620 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL,
1621 5, 5);
1622 label = gtk_label_new("Horizontal Resolution:");
1623 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
1624 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL,
1625 5, 5);
1626 label = gtk_label_new("Vertical Resolution:");
1627 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
1628 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL,
1629 5, 5);
1630
1631 /*
1632 * Make the spin buttons.
1633 */
1634 adj = (GtkAdjustment *) gtk_adjustment_new(0.0, 4.0, 256.0, 1.0, 2.0, 0.0);
1635 otf_point_size = gtk_spin_button_new(adj, 1.0, 0);
1636 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(otf_point_size), TRUE);
1637 gtk_widget_set_size_request(otf_point_size, 100, -1);
1638 gtk_spin_button_set_value(GTK_SPIN_BUTTON(otf_point_size),
1639 (gfloat) options.font_opts.point_size);
1640 gtk_table_attach(GTK_TABLE(table), otf_point_size, 1, 2, 0, 1,
1641 GTK_FILL, GTK_FILL, 5, 5);
1642
1643 adj = (GtkAdjustment *) gtk_adjustment_new(0.0, 72.0, 1200.0,
1644 1.0, 10.0, 0.0);
1645 otf_hres = gtk_spin_button_new(adj, 1.0, 0);
1646 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(otf_hres), TRUE);
1647 gtk_widget_set_size_request(otf_hres, 100, -1);
1648 gtk_spin_button_set_value(GTK_SPIN_BUTTON(otf_hres),
1649 (gfloat) options.font_opts.resolution_x);
1650 gtk_table_attach(GTK_TABLE(table), otf_hres, 1, 2, 1, 2,
1651 GTK_FILL, GTK_FILL, 5, 5);
1652
1653 adj = (GtkAdjustment *) gtk_adjustment_new(0.0, 72.0, 1200.0,
1654 1.0, 10.0, 0.0);
1655 otf_vres = gtk_spin_button_new(adj, 1.0, 0);
1656 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(otf_vres), TRUE);
1657 gtk_widget_set_size_request(otf_vres, 100, -1);
1658 gtk_spin_button_set_value(GTK_SPIN_BUTTON(otf_vres),
1659 (gfloat) options.font_opts.resolution_y);
1660 (void) g_signal_connect(G_OBJECT(otf_vres), "focus-in-event",
1661 G_CALLBACK(otf_sync_res),
1662 (gpointer) otf_hres);
1663 (void) g_signal_connect(G_OBJECT(otf_hres), "focus-in-event",
1664 G_CALLBACK(otf_sync_res),
1665 (gpointer) otf_vres);
1666 gtk_table_attach(GTK_TABLE(table), otf_vres, 1, 2, 2, 3,
1667 GTK_FILL, GTK_FILL, 5, 5);
1668
1669 /*
1670 * Make the reset button.
1671 */
1672 label = gtk_button_new_with_label("Reset");
1673 (void) g_signal_connect(G_OBJECT(label), "clicked",
1674 G_CALLBACK(otf_reset_metrics), 0);
1675 gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, GTK_FILL, GTK_FILL,
1676 10, 0);
1677
1678 /*
1679 * Do some fiddling to adjust the focus chain so the Reset button is at
1680 * the end instead of in the middle.
1681 */
1682 fchain = g_list_append(NULL, (gpointer) otf_point_size);
1683 fchain = g_list_append(fchain, (gpointer) otf_hres);
1684 fchain = g_list_append(fchain, (gpointer) otf_vres);
1685 fchain = g_list_append(fchain, (gpointer) label);
1686 gtk_container_set_focus_chain(GTK_CONTAINER(table), fchain);
1687 g_list_free(fchain);
1688
1689 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, FALSE, 10);
1690
1691 /*
1692 * Add the buttons at the bottom of the dialog.
1693 */
1694 hbox = GTK_DIALOG(otf_dialog)->action_area;
1695
1696 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1697 gtk_container_add(GTK_CONTAINER(hbox), button);
1698 (void) g_signal_connect(G_OBJECT(button), "clicked",
1699 G_CALLBACK(otf_dialog_done),
1700 GINT_TO_POINTER(-1));
1701 button = gtk_button_new_from_stock(GTK_STOCK_OK);
1702 gtk_container_add(GTK_CONTAINER(hbox), button);
1703 (void) g_signal_connect(G_OBJECT(button), "clicked",
1704 G_CALLBACK(otf_dialog_done),
1705 GINT_TO_POINTER(1));
1706
1707 gtk_widget_show_all(vbox);
1708 gtk_widget_show_all(hbox);
1709 }
1710
1711 static void
load_otf_font(gbdfed_editor_t * ed,gchar * fullpath,gchar * dot,gchar * dir,gchar * file)1712 load_otf_font(gbdfed_editor_t *ed, gchar *fullpath, gchar *dot,
1713 gchar *dir, gchar *file)
1714 {
1715 gint i, res;
1716 gint32 psize, hres, vres;
1717 gchar *np;
1718 bdf_font_t *font;
1719 bdf_property_t prop;
1720 GtkListStore *store;
1721 GtkTreeIter iter;
1722
1723 active_editor = ed;
1724 otf_fullpath = fullpath;
1725
1726 /*
1727 * Determine if this is an OT collection or just a normal font.
1728 */
1729 np = dot + strlen(dot) - 1;
1730 otf_collection = (*np == 'c' || *np == 'C') ? TRUE : FALSE;
1731
1732 /*
1733 * Initialize the FreeType engine once.
1734 */
1735 if (!ftinit) {
1736 if (FT_Init_FreeType(&library) != 0) {
1737 strcpy(buffer1,
1738 "Import Font: Unable to initialize the FreeType engine.");
1739 guiutil_error_message(ed->shell, buffer1);
1740 return;
1741 }
1742 ftinit = TRUE;
1743 }
1744
1745 /*
1746 * Attempt to open the font or collection.
1747 */
1748 if (FT_New_Face(library, fullpath, 0, &face)) {
1749 if (!otf_collection)
1750 sprintf(buffer1, "Import Font: Unable to open OpenType font '%s'.",
1751 file);
1752 else
1753 sprintf(buffer1,
1754 "Import Font: Unable to open OpenType collection '%s'.",
1755 file);
1756 guiutil_error_message(ed->shell, buffer1);
1757 return;
1758 }
1759
1760 /*
1761 * Construct the dialog that will display various choices that will be
1762 * needed when loading the font.
1763 */
1764 if (otf_dialog == 0)
1765 make_otf_import_dialog();
1766
1767 /*
1768 * Clear the lists and reset the values.
1769 */
1770 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(otf_faces)));
1771 gtk_list_store_clear(store);
1772
1773 otf_face_open = TRUE;
1774 otf_collection = face->num_faces;
1775 np = buffer1;
1776
1777 if (otf_collection == 1) {
1778 if (bdfotf_get_english_string(face, BDFOTF_FULLNAME_STRING,
1779 0, buffer1) == 0)
1780 (void) strcpy(buffer1, "Unknown");
1781 gtk_list_store_append(store, &iter);
1782 gtk_list_store_set(store, &iter, 0, buffer1, -1);
1783 } else {
1784 otf_face_open = FALSE;
1785 FT_Done_Face(face);
1786 for (i = 0; i < otf_collection; i++) {
1787 if (!FT_New_Face(library, fullpath, i, &face)) {
1788 if (bdfotf_get_english_string(face, BDFOTF_FULLNAME_STRING,
1789 0, buffer1) == 0)
1790 sprintf(buffer1, "Unknown%d", i);
1791
1792 gtk_list_store_append(store, &iter);
1793 gtk_list_store_set(store, &iter, 0, buffer1, -1);
1794
1795 FT_Done_Face(face);
1796 }
1797 }
1798 }
1799
1800 guiutil_show_dialog_centered(otf_dialog, ed->shell);
1801
1802 /*
1803 * Force the user to interact with this dialog before doing anything else.
1804 */
1805 gtk_window_set_modal(GTK_WINDOW(otf_dialog), TRUE);
1806
1807 otf_select_done = 0;
1808 while (otf_select_done == 0)
1809 gtk_main_iteration();
1810
1811 /*
1812 * Reinitialize various globals when we are done.
1813 */
1814 active_editor = 0;
1815 otf_fullpath = 0;
1816
1817 if (otf_select_done < 0) {
1818 if (otf_face_open)
1819 FT_Done_Face(face);
1820 otf_face_open = FALSE;
1821 return;
1822 }
1823
1824 /*
1825 * Get the requested point size and resolutions.
1826 */
1827 psize = (gint32)
1828 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(otf_point_size));
1829 hres = (gint32)
1830 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(otf_hres));
1831 vres = (gint32)
1832 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(otf_vres));
1833
1834 guiutil_busy_cursor(ed->shell, TRUE);
1835 guiutil_busy_cursor(ed->open_dialog, TRUE);
1836
1837 /*
1838 * Actually store the resolution and point size to the options so they
1839 * will be used for other imports. The setup dialog will unfortunately
1840 * assume this are the default values. May fix later so setup knows the
1841 * values changed.
1842 */
1843 options.font_opts.point_size = psize;
1844 options.font_opts.resolution_x = hres;
1845 options.font_opts.resolution_y = vres;
1846
1847 /*
1848 * Actually load the font.
1849 */
1850 res = bdfotf_load_font(face, platforms[otf_pid_pos],
1851 encodings[otf_eid_pos], &options.font_opts,
1852 0, 0, &font);
1853
1854 guiutil_busy_cursor(ed->shell, FALSE);
1855 guiutil_busy_cursor(ed->open_dialog, FALSE);
1856
1857 FT_Done_Face(face);
1858 otf_face_open = FALSE;
1859
1860 if (!res) {
1861 /*
1862 * Make an error message.
1863 */
1864 sprintf(buffer1, "Import Font: Unable to load OpenType font %s.",
1865 file);
1866 guiutil_error_message(ed->shell, buffer1);
1867 return;
1868 }
1869
1870 /*
1871 * Hide the open dialog.
1872 */
1873 gtk_widget_hide(ed->open_dialog);
1874
1875 /*
1876 * Add the _OTF_FONTFILE property using the original filename.
1877 */
1878 prop.name = "_OTF_FONTFILE";
1879 prop.format = BDF_ATOM;
1880 prop.value.atom = file;
1881 bdf_add_font_property(font, &prop);
1882
1883 /*
1884 * Now set up a file name.
1885 */
1886 sprintf(buffer1, "%.*s.bdf", dot - file, file);
1887
1888 /*
1889 * Delete the file and path names so they can be updated.
1890 */
1891 if (ed->file != 0)
1892 g_free(ed->file);
1893 if (ed->path != 0)
1894 g_free(ed->path);
1895
1896 ed->file = strdup(buffer1);
1897 ed->path = strdup(dir);
1898
1899 /*
1900 * Update the window title.
1901 */
1902 sprintf(buffer1, "%s - %s [modified]", g_get_prgname(), ed->file);
1903 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
1904
1905 /*
1906 * Tell the glyphtest widget to remove references to
1907 * the current font if it has any, and redraw.
1908 */
1909 if (glyphtest != 0)
1910 glyphtest_remove_font(GLYPHTEST(glyphtest),
1911 fontgrid_get_font(FONTGRID(ed->fgrid)));
1912
1913 fontgrid_set_font(FONTGRID(ed->fgrid), font, -1);
1914
1915 /*
1916 * Indicate the font was imported.
1917 */
1918 ed->imported = TRUE;
1919
1920 /*
1921 * Finally, update the font name field.
1922 */
1923 gtk_entry_set_text(GTK_ENTRY(ed->fontname),
1924 fontgrid_get_font_name(FONTGRID(ed->fgrid)));
1925 }
1926
1927 #endif /* HAVE_FREETYPE */
1928
1929 #ifdef HAVE_HBF
1930
1931 /**************************************************************************
1932 *
1933 * HBF section.
1934 *
1935 **************************************************************************/
1936
1937 static void
load_hbf_font(gbdfed_editor_t * ed,gchar * fullpath,gchar * dot,gchar * dir,gchar * file)1938 load_hbf_font(gbdfed_editor_t *ed, gchar *fullpath, gchar *dot,
1939 gchar *dir, gchar *file)
1940 {
1941 bdf_font_t *font;
1942
1943 guiutil_busy_cursor(ed->shell, TRUE);
1944 guiutil_busy_cursor(ed->open_dialog, TRUE);
1945
1946 font = bdf_load_hbf_font(fullpath, &options.font_opts, 0, 0);
1947
1948 guiutil_busy_cursor(ed->shell, FALSE);
1949 guiutil_busy_cursor(ed->open_dialog, FALSE);
1950
1951 /*
1952 * Check to see if the file can be opened.
1953 */
1954 if (font == 0) {
1955 g_free(dir);
1956 sprintf(buffer1, "Import Font: Unable to import %s.", file);
1957 guiutil_error_message(ed->shell, buffer1);
1958 return;
1959 }
1960
1961 gtk_widget_hide(ed->open_dialog);
1962
1963 /*
1964 * Now set up a file name.
1965 */
1966 sprintf(buffer1, "%.*s.bdf", (int) (dot - file), file);
1967
1968 /*
1969 * Delete the file and path names so they can be updated.
1970 */
1971 if (ed->file != 0)
1972 g_free(ed->file);
1973 if (ed->path != 0)
1974 g_free(ed->path);
1975
1976 ed->file = strdup(buffer1);
1977 ed->path = dir;
1978
1979 /*
1980 * Update the window title.
1981 */
1982 sprintf(buffer1, "%s - %s [modified]", g_get_prgname(), ed->file);
1983 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
1984
1985 /*
1986 * Tell the glyphtest widget to remove references to
1987 * the current font if it has any, and redraw.
1988 */
1989 if (glyphtest != 0)
1990 glyphtest_remove_font(GLYPHTEST(glyphtest),
1991 fontgrid_get_font(FONTGRID(ed->fgrid)));
1992
1993 fontgrid_set_font(FONTGRID(ed->fgrid), font, -1);
1994
1995 /*
1996 * Indicate the font was imported.
1997 */
1998 ed->imported = TRUE;
1999
2000 /*
2001 * Finally, update the font name field.
2002 */
2003 gtk_entry_set_text(GTK_ENTRY(ed->fontname),
2004 fontgrid_get_font_name(FONTGRID(ed->fgrid)));
2005 }
2006
2007 #endif
2008
2009 /*
2010 * This routine actually does the work of opening the font.
2011 */
2012 static void
really_open_font(guint ed_id)2013 really_open_font(guint ed_id)
2014 {
2015 gbdfed_editor_t *ed = editors + ed_id;
2016 gchar *filename, *path, *file, *dot;
2017 GtkFileChooser *fs;
2018 #if (GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 10)
2019 GtkRecentManager *recent;
2020 #endif
2021
2022 fs = GTK_FILE_CHOOSER(ed->open_dialog);
2023 filename = gtk_file_chooser_get_filename(fs);
2024
2025 /*
2026 * Split the filename into path and file, locate the extension position in
2027 * the file name, and make a version of the name with no '-' characters
2028 * which are field separators in XLFD font names.
2029 */
2030 file = g_path_get_basename(filename);
2031 path = g_path_get_dirname(filename);
2032 if ((dot = strrchr(file, '.')) == 0)
2033 dot = file + strlen(file);
2034
2035 /*
2036 * If the last character of the filename is a slash, no file name was
2037 * provided.
2038 */
2039 if (filename[strlen(filename) - 1] == G_DIR_SEPARATOR) {
2040 guiutil_error_message(ed->shell,
2041 "Import Font: No file name provided.");
2042 if (path)
2043 g_free(path);
2044 if (file)
2045 g_free(file);
2046 g_free(filename);
2047 return;
2048 }
2049
2050 #if (GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 10)
2051 recent = gtk_recent_manager_get_default();
2052 sprintf(buffer1, "file://%s", filename);
2053 if (gtk_recent_manager_has_item(recent,
2054 (const gchar *) buffer1) == FALSE)
2055 gtk_recent_manager_add_item(recent,
2056 (const gchar *) buffer1);
2057 #endif
2058
2059 switch (ed->import_format) {
2060 case BDF_FORMAT:
2061 load_bdf_font(ed, (const gchar *) filename, (const gchar *) path,
2062 (const gchar *) file);
2063 break;
2064 case CONSOLE_FORMAT:
2065 load_console_font(ed, filename, dot, path, file);
2066 break;
2067 case PKGF_FORMAT:
2068 load_pkgf_font(ed, filename, dot, path, file);
2069 break;
2070 case FNT_FORMAT:
2071 load_windows_font(ed, filename, dot, path, file);
2072 break;
2073 #ifdef HAVE_HBF
2074 case HBF_FORMAT:
2075 load_hbf_font(ed, filename, dot, path, file);
2076 break;
2077 #endif
2078 #ifdef HAVE_FREETYPE
2079 case OTF_FORMAT:
2080 load_otf_font(ed, filename, dot, path, file);
2081 break;
2082 #endif /* HAVE_FREETYPE */
2083 }
2084
2085 if (path)
2086 g_free(path);
2087 if (file)
2088 g_free(file);
2089
2090 g_free(filename);
2091
2092 /*
2093 * In case the editor list changed, set the pointer to the editor again.
2094 */
2095 ed = editors + ed_id;
2096
2097 /*
2098 * Force the editor's info to be updated for the new font. This causes
2099 * it to change if it is already visible.
2100 */
2101 guiedit_update_font_info(ed);
2102 }
2103
2104 static gchar *
make_file_dialog_title(guint type,gboolean save)2105 make_file_dialog_title(guint type, gboolean save)
2106 {
2107 gchar *title = 0;
2108
2109 switch (type) {
2110 case BDF_FORMAT: title = "BDF"; break;
2111 case CONSOLE_FORMAT: title = "Console"; break;
2112 case PKGF_FORMAT: title = "PK/GF"; break;
2113 case FNT_FORMAT: title = "Windows"; break;
2114 #ifdef HAVE_HBF
2115 case HBF_FORMAT: title = "HBF"; break;
2116 #endif
2117 case OTF_FORMAT: title = "TrueType"; break;
2118 case PSF_FORMAT: title = "PSF"; break;
2119 case HEX_FORMAT: title = "HEX"; break;
2120 }
2121
2122 if (save) {
2123 if (type == BDF_FORMAT)
2124 sprintf(buffer1, "Save %s Font", title);
2125 else
2126 sprintf(buffer1, "Export %s Font", title);
2127 } else
2128 sprintf(buffer1, "Open %s Font", title);
2129
2130 return buffer1;
2131 }
2132
2133 static void
handle_open_response(GtkDialog * d,gint response,gpointer data)2134 handle_open_response(GtkDialog *d, gint response, gpointer data)
2135 {
2136 switch (response) {
2137 case GTK_RESPONSE_ACCEPT:
2138 really_open_font(GPOINTER_TO_UINT(data));
2139 break;
2140 case GTK_RESPONSE_CANCEL:
2141 gtk_widget_hide(GTK_WIDGET(d));
2142 break;
2143 }
2144 }
2145
2146 static void
update_open_dialog(gbdfed_editor_t * ed,guint type)2147 update_open_dialog(gbdfed_editor_t *ed, guint type)
2148 {
2149 GtkFileChooser *fs;
2150
2151 if (ed->open_dialog == 0) {
2152 /*
2153 * Create the file chooser filters if they haven't already been
2154 * created.
2155 */
2156 make_file_chooser_filters();
2157
2158 ed->open_dialog =
2159 gtk_file_chooser_dialog_new(make_file_dialog_title(type, FALSE),
2160 GTK_WINDOW(ed->shell),
2161 GTK_FILE_CHOOSER_ACTION_OPEN,
2162 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2163 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
2164 NULL);
2165
2166 (void) g_signal_connect(G_OBJECT(ed->open_dialog), "response",
2167 G_CALLBACK(handle_open_response),
2168 GUINT_TO_POINTER(ed->id));
2169 (void) g_signal_connect(G_OBJECT(ed->open_dialog), "delete_event",
2170 G_CALLBACK(gtk_widget_hide), 0);
2171 } else if (ed->import_format != type)
2172 gtk_window_set_title(GTK_WINDOW(ed->open_dialog),
2173 make_file_dialog_title(type, FALSE));
2174 fs = GTK_FILE_CHOOSER(ed->open_dialog);
2175
2176 /*
2177 * Set the file filter.
2178 */
2179 gtk_file_chooser_set_filter(fs, filename_filters[type]);
2180
2181 ed->import_format = type;
2182
2183 /*
2184 * Set the initial path as a file if it exists. This is necessary to
2185 * force the open to occur in the directory where this font was last
2186 * saved, which might be different than the directory that is currently in
2187 * the open file selection dialog.
2188 */
2189 if (ed->path != 0 && ed->path[0] == G_DIR_SEPARATOR)
2190 gtk_file_chooser_set_current_folder(fs, ed->path);
2191 }
2192
2193 static void
hide_save_dialog(GtkWidget * w,gpointer data)2194 hide_save_dialog(GtkWidget *w, gpointer data)
2195 {
2196 gtk_widget_hide(w);
2197 save_dialog_done = TRUE;
2198 }
2199
2200 static void
set_psf_option(GtkWidget * w,gpointer data)2201 set_psf_option(GtkWidget *w, gpointer data)
2202 {
2203 guint flags = 0;
2204 gint dotpos;
2205 gchar *fname, *dot, *slash, *suff = 0;
2206 GtkFileChooser *fs;
2207
2208 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(w))) {
2209 case 0:
2210 flags = BDF_PSF_UNIMAP|BDF_PSF_FONT;
2211 break;
2212 case 1:
2213 flags = BDF_PSF_FONT;
2214 break;
2215 case 2:
2216 flags = BDF_PSF_UNIMAP;
2217 break;
2218 }
2219
2220 if (flags == BDF_PSF_UNIMAP)
2221 /*
2222 * Have to change to the .uni suffix.
2223 */
2224 suff = ".uni";
2225 else if (options.font_opts.psf_flags == BDF_PSF_UNIMAP)
2226 /*
2227 * Have to change back to the .psfu suffix.
2228 */
2229 suff = ".psfu";
2230
2231 options.font_opts.psf_flags = flags;
2232
2233 if (suff) {
2234 /*
2235 * Change the suffix on the filename in the entry area.
2236 */
2237 fs = GTK_FILE_CHOOSER(g_object_get_data(G_OBJECT(w),
2238 "file-selection-dialog"));
2239 fname = gtk_file_chooser_get_filename(fs);
2240
2241 slash = fname;
2242 if ((dot = (gchar *) strrchr(fname, '.')) != 0) {
2243 if ((slash = (gchar *) strrchr(fname, G_DIR_SEPARATOR)) == 0)
2244 slash = fname;
2245 dotpos = (gint) (dot - slash) - 1;
2246
2247 /*
2248 * Copy the new extension in.
2249 */
2250 (void) strcpy(dot, suff);
2251 } else
2252 dotpos = -1;
2253
2254 if (*slash == G_DIR_SEPARATOR)
2255 *slash++ = 0;
2256
2257 gtk_file_chooser_set_current_name(fs, slash);
2258 g_free(fname);
2259 }
2260 }
2261
2262 static void
handle_save_response(GtkDialog * d,gint response,gpointer data)2263 handle_save_response(GtkDialog *d, gint response, gpointer data)
2264 {
2265 switch (response) {
2266 case GTK_RESPONSE_ACCEPT:
2267 really_save_font(GPOINTER_TO_UINT(data));
2268 break;
2269 case GTK_RESPONSE_CANCEL:
2270 gtk_widget_hide(GTK_WIDGET(d));
2271 break;
2272 }
2273 }
2274
2275 static void
update_save_dialog(gbdfed_editor_t * ed,guint type)2276 update_save_dialog(gbdfed_editor_t *ed, guint type)
2277 {
2278 GtkWidget *vbox;
2279 gchar *dot, *slash;
2280 gint dotpos;
2281
2282 if (ed->save_dialog == 0) {
2283 /*
2284 * Create the file chooser filters if they haven't already been
2285 * created.
2286 */
2287 make_file_chooser_filters();
2288
2289 ed->save_dialog =
2290 gtk_file_chooser_dialog_new(make_file_dialog_title(type, TRUE),
2291 GTK_WINDOW(ed->shell),
2292 GTK_FILE_CHOOSER_ACTION_SAVE,
2293 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2294 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
2295 NULL);
2296
2297 vbox = GTK_DIALOG(ed->save_dialog)->vbox;
2298
2299 psf_export_options = gtk_combo_box_new_text();
2300 /*
2301 * Since the flags have to be set in the save dialog, attach the
2302 * save dialog to the object so we can set the bits appropriately.
2303 */
2304 g_object_set_data(G_OBJECT(psf_export_options),
2305 "file-selection-dialog",
2306 (gpointer) ed->save_dialog);
2307 (void) g_signal_connect(G_OBJECT(psf_export_options), "changed",
2308 G_CALLBACK(set_psf_option), 0);
2309 gtk_combo_box_append_text(GTK_COMBO_BOX(psf_export_options),
2310 "Font and Unicode Map");
2311 gtk_combo_box_append_text(GTK_COMBO_BOX(psf_export_options),
2312 "Font Only");
2313 gtk_combo_box_append_text(GTK_COMBO_BOX(psf_export_options),
2314 "Unicode Map Only");
2315 gtk_combo_box_set_active(GTK_COMBO_BOX(psf_export_options), 0);
2316
2317 psf_export_frame = labcon_new_label_defaults("PSF Export Options:",
2318 psf_export_options, 0);
2319
2320 (void) g_signal_connect(G_OBJECT(ed->save_dialog), "delete_event",
2321 G_CALLBACK(hide_save_dialog), 0);
2322
2323 (void) g_signal_connect(G_OBJECT(ed->save_dialog), "response",
2324 G_CALLBACK(handle_save_response),
2325 GUINT_TO_POINTER(ed->id));
2326
2327 gtk_widget_show_all(psf_export_frame);
2328 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(ed->save_dialog),
2329 psf_export_frame);
2330 } else if (ed->export_format != type)
2331 gtk_window_set_title(GTK_WINDOW(ed->save_dialog),
2332 make_file_dialog_title(type, TRUE));
2333
2334 /*
2335 * Set the file filter.
2336 */
2337 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(ed->save_dialog),
2338 filename_filters[type]);
2339
2340
2341 ed->export_format = type;
2342
2343 /*
2344 * Show or hide the PSF exporting options.
2345 */
2346 if (type == PSF_FORMAT)
2347 gtk_widget_show(psf_export_frame);
2348 else
2349 gtk_widget_hide(psf_export_frame);
2350
2351 /*
2352 * Use the current path and filename as the default. This is done in case
2353 * the font was loaded from some directory other than the current default
2354 * in the file selection dialog for saving.
2355 */
2356 if (ed->file != 0)
2357 sprintf(buffer1, "%s", ed->file);
2358 else
2359 sprintf(buffer1, "unnamed%d.bdf", ed->id);
2360
2361 if ((dot = (gchar *) strrchr(buffer1, '.'))) {
2362 if ((slash = (gchar *) strrchr(buffer1, G_DIR_SEPARATOR)) == 0)
2363 slash = buffer1;
2364 dotpos = (gint) (dot - slash) - 1;
2365
2366 /*
2367 * If a PSF or HEX font is being exported, change the extension
2368 * here.
2369 */
2370 if (type == PSF_FORMAT)
2371 (void) strcpy(dot, ".psfu");
2372 else if (type == HEX_FORMAT)
2373 (void) strcpy(dot, ".hex");
2374
2375 } else
2376 dotpos = -1;
2377
2378 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(ed->save_dialog),
2379 buffer1);
2380 if (ed->path != 0 && ed->path[0] == G_DIR_SEPARATOR)
2381 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(ed->save_dialog),
2382 ed->path);
2383 #if 0
2384 gtk_editable_set_position(GTK_EDITABLE(fs->selection_entry), dotpos);
2385 gtk_editable_select_region(GTK_EDITABLE(fs->selection_entry), 0, dotpos);
2386 #endif
2387 }
2388
2389 void
guifile_import_bdf_font(GtkWidget * w,gpointer data)2390 guifile_import_bdf_font(GtkWidget *w, gpointer data)
2391 {
2392 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2393
2394 if (fontgrid_get_font_modified(FONTGRID(ed->fgrid))) {
2395 if (ed->file == 0)
2396 sprintf(buffer1, "Save Font: (unnamed%d) modified. Save?", ed->id);
2397 else
2398 sprintf(buffer1, "Save Font: %s modified. Save?", ed->file);
2399 if (guiutil_yes_or_no(ed->shell, buffer1, TRUE)) {
2400 /*
2401 * If the current file was imported, then make sure to use the
2402 * Save As... dialog instead of just saving under the name that
2403 * was constructed when importing. The user won't know what the
2404 * default BDF file name of imported fonts look like.
2405 */
2406 if (ed->imported)
2407 guifile_save_as_wait(w, data);
2408 else
2409 guifile_save(w, data);
2410 return;
2411 }
2412 }
2413
2414 update_open_dialog(ed, BDF_FORMAT);
2415
2416 guiutil_show_dialog_centered(ed->open_dialog, ed->shell);
2417 }
2418
2419 void
guifile_import_console_font(GtkWidget * w,gpointer data)2420 guifile_import_console_font(GtkWidget *w, gpointer data)
2421 {
2422 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2423
2424 if (fontgrid_get_font_modified(FONTGRID(ed->fgrid))) {
2425 if (ed->file == 0)
2426 sprintf(buffer1, "Save Font: (unnamed%d) modified. Save?", ed->id);
2427 else
2428 sprintf(buffer1, "Save Font: %s modified. Save?", ed->file);
2429 if (guiutil_yes_or_no(ed->shell, buffer1, TRUE)) {
2430 /*
2431 * If the current file was imported, then make sure to use the
2432 * Save As... dialog instead of just saving under the name that
2433 * was constructed when importing. The user won't know what the
2434 * default BDF file name of imported fonts look like.
2435 */
2436 if (ed->imported)
2437 guifile_save_as_wait(w, data);
2438 else
2439 guifile_save(w, data);
2440 return;
2441 }
2442 }
2443
2444 update_open_dialog(ed, CONSOLE_FORMAT);
2445
2446 guiutil_show_dialog_centered(ed->open_dialog, ed->shell);
2447 }
2448
2449 void
guifile_import_pkgf_font(GtkWidget * w,gpointer data)2450 guifile_import_pkgf_font(GtkWidget *w, gpointer data)
2451 {
2452 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2453
2454 if (fontgrid_get_font_modified(FONTGRID(ed->fgrid))) {
2455 if (ed->file == 0)
2456 sprintf(buffer1, "Save Font: (unnamed%d) modified. Save?", ed->id);
2457 else
2458 sprintf(buffer1, "Save Font: %s modified. Save?", ed->file);
2459 if (guiutil_yes_or_no(ed->shell, buffer1, TRUE)) {
2460 /*
2461 * If the current file was imported, then make sure to use the
2462 * Save As... dialog instead of just saving under the name that
2463 * was constructed when importing. The user won't know what the
2464 * default BDF file name of imported fonts look like.
2465 */
2466 if (ed->imported)
2467 guifile_save_as_wait(w, data);
2468 else
2469 guifile_save(w, data);
2470 return;
2471 }
2472 }
2473
2474 update_open_dialog(ed, PKGF_FORMAT);
2475
2476 guiutil_show_dialog_centered(ed->open_dialog, ed->shell);
2477 }
2478
2479 void
guifile_import_windows_font(GtkWidget * w,gpointer data)2480 guifile_import_windows_font(GtkWidget *w, gpointer data)
2481 {
2482 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2483
2484 if (fontgrid_get_font_modified(FONTGRID(ed->fgrid))) {
2485 if (ed->file == 0)
2486 sprintf(buffer1, "Save Font: (unnamed%d) modified. Save?", ed->id);
2487 else
2488 sprintf(buffer1, "Save Font: %s modified. Save?", ed->file);
2489 if (guiutil_yes_or_no(ed->shell, buffer1, TRUE)) {
2490 /*
2491 * If the current file was imported, then make sure to use the
2492 * Save As... dialog instead of just saving under the name that
2493 * was constructed when importing. The user won't know what the
2494 * default BDF file name of imported fonts look like.
2495 */
2496 if (ed->imported)
2497 guifile_save_as_wait(w, data);
2498 else
2499 guifile_save(w, data);
2500 return;
2501 }
2502 }
2503
2504 update_open_dialog(ed, FNT_FORMAT);
2505
2506 guiutil_show_dialog_centered(ed->open_dialog, ed->shell);
2507 }
2508
2509 #ifdef HAVE_HBF
2510
2511 void
guifile_import_hbf_font(GtkWidget * w,gpointer data)2512 guifile_import_hbf_font(GtkWidget *w, gpointer data)
2513 {
2514 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2515
2516 if (fontgrid_get_font_modified(FONTGRID(ed->fgrid))) {
2517 if (ed->file == 0)
2518 sprintf(buffer1, "Save Font: (unnamed%d) modified. Save?", ed->id);
2519 else
2520 sprintf(buffer1, "Save Font: %s modified. Save?", ed->file);
2521 if (guiutil_yes_or_no(ed->shell, buffer1, TRUE)) {
2522 /*
2523 * If the current file was imported, then make sure to use the
2524 * Save As... dialog instead of just saving under the name that
2525 * was constructed when importing. The user won't know what the
2526 * default BDF file name of imported fonts look like.
2527 */
2528 if (ed->imported)
2529 guifile_save_as_wait(w, data);
2530 else
2531 guifile_save(w, data);
2532 return;
2533 }
2534 }
2535
2536 update_open_dialog(ed, HBF_FORMAT);
2537
2538 guiutil_show_dialog_centered(ed->open_dialog, ed->shell);
2539 }
2540
2541 #endif
2542
2543 #ifdef HAVE_FREETYPE
2544
2545 void
guifile_import_otf_font(GtkWidget * w,gpointer data)2546 guifile_import_otf_font(GtkWidget *w, gpointer data)
2547 {
2548 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2549
2550 if (fontgrid_get_font_modified(FONTGRID(ed->fgrid))) {
2551 if (ed->file == 0)
2552 sprintf(buffer1, "Save Font: (unnamed%d) modified. Save?", ed->id);
2553 else
2554 sprintf(buffer1, "Save Font: %s modified. Save?", ed->file);
2555 if (guiutil_yes_or_no(ed->shell, buffer1, TRUE)) {
2556 /*
2557 * If the current file was imported, then make sure to use the
2558 * Save As... dialog instead of just saving under the name that
2559 * was constructed when importing. The user won't know what the
2560 * default BDF file name of imported fonts look like.
2561 */
2562 if (ed->imported)
2563 guifile_save_as_wait(w, data);
2564 else
2565 guifile_save(w, data);
2566 return;
2567 }
2568 }
2569
2570 update_open_dialog(ed, OTF_FORMAT);
2571
2572 guiutil_show_dialog_centered(ed->open_dialog, ed->shell);
2573 }
2574
2575 #endif /* HAVE_FREETYPE */
2576
2577 /**************************************************************************
2578 *
2579 * X server section.
2580 *
2581 **************************************************************************/
2582
2583 #ifdef HAVE_XLIB
2584 /*
2585 * Only compile this in if it is being built for machine running X.
2586 */
2587
2588 static void
xsrv_filter(GtkWidget * w,gpointer data)2589 xsrv_filter(GtkWidget *w, gpointer data)
2590 {
2591 gchar *pattern, **fonts;
2592 gint i, nfonts;
2593 GtkListStore *store;
2594 GtkTreeViewColumn *col;
2595 GtkTreeIter iter;
2596
2597 pattern = (gchar *) gtk_entry_get_text(GTK_ENTRY(xsrv_filter_text));
2598
2599 fonts = XListFonts(GDK_DISPLAY(), pattern, _XSRV_MAX_FONTS, &nfonts);
2600
2601 store =
2602 GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(xsrv_font_list)));
2603 col = gtk_tree_view_get_column(GTK_TREE_VIEW(xsrv_font_list), 0);
2604
2605 /*
2606 * Update the label on the font list with the number of fonts.
2607 */
2608 sprintf(buffer1, "Font List: %d", nfonts);
2609 gtk_tree_view_column_set_title(col, buffer1);
2610
2611 gtk_list_store_clear(store);
2612 for (i = 0; i < nfonts; i++) {
2613 gtk_list_store_append(store, &iter);
2614 gtk_list_store_set(store, &iter, 0, fonts[i], -1);
2615 }
2616
2617 XFreeFontNames(fonts);
2618 }
2619
2620 static void
xsrv_xlfd_filter(GtkWidget * w,gpointer data)2621 xsrv_xlfd_filter(GtkWidget *w, gpointer data)
2622 {
2623 gtk_entry_set_text(GTK_ENTRY(xsrv_filter_text), _XSRV_DEFAULT_FILTER);
2624 gtk_widget_activate(xsrv_filter_text);
2625 }
2626
2627 static void
xsrv_select_font(GtkTreeSelection * sel,gpointer data)2628 xsrv_select_font(GtkTreeSelection *sel, gpointer data)
2629 {
2630 gchar *name;
2631 GtkTreeModel *model;
2632 GtkTreeIter iter;
2633
2634 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
2635 gtk_tree_model_get (model, &iter, 0, &name, -1);
2636 gtk_entry_set_text(GTK_ENTRY(xsrv_selection_text), name);
2637 g_free(name);
2638 }
2639 }
2640
2641 static void
xsrv_clear_selection_text(GtkWidget * w,gpointer data)2642 xsrv_clear_selection_text(GtkWidget *w, gpointer data)
2643 {
2644 gtk_entry_set_text(GTK_ENTRY(xsrv_selection_text), "");
2645 }
2646
2647 static void
xsrv_import_font(GtkWidget * w,gpointer data)2648 xsrv_import_font(GtkWidget *w, gpointer data)
2649 {
2650 gbdfed_editor_t *ed = editors + xsrv_active_editor;
2651 XFontStruct *xfont;
2652 bdf_font_t *font;
2653 gchar *name;
2654
2655 name = (gchar *) gtk_entry_get_text(GTK_ENTRY(xsrv_selection_text));
2656 if (strcmp(name, "") == 0) {
2657 guiutil_error_message(ed->shell,
2658 "Import Font: No font name provided.");
2659 return;
2660 }
2661
2662 guiutil_busy_cursor(ed->shell, TRUE);
2663 guiutil_busy_cursor(xsrv_dialog, TRUE);
2664 if ((xfont = XLoadQueryFont(GDK_DISPLAY(), name)) == 0) {
2665 guiutil_busy_cursor(ed->shell, FALSE);
2666 guiutil_busy_cursor(xsrv_dialog, FALSE);
2667 sprintf(buffer1, "Import Font: Unable to load server font %s.",
2668 name);
2669 guiutil_error_message(ed->shell, buffer1);
2670 return;
2671 }
2672
2673 font = bdf_load_server_font(GDK_DISPLAY(), xfont, name,
2674 &options.font_opts, 0, 0);
2675 guiutil_busy_cursor(ed->shell, FALSE);
2676 guiutil_busy_cursor(xsrv_dialog, FALSE);
2677 XFreeFont(GDK_DISPLAY(), xfont);
2678
2679 if (font == 0) {
2680 sprintf(buffer1, "Import Font: Unable to import server font %s.",
2681 name);
2682 guiutil_error_message(ed->shell, buffer1);
2683 return;
2684 }
2685
2686 /*
2687 * Close the dialog.
2688 */
2689 gtk_widget_hide(xsrv_dialog);
2690
2691 if (ed->file != 0)
2692 g_free(ed->file);
2693 if (ed->path != 0)
2694 g_free(ed->path);
2695 ed->file = ed->path = 0;
2696
2697 sprintf(buffer1, "%s - unnamed%d [modified]", g_get_prgname(),
2698 ed->id);
2699 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
2700
2701 /*
2702 * Tell the glyphtest widget to remove references to
2703 * the current font if it has any, and redraw.
2704 */
2705 if (glyphtest != 0)
2706 glyphtest_remove_font(GLYPHTEST(glyphtest),
2707 fontgrid_get_font(FONTGRID(ed->fgrid)));
2708
2709 fontgrid_set_font(FONTGRID(ed->fgrid), font, -1);
2710
2711 /*
2712 * Indicate the font was imported.
2713 */
2714 ed->imported = TRUE;
2715
2716 /*
2717 * Finally, update the font name field.
2718 */
2719 gtk_entry_set_text(GTK_ENTRY(ed->fontname),
2720 fontgrid_get_font_name(FONTGRID(ed->fgrid)));
2721 }
2722
2723 static void
xsrv_activate_font(GtkTreeView * view,GtkTreePath * path,GtkTreeViewColumn * col,gpointer data)2724 xsrv_activate_font(GtkTreeView *view, GtkTreePath *path,
2725 GtkTreeViewColumn *col, gpointer data)
2726 {
2727 xsrv_import_font(GTK_WIDGET(view), data);
2728 }
2729
2730 void
guifile_import_xserver_font(GtkWidget * w,gpointer data)2731 guifile_import_xserver_font(GtkWidget *w, gpointer data)
2732 {
2733 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2734 GtkWidget *label, *hbox, *vbox, *text, *swin, *button;
2735 gchar *name, **fonts;
2736 gint i, nfonts;
2737 GtkListStore *store;
2738 GtkTreeViewColumn *column;
2739 GtkCellRenderer *cell_renderer;
2740 GtkTreeSelection *sel;
2741 GtkTreeIter iter;
2742
2743 if (fontgrid_get_font_modified(FONTGRID(ed->fgrid))) {
2744 if (ed->file == 0)
2745 sprintf(buffer1, "Save Font: (unnamed%d) modified. Save?", ed->id);
2746 else
2747 sprintf(buffer1, "Save Font: %s modified. Save?", ed->file);
2748 if (guiutil_yes_or_no(ed->shell, buffer1, TRUE)) {
2749 /*
2750 * If the current file was imported, then make sure to use the
2751 * Save As... dialog instead of just saving under the name that
2752 * was constructed when importing. The user won't know what the
2753 * default BDF file name of imported fonts look like.
2754 */
2755 if (ed->imported)
2756 guifile_save_as_wait(w, data);
2757 else
2758 guifile_save(w, data);
2759 return;
2760 }
2761 }
2762
2763 xsrv_active_editor = ed->id;
2764
2765 if (xsrv_dialog == 0) {
2766 xsrv_dialog = gtk_dialog_new();
2767 gtk_window_set_title(GTK_WINDOW(xsrv_dialog),
2768 "X Server Font Selection");
2769 (void) g_signal_connect(G_OBJECT(xsrv_dialog), "delete_event",
2770 G_CALLBACK(gtk_widget_hide), 0);
2771
2772 vbox = GTK_DIALOG(xsrv_dialog)->vbox;
2773 hbox = GTK_DIALOG(xsrv_dialog)->action_area;
2774
2775 label = gtk_label_new("Filter");
2776 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
2777 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
2778
2779 text = xsrv_filter_text = gtk_entry_new();
2780 gtk_entry_set_text(GTK_ENTRY(text), _XSRV_DEFAULT_FILTER);
2781 (void) g_signal_connect(G_OBJECT(text), "activate",
2782 G_CALLBACK(xsrv_filter), 0);
2783 gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 0);
2784
2785 swin = gtk_scrolled_window_new(0, 0);
2786 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
2787 GTK_POLICY_AUTOMATIC,
2788 GTK_POLICY_ALWAYS);
2789
2790 store = gtk_list_store_new(1, G_TYPE_STRING);
2791 xsrv_font_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2792 g_object_unref(store);
2793
2794 (void) g_signal_connect(G_OBJECT(xsrv_font_list), "row_activated",
2795 G_CALLBACK(xsrv_activate_font),
2796 GUINT_TO_POINTER(ed->id));
2797
2798 cell_renderer = gtk_cell_renderer_text_new();
2799 column = gtk_tree_view_column_new_with_attributes ("Fonts Found: 0",
2800 cell_renderer,
2801 "text", 0,
2802 NULL);
2803
2804 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
2805 gtk_tree_view_append_column (GTK_TREE_VIEW(xsrv_font_list), column);
2806
2807 /*
2808 * Force the list to have a certain width and height.
2809 */
2810 gtk_widget_set_size_request(xsrv_font_list, 550, 200);
2811
2812 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(xsrv_font_list));
2813 gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
2814
2815 (void) g_signal_connect(G_OBJECT(sel), "changed",
2816 G_CALLBACK(xsrv_select_font), NULL);
2817
2818 gtk_container_add(GTK_CONTAINER(swin), xsrv_font_list);
2819
2820 gtk_box_pack_start(GTK_BOX(vbox), swin, TRUE, TRUE, 0);
2821
2822 label = gtk_label_new("Selection");
2823 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
2824 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
2825
2826 text = xsrv_selection_text = gtk_entry_new();
2827 (void) g_signal_connect(G_OBJECT(text), "activate",
2828 G_CALLBACK(xsrv_import_font),
2829 GUINT_TO_POINTER(ed->id));
2830 gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 0);
2831
2832 /*
2833 * Now add the buttons.
2834 */
2835 button = xsrv_import = gtk_button_new_with_label("Import");
2836 (void) g_signal_connect(G_OBJECT(button), "clicked",
2837 G_CALLBACK(xsrv_import_font),
2838 GUINT_TO_POINTER(ed->id));
2839 gtk_container_add(GTK_CONTAINER(hbox), button);
2840
2841 button = xsrv_import = gtk_button_new_with_label("Clear Selection");
2842 (void) g_signal_connect(G_OBJECT(button), "clicked",
2843 G_CALLBACK(xsrv_clear_selection_text), 0);
2844 gtk_container_add(GTK_CONTAINER(hbox), button);
2845
2846 button = gtk_button_new_with_label("Filter");
2847 (void) g_signal_connect(G_OBJECT(button), "clicked",
2848 G_CALLBACK(xsrv_filter), 0);
2849 gtk_container_add(GTK_CONTAINER(hbox), button);
2850
2851 button = gtk_button_new_with_label("XLFD Filter");
2852 (void) g_signal_connect(G_OBJECT(button), "clicked",
2853 G_CALLBACK(xsrv_xlfd_filter), 0);
2854 gtk_container_add(GTK_CONTAINER(hbox), button);
2855
2856 button = gtk_button_new_with_label("Cancel");
2857 (void) g_signal_connect_object(G_OBJECT(button), "clicked",
2858 G_CALLBACK(gtk_widget_hide),
2859 (gpointer) xsrv_dialog,
2860 G_CONNECT_SWAPPED);
2861 gtk_container_add(GTK_CONTAINER(hbox), button);
2862
2863 gtk_widget_show_all(vbox);
2864 gtk_widget_show_all(hbox);
2865 }
2866
2867 store =
2868 GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(xsrv_font_list)));
2869 column = gtk_tree_view_get_column(GTK_TREE_VIEW(xsrv_font_list), 0);
2870
2871 /*
2872 * Load the list of fonts using the current filter pattern. This needs to
2873 * be done each time in case the list of font paths has changed between
2874 * calls.
2875 */
2876 name = (gchar *) gtk_entry_get_text(GTK_ENTRY(xsrv_filter_text));
2877 fonts = XListFonts(GDK_DISPLAY(), name, _XSRV_MAX_FONTS, &nfonts);
2878
2879 /*
2880 * Update the label on the font list with the number of fonts.
2881 */
2882 sprintf(buffer1, "Fonts Found: %d", nfonts);
2883 gtk_tree_view_column_set_title(column, buffer1);
2884
2885 gtk_list_store_clear(store);
2886 for (i = 0; i < nfonts; i++) {
2887 gtk_list_store_append(store, &iter);
2888 gtk_list_store_set(store, &iter, 0, fonts[i], -1);
2889 }
2890
2891 XFreeFontNames(fonts);
2892
2893 /*
2894 * Show the dialog.
2895 */
2896 guiutil_show_dialog_centered(xsrv_dialog, ed->shell);
2897
2898 }
2899
2900 #endif /* HAVE_XLIB */
2901
2902 void
guifile_export_psf_font(GtkWidget * w,gpointer data)2903 guifile_export_psf_font(GtkWidget *w, gpointer data)
2904 {
2905 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2906 bdf_font_t *font;
2907
2908 font = fontgrid_get_font(FONTGRID(ed->fgrid));
2909
2910 /*
2911 * Only character cell and mono width fonts can be exported as PSF2.
2912 */
2913 if (font->spacing == BDF_PROPORTIONAL) {
2914 sprintf(buffer2,
2915 "Export Font: Font cannot be saved as PSF because %s ",
2916 "the font has proportional width.");
2917 guiutil_error_message(ed->shell, buffer2);
2918 return;
2919 }
2920
2921 update_save_dialog(ed, PSF_FORMAT);
2922
2923 guiutil_show_dialog_centered(ed->save_dialog, ed->shell);
2924 }
2925
2926 void
guifile_export_hex_font(GtkWidget * w,gpointer data)2927 guifile_export_hex_font(GtkWidget *w, gpointer data)
2928 {
2929 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2930
2931 /*
2932 * No check is done for a "valid" HEX font because it actually pads the
2933 * output font into bitmaps of two sizes, the wider size twice as wide
2934 * as the narrower size.
2935 */
2936
2937 update_save_dialog(ed, HEX_FORMAT);
2938
2939 guiutil_show_dialog_centered(ed->save_dialog, ed->shell);
2940 }
2941
2942 void
guifile_save_as(GtkWidget * w,gpointer data)2943 guifile_save_as(GtkWidget *w, gpointer data)
2944 {
2945 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2946
2947 update_save_dialog(ed, BDF_FORMAT);
2948
2949 guiutil_show_dialog_centered(ed->save_dialog, ed->shell);
2950 }
2951
2952 void
guifile_save_as_wait(GtkWidget * w,gpointer data)2953 guifile_save_as_wait(GtkWidget *w, gpointer data)
2954 {
2955 save_dialog_done = FALSE;
2956
2957 guifile_save_as(w, data);
2958 while (save_dialog_done == FALSE)
2959 gtk_main_iteration();
2960 }
2961
2962 void
guifile_save(GtkWidget * w,gpointer data)2963 guifile_save(GtkWidget *w, gpointer data)
2964 {
2965 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
2966
2967 /*
2968 * If this is a new font, then we need to show the file selection dialog.
2969 * Otherwise, simply write the font out.
2970 */
2971 if (ed->path == 0 && ed->file == 0) {
2972 guifile_save_as(w, data);
2973 return;
2974 }
2975
2976 ed->export_format = BDF_FORMAT;
2977 sprintf(buffer1, "%s/%s", ed->path, ed->file);
2978 export_font(buffer1, ed, FALSE);
2979 }
2980
2981 void
guifile_new_editor(GtkWidget * w,gpointer data)2982 guifile_new_editor(GtkWidget *w, gpointer data)
2983 {
2984 guint n;
2985
2986 n = gbdfed_make_editor(0, FALSE);
2987
2988 gtk_widget_show_all(editors[n].shell);
2989 }
2990
2991 /*
2992 * A routine to load a BDF font directly.
2993 */
2994 void
guifile_load_bdf_font(gbdfed_editor_t * ed,const gchar * fullpath)2995 guifile_load_bdf_font(gbdfed_editor_t *ed, const gchar *fullpath)
2996 {
2997 gchar *dir, *file;
2998
2999 if (fullpath == NULL)
3000 return;
3001
3002 file = g_path_get_basename(fullpath);
3003 dir = g_path_get_dirname(fullpath);
3004 load_bdf_font(ed, fullpath, dir, file);
3005 if (dir != NULL)
3006 g_free(dir);
3007 if (file != NULL)
3008 g_free(file);
3009 }
3010