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