2 * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 /**************************************************************************
28 * Application globals.
30 **************************************************************************/
32 gchar buffer1[BUFSIZ];
33 gchar buffer2[BUFSIZ];
34 gbdfed_options_t options;
37 * The list of editors that exist.
39 gbdfed_editor_t *editors;
42 /**************************************************************************
44 * Forward declarations and local variables.
46 **************************************************************************/
49 * These are formats that can appear in the editor for importing/loading and
52 #define XMBDFED_BDF_FORMAT 1
53 #define XMBDFED_CONSOLE_FORMAT 2
54 #define XMBDFED_PKGF_FORMAT 3
55 #define XMBDFED_FNT_FORMAT 4
56 #define XMBDFED_HBF_FORMAT 5
57 #define XMBDFED_TTF_FORMAT 6
58 #define XMBDFED_PSF_FORMAT 7
59 #define XMBDFED_HEX_FORMAT 8
61 /**************************************************************************
65 **************************************************************************/
67 static const gchar *gbdfed_16x16[] = {
68 /* width height num_colors chars_per_pixel */
95 static const gchar *gbdfed_32x32[] = {
96 /* width height num_colors chars_per_pixel */
104 ".##a##.##.##.##.##.##.##.##.##.#",
105 ".##a##.##.##.##.##.##.##.##.##.#",
106 "...a............................",
107 ".##a##.##.##.##.##.##.##.##.##.#",
108 ".##a##.##.##.##.##.##.##.##.##.#",
109 "...a............................",
110 ".##abb.bb.bb.##.##.##.##.##.bb.#",
111 ".##abb.bb.bb.##.##.##.##.##.bb.#",
112 "...a............................",
113 ".##a##.bb.bb.bb.##.##.##.bb.##.#",
114 ".##a##.bb.bb.bb.##.##.##.bb.##.#",
115 "...a............................",
116 ".##a##.##.bb.bb.bb.##.bb.##.##.#",
117 ".##a##.##.bb.bb.bb.##.bb.##.##.#",
118 "...a............................",
119 ".##a##.##.##.bb.##.bb.##.##.##.#",
120 ".##a##.##.##.bb.##.bb.##.##.##.#",
121 "...a............................",
122 ".##a##.##.bb.##.bb.bb.bb.##.##.#",
123 ".##a##.##.bb.##.bb.bb.bb.##.##.#",
124 "...a............................",
125 ".##a##.bb.##.##.##.bb.bb.bb.##.#",
126 ".##a##.bb.##.##.##.bb.bb.bb.##.#",
127 "...a............................",
128 ".##abb.##.##.##.##.##.bb.bb.bb.#",
129 ".##abb.##.##.##.##.##.bb.bb.bb.#",
130 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
131 ".##a##.##.##.##.##.##.##.##.##.#",
132 ".##a##.##.##.##.##.##.##.##.##.#",
133 "...a............................",
134 ".##a##.##.##.##.##.##.##.##.##.#",
135 ".##a##.##.##.##.##.##.##.##.##.#"
138 static const gchar *gbdfed_48x48[] = {
139 /* width height num_colors chars_per_pixel */
147 "....#...........................................",
148 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa",
149 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa",
150 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa..aa.aaa.aaa",
151 "....#...........................................",
152 ".aaa#bbb.bbb.bbb.aaa.aaa.aaa.aaa.aaa.aaa.aaa.bbb",
153 ".aaa#bbb.bbb.bbb.aaa.aaa.aaa.aaa.aaa.aaa.aaa.bbb",
154 ".aaa#bbb.bbb.bbb.aaa.aaa.aaa.aaa.aaa.aaa.aaa.bbb",
155 "....#...........................................",
156 ".aaa#aaa.bbb.bbb.bbb.aaa.aaa.aaa.aaa.aaa.bbb.aaa",
157 ".aaa#aaa.bbb.bbb.bbb.aaa.aaa.aaa.aaa.aaa.bbb.aaa",
158 ".aaa#aaa.bbb.bbb.bbb.aaa.aaa.aaa.aaa.aaa.bbb.aaa",
159 "....#...........................................",
160 ".aaa#aaa.aaa.bbb.bbb.bbb.aaa.aaa.aaa.bbb.aaa.aaa",
161 ".aaa#aaa.aaa.bbb.bbb.bbb.aaa.aaa.aaa.bbb.aaa.aaa",
162 ".aaa#aaa.aaa.bbb.bbb.bbb.aaa.aaa.aaa.bbb.aaa.aaa",
163 "....#...........................................",
164 ".aaa#aaa.aaa.aaa.bbb.bbb.bbb.aaa.bbb.aaa.aaa.aaa",
165 ".aaa#aaa.aaa.aaa.bbb.bbb.bbb.aaa.bbb.aaa.aaa.aaa",
166 ".aaa#aaa.aaa.aaa.bbb.bbb.bbb.aaa.bbb.aaa.aaa.aaa",
167 "....#...........................................",
168 ".aaa#aaa.aaa.aaa.aaa.bbb.aaa.bbb.aaa.aaa.aaa.aaa",
169 ".aaa#aaa.aaa.aaa.aaa.bbb.aaa.bbb.aaa.aaa.aaa.aaa",
170 ".aaa#aaa.aaa.aaa.aaa.bbb.aaa.bbb.aaa.aaa.aaa.aaa",
171 "....#...........................................",
172 ".aaa#aaa.aaa.aaa.bbb.aaa.bbb.bbb.bbb.aaa.aaa.aaa",
173 ".aaa#aaa.aaa.aaa.bbb.aaa.bbb.bbb.bbb.aaa.aaa.aaa",
174 ".aaa#aaa.aaa.aaa.bbb.aaa.bbb.bbb.bbb.aaa.aaa.aaa",
175 "....#...........................................",
176 ".aaa#aaa.aaa.bbb.aaa.aaa.aaa.bbb.bbb.bbb.aaa.aaa",
177 ".aaa#aaa.aaa.bbb.aaa.aaa.aaa.bbb.bbb.bbb.aaa.aaa",
178 ".aaa#aaa.aaa.bbb.aaa.aaa.aaa.bbb.bbb.bbb.aaa.aaa",
179 "....#...........................................",
180 ".aaa#aaa.bbb.aaa.aaa.aaa.aaa.aaa.bbb.bbb.bbb.aaa",
181 ".aaa#aaa.bbb.aaa.aaa.aaa.aaa.aaa.bbb.bbb.bbb.aaa",
182 ".aaa#aaa.bbb.aaa.aaa.aaa.aaa.aaa.bbb.bbb.bbb.aaa",
183 "....#...........................................",
184 ".aaa#bbb.aaa.aaa.aaa.aaa.aaa.aaa.aaa.bbb.bbb.bbb",
185 ".aaa#bbb.aaa.aaa.aaa.aaa.aaa.aaa.aaa.bbb.bbb.bbb",
186 ".aaa#bbb.aaa.aaa.aaa.aaa.aaa.aaa.aaa.bbb.bbb.bbb",
187 "################################################",
188 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa",
189 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa",
190 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa",
191 "....#...........................................",
192 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa",
193 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa",
194 ".aaa#aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa.aaa"
197 static gboolean icons_set = FALSE;
199 /**************************************************************************
201 * GTK signal handlers.
203 **************************************************************************/
206 quit_application(GtkWidget *w, GdkEvent *ev, gpointer data)
210 for (i = modified = 0; i < num_editors; i++) {
211 if (fontgrid_get_font_modified(FONTGRID(editors[i].fgrid)))
217 sprintf(buffer1, "Save Font: One font was modified. Save?");
219 sprintf(buffer1, "Save Font: %d fonts were modified. Save?",
221 if (guiutil_yes_or_no(editors[0].shell, buffer1, TRUE)) {
224 * Go through each editor and ask if the font should be saved if
225 * it has been modified.
227 for (i = 0; i < num_editors; i++) {
228 if (fontgrid_get_font_modified(FONTGRID(editors[i].fgrid))) {
230 * Ask if this font should be saved.
233 sprintf(buffer1, "Save Font: Save %s?", editors[i].file);
235 sprintf(buffer1, "Save Font: Save unnamed%d.bdf?", i);
238 * Always ask this question using the shell window of the
239 * first editor so the dialog box doesn't move around.
241 if (guiutil_yes_or_no(editors[0].shell, buffer1, TRUE))
242 guifile_save_as_wait(w, GUINT_TO_POINTER(i));
249 * Ask if the user really wants to exit if their preferences specify this
250 * question should be asked.
252 if (options.really_exit &&
253 !guiutil_yes_or_no(editors[0].shell, "Really Quit?", TRUE))
257 * Call all the cleanup routines in case something really needs to be
261 guiedit_preference_cleanup();
262 guiutil_cursor_cleanup();
271 show_editor(GtkWidget *w, gpointer data)
273 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
276 * Nothing seems to force the original window to the top of the stack
277 * on the screen, but this supposedly does everything necessary.
279 gtk_widget_show_all(ed->shell);
280 gtk_window_present(GTK_WINDOW(ed->shell));
284 goto_other_page(GtkWidget *w, gpointer editor)
286 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
290 fontgrid_get_page_info(FONTGRID(ed->fgrid), &pi);
292 if (!pi.unencoded_page) {
293 opage = ed->last_pageno;
294 ed->last_pageno = pi.current_page;
296 opage = ed->last_upageno;
297 ed->last_upageno = pi.current_page;
300 if (opage != -1 && opage != pi.current_page)
301 fontgrid_goto_page(FONTGRID(ed->fgrid), opage);
305 toggle_encoding_view(GtkWidget *w, gpointer editor)
307 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
311 if (fontgrid_viewing_unencoded(FONTGRID(ed->fgrid)))
315 lw = GTK_LABEL(GTK_BIN(ed->view_unencoded)->child);
316 gtk_label_set_text(lw, label);
318 fontgrid_switch_encoding_view(FONTGRID(ed->fgrid));
322 toggle_view_orientation(GtkWidget *w, gpointer editor)
324 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
328 if (fontgrid_get_orientation(FONTGRID(ed->fgrid)) ==
329 GTK_ORIENTATION_VERTICAL) {
330 fontgrid_set_orientation(FONTGRID(ed->fgrid),
331 GTK_ORIENTATION_HORIZONTAL);
332 label = "Vertical View";
334 fontgrid_set_orientation(FONTGRID(ed->fgrid),
335 GTK_ORIENTATION_VERTICAL);
336 label = "Horizontal View";
338 lw = GTK_LABEL(GTK_BIN(ed->view_orientation)->child);
339 gtk_label_set_text(lw, label);
343 set_code_base(GtkWidget *w, gpointer editor)
345 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
348 if (w == ed->view_oct)
350 else if (w == ed->view_dec)
355 fontgrid_set_code_base(FONTGRID(ed->fgrid), base);
358 * Make sure the font info editor is updated when the code base
361 guiedit_update_code_base(ed);
362 guigedit_set_code_base(base);
366 page_change(GtkWidget *w, gpointer pinfo, gpointer editor)
368 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
369 FontgridPageInfo *pi = (FontgridPageInfo *) pinfo;
373 if (pi->previous_page < 0) {
374 gtk_widget_set_sensitive(ed->prev, FALSE);
375 gtk_widget_set_sensitive(ed->first, FALSE);
377 gtk_widget_set_sensitive(ed->prev, TRUE);
378 gtk_widget_set_sensitive(ed->first, TRUE);
381 if (pi->next_page < 0) {
382 gtk_widget_set_sensitive(ed->next, FALSE);
383 gtk_widget_set_sensitive(ed->last, FALSE);
385 gtk_widget_set_sensitive(ed->next, TRUE);
386 gtk_widget_set_sensitive(ed->last, TRUE);
390 * Update the page number field with the current page.
392 sprintf(buffer1, "%d", pi->current_page);
393 gtk_entry_set_text(GTK_ENTRY(ed->pageno), buffer1);
394 gtk_editable_set_position(GTK_EDITABLE(ed->pageno), -1);
397 * Finally, modify the label on the Encoded/Unencoded view menu item.
399 label = (pi->unencoded_page) ? "Encoded" : "Unencoded";
400 lw = GTK_LABEL(GTK_BIN(ed->view_unencoded)->child);
401 gtk_label_set_text(lw, label);
405 first_page(GtkWidget *w, gpointer editor)
407 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
409 fontgrid_goto_first_page(FONTGRID(ed->fgrid));
412 * Force the focus back to the Fontgrid.
414 gtk_widget_grab_focus(ed->fgrid);
418 previous_page(GtkWidget *w, gpointer editor)
420 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
422 fontgrid_goto_previous_page(FONTGRID(ed->fgrid));
425 * Force the focus back to the Fontgrid.
427 gtk_widget_grab_focus(ed->fgrid);
431 next_page(GtkWidget *w, gpointer editor)
433 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
435 fontgrid_goto_next_page(FONTGRID(ed->fgrid));
438 * Force the focus back to the Fontgrid.
440 gtk_widget_grab_focus(ed->fgrid);
444 last_page(GtkWidget *w, gpointer editor)
446 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
448 fontgrid_goto_last_page(FONTGRID(ed->fgrid));
451 * Force the focus back to the Fontgrid.
453 gtk_widget_grab_focus(ed->fgrid);
457 goto_page_or_code(GtkWidget *w, gpointer editor)
459 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
464 fontgrid_get_page_info(FONTGRID(ed->fgrid), &pi);
466 if (!pi.unencoded_page)
467 ed->last_pageno = pi.current_page;
469 ed->last_upageno = pi.current_page;
471 if (w == ed->pageno) {
472 text = gtk_entry_get_text(GTK_ENTRY(ed->pageno));
473 fontgrid_goto_page(FONTGRID(ed->fgrid),
474 _bdf_atol((char *) text, 0, 10));
476 text = gtk_entry_get_text(GTK_ENTRY(ed->charno));
477 code = _bdf_atol((char *) text, 0,
478 fontgrid_get_code_base(FONTGRID(ed->fgrid)));
479 fontgrid_goto_code(FONTGRID(ed->fgrid), code);
484 update_selection_info(GtkWidget *w, gpointer sinfo, gpointer editor)
486 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
487 FontgridSelectionInfo *si = (FontgridSelectionInfo *) sinfo;
488 short as, ds, rt, lt;
490 guint b1 = 0, b2 = 0, b3, b4;
492 as = ds = rt = lt = 0;
493 if (si->start == si->end) {
494 if (si->num_glyphs != 0 && si->glyphs != 0) {
495 b1 = (si->start >> 8) & 0xff;
496 b2 = si->start & 0xff;
498 as = si->glyphs->bbx.ascent;
499 ds = si->glyphs->bbx.descent;
500 lt = si->glyphs->bbx.x_offset;
501 rt = si->glyphs->bbx.width + lt;
502 if (si->glyphs->name != 0)
503 (void) strcpy(buffer1, si->glyphs->name);
505 sprintf(buffer1, "char%d", si->glyphs->encoding);
508 * If the glyph test dialog is active, send it the glyph if this
509 * is an end selection event.
511 if (si->reason == FONTGRID_END_SELECTION && glyphtest != 0)
512 glyphtest_add_glyph(GLYPHTEST(glyphtest),
513 fontgrid_get_font(FONTGRID(ed->fgrid)),
516 sprintf(buffer1, "char%d", si->start);
520 sprintf(buffer2, "\"%s\" %o (%o, %o)", buffer1,
524 sprintf(buffer2, "\"%s\" %d (%d, %d)", buffer1,
528 sprintf(buffer2, "\"%s\" %04X (%02X, %02X)", buffer1,
535 * A range of glyphs has been selected.
537 if (si->end < si->start) {
544 b1 = (start >> 8) & 0xff;
546 b3 = (end >> 8) & 0xff;
551 sprintf(buffer2, "Selection %o (%o, %o) - %o (%o, %o)",
552 start, b1, b2, end, b3, b4);
555 sprintf(buffer2, "Selection %d (%d, %d) - %d (%d, %d)",
556 start, b1, b2, end, b3, b4);
559 sprintf(buffer2, "Selection %04X (%02X, %02X) - %04X (%02X, %02X)",
560 start, b1, b2, end, b3, b4);
566 * Update the glyph info label.
568 gtk_label_set_text(GTK_LABEL(ed->charinfo), buffer2);
571 * Update the metrics label.
573 sprintf(buffer1, "ascent %hd descent %hd right %hd left %hd",
575 gtk_label_set_text(GTK_LABEL(ed->metrics), buffer1);
577 switch (si->reason) {
578 case FONTGRID_START_SELECTION:
580 case FONTGRID_EXTEND_SELECTION:
582 case FONTGRID_END_SELECTION:
584 case FONTGRID_ACTIVATE:
585 guigedit_edit_glyph(ed, si);
587 case FONTGRID_BASE_CHANGE:
593 handle_modified_signal(GtkWidget *w, gpointer minfo, gpointer editor)
595 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
596 gchar *prgname = g_get_prgname();
597 FontgridModificationInfo *mi;
599 mi = (FontgridModificationInfo *) minfo;
602 * Check to see what change was made so updates can be handled
605 if (mi->reason == FONTGRID_NAME_MODIFIED)
606 gtk_entry_set_text(GTK_ENTRY(ed->fontname), mi->name);
607 else if (mi->reason == FONTGRID_PROPERTIES_MODIFIED)
609 * Make sure the font info editing dialog knows that the list of
610 * font properties changed.
612 guiedit_update_font_properties(ed);
613 else if (mi->reason == FONTGRID_GLYPHS_DELETED ||
614 mi->reason == FONTGRID_GLYPHS_PASTED)
615 guiedit_update_font_details(ed);
616 else if ((mi->reason == FONTGRID_DEVICE_WIDTH_MODIFIED ||
617 mi->reason == FONTGRID_GLYPHS_MODIFIED) && glyphtest != 0)
619 * Update the glyph test widget with the new device width.
621 glyphtest_update_device_width(GLYPHTEST(glyphtest),
622 fontgrid_get_font(FONTGRID(ed->fgrid)));
628 sprintf(buffer1, "%s - (unnamed%d) [modified]", prgname, ed->id);
630 sprintf(buffer1, "%s - %s [modified]", prgname, ed->file);
632 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
636 view_font_messages(GtkWidget *w, gpointer editor)
638 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(editor);
639 GtkWidget *dialog, *frame, *button, *label, *vbox, *sw;
643 if (ed->messages_dialog == 0) {
645 * Special case of no messages and the menu item hasn't been
646 * checked for sensitivity yet.
648 if (fontgrid_get_font_messages(FONTGRID(ed->fgrid)) == 0)
651 dialog = ed->messages_dialog = gtk_dialog_new();
652 (void) g_signal_connect(G_OBJECT(dialog), "delete_event",
653 G_CALLBACK(gtk_widget_hide), 0);
655 frame = gtk_frame_new(0);
656 label = ed->messages_label = gtk_label_new("");
657 gtk_container_add(GTK_CONTAINER(frame), label);
659 vbox = GTK_DIALOG(dialog)->vbox;
660 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
662 sw = gtk_scrolled_window_new(NULL, NULL);
663 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
666 gtk_box_pack_start(GTK_BOX(vbox), sw, FALSE, FALSE, 0);
669 * Add the text widget.
671 text = gtk_text_buffer_new(NULL);
672 ed->messages_text = gtk_text_view_new_with_buffer(text);
673 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ed->messages_text),
675 gtk_widget_set_size_request(ed->messages_text, 500, 200);
677 gtk_text_view_set_editable(GTK_TEXT_VIEW(ed->messages_text), FALSE);
678 gtk_container_add(GTK_CONTAINER(sw), ed->messages_text);
680 button = gtk_button_new_with_label("Close");
681 (void) g_signal_connect_object(G_OBJECT(button), "clicked",
682 G_CALLBACK(gtk_widget_hide),
685 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
688 gtk_widget_show_all(GTK_DIALOG(ed->messages_dialog)->vbox);
689 gtk_widget_show_all(GTK_DIALOG(ed->messages_dialog)->action_area);
691 text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ed->messages_text));
694 * Update the label with the font name in case it changed since the last
695 * time the messages were shown.
698 sprintf(buffer1, "%s: Messages", ed->file);
700 sprintf(buffer1, "unnamed%d.bdf: Messages", ed->id);
701 gtk_label_set_text(GTK_LABEL(ed->messages_label), buffer1);
704 * Now change the text itself.
706 if ((msgs = fontgrid_get_font_messages(FONTGRID(ed->fgrid))) == 0)
708 gtk_text_buffer_set_text(text, msgs, -1);
710 guiutil_show_dialog_centered(ed->messages_dialog, ed->shell);
713 /**************************************************************************
717 **************************************************************************/
720 make_accel_menu_item(GtkWidget *menu, const gchar *text, const gchar *accel,
725 GdkModifierType mods;
727 mi = gtk_menu_item_new_with_mnemonic(text);
729 gtk_accelerator_parse(accel, &key, &mods);
730 gtk_widget_add_accelerator(mi, "activate", ag, key, mods,
731 GTK_ACCEL_VISIBLE|GTK_ACCEL_LOCKED);
732 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
738 * Handle all the menu checking needed to enable or disable menu items on
742 menu_popup(GtkWidget *w, GdkEvent *event, gpointer data)
752 * Get a pointer to the editor.
754 ed = editors + GPOINTER_TO_UINT(data);
756 font = fontgrid_get_font(FONTGRID(ed->fgrid));
758 if (event->type == GDK_MAP) {
759 if (w == ed->file_menu) {
760 if (font && font->modified)
761 gtk_widget_set_sensitive(ed->file_save, TRUE);
763 gtk_widget_set_sensitive(ed->file_save, FALSE);
765 if (font && font->glyphs_used > 0)
766 gtk_widget_set_sensitive(ed->file_export, TRUE);
768 gtk_widget_set_sensitive(ed->file_export, FALSE);
769 } else if (w == ed->edit_menu) {
771 * If the fontgrid clipboard is empty, then disable the paste,
772 * overlay, and insert menu options.
774 flag = fontgrid_clipboard_empty(FONTGRID(ed->fgrid)) ?
776 gtk_widget_set_sensitive(ed->edit_paste, flag);
777 gtk_widget_set_sensitive(ed->edit_overlay, flag);
778 gtk_widget_set_sensitive(ed->edit_insert, flag);
781 * If there is no selection, disable the cut and copy menu
784 flag = fontgrid_has_selection(FONTGRID(ed->fgrid), 0) ?
786 gtk_widget_set_sensitive(ed->edit_cut, flag);
787 gtk_widget_set_sensitive(ed->edit_copy, flag);
789 flag = (font && font->glyphs_used > 0) ? TRUE : FALSE;
792 * Disable glyph rename when viewing unecoded glyphs because their
793 * encoding values are not actual.
795 if (fontgrid_viewing_unencoded(FONTGRID(ed->fgrid)) || !flag)
796 gtk_widget_set_sensitive(ed->edit_rename_glyphs, FALSE);
798 gtk_widget_set_sensitive(ed->edit_rename_glyphs, TRUE);
800 gtk_widget_set_sensitive(ed->edit_test_glyphs, flag);
801 } else if (w == ed->edit_rename_menu) {
802 if (options.adobe_name_file != 0)
803 gtk_widget_set_sensitive(ed->edit_adobe_names, TRUE);
805 gtk_widget_set_sensitive(ed->edit_adobe_names, FALSE);
806 if (options.unicode_name_file != 0)
807 gtk_widget_set_sensitive(ed->edit_unicode_names, TRUE);
809 gtk_widget_set_sensitive(ed->edit_unicode_names, FALSE);
810 } else if (w == ed->name_submenu) {
811 flag = (!font || bdf_has_xlfd_name(font)) ? FALSE : TRUE;
812 gtk_widget_set_sensitive(ed->edit_make_xlfd, flag);
813 } else if (w == ed->view_menu) {
814 if (fontgrid_get_font_messages(FONTGRID(ed->fgrid)))
815 gtk_widget_set_sensitive(ed->view_messages, TRUE);
817 gtk_widget_set_sensitive(ed->view_messages, FALSE);
818 } else if (w == ed->win_menu) {
820 * Go through and update the file names that might have changed
821 * since the last time this menu popped up.
823 for (i = 0, kids = GTK_MENU(w)->menu_shell.children; kids != 0;
824 kids = kids->next, i++) {
825 if (editors[i].file == 0)
826 sprintf(buffer1, "(unnamed%d)", i);
828 strcpy(buffer1, editors[i].file);
829 label = gtk_container_get_children(GTK_CONTAINER(kids->data));
830 gtk_label_set_text(GTK_LABEL(label->data), buffer1);
834 * Add any new editors that were created since the last time this
837 for (; i < num_editors; i++) {
838 if (editors[i].file == 0)
839 sprintf(buffer1, "(unnamed%d)", editors[i].id);
841 strcpy(buffer1, editors[i].file);
843 mitem = gtk_menu_item_new_with_label(buffer1);
844 (void) g_signal_connect(G_OBJECT(mitem), "activate",
845 G_CALLBACK(show_editor),
846 GUINT_TO_POINTER(i));
847 gtk_menu_shell_append(GTK_MENU_SHELL(ed->win_menu), mitem);
848 gtk_widget_show(mitem);
852 * Disable the item for this editor.
854 gtk_widget_set_sensitive(ed->win_menu_item, FALSE);
856 } else if (event->type == GDK_UNMAP) {
858 * Enable everything again, so it doesn't get forgotten.
860 gtk_widget_set_sensitive(ed->file_save, TRUE);
861 gtk_widget_set_sensitive(ed->file_export, TRUE);
862 gtk_widget_set_sensitive(ed->edit_paste, TRUE);
863 gtk_widget_set_sensitive(ed->edit_overlay, TRUE);
864 gtk_widget_set_sensitive(ed->edit_insert, TRUE);
865 gtk_widget_set_sensitive(ed->edit_cut, TRUE);
866 gtk_widget_set_sensitive(ed->edit_copy, TRUE);
867 gtk_widget_set_sensitive(ed->edit_rename_glyphs, TRUE);
868 gtk_widget_set_sensitive(ed->edit_adobe_names, TRUE);
869 gtk_widget_set_sensitive(ed->edit_unicode_names, TRUE);
870 gtk_widget_set_sensitive(ed->edit_test_glyphs, TRUE);
871 gtk_widget_set_sensitive(ed->edit_make_xlfd, TRUE);
872 gtk_widget_set_sensitive(ed->win_menu_item, TRUE);
873 gtk_widget_set_sensitive(ed->view_messages, TRUE);
879 #if (GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 10)
881 open_recent_font(GtkWidget *w, gpointer data)
883 gchar *p, *uri = gtk_recent_chooser_get_current_uri(GTK_RECENT_CHOOSER(w));
884 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
890 * Skip the URI prefix to get to the path. The URI's are strictly local
893 for (p = uri; *p && *p != ':'; p++);
897 if (*p == '/' && *(p + 1) == '/')
899 guifile_load_bdf_font(ed, (const gchar *) p);
904 make_recent_menu(guint ed_id)
907 GtkRecentFilter *filter;
908 GtkRecentManager *manager;
910 manager = gtk_recent_manager_get_default();
911 menu = gtk_recent_chooser_menu_new_for_manager(manager);
912 gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER(menu), 10);
913 gtk_recent_chooser_set_sort_type(GTK_RECENT_CHOOSER(menu),
914 GTK_RECENT_SORT_MRU);
915 gtk_recent_chooser_set_show_tips(GTK_RECENT_CHOOSER(menu), TRUE);
916 gtk_recent_chooser_menu_set_show_numbers(GTK_RECENT_CHOOSER_MENU(menu),
918 gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(menu), TRUE);
919 filter = gtk_recent_filter_new();
920 gtk_recent_filter_add_pattern(filter, "*.[Bb][Dd][Ff]");
921 gtk_recent_chooser_set_filter(GTK_RECENT_CHOOSER(menu), filter);
923 (void) g_signal_connect(G_OBJECT(menu), "item_activated",
924 G_CALLBACK(open_recent_font),
925 GUINT_TO_POINTER(ed_id));
932 make_file_menu(gbdfed_editor_t *ed, GtkWidget *menubar)
934 GtkWidget *file, *menu, *submenu, *mitem, *sep;
937 * Create the File menu.
939 file = gtk_menu_item_new_with_mnemonic("_File");
941 ed->file_menu = menu = gtk_menu_new();
942 (void) g_signal_connect(G_OBJECT(menu), "map_event",
943 G_CALLBACK(menu_popup),
944 GUINT_TO_POINTER(ed->id));
946 mitem = make_accel_menu_item(menu, "_New", "<Control>N", ed->ag);
947 (void) g_signal_connect(G_OBJECT(mitem), "activate",
948 G_CALLBACK(guifile_new_editor), 0);
950 mitem = make_accel_menu_item(menu, "_Open", "<Control>O", ed->ag);
951 (void) g_signal_connect(G_OBJECT(mitem), "activate",
952 G_CALLBACK(guifile_import_bdf_font),
953 GUINT_TO_POINTER(ed->id));
955 ed->file_save = make_accel_menu_item(menu, "_Save", "<Control>S", ed->ag);
956 (void) g_signal_connect(G_OBJECT(ed->file_save), "activate",
957 G_CALLBACK(guifile_save),
958 GUINT_TO_POINTER(ed->id));
959 mitem = make_accel_menu_item(menu, "Save _As...", "<Control>W", ed->ag);
960 (void) g_signal_connect(G_OBJECT(mitem), "activate",
961 G_CALLBACK(guifile_save_as),
962 GUINT_TO_POINTER(ed->id));
967 sep = gtk_menu_item_new();
968 gtk_widget_set_sensitive(sep, FALSE);
969 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
972 * Create the Import and Export menu items with their submenus.
974 mitem = gtk_menu_item_new_with_mnemonic("_Import");
975 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
977 submenu = gtk_menu_new();
978 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), submenu);
980 mitem = make_accel_menu_item(submenu, "_PK/GF Font", "<Control>K", ed->ag);
981 (void) g_signal_connect(G_OBJECT(mitem), "activate",
982 G_CALLBACK(guifile_import_pkgf_font),
983 GUINT_TO_POINTER(ed->id));
984 mitem = make_accel_menu_item(submenu, "_Console Font", "<Control>L",
986 (void) g_signal_connect(G_OBJECT(mitem), "activate",
987 G_CALLBACK(guifile_import_console_font),
988 GUINT_TO_POINTER(ed->id));
990 mitem = make_accel_menu_item(submenu, "_HBF Font", "<Control>H",
992 (void) g_signal_connect(G_OBJECT(mitem), "activate",
993 G_CALLBACK(guifile_import_hbf_font),
994 GUINT_TO_POINTER(ed->id));
997 mitem = make_accel_menu_item(submenu, "_Windows Font", "<Control>B",
1000 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1001 G_CALLBACK(guifile_import_windows_font),
1002 GUINT_TO_POINTER(ed->id));
1003 #ifdef HAVE_FREETYPE
1004 mitem = make_accel_menu_item(submenu, "_OpenType Font", "<Control>Y",
1006 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1007 G_CALLBACK(guifile_import_otf_font),
1008 GUINT_TO_POINTER(ed->id));
1009 #endif /* HAVE_FREETYPE */
1015 sep = gtk_menu_item_new();
1016 gtk_widget_set_sensitive(sep, FALSE);
1017 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), sep);
1019 mitem = make_accel_menu_item(submenu, "_X Server Font", "<Control>G",
1021 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1022 G_CALLBACK(guifile_import_xserver_font),
1023 GUINT_TO_POINTER(ed->id));
1026 ed->file_export = gtk_menu_item_new_with_mnemonic("Ex_port");
1027 gtk_menu_shell_append(GTK_MENU_SHELL(menu), ed->file_export);
1029 submenu = gtk_menu_new();
1030 gtk_menu_item_set_submenu(GTK_MENU_ITEM(ed->file_export), submenu);
1032 mitem = make_accel_menu_item(submenu, "_PSF Font", "<Control>F",
1034 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1035 G_CALLBACK(guifile_export_psf_font),
1036 GUINT_TO_POINTER(ed->id));
1037 mitem = gtk_menu_item_new_with_mnemonic("_HEX");
1038 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1039 G_CALLBACK(guifile_export_hex_font),
1040 GUINT_TO_POINTER(ed->id));
1041 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1046 sep = gtk_menu_item_new();
1047 gtk_widget_set_sensitive(sep, FALSE);
1048 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1050 #if (GTK_MAJOR_VERSION >=2 && GTK_MINOR_VERSION >= 10)
1052 * Only add the Recent Fonts menu if the GTK version supports it.
1054 mitem = gtk_menu_item_new_with_mnemonic("_Recent Fonts");
1055 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1056 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), make_recent_menu(ed->id));
1061 sep = gtk_menu_item_new();
1062 gtk_widget_set_sensitive(sep, FALSE);
1063 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1067 mitem = make_accel_menu_item(menu, "E_xit", "<Control>F4", ed->ag);
1069 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1070 G_CALLBACK(quit_application),
1071 GUINT_TO_POINTER(ed->id));
1073 mitem = make_accel_menu_item(menu, "Clos_e", "<Control>F4", ed->ag);
1075 (void) g_signal_connect_object(G_OBJECT(mitem), "activate",
1076 G_CALLBACK(gtk_widget_hide),
1077 (gpointer) ed->shell,
1081 gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), menu);
1087 make_xlfd_name(GtkWidget *w, gpointer data)
1089 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
1091 fontgrid_make_xlfd_font_name(FONTGRID(ed->fgrid));
1095 update_name_from_props(GtkWidget *w, gpointer data)
1097 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
1099 fontgrid_update_font_name_from_properties(FONTGRID(ed->fgrid));
1103 update_props_from_name(GtkWidget *w, gpointer data)
1105 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
1107 fontgrid_update_properties_from_font_name(FONTGRID(ed->fgrid));
1111 make_edit_menu(gbdfed_editor_t *ed, GtkWidget *menubar)
1113 GtkWidget *edit, *menu, *submenu, *mitem, *sep;
1116 * Create the Edit menu.
1118 edit = gtk_menu_item_new_with_mnemonic("_Edit");
1120 ed->edit_menu = menu = gtk_menu_new();
1121 (void) g_signal_connect(G_OBJECT(menu), "map_event",
1122 G_CALLBACK(menu_popup),
1123 GUINT_TO_POINTER(ed->id));
1125 ed->edit_copy = make_accel_menu_item(menu, "_Copy", "<Control>C", ed->ag);
1126 (void) g_signal_connect(G_OBJECT(ed->edit_copy), "activate",
1127 G_CALLBACK(guiedit_copy_selection),
1128 GUINT_TO_POINTER(ed->id));
1130 ed->edit_cut = make_accel_menu_item(menu, "C_ut", "<Control>X", ed->ag);
1131 (void) g_signal_connect(G_OBJECT(ed->edit_cut), "activate",
1132 G_CALLBACK(guiedit_cut_selection),
1133 GUINT_TO_POINTER(ed->id));
1135 ed->edit_paste = make_accel_menu_item(menu, "_Paste", "<Control>V",
1137 (void) g_signal_connect(G_OBJECT(ed->edit_paste), "activate",
1138 G_CALLBACK(guiedit_paste_selection),
1139 GUINT_TO_POINTER(ed->id));
1141 ed->edit_overlay = make_accel_menu_item(menu, "_Overlay",
1142 "<Shift><Control>V", ed->ag);
1143 (void) g_signal_connect(G_OBJECT(ed->edit_overlay), "activate",
1144 G_CALLBACK(guiedit_overlay_selection),
1145 GUINT_TO_POINTER(ed->id));
1147 ed->edit_insert = make_accel_menu_item(menu, "_Insert",
1148 "<Control><Alt>V", ed->ag);
1149 (void) g_signal_connect(G_OBJECT(ed->edit_insert), "activate",
1150 G_CALLBACK(guiedit_insert_selection),
1151 GUINT_TO_POINTER(ed->id));
1156 sep = gtk_menu_item_new();
1157 gtk_widget_set_sensitive(sep, FALSE);
1158 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1160 mitem = make_accel_menu_item(menu, "P_roperties", "<Control>P", ed->ag);
1161 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1162 G_CALLBACK(guiedit_show_font_properties),
1163 GUINT_TO_POINTER(ed->id));
1165 mitem = make_accel_menu_item(menu, "Co_mments", "<Control>M", ed->ag);
1166 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1167 G_CALLBACK(guiedit_show_font_comments),
1168 GUINT_TO_POINTER(ed->id));
1170 mitem = make_accel_menu_item(menu, "_Font Info", "<Control>I", ed->ag);
1171 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1172 G_CALLBACK(guiedit_show_font_info),
1173 GUINT_TO_POINTER(ed->id));
1177 sep = gtk_menu_item_new();
1178 gtk_widget_set_sensitive(sep, FALSE);
1179 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1182 * Create the Font Name submenu.
1184 mitem = gtk_menu_item_new_with_mnemonic("Font _Name");
1185 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1187 ed->name_submenu = submenu = gtk_menu_new();
1188 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), submenu);
1189 (void) g_signal_connect(G_OBJECT(submenu), "map_event",
1190 G_CALLBACK(menu_popup),
1191 GUINT_TO_POINTER(ed->id));
1193 ed->edit_make_xlfd = gtk_menu_item_new_with_mnemonic("Make _XLFD Name");
1194 (void) g_signal_connect(G_OBJECT(ed->edit_make_xlfd), "activate",
1195 G_CALLBACK(make_xlfd_name),
1196 GUINT_TO_POINTER(ed->id));
1197 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), ed->edit_make_xlfd);
1199 mitem = gtk_menu_item_new_with_mnemonic("Update _Name From Properties");
1200 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1201 G_CALLBACK(update_name_from_props),
1202 GUINT_TO_POINTER(ed->id));
1203 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1205 mitem = gtk_menu_item_new_with_mnemonic("Update _Properties From Name");
1206 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1207 G_CALLBACK(update_props_from_name),
1208 GUINT_TO_POINTER(ed->id));
1209 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1210 mitem = gtk_menu_item_new_with_mnemonic("Update _Average Width");
1211 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1216 sep = gtk_menu_item_new();
1217 gtk_widget_set_sensitive(sep, FALSE);
1218 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1221 * Make the glyph naming menus and submenus.
1223 ed->edit_rename_glyphs = gtk_menu_item_new_with_mnemonic("Ren_ame Glyphs");
1224 gtk_menu_shell_append(GTK_MENU_SHELL(menu), ed->edit_rename_glyphs);
1226 ed->edit_rename_menu = submenu = gtk_menu_new();
1227 (void) g_signal_connect(G_OBJECT(submenu), "map_event",
1228 G_CALLBACK(menu_popup),
1229 GUINT_TO_POINTER(ed->id));
1230 gtk_menu_item_set_submenu(GTK_MENU_ITEM(ed->edit_rename_glyphs), submenu);
1232 ed->edit_unicode_names = gtk_menu_item_new_with_mnemonic("_Unicode Names");
1233 (void) g_signal_connect(G_OBJECT(ed->edit_unicode_names), "activate",
1234 G_CALLBACK(guiedit_set_unicode_glyph_names),
1235 GUINT_TO_POINTER(ed->id));
1236 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), ed->edit_unicode_names);
1238 ed->edit_adobe_names = gtk_menu_item_new_with_mnemonic("_Adobe Names");
1239 (void) g_signal_connect(G_OBJECT(ed->edit_adobe_names), "activate",
1240 G_CALLBACK(guiedit_set_adobe_glyph_names),
1241 GUINT_TO_POINTER(ed->id));
1242 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), ed->edit_adobe_names);
1244 mitem = gtk_menu_item_new_with_mnemonic("_Hexadecimal Values");
1245 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1246 submenu = gtk_menu_new();
1247 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), submenu);
1249 mitem = gtk_menu_item_new_with_mnemonic("_uniXXXX");
1250 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1251 G_CALLBACK(guiedit_set_uni_glyph_names),
1252 GUINT_TO_POINTER(ed->id));
1253 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1255 mitem = gtk_menu_item_new_with_mnemonic("0_xXXXX");
1256 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1257 G_CALLBACK(guiedit_set_zerox_glyph_names),
1258 GUINT_TO_POINTER(ed->id));
1259 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1261 mitem = gtk_menu_item_new_with_mnemonic("U_+XXXX");
1262 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1263 G_CALLBACK(guiedit_set_uplus_glyph_names),
1264 GUINT_TO_POINTER(ed->id));
1265 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1267 mitem = gtk_menu_item_new_with_mnemonic("_\\uXXXX");
1268 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1269 G_CALLBACK(guiedit_set_bslashu_glyph_names),
1270 GUINT_TO_POINTER(ed->id));
1271 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1273 ed->edit_test_glyphs = make_accel_menu_item(menu, "_Test Glyphs",
1274 "<Control>Z", ed->ag);
1275 (void) g_signal_connect(G_OBJECT(ed->edit_test_glyphs), "activate",
1276 G_CALLBACK(guiedit_show_glyphtest),
1277 GUINT_TO_POINTER(ed->id));
1282 sep = gtk_menu_item_new();
1283 gtk_widget_set_sensitive(sep, FALSE);
1284 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1286 mitem = make_accel_menu_item(menu, "Pr_eferences", "<Control>T", ed->ag);
1287 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1288 G_CALLBACK(guiedit_show_preferences), 0);
1290 gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit), menu);
1296 make_view_menu(gbdfed_editor_t *ed, GtkWidget *menubar)
1298 GtkWidget *view, *menu, *submenu, *mitem, *sep;
1300 GtkRadioMenuItem *ri;
1303 * Create the View menu.
1305 view = gtk_menu_item_new_with_mnemonic("_View");
1307 ed->view_menu = menu = gtk_menu_new();
1308 (void) g_signal_connect(G_OBJECT(menu), "map_event",
1309 G_CALLBACK(menu_popup),
1310 GUINT_TO_POINTER(ed->id));
1312 ed->view_unencoded = mitem =
1313 make_accel_menu_item(menu, "Unencoded", "<Control>E", ed->ag);
1314 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1315 G_CALLBACK(toggle_encoding_view),
1316 GUINT_TO_POINTER(ed->id));
1319 * Create the Code Base submenu.
1321 mitem = gtk_menu_item_new_with_mnemonic("_Code Base");
1322 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1324 submenu = gtk_menu_new();
1325 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), submenu);
1327 ed->view_oct = mitem = gtk_radio_menu_item_new_with_mnemonic(0, "_Octal");
1328 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1329 ri = GTK_RADIO_MENU_ITEM(mitem);
1330 if (options.code_base == 8)
1331 gtk_check_menu_item_set_active(&ri->check_menu_item, TRUE);
1333 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem));
1334 ed->view_dec = mitem =
1335 gtk_radio_menu_item_new_with_mnemonic(group, "_Decimal");
1336 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1337 ri = GTK_RADIO_MENU_ITEM(mitem);
1338 if (options.code_base == 10)
1339 gtk_check_menu_item_set_active(&ri->check_menu_item, TRUE);
1341 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem));
1342 ed->view_hex = mitem =
1343 gtk_radio_menu_item_new_with_mnemonic(group, "_Hexadecimal");
1344 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
1345 ri = GTK_RADIO_MENU_ITEM(mitem);
1346 if (options.code_base == 16)
1347 gtk_check_menu_item_set_active(&ri->check_menu_item, TRUE);
1350 * Add the code base toggle handler to the three toggles.
1352 (void) g_signal_connect(G_OBJECT(ed->view_oct), "toggled",
1353 G_CALLBACK(set_code_base),
1354 GUINT_TO_POINTER(ed->id));
1355 (void) g_signal_connect(G_OBJECT(ed->view_dec), "toggled",
1356 G_CALLBACK(set_code_base),
1357 GUINT_TO_POINTER(ed->id));
1358 (void) g_signal_connect(G_OBJECT(ed->view_hex), "toggled",
1359 G_CALLBACK(set_code_base),
1360 GUINT_TO_POINTER(ed->id));
1365 sep = gtk_menu_item_new();
1366 gtk_widget_set_sensitive(sep, FALSE);
1367 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1369 mitem = make_accel_menu_item(menu, "_Other Page", "<Shift><Control>S",
1371 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1372 G_CALLBACK(goto_other_page),
1373 GUINT_TO_POINTER(ed->id));
1375 if (options.orientation == GTK_ORIENTATION_VERTICAL)
1376 ed->view_orientation = mitem =
1377 make_accel_menu_item(menu, "Horizontal View", "<Control>Q", ed->ag);
1379 ed->view_orientation = mitem =
1380 make_accel_menu_item(menu, "Vertical View", "<Control>Q", ed->ag);
1381 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1382 G_CALLBACK(toggle_view_orientation),
1383 GUINT_TO_POINTER(ed->id));
1388 sep = gtk_menu_item_new();
1389 gtk_widget_set_sensitive(sep, FALSE);
1390 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1395 ed->view_messages = mitem =
1396 make_accel_menu_item(menu, "_Messages", "<Control>A", ed->ag);
1397 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1398 G_CALLBACK(view_font_messages),
1399 GUINT_TO_POINTER(ed->id));
1401 gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), menu);
1407 make_ops_menu(gbdfed_editor_t *ed, GtkWidget *menubar)
1409 GtkWidget *ops, *menu, *mitem;
1412 * Create the Edit menu.
1414 ops = gtk_menu_item_new_with_mnemonic("_Operations");
1416 ed->ops_menu = menu = gtk_menu_new();
1417 (void) g_signal_connect(G_OBJECT(menu), "map_event",
1418 G_CALLBACK(menu_popup),
1419 GUINT_TO_POINTER(ed->id));
1421 mitem = make_accel_menu_item(menu, "_Translate Glyphs", "<Control>D",
1423 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1424 G_CALLBACK(guiops_show_translate),
1425 GUINT_TO_POINTER(ed->id));
1427 mitem = make_accel_menu_item(menu, "_Rotate Glyphs", "<Control>R",
1429 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1430 G_CALLBACK(guiops_show_rotate),
1431 GUINT_TO_POINTER(ed->id));
1433 mitem = make_accel_menu_item(menu, "_Shear Glyphs", "<Control>J",
1435 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1436 G_CALLBACK(guiops_show_shear),
1437 GUINT_TO_POINTER(ed->id));
1439 mitem = make_accel_menu_item(menu, "_Embolden Glyphs", "<Shift><Control>B",
1441 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1442 G_CALLBACK(guiops_show_embolden),
1443 GUINT_TO_POINTER(ed->id));
1445 gtk_menu_item_set_submenu(GTK_MENU_ITEM(ops), menu);
1451 make_windows_menu(gbdfed_editor_t *ed, GtkWidget *menubar)
1453 GtkWidget *win, *menu, *mitem;
1456 win = gtk_menu_item_new_with_mnemonic("_Windows");
1458 ed->win_menu = menu = gtk_menu_new();
1459 (void) g_signal_connect(G_OBJECT(menu), "map_event",
1460 G_CALLBACK(menu_popup),
1461 GUINT_TO_POINTER(ed->id));
1463 for (i = 0; i < num_editors; i++) {
1464 if (editors[i].file == 0)
1465 sprintf(buffer1, "(unnamed%d)", editors[i].id);
1467 strcpy(buffer1, editors[i].file);
1469 ed->win_menu_item = mitem = gtk_menu_item_new_with_label(buffer1);
1470 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1471 G_CALLBACK(show_editor),
1472 GUINT_TO_POINTER(ed->id));
1473 gtk_menu_shell_append(GTK_MENU_SHELL(ed->win_menu), mitem);
1476 gtk_menu_item_set_submenu(GTK_MENU_ITEM(win), menu);
1482 make_help_menu(gbdfed_editor_t *ed, GtkWidget *menubar)
1484 GtkWidget *help, *menu, *mitem, *sep;
1487 * Create the Edit menu.
1489 help = gtk_menu_item_new_with_mnemonic("_Help");
1490 gtk_menu_item_set_right_justified(GTK_MENU_ITEM(help), TRUE);
1492 menu = gtk_menu_new();
1494 mitem = gtk_menu_item_new_with_mnemonic("The _Program");
1495 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1496 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1497 G_CALLBACK(guihelp_show_help),
1498 GINT_TO_POINTER(GUIHELP_PROGRAM));
1500 mitem = gtk_menu_item_new_with_mnemonic("_Font Grid");
1501 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1502 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1503 G_CALLBACK(guihelp_show_help),
1504 GINT_TO_POINTER(GUIHELP_FONTGRID));
1506 mitem = gtk_menu_item_new_with_mnemonic("_Glyph Editor");
1507 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1508 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1509 G_CALLBACK(guihelp_show_help),
1510 GINT_TO_POINTER(GUIHELP_GLYPH_EDITOR));
1512 mitem = gtk_menu_item_new_with_mnemonic("_Configuration File");
1513 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1514 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1515 G_CALLBACK(guihelp_show_help),
1516 GINT_TO_POINTER(GUIHELP_CONFIG_FILE));
1518 mitem = gtk_menu_item_new_with_mnemonic("P_references Dialog");
1519 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1520 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1521 G_CALLBACK(guihelp_show_help),
1522 GINT_TO_POINTER(GUIHELP_PREFERENCES));
1527 sep = gtk_menu_item_new();
1528 gtk_widget_set_sensitive(sep, FALSE);
1529 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1531 mitem = gtk_menu_item_new_with_mnemonic("_Windows Font Notes");
1532 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1533 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1534 G_CALLBACK(guihelp_show_help),
1535 GINT_TO_POINTER(GUIHELP_FNT));
1537 mitem = gtk_menu_item_new_with_mnemonic("_OpenType Font Notes");
1538 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1539 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1540 G_CALLBACK(guihelp_show_help),
1541 GINT_TO_POINTER(GUIHELP_OTF));
1543 mitem = gtk_menu_item_new_with_mnemonic("P_SF Font Notes");
1544 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1545 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1546 G_CALLBACK(guihelp_show_help),
1547 GINT_TO_POINTER(GUIHELP_PSF));
1549 mitem = gtk_menu_item_new_with_mnemonic("_HEX Font Notes");
1550 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1551 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1552 G_CALLBACK(guihelp_show_help),
1553 GINT_TO_POINTER(GUIHELP_HEX));
1558 sep = gtk_menu_item_new();
1559 gtk_widget_set_sensitive(sep, FALSE);
1560 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1562 mitem = gtk_menu_item_new_with_mnemonic("C_olor Notes");
1563 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1564 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1565 G_CALLBACK(guihelp_show_help),
1566 GINT_TO_POINTER(GUIHELP_COLOR));
1571 sep = gtk_menu_item_new();
1572 gtk_widget_set_sensitive(sep, FALSE);
1573 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1575 mitem = gtk_menu_item_new_with_mnemonic("T_ips");
1576 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1577 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1578 G_CALLBACK(guihelp_show_help),
1579 GINT_TO_POINTER(GUIHELP_TIPS));
1584 sep = gtk_menu_item_new();
1585 gtk_widget_set_sensitive(sep, FALSE);
1586 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1588 sprintf(buffer1, "_About %s", g_get_prgname());
1589 mitem = gtk_menu_item_new_with_mnemonic(buffer1);
1590 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
1591 (void) g_signal_connect(G_OBJECT(mitem), "activate",
1592 G_CALLBACK(guihelp_show_help),
1593 GINT_TO_POINTER(GUIHELP_ABOUT));
1595 gtk_menu_item_set_submenu(GTK_MENU_ITEM(help), menu);
1600 #define UPDMSG "Font Name: XLFD name has been modified.\nDo you want to update the font properties from the name?"
1603 update_font_name(GtkWidget *w, gpointer data)
1605 gbdfed_editor_t *ed = editors + GPOINTER_TO_UINT(data);
1609 name = (gchar *) gtk_entry_get_text(GTK_ENTRY(ed->fontname));
1611 font = fontgrid_get_font(FONTGRID(ed->fgrid));
1612 if (font && strcmp(name, font->name) == 0)
1614 * There was no actual change to the name.
1618 fontgrid_set_font_name(FONTGRID(ed->fgrid), name);
1621 * If the new name is an XLFD name, then offer to update the
1622 * font properties from the name.
1624 if (font && bdf_has_xlfd_name(font)) {
1625 if (guiutil_yes_or_no(ed->shell, UPDMSG, TRUE)) {
1626 fontgrid_update_properties_from_font_name(FONTGRID(ed->fgrid));
1629 * If the font info dialog is up, make sure it is updated with
1630 * the font property changes.
1632 guiedit_update_font_properties(ed);
1638 gbdfed_make_editor(gchar *filename, gboolean cmdline)
1641 GtkWidget *mb, *mitem, *table;
1642 GtkWidget *vbox, *hbox, *bbox, *frame;
1643 gbdfed_editor_t *ed;
1646 GList *icon_list = 0;
1647 FontgridPageInfo pageinfo;
1652 * Attempt to load the specified font before doing anything else.
1654 if (filename != 0) {
1656 * Change code to put up an error dialog if the font won't load.
1658 if ((in = fopen(filename, "r")) == 0) {
1659 fprintf(stderr, "%s: unable to open BDF font '%s'.\n",
1660 g_get_prgname(), filename);
1661 if (num_editors > 0 && !cmdline)
1665 font = bdf_load_font(in, &options.font_opts, 0, 0);
1668 fprintf(stderr, "%s: problem loading BDF font '%s'.\n",
1669 g_get_prgname(), filename);
1674 * Create the icon list if it hasn't already been created.
1676 if (icons_set == FALSE) {
1678 * Create the 16x16 icon.
1680 icon_list = g_list_append(icon_list,
1681 gdk_pixbuf_new_from_xpm_data(gbdfed_48x48));
1682 icon_list = g_list_append(icon_list,
1683 gdk_pixbuf_new_from_xpm_data(gbdfed_32x32));
1684 icon_list = g_list_append(icon_list,
1685 gdk_pixbuf_new_from_xpm_data(gbdfed_16x16));
1687 gtk_window_set_default_icon_list(icon_list);
1693 * Create a new editor structure.
1695 if (num_editors == 0)
1696 editors = g_malloc(sizeof(gbdfed_editor_t));
1698 editors = g_realloc(editors,
1699 sizeof(gbdfed_editor_t) * (num_editors + 1));
1701 ed = editors + num_editors;
1702 (void) memset(ed, 0, sizeof(gbdfed_editor_t));
1703 ed->id = num_editors++;
1706 * Construct the path and filename from the one passed. This makes copies
1709 if (font != 0 && filename != 0) {
1710 if (filename[0] != G_DIR_SEPARATOR) {
1711 path = g_get_current_dir();
1712 sprintf(buffer1, "%s%c%s", path, G_DIR_SEPARATOR, filename);
1715 strcpy(buffer1, filename);
1717 ed->file = g_path_get_basename(buffer1);
1718 ed->path = g_path_get_dirname(buffer1);
1722 * Create the top level window for the editor.
1724 ed->shell = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1727 * This is a bit risky, but it allows the shell to shrink to fit new
1728 * fonts when they are added.
1730 gtk_window_set_resizable(GTK_WINDOW(ed->shell), TRUE);
1733 (void) g_signal_connect(G_OBJECT(ed->shell), "destroy_event",
1734 G_CALLBACK(quit_application),
1735 GUINT_TO_POINTER(ed->id));
1736 (void) g_signal_connect(G_OBJECT(ed->shell), "delete_event",
1737 G_CALLBACK(quit_application),
1738 GUINT_TO_POINTER(ed->id));
1740 (void) g_signal_connect(G_OBJECT(ed->shell), "destroy_event",
1741 G_CALLBACK(gtk_widget_hide), 0);
1742 (void) g_signal_connect(G_OBJECT(ed->shell), "delete_event",
1743 G_CALLBACK(gtk_widget_hide), 0);
1747 * Determine the name for the window.
1750 sprintf(buffer1, "%s - (unnamed%d)", g_get_prgname(), ed->id);
1752 if (font && font->modified)
1753 sprintf(buffer1, "%s - %s [modified]", g_get_prgname(), ed->file);
1755 sprintf(buffer1, "%s - %s", g_get_prgname(), ed->file);
1757 gtk_window_set_title(GTK_WINDOW(ed->shell), buffer1);
1760 * Create the vertical box that will contain the widgets.
1762 table = gtk_table_new(5, 1, FALSE);
1763 gtk_container_add(GTK_CONTAINER(ed->shell), table);
1765 ed->ag = gtk_accel_group_new();
1767 mb = gtk_menu_bar_new();
1768 gtk_table_attach(GTK_TABLE(table), mb, 0, 1, 0, 1, GTK_FILL, GTK_FILL,
1772 * Create the File menu.
1774 mitem = make_file_menu(ed, mb);
1775 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1778 * Create the Edit menu.
1780 mitem = make_edit_menu(ed, mb);
1781 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1784 * Create the View menu.
1786 mitem = make_view_menu(ed, mb);
1787 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1790 * Create the Operations menu.
1792 mitem = make_ops_menu(ed, mb);
1793 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1796 * Create the Windows menu.
1798 mitem = make_windows_menu(ed, mb);
1799 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1802 * Create the Help menu.
1804 mitem = make_help_menu(ed, mb);
1805 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1808 * Attach the accelerators to the editor.
1810 gtk_window_add_accel_group(GTK_WINDOW(ed->shell), ed->ag);
1813 * 1. Add the font name widget.
1815 frame = gtk_frame_new(0);
1816 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
1817 gtk_table_attach(GTK_TABLE(table), frame, 0, 1, 1, 2, GTK_FILL, GTK_FILL,
1820 ed->fontname = gtk_widget_new(gtk_entry_get_type(),
1821 "max_length", 128, NULL);
1822 mitem = labcon_new_label_defaults("Font:", ed->fontname, 0);
1823 gtk_container_add(GTK_CONTAINER(frame), mitem);
1824 g_signal_connect(G_OBJECT(ed->fontname), "activate",
1825 G_CALLBACK(update_font_name), GUINT_TO_POINTER(ed->id));
1828 * 2. Add the glyph information widgets.
1830 frame = gtk_frame_new(0);
1831 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
1832 gtk_table_attach(GTK_TABLE(table), frame, 0, 1, 2, 3, GTK_FILL, GTK_FILL,
1835 vbox = gtk_vbox_new(TRUE, 0);
1836 ed->charinfo = gtk_label_new("\"None\" (0000) (00,00)");
1837 ed->metrics = gtk_label_new("ascent 0 descent 0 right 0 left 0");
1838 gtk_misc_set_alignment(GTK_MISC(ed->charinfo), 0.0, 0.5);
1839 gtk_misc_set_alignment(GTK_MISC(ed->metrics), 0.0, 0.5);
1840 gtk_box_pack_start(GTK_BOX(vbox), ed->charinfo, TRUE, TRUE, 0);
1841 gtk_box_pack_start(GTK_BOX(vbox), ed->metrics, TRUE, TRUE, 0);
1843 mitem = labcon_new_label_defaults("Glyph:", vbox, mitem);
1844 gtk_container_add(GTK_CONTAINER(frame), mitem);
1846 frame = gtk_frame_new(0);
1847 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
1848 gtk_table_attach(GTK_TABLE(table), frame, 0, 1, 3, 4, GTK_FILL, GTK_FILL,
1851 hbox = gtk_hbox_new(FALSE, 2);
1853 bbox = gtk_hbox_new(FALSE, 0);
1855 ed->first = gtk_button_new_with_label("First Page");
1856 (void) g_signal_connect(G_OBJECT(ed->first), "released",
1857 G_CALLBACK(first_page),
1858 GUINT_TO_POINTER(ed->id));
1860 ed->prev = gtk_button_new_with_label("Previous Page");
1861 (void) g_signal_connect(G_OBJECT(ed->prev), "released",
1862 G_CALLBACK(previous_page),
1863 GUINT_TO_POINTER(ed->id));
1865 ed->next = gtk_button_new_with_label("Next Page");
1866 (void) g_signal_connect(G_OBJECT(ed->next), "released",
1867 G_CALLBACK(next_page),
1868 GUINT_TO_POINTER(ed->id));
1870 ed->last = gtk_button_new_with_label("Last Page");
1871 (void) g_signal_connect(G_OBJECT(ed->last), "released",
1872 G_CALLBACK(last_page),
1873 GUINT_TO_POINTER(ed->id));
1875 gtk_box_pack_start(GTK_BOX(bbox), ed->first, FALSE, FALSE, 0);
1876 gtk_box_pack_start(GTK_BOX(bbox), ed->prev, FALSE, FALSE, 0);
1877 gtk_box_pack_start(GTK_BOX(bbox), ed->next, FALSE, FALSE, 0);
1878 gtk_box_pack_start(GTK_BOX(bbox), ed->last, FALSE, FALSE, 0);
1880 gtk_box_pack_start(GTK_BOX(hbox), bbox, FALSE, FALSE, 0);
1882 mitem = gtk_label_new("Page:");
1883 ed->pageno = gtk_widget_new(gtk_entry_get_type(),
1885 "width-request", 70,
1887 (void) g_signal_connect(G_OBJECT(ed->pageno), "activate",
1888 G_CALLBACK(goto_page_or_code),
1889 GUINT_TO_POINTER(ed->id));
1891 gtk_box_pack_start(GTK_BOX(hbox), mitem, FALSE, FALSE, 0);
1892 gtk_box_pack_start(GTK_BOX(hbox), ed->pageno, FALSE, FALSE, 0);
1894 mitem = gtk_label_new("Code:");
1895 ed->charno = gtk_widget_new(gtk_entry_get_type(),
1897 "width-request", 70,
1899 (void) g_signal_connect(G_OBJECT(ed->charno), "activate",
1900 G_CALLBACK(goto_page_or_code),
1901 GUINT_TO_POINTER(ed->id));
1903 gtk_box_pack_start(GTK_BOX(hbox), mitem, FALSE, FALSE, 0);
1904 gtk_box_pack_start(GTK_BOX(hbox), ed->charno, FALSE, FALSE, 0);
1906 gtk_container_add(GTK_CONTAINER(frame), hbox);
1909 * Now add the font grid itself.
1911 ed->fgrid = fontgrid_newv(font,
1912 options.font_opts.point_size,
1913 options.font_opts.font_spacing,
1915 options.overwrite_mode,
1918 options.initial_glyph,
1920 options.orientation,
1921 options.font_opts.bits_per_pixel,
1922 options.font_opts.resolution_x,
1923 options.font_opts.resolution_y,
1925 (void) g_signal_connect(G_OBJECT(ed->fgrid), "turn_to_page",
1926 G_CALLBACK(page_change),
1927 GUINT_TO_POINTER(ed->id));
1928 (void) g_signal_connect(G_OBJECT(ed->fgrid), "selection-start",
1929 G_CALLBACK(update_selection_info),
1930 GUINT_TO_POINTER(ed->id));
1931 (void) g_signal_connect(G_OBJECT(ed->fgrid), "selection-extend",
1932 G_CALLBACK(update_selection_info),
1933 GUINT_TO_POINTER(ed->id));
1934 (void) g_signal_connect(G_OBJECT(ed->fgrid), "selection-end",
1935 G_CALLBACK(update_selection_info),
1936 GUINT_TO_POINTER(ed->id));
1937 (void) g_signal_connect(G_OBJECT(ed->fgrid), "activate",
1938 G_CALLBACK(update_selection_info),
1939 GUINT_TO_POINTER(ed->id));
1940 (void) g_signal_connect(G_OBJECT(ed->fgrid), "modified",
1941 G_CALLBACK(handle_modified_signal),
1942 GUINT_TO_POINTER(ed->id));
1943 gtk_table_attach(GTK_TABLE(table), ed->fgrid, 0, 1, 4, 5,
1944 GTK_FILL|GTK_EXPAND|GTK_SHRINK,
1945 GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0);
1948 * Set up the initial page information.
1950 page_change(ed->fgrid, &pageinfo, GUINT_TO_POINTER(ed->id));
1953 * Show the editor if it the first one created or is not being created
1954 * from the command line.
1957 gtk_widget_show_all(ed->shell);
1961 * Get the initial selection info to set up the glyph info labels.
1963 * NOTE: This has to be done here because for some reason labels
1964 * do not display properly if changed before the editor is fully
1967 FontgridSelectionInfo sinfo;
1968 if (fontgrid_has_selection(FONTGRID(ed->fgrid), &sinfo) == TRUE)
1969 update_selection_info(ed->fgrid, (gpointer) &sinfo,
1970 GUINT_TO_POINTER(ed->id));
1974 * Set the font name in the entry field if the font exists.
1976 gtk_entry_set_text(GTK_ENTRY(ed->fontname),
1977 fontgrid_get_font_name(FONTGRID(ed->fgrid)));
1980 * Change the focus to the Fontgrid.
1982 gtk_widget_grab_focus(ed->fgrid);
1988 handle_unknown_options(bdf_options_t *opts, char **params,
1989 unsigned int nparams, void *client_data)
1992 gbdfed_options_t *op;
1994 op = (gbdfed_options_t *) client_data;
2000 * Handle the 2 bits per pixel color list.
2002 if (strncmp(params[0], "2bpp_grays", 10) == 0) {
2003 for (idx = 1; idx < 5; idx++)
2004 op->colors[idx] = (unsigned short) _bdf_atos(params[idx], 0, 10);
2009 * Handle the 4 bits per pixel color list.
2011 if (strncmp(params[0], "4bpp_grays", 10) == 0) {
2012 for (idx = 1; idx < 17; idx++)
2013 op->colors[idx-1+4] = (unsigned short) _bdf_atos(params[idx], 0, 10);
2017 if (params[0][0] == 'a' &&
2018 strncmp(params[0], "adobe_name_file", 15) == 0) {
2019 if (op->adobe_name_file != 0)
2020 g_free(op->adobe_name_file);
2021 if (params[1] == 0 || params[1][0] == 0)
2022 op->adobe_name_file = 0;
2024 op->adobe_name_file = g_strdup(params[1]);
2028 if (params[0][0] == 'c') {
2029 if (strncmp(params[0], "close_accelerator", 17) == 0) {
2030 if (params[0][17] == 0) {
2032 * We have the accelerator itself. Add code to convert Xt key
2035 if (op->accelerator != 0)
2036 g_free(op->accelerator);
2037 if (params[1] == 0 || params[1][0] == 0)
2038 op->accelerator = 0;
2040 op->accelerator = g_strdup(params[1]);
2044 * Ignore instances of 'close_accelerator_text'. GTK+ figures this
2051 if (strncmp(params[0], "code_base", 9) == 0) {
2052 switch (params[1][0]) {
2053 case 'o': case 'O': op->code_base = 8; break;
2054 case 'd': case 'D': op->code_base = 10; break;
2055 case 'h': case 'H': op->code_base = 16; break;
2056 default: op->code_base = 16;
2062 * Ignore the old grayscale specification keywords.
2064 if (strncmp(params[0], "color", 5) == 0) {
2066 * Quietly ignore the old color list.
2072 if (params[0][0] == 'f' &&
2073 strncmp(params[0], "font_grid_horizontal", 20) == 0) {
2074 switch (params[1][0]) {
2075 case '0': case 'F': case 'f': case 'N': case 'n':
2076 op->orientation = GTK_ORIENTATION_VERTICAL;
2078 case '1': case 'T': case 't': case 'Y': case 'y':
2079 op->orientation = GTK_ORIENTATION_HORIZONTAL;
2085 if (params[0][0] == 'g') {
2086 if (strncmp(params[0], "grid_overwrite_mode", 19) == 0) {
2087 switch (params[1][0]) {
2088 case '0': case 'F': case 'f': case 'N': case 'n':
2089 op->overwrite_mode = FALSE;
2091 case '1': case 'T': case 't': case 'Y': case 'y':
2092 op->overwrite_mode = TRUE;
2098 if (strncmp(params[0], "generate_sbit_metrics", 21) == 0) {
2099 switch (params[1][0]) {
2100 case '0': case 'F': case 'f': case 'N': case 'n':
2103 case '1': case 'T': case 't': case 'Y': case 'y':
2111 if (params[0][0] == 'm' && strncmp(params[0], "make_backups", 12) == 0) {
2112 switch (params[1][0]) {
2113 case '0': case 'F': case 'f': case 'N': case 'n':
2114 op->backups = FALSE;
2116 case '1': case 'T': case 't': case 'Y': case 'y':
2123 if ((params[0][0] == 'n' && strncmp(params[0], "name_file", 9) == 0) ||
2124 (params[0][0] == 'u' &&
2125 strncmp(params[0], "unicode_name_file", 17) == 0)) {
2126 if (op->unicode_name_file != 0)
2127 g_free(op->unicode_name_file);
2128 if (params[1] == 0 || params[1][0] == 0)
2129 op->unicode_name_file = 0;
2131 op->unicode_name_file = g_strdup(params[1]);
2135 if (params[0][0] == 'o' && strncmp(params[0], "orientation", 11) == 0) {
2136 switch (params[1][0]) {
2138 op->orientation = GTK_ORIENTATION_HORIZONTAL;
2141 op->orientation = GTK_ORIENTATION_VERTICAL;
2147 if (params[0][0] == 'p') {
2148 if (strncmp(params[0], "pixel_size", 10) == 0) {
2149 op->pixel_size = _bdf_atoul(params[1], 0, 10);
2150 if (op->pixel_size < 2)
2152 else if (op->pixel_size > 20)
2153 op->pixel_size = 20;
2157 if (strncmp(params[0], "power2", 6) == 0) {
2158 switch (params[1][0]) {
2159 case '0': case 'F': case 'f': case 'N': case 'n':
2162 case '1': case 'T': case 't': case 'Y': case 'y':
2169 if (strncmp(params[0], "percentage_only", 15) == 0)
2171 * Ignore this option. No longer needed.
2175 if (strncmp(params[0], "progress_bar", 12) == 0)
2177 * The progress bar is no longer being used as of version 5.0.
2182 if (params[0][0] == 'r') {
2183 if (strncmp(params[0], "resolution", 10) == 0) {
2184 op->resolution = _bdf_atoul(params[1], 0, 10);
2188 if (strncmp(params[0], "really_exit", 11) == 0) {
2189 switch (params[1][0]) {
2190 case '0': case 'F': case 'f': case 'N': case 'n':
2191 op->really_exit = FALSE;
2193 case '1': case 'T': case 't': case 'Y': case 'y':
2194 op->really_exit = TRUE;
2201 if (params[0][0] == 's') {
2202 if (strncmp(params[0], "skip_blank_pages", 16) == 0) {
2203 switch (params[1][0]) {
2204 case '0': case 'F': case 'f': case 'N': case 'n':
2205 op->no_blanks = FALSE;
2207 case '1': case 'T': case 't': case 'Y': case 'y':
2208 op->no_blanks = TRUE;
2214 if (strncmp(params[0], "show_cap_height", 15) == 0) {
2215 switch (params[1][0]) {
2216 case '0': case 'F': case 'f': case 'N': case 'n':
2217 op->show_cap_height = FALSE;
2219 case '1': case 'T': case 't': case 'Y': case 'y':
2220 op->show_cap_height = TRUE;
2226 if (strncmp(params[0], "show_x_height", 13) == 0) {
2227 switch (params[1][0]) {
2228 case '0': case 'F': case 'f': case 'N': case 'n':
2229 op->show_x_height = FALSE;
2231 case '1': case 'T': case 't': case 'Y': case 'y':
2232 op->show_x_height = TRUE;
2245 fprintf(stderr, "Usage: %s [font1.bdf .....]\n", g_get_prgname());
2250 editor_setup(int argc, char *argv[])
2255 gboolean need_editor;
2259 * Get the default BDF options.
2261 bdf_default_options(&options.font_opts);
2263 options.accelerator = options.accelerator_text =
2264 options.unicode_name_file = options.adobe_name_file = 0;
2265 options.pixel_size = 10;
2266 options.resolution = 0;
2267 options.no_blanks = options.really_exit =
2268 options.overwrite_mode = options.power2 =
2269 options.backups = TRUE;
2270 options.show_cap_height = options.show_x_height =
2271 options.sbit = options.gbdfed_opts = FALSE;
2272 options.initial_glyph = -1;
2273 options.code_base = 16;
2275 options.orientation = GTK_ORIENTATION_HORIZONTAL;
2278 * Set the default colors for 2 bits per pixel.
2280 options.colors[0] = 0;
2281 options.colors[1] = 175;
2282 options.colors[2] = 207;
2283 options.colors[3] = 239;
2286 * Set the default colors for 4 bits per pixel.
2288 options.colors[4] = 0;
2289 options.colors[5] = 31;
2290 options.colors[6] = 63;
2291 options.colors[7] = 95;
2292 options.colors[8] = 127;
2293 options.colors[9] = 159;
2294 options.colors[10] = 167;
2295 options.colors[11] = 175;
2296 options.colors[12] = 183;
2297 options.colors[13] = 191;
2298 options.colors[14] = 199;
2299 options.colors[15] = 207;
2300 options.colors[16] = 215;
2301 options.colors[17] = 223;
2302 options.colors[18] = 231;
2303 options.colors[19] = 239;
2306 * Attempt to load the user config file.
2308 if ((ap = getenv("HOME")) != 0) {
2309 sprintf(buffer1, "%s/.gbdfedrc", ap);
2310 if ((in = fopen(buffer1, "r")) != 0) {
2311 bdf_load_options(in, &options.font_opts, handle_unknown_options,
2316 * Try reading the older ".xmbdfedrc".
2318 sprintf(buffer1, "%s/.xmbdfedrc", ap);
2319 if ((in = fopen(buffer1, "r")) != 0) {
2320 bdf_load_options(in, &options.font_opts,
2321 handle_unknown_options, (void *) &options);
2328 * Determine the horizontal and vertical resolutions if they have not been
2329 * set on the command line or from the config file.
2331 if (options.resolution != 0)
2332 options.font_opts.resolution_x = options.font_opts.resolution_y =
2335 screen = gdk_drawable_get_screen(GDK_DRAWABLE(gdk_get_default_root_window()));
2336 if (options.font_opts.resolution_x == 0)
2337 options.font_opts.resolution_x =
2338 (unsigned int) ((((double) gdk_screen_get_width(screen)) * 25.4) /
2339 ((double) gdk_screen_get_width_mm(screen)) + 0.5);
2341 if (options.font_opts.resolution_y == 0)
2342 options.font_opts.resolution_y =
2343 (unsigned int) ((((double) gdk_screen_get_height(screen)) * 25.4) /
2344 ((double) gdk_screen_get_height_mm(screen)) + 0.5);
2347 * Handle the case of no command line options here.
2350 (void) gbdfed_make_editor(0, TRUE);
2355 * If a filename is not present on the command line, make sure an
2356 * editor is created after the command line is parsed.
2361 * Now parse the options from the command line.
2366 if (strcmp(ap + 1, "nm") == 0)
2367 options.font_opts.correct_metrics = 0;
2368 else if (strcmp(ap + 1, "nu") == 0)
2369 options.font_opts.keep_unencoded = 0;
2370 else if (strcmp(ap + 1, "nc") == 0)
2371 options.font_opts.keep_comments = 0;
2372 else if (strcmp(ap + 1, "np") == 0)
2373 options.font_opts.pad_cells = 0;
2374 else if (strcmp(ap + 1, "bp") == 0)
2375 options.no_blanks = FALSE;
2376 else if (strcmp(ap + 1, "ed") == 0)
2377 options.really_exit = FALSE;
2378 else if (strcmp(ap + 1, "im") == 0)
2379 options.overwrite_mode = FALSE;
2380 else if (strcmp(ap + 1, "o") == 0) {
2383 options.orientation =
2384 (argv[0][0] == 'v' || argv[0][0] == 'V') ?
2385 GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL;
2386 } else if (strcmp(ap + 1, "ps") == 0) {
2389 options.font_opts.point_size = _bdf_atoul(*argv, 0, 10);
2390 } else if (strcmp(ap + 1, "res") == 0) {
2393 options.resolution = _bdf_atoul(*argv, 0, 10);
2394 options.font_opts.resolution_x =
2395 options.font_opts.resolution_y = options.resolution;
2396 } else if (strcmp(ap + 1, "hres") == 0) {
2399 options.font_opts.resolution_x = _bdf_atoul(*argv, 0, 10);
2400 } else if (strcmp(ap + 1, "vres") == 0) {
2403 options.font_opts.resolution_y = _bdf_atoul(*argv, 0, 10);
2404 } else if (strcmp(ap + 1, "bpp") == 0) {
2407 options.font_opts.bits_per_pixel = _bdf_atoul(*argv, 0, 10);
2408 } else if (strcmp(ap + 1, "g") == 0) {
2413 switch (*(ap + 1)) {
2414 case 'u': case 'x': base = 16; ap += 2; break;
2415 case 'o': base = 8; ap += 2; break;
2416 case 'd': base = 10; ap += 2; break;
2418 } else if ((*ap == 'U' && (*(ap + 1) == '+' ||
2419 *(ap + 1) == '-')) ||
2420 (*ap == '0' && (*(ap + 1) == 'x' ||
2421 *(ap + 1) == 'X'))) {
2424 } else if (*ap == '0')
2427 options.initial_glyph = _bdf_atol(ap, 0, base);
2428 } else if (strcmp(ap + 1, "sp") == 0) {
2431 switch (argv[0][0]) {
2433 options.font_opts.font_spacing = BDF_CHARCELL; break;
2435 options.font_opts.font_spacing = BDF_MONOWIDTH; break;
2437 options.font_opts.font_spacing = BDF_PROPORTIONAL; break;
2439 } else if (strcmp(ap + 1, "eol") == 0) {
2442 switch (argv[0][0]) {
2444 options.font_opts.eol = BDF_DOS_EOL; break;
2446 options.font_opts.eol = BDF_MAC_EOL; break;
2448 options.font_opts.eol = BDF_UNIX_EOL; break;
2450 } else if (strcmp(ap + 1, "cb") == 0) {
2453 switch (argv[0][0]) {
2455 options.code_base = 10; break;
2457 options.code_base = 16; break;
2459 options.code_base = 8; break;
2463 fprintf(stderr, "%s: unknown parameter '%s'.\n",
2464 g_get_prgname(), ap);
2468 need_editor = FALSE;
2469 (void) gbdfed_make_editor(argv[0], TRUE);
2476 if (need_editor == TRUE)
2478 * If an editor was not created, make one here.
2480 (void) gbdfed_make_editor(0, TRUE);
2484 main(int argc, char* argv[])
2489 * Make sure the BDF library is initialized.
2493 gtk_init(&argc, &argv);
2498 editor_setup(argc, argv);