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.
24 #include "glyphedit.h"
28 #define UPMSG "Glyph Edit: The glyph has been modified.\nDo you want to save?"
30 static const gchar *lb_xpm[] = {
31 /* width height num_colors chars_per_pixel */
38 "...........##...................",
39 "...........##...................",
40 "................................",
41 "................................",
42 "...........##...................",
43 "...........##...................",
44 "................................",
45 "..r....r........................",
46 ".rr....rr..##...................",
47 "rrrrrrrrrr.##...................",
48 ".rr....rr.......................",
49 "..r....r........................",
50 "...........##...................",
51 "...........##...................",
52 "................................",
53 "................................",
54 "...........##...................",
55 "...........##...................",
56 "................................",
57 "##..##..##.##.##..##..##..##..##",
58 "##..##..##.##.##..##..##..##..##",
59 "................................",
60 "...........##...................",
61 "...........##...................",
62 "................................",
63 "................................",
64 "...........##...................",
65 "...........##...................",
66 "................................",
67 "................................",
68 "...........##...................",
69 "...........##..................."
72 static const gchar *rb_xpm[] = {
73 /* width height num_colors chars_per_pixel */
80 "...........##...................",
81 "...........##...................",
82 "................................",
83 "................................",
84 "...........##...................",
85 "...........##...................",
86 "................................",
87 "................r............r..",
88 "...........##..rr............rr.",
89 "...........##.rrrrrrrrrrrrrrrrrr",
90 "...............rr............rr.",
91 "................r............r..",
92 "...........##...................",
93 "...........##...................",
94 "................................",
95 "................................",
96 "...........##...................",
97 "...........##...................",
98 "................................",
99 "##..##..##.##.##..##..##..##..##",
100 "##..##..##.##.##..##..##..##..##",
101 "................................",
102 "...........##...................",
103 "...........##...................",
104 "................................",
105 "................................",
106 "...........##...................",
107 "...........##...................",
108 "................................",
109 "................................",
110 "...........##...................",
111 "...........##..................."
114 static const gchar *as_xpm[] = {
115 /* width height num_colors chars_per_pixel */
122 "...........##.........r.........",
123 "...........##........rrr........",
124 "....................rrrrr.......",
125 "......................r.........",
126 "...........##.........r.........",
127 "...........##.........r.........",
128 "......................r.........",
129 "......................r.........",
130 "...........##.........r.........",
131 "...........##.........r.........",
132 "......................r.........",
133 "......................r.........",
134 "...........##.........r.........",
135 "...........##.........r.........",
136 "......................r.........",
137 "....................rrrrr.......",
138 "...........##........rrr........",
139 "...........##.........r.........",
140 "................................",
141 "##..##..##.##.##..##..##..##..##",
142 "##..##..##.##.##..##..##..##..##",
143 "................................",
144 "...........##...................",
145 "...........##...................",
146 "................................",
147 "................................",
148 "...........##...................",
149 "...........##...................",
150 "................................",
151 "................................",
152 "...........##...................",
153 "...........##..................."
156 static const char *ds_xpm[] = {
157 /* width height num_colors chars_per_pixel */
164 "...........##...................",
165 "...........##...................",
166 "................................",
167 "................................",
168 "...........##...................",
169 "...........##...................",
170 "................................",
171 "................................",
172 "...........##...................",
173 "...........##...................",
174 "................................",
175 "................................",
176 "...........##...................",
177 "...........##...................",
178 "................................",
179 "................................",
180 "...........##...................",
181 "...........##...................",
182 "................................",
183 "##..##..##.##.##..##..##..##..##",
184 "##..##..##.##.##..##..##..##..##",
185 "................................",
186 "...........##.........r.........",
187 "...........##........rrr........",
188 "....................rrrrr.......",
189 "......................r.........",
190 "...........##.........r.........",
191 "...........##.........r.........",
192 "......................r.........",
193 "....................rrrrr.......",
194 "...........##........rrr........",
195 "...........##.........r........."
201 static GdkPixbuf *lb_image = 0;
202 static GdkPixbuf *rb_image = 0;
203 static GdkPixbuf *as_image = 0;
204 static GdkPixbuf *ds_image = 0;
212 * The rotate/shear tab.
216 GtkAdjustment *rotate_adj;
217 GtkAdjustment *shear_adj;
219 gboolean degrees_modified;
222 * The bounding box resize tab.
228 gboolean resize_modified;
231 * The PSF mappings tab.
234 GtkWidget *psf_delete;
235 GtkWidget *psf_mappings;
236 GtkWidget *psf_input;
237 gboolean psf_modified;
238 } GlypheditNotebookRec;
255 GtkWidget *gectltips;
257 GtkWidget *file_menu;
259 GtkWidget *update_prev;
260 GtkWidget *update_next;
262 GtkWidget *button_update;
263 GtkWidget *button_prev;
264 GtkWidget *button_next;
266 GtkWidget *edit_menu;
272 GtkWidget *select_all;
276 GtkWidget *unimap_page;
279 GlypheditNotebookRec ops;
282 static GlypheditRec *glyph_editors;
283 static gulong num_glyph_editors;
285 static GlypheditRec *
286 _guigedit_get_glyph_editor(gulong owner)
291 if (num_glyph_editors == 0) {
293 (GlypheditRec *) g_malloc0(sizeof(GlypheditRec));
294 ge->id = num_glyph_editors++;
296 for (i = 0; i < num_glyph_editors; i++) {
297 if (glyph_editors[i].owner == ~0) {
298 ge = &glyph_editors[i];
303 glyph_editors = (GlypheditRec *)
304 g_realloc(glyph_editors,
305 sizeof(GlypheditRec) * (num_glyph_editors + 1));
307 ge = glyph_editors + num_glyph_editors;
308 (void) memset((char *) ge, 0, sizeof(GlypheditRec));
309 ge->id = num_glyph_editors++;
315 /**************************************************************************
319 **************************************************************************/
322 make_accel_menu_item(GtkWidget *menu, const gchar *text, const gchar *accel,
327 GdkModifierType mods;
329 mi = gtk_menu_item_new_with_mnemonic(text);
331 gtk_accelerator_parse(accel, &key, &mods);
332 gtk_widget_add_accelerator(mi, "activate", ag, key, mods,
333 GTK_ACCEL_VISIBLE|GTK_ACCEL_LOCKED);
334 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
340 update_font(GtkWidget *w, gpointer data)
342 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
343 gbdfed_editor_t *ed = editors + ge->owner;
345 gchar *prgname = g_get_prgname();
348 GlypheditOperation op;
350 if (GTK_WIDGET_IS_SENSITIVE(ge->update) == TRUE) {
351 if (glyphedit_get_selecting(GLYPHEDIT(ge->gedit)) == TRUE) {
353 * A selection operation is in progress. Need to switch back to
354 * the Draw operation to finalize the selection and then switch
357 op = glyphedit_get_operation(GLYPHEDIT(ge->gedit));
358 glyphedit_change_operation(GLYPHEDIT(ge->gedit), GLYPHEDIT_DRAW);
359 glyphedit_change_operation(GLYPHEDIT(ge->gedit), op);
362 glyph = glyphedit_get_glyph(GLYPHEDIT(ge->gedit), &unencoded);
365 * Set the new name and device width for the glyph. These may not
366 * have actually changed, but this is simplest for the moment.
368 if (glyph->name != 0)
370 glyph->name = (gchar *) gtk_entry_get_text(GTK_ENTRY(ge->name));
371 s = gtk_entry_get_text(GTK_ENTRY(ge->dwidth));
372 glyph->dwidth = (guint16) _bdf_atos((char *) s, 0, 10);
375 * Now update the font itself.
377 fontgrid_update_glyph(FONTGRID(ed->fgrid), glyph, unencoded);
380 * Free the glyph structure. The name has already been deallocated
381 * and replaced with a possibly new name.
383 if (glyph->bytes > 0)
387 glyphedit_set_modified(GLYPHEDIT(ge->gedit), FALSE);
391 * Just modified the PSF mappings.
393 fontgrid_update_psf_mappings(FONTGRID(ed->fgrid),
394 glyphedit_get_encoding(GLYPHEDIT(ge->gedit)),
395 glyphedit_get_psf_mappings(GLYPHEDIT(ge->gedit)));
398 * Unset the modified flag and update the title.
400 glyphedit_set_modified(GLYPHEDIT(ge->gedit), FALSE);
402 sprintf(buffer1, "%s - Glyph Edit: (unnamed%d)",
405 sprintf(buffer1, "%s - Glyph Edit: %s", prgname, ed->file);
407 gtk_window_set_title(GTK_WINDOW(ge->shell), buffer1);
410 gtk_widget_set_sensitive(ge->update, FALSE);
411 gtk_widget_set_sensitive(ge->update_next, FALSE);
412 gtk_widget_set_sensitive(ge->update_prev, FALSE);
413 gtk_widget_set_sensitive(ge->button_update, FALSE);
416 * Force the focus to be on the glyph grid
418 gtk_widget_grab_focus(ge->gedit);
422 * Code common to both next_glyph() and previous_glyph().
425 update_glyphedit(gbdfed_editor_t *ed, GlypheditRec *ge, bdf_glyph_grid_t *grid)
429 gw = GLYPHEDIT(ge->gedit);
430 gtk_entry_set_text(GTK_ENTRY(ge->name), grid->name);
433 sprintf(buffer1, "-1");
435 switch (fontgrid_get_code_base(FONTGRID(ed->fgrid))) {
436 case 8: sprintf(buffer1, "%o", grid->encoding); break;
437 case 10: sprintf(buffer1, "%d", grid->encoding); break;
438 case 16: sprintf(buffer1, "%04X", grid->encoding); break;
441 gtk_label_set_text(GTK_LABEL(ge->encoding), buffer1);
443 sprintf(buffer1, "%hd", grid->dwidth);
444 gtk_widget_set_sensitive(ge->dwidth, TRUE);
445 g_signal_handler_block(G_OBJECT(ge->dwidth), ge->handler);
446 gtk_entry_set_text(GTK_ENTRY(ge->dwidth), buffer1);
447 g_signal_handler_unblock(G_OBJECT(ge->dwidth), ge->handler);
449 if (grid->spacing != BDF_PROPORTIONAL) {
450 gtk_widget_set_sensitive(ge->dwidth, FALSE);
451 if (ge->unimap_page != 0)
452 gtk_widget_set_sensitive(ge->unimap_page, TRUE);
453 } else if (ge->unimap_page != 0)
454 gtk_widget_set_sensitive(ge->unimap_page, FALSE);
456 sprintf(buffer1, "width %hd height %hd\r\nascent %hd descent %hd",
457 grid->glyph_bbx.width, grid->glyph_bbx.height,
458 grid->glyph_bbx.ascent, grid->glyph_bbx.descent);
459 gtk_label_set_text(GTK_LABEL(ge->metrics), buffer1);
462 * Set the new grid in the glyph editor.
464 glyphedit_set_grid(gw, grid);
467 * Set the sensitivity of the update menu items appropriately.
469 if (grid->modified) {
470 gtk_widget_set_sensitive(ge->update, TRUE);
471 gtk_widget_set_sensitive(ge->update_next, TRUE);
472 gtk_widget_set_sensitive(ge->update_prev, TRUE);
473 gtk_widget_set_sensitive(ge->button_update, TRUE);
475 gtk_widget_set_sensitive(ge->update, FALSE);
476 gtk_widget_set_sensitive(ge->update_next, FALSE);
477 gtk_widget_set_sensitive(ge->update_prev, FALSE);
478 gtk_widget_set_sensitive(ge->button_update, FALSE);
481 if (glyphedit_get_encoding(gw) == 0)
482 gtk_widget_set_sensitive(ge->button_prev, FALSE);
484 gtk_widget_set_sensitive(ge->button_prev, TRUE);
486 if (glyphedit_get_encoding(gw) == 0xffff)
487 gtk_widget_set_sensitive(ge->button_next, FALSE);
489 gtk_widget_set_sensitive(ge->button_next, TRUE);
492 * Force the focus to be on the glyph grid.
494 gtk_widget_grab_focus(ge->gedit);
498 next_glyph(GtkWidget *w, gpointer data)
500 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
501 gbdfed_editor_t *ed = editors + ge->owner;
503 bdf_glyph_grid_t *grid;
506 if (GTK_WIDGET_IS_SENSITIVE(ge->update) == TRUE) {
507 if (guiutil_yes_or_no(ge->shell, UPMSG, TRUE))
508 update_font(w, GUINT_TO_POINTER(ge->id));
511 grid = glyphedit_get_grid(GLYPHEDIT(ge->gedit));
513 if (fontgrid_select_next_glyph(FONTGRID(ed->fgrid), grid->encoding) == FALSE)
516 font = fontgrid_get_font(FONTGRID(ed->fgrid));
519 grid = bdf_make_glyph_grid(font, grid->encoding + 1, 1);
521 grid = bdf_make_glyph_grid(font, grid->encoding + 1, 0);
523 update_glyphedit(ed, ge, grid);
525 glyphedit_get_image(GLYPHEDIT(ge->gedit), &image);
526 gecontrol_set_glyph_image(GECONTROL(ge->gectrl), &image);
532 previous_glyph(GtkWidget *w, gpointer data)
534 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
535 gbdfed_editor_t *ed = editors + ge->owner;
537 bdf_glyph_grid_t *grid;
540 if (GTK_WIDGET_IS_SENSITIVE(ge->update) == TRUE) {
541 if (guiutil_yes_or_no(ge->shell, UPMSG, TRUE))
542 update_font(w, GUINT_TO_POINTER(ge->id));
545 grid = glyphedit_get_grid(GLYPHEDIT(ge->gedit));
547 if (fontgrid_select_previous_glyph(FONTGRID(ed->fgrid), grid->encoding) == FALSE)
550 font = fontgrid_get_font(FONTGRID(ed->fgrid));
553 grid = bdf_make_glyph_grid(font, grid->encoding - 1, 1);
555 grid = bdf_make_glyph_grid(font, grid->encoding - 1, 0);
557 update_glyphedit(ed, ge, grid);
559 glyphedit_get_image(GLYPHEDIT(ge->gedit), &image);
560 gecontrol_set_glyph_image(GECONTROL(ge->gectrl), &image);
566 update_and_next_glyph(GtkWidget *w, gpointer data)
568 update_font(w, data);
573 update_and_previous_glyph(GtkWidget *w, gpointer data)
575 update_font(w, data);
576 previous_glyph(w, data);
580 close_glyph_editor(GtkWidget *w, GdkEvent *ev, gpointer data)
582 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
585 * Glyph editors with no owners are ignored. This lets us call this
586 * routine at application shutdown time to update all modified
593 * We don't check to see if the grid has been modified, because
594 * certain operations cause the modify flag to be set, but they
595 * don't really represent a modification.
597 if (GTK_WIDGET_IS_SENSITIVE(ge->update) == TRUE) {
598 if (guiutil_yes_or_no(ge->shell, UPMSG, TRUE))
599 update_font(w, GUINT_TO_POINTER(ge->id));
603 * Release this editor back into the pool to be reused.
610 gtk_widget_hide(ge->shell);
616 activate_close_glyph_editor(GtkWidget *w, gpointer data)
618 (void) close_glyph_editor(w, 0, data);
622 make_file_menu(GlypheditRec *ge, GtkWidget *menubar)
624 GtkWidget *file, *menu, *mitem, *sep;
627 * Create the File menu.
629 file = gtk_menu_item_new_with_mnemonic("_File");
631 ge->file_menu = menu = gtk_menu_new();
633 ge->update = make_accel_menu_item(menu, "_Update",
634 "<Control>S", ge->ag);
635 g_signal_connect(G_OBJECT(ge->update), "activate",
636 G_CALLBACK(update_font), GUINT_TO_POINTER(ge->id));
638 ge->update_next = make_accel_menu_item(menu, "Update and _Next",
639 "<Control>U", ge->ag);
640 g_signal_connect(G_OBJECT(ge->update_next), "activate",
641 G_CALLBACK(update_and_next_glyph),
642 GUINT_TO_POINTER(ge->id));
644 ge->update_prev = make_accel_menu_item(menu, "Update and _Previous",
645 "<Control>B", ge->ag);
646 g_signal_connect(G_OBJECT(ge->update_prev), "activate",
647 G_CALLBACK(update_and_previous_glyph),
648 GUINT_TO_POINTER(ge->id));
653 sep = gtk_menu_item_new();
654 gtk_widget_set_sensitive(sep, FALSE);
655 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
657 mitem = make_accel_menu_item(menu, "_Close", "<Control>F4", ge->ag);
658 (void) g_signal_connect(G_OBJECT(mitem), "activate",
659 G_CALLBACK(activate_close_glyph_editor),
660 GUINT_TO_POINTER(ge->id));
662 gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), menu);
668 edit_menu_up(GtkWidget *w, GdkEvent *event, gpointer data)
670 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
673 gw = GLYPHEDIT(ge->gedit);
675 if (glyphedit_clipboard_empty(gw))
676 gtk_widget_set_sensitive(ge->paste, FALSE);
678 gtk_widget_set_sensitive(ge->paste, TRUE);
680 gtk_widget_set_sensitive(ge->copy,
681 glyphedit_get_selecting(gw));
682 gtk_widget_set_sensitive(ge->cut,
683 glyphedit_get_selecting(gw));
685 if (glyphedit_get_encoding(gw) == 0)
686 gtk_widget_set_sensitive(ge->prev, FALSE);
688 gtk_widget_set_sensitive(ge->prev, TRUE);
690 if (glyphedit_get_encoding(gw) == 0xffff)
691 gtk_widget_set_sensitive(ge->next, FALSE);
693 gtk_widget_set_sensitive(ge->next, TRUE);
695 gtk_widget_set_sensitive(ge->reload, glyphedit_get_modified(gw));
697 if (glyphedit_get_spacing(gw) != BDF_PROPORTIONAL)
698 gtk_widget_set_sensitive(ge->unimap, TRUE);
700 gtk_widget_set_sensitive(ge->unimap, FALSE);
706 edit_menu_down(GtkWidget *w, GdkEvent *event, gpointer data)
708 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
710 gtk_widget_set_sensitive(ge->paste, TRUE);
711 gtk_widget_set_sensitive(ge->copy, TRUE);
712 gtk_widget_set_sensitive(ge->cut, TRUE);
713 gtk_widget_set_sensitive(ge->prev, TRUE);
714 gtk_widget_set_sensitive(ge->next, TRUE);
715 gtk_widget_set_sensitive(ge->reload, TRUE);
716 gtk_widget_set_sensitive(ge->unimap, TRUE);
722 reload_glyph(GtkWidget *w, gpointer data)
724 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
725 gbdfed_editor_t *ed = editors + ge->owner;
727 bdf_glyph_grid_t *grid;
730 font = fontgrid_get_font(FONTGRID(ed->fgrid));
731 grid = glyphedit_get_grid(GLYPHEDIT(ge->gedit));
733 grid = bdf_make_glyph_grid(font, grid->encoding, grid->unencoded);
735 update_glyphedit(ed, ge, grid);
737 glyphedit_get_image(GLYPHEDIT(ge->gedit), &image);
738 gecontrol_set_glyph_image(GECONTROL(ge->gectrl), &image);
744 copy_selection(GtkWidget *w, gpointer data)
746 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
748 glyphedit_copy_selection(GLYPHEDIT(ge->gedit));
752 cut_selection(GtkWidget *w, gpointer data)
754 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
757 glyphedit_cut_selection(GLYPHEDIT(ge->gedit));
758 glyphedit_get_image(GLYPHEDIT(ge->gedit), &image);
759 gecontrol_set_glyph_image(GECONTROL(ge->gectrl), &image);
765 paste_selection(GtkWidget *w, gpointer data)
767 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
770 glyphedit_paste_selection(GLYPHEDIT(ge->gedit));
771 glyphedit_get_image(GLYPHEDIT(ge->gedit), &image);
772 gecontrol_set_glyph_image(GECONTROL(ge->gectrl), &image);
778 select_all(GtkWidget *w, gpointer data)
780 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
782 glyphedit_select_all(GLYPHEDIT(ge->gedit));
786 make_edit_menu(GlypheditRec *ge, GtkWidget *menubar)
788 GtkWidget *edit, *menu, *sep;
791 * Create the Edit menu.
793 edit = gtk_menu_item_new_with_mnemonic("_Edit");
795 ge->edit_menu = menu = gtk_menu_new();
796 g_signal_connect(G_OBJECT(menu), "map_event", G_CALLBACK(edit_menu_up),
797 GUINT_TO_POINTER(ge->id));
798 g_signal_connect(G_OBJECT(menu), "unmap_event", G_CALLBACK(edit_menu_down),
799 GUINT_TO_POINTER(ge->id));
801 ge->reload = make_accel_menu_item(menu, "Re_load",
802 "<Control>L", ge->ag);
803 g_signal_connect(G_OBJECT(ge->reload), "activate",
804 G_CALLBACK(reload_glyph), GUINT_TO_POINTER(ge->id));
809 sep = gtk_menu_item_new();
810 gtk_widget_set_sensitive(sep, FALSE);
811 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
813 ge->copy = make_accel_menu_item(menu, "_Copy",
814 "<Control>C", ge->ag);
815 g_signal_connect(G_OBJECT(ge->copy), "activate",
816 G_CALLBACK(copy_selection),
817 GUINT_TO_POINTER(ge->id));
819 ge->cut = make_accel_menu_item(menu, "C_ut",
820 "<Control>X", ge->ag);
821 g_signal_connect(G_OBJECT(ge->cut), "activate",
822 G_CALLBACK(cut_selection),
823 GUINT_TO_POINTER(ge->id));
825 ge->paste = make_accel_menu_item(menu, "_Paste",
826 "<Control>V", ge->ag);
827 g_signal_connect(G_OBJECT(ge->paste), "activate",
828 G_CALLBACK(paste_selection),
829 GUINT_TO_POINTER(ge->id));
834 sep = gtk_menu_item_new();
835 gtk_widget_set_sensitive(sep, FALSE);
836 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
838 ge->select_all = make_accel_menu_item(menu, "Select _All",
839 "<Control>A", ge->ag);
840 g_signal_connect(G_OBJECT(ge->select_all), "activate",
841 G_CALLBACK(select_all),
842 GUINT_TO_POINTER(ge->id));
847 sep = gtk_menu_item_new();
848 gtk_widget_set_sensitive(sep, FALSE);
849 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
851 ge->next = make_accel_menu_item(menu, "_Next Glyph",
852 "<Control>N", ge->ag);
853 g_signal_connect(G_OBJECT(ge->next), "activate",
854 G_CALLBACK(next_glyph), GUINT_TO_POINTER(ge->id));
856 ge->prev = make_accel_menu_item(menu, "Pre_vious Glyph",
857 "<Control>P", ge->ag);
858 g_signal_connect(G_OBJECT(ge->prev), "activate",
859 G_CALLBACK(previous_glyph), GUINT_TO_POINTER(ge->id));
861 gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit), menu);
867 operations_menu_up(GtkWidget *w, GdkEvent *event, gpointer data)
869 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
872 gw = GLYPHEDIT(ge->gedit);
874 if (glyphedit_get_spacing(gw) != BDF_PROPORTIONAL)
875 gtk_widget_set_sensitive(ge->unimap, TRUE);
877 gtk_widget_set_sensitive(ge->unimap, FALSE);
883 operations_menu_down(GtkWidget *w, GdkEvent *event, gpointer data)
885 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
888 gw = GLYPHEDIT(ge->gedit);
889 gtk_widget_set_sensitive(ge->unimap, TRUE);
895 draw_operation(GtkWidget *w, gpointer data)
897 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
898 glyphedit_change_operation(GLYPHEDIT(ge->gedit), GLYPHEDIT_DRAW);
899 gecontrol_change_operation(GECONTROL(ge->gectrl), GECONTROL_DRAW);
903 move_operation(GtkWidget *w, gpointer data)
905 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
906 glyphedit_change_operation(GLYPHEDIT(ge->gedit), GLYPHEDIT_MOVE);
907 gecontrol_change_operation(GECONTROL(ge->gectrl), GECONTROL_MOVE);
911 copy_operation(GtkWidget *w, gpointer data)
913 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
914 glyphedit_change_operation(GLYPHEDIT(ge->gedit), GLYPHEDIT_COPY);
915 gecontrol_change_operation(GECONTROL(ge->gectrl), GECONTROL_COPY);
919 set_rotate_limits(GtkWidget *w, gpointer data)
921 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
923 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ge->ops.rotate)))
924 gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(ge->ops.degrees),
929 set_shear_limits(GtkWidget *w, gpointer data)
931 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
935 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ge->ops.shear))) {
937 * This little tap dance is to avoid a minor, but ugly GUI
938 * situation where the value in the spin button may be obscured
939 * when the adjustment is changed back. The shear value can have
940 * at most 2 digits where the rotate value can have 3. Changing
941 * back to the shear adjustment can cause a resize of the spin
942 * button, sometimes obscuring the value left over from the rotate
945 s = gtk_entry_get_text(GTK_ENTRY(ge->ops.degrees));
946 v = (gint16) _bdf_atos((char *) s, 0, 10);
952 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ge->ops.degrees),
954 gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(ge->ops.degrees),
960 * Called when the value for rotating or shearing a glyph has changed.
963 degrees_changed(GtkWidget *w, gpointer data)
965 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
967 gtk_widget_set_sensitive(ge->ops.apply, TRUE);
968 ge->ops.degrees_modified = TRUE;
972 * Called when any of the fields in the resize tab are changed.
975 resize_changed(GtkWidget *w, gpointer data)
977 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
979 gtk_widget_set_sensitive(ge->ops.apply, TRUE);
980 ge->ops.resize_modified = TRUE;
984 count_list_items(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *i,
987 gint *n = (gint *) data;
994 collect_list_items(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *i,
997 gchar **mappings = (gchar **) data;
999 gtk_tree_model_get(m, i, 0,
1000 &mappings[gtk_tree_path_get_indices(p)[0]], -1);
1005 * Called when the Apply button is pressed.
1008 apply_operations(GtkWidget *w, gint response, gpointer data)
1010 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1012 gint16 lb, rb, as, ds, degrees;
1014 GtkTreeModel *model;
1016 bdf_psf_unimap_t *mp;
1017 bdf_metrics_t metrics;
1019 if (ge->ops.degrees_modified) {
1021 * The degrees of rotatation or shearing have been modified.
1023 s = gtk_entry_get_text(GTK_ENTRY(ge->ops.degrees));
1024 degrees = (gint16) _bdf_atos((char *) s, 0, 10);
1025 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ge->ops.rotate)))
1026 glyphedit_rotate_glyph(GLYPHEDIT(ge->gedit), degrees);
1028 glyphedit_shear_glyph(GLYPHEDIT(ge->gedit), degrees);
1029 ge->ops.degrees_modified = FALSE;
1032 if (ge->ops.resize_modified) {
1034 * The bounding box has been modified.
1036 s = gtk_entry_get_text(GTK_ENTRY(ge->ops.lbearing));
1037 lb = (gint16) _bdf_atos((char *) s, 0, 10);
1038 s = gtk_entry_get_text(GTK_ENTRY(ge->ops.rbearing));
1039 rb = (gint16) _bdf_atos((char *) s, 0, 10);
1040 s = gtk_entry_get_text(GTK_ENTRY(ge->ops.ascent));
1041 as = (gint16) _bdf_atos((char *) s, 0, 10);
1042 s = gtk_entry_get_text(GTK_ENTRY(ge->ops.descent));
1043 ds = (gint16) _bdf_atos((char *) s, 0, 10);
1045 metrics.width = rb - lb;
1046 metrics.x_offset = lb;
1047 metrics.ascent = as;
1048 metrics.descent = ds;
1049 metrics.height = as + ds;
1050 metrics.y_offset = -ds;
1052 glyphedit_set_metrics(GLYPHEDIT(ge->gedit), &metrics);
1053 ge->ops.degrees_modified = FALSE;
1056 if (ge->ops.psf_modified) {
1057 model = gtk_tree_view_get_model(GTK_TREE_VIEW(ge->ops.psf_mappings));
1059 gtk_tree_model_foreach(model, count_list_items, (gpointer) &n);
1060 mappings = (gchar **) g_malloc(sizeof(gchar *) * n);
1061 gtk_tree_model_foreach(model, collect_list_items, (gpointer) mappings);
1062 mp = glyphedit_get_psf_mappings(GLYPHEDIT(ge->gedit));
1063 _bdf_psf_pack_mapping(mappings, n,
1064 glyphedit_get_encoding(GLYPHEDIT(ge->gedit)),
1066 for (i = 0; i < n; i++)
1067 g_free(mappings[i]);
1070 glyphedit_set_modified(GLYPHEDIT(ge->gedit), TRUE);
1071 glyphedit_signal_modified(GLYPHEDIT(ge->gedit));
1072 ge->ops.psf_modified = FALSE;
1076 * Only disable the Apply button if everything has been updated.
1078 if (ge->ops.degrees_modified == FALSE &&
1079 ge->ops.resize_modified == FALSE &&
1080 ge->ops.psf_modified == FALSE)
1081 gtk_widget_set_sensitive(ge->ops.apply, FALSE);
1083 gtk_widget_hide(ge->ops.dialog);
1087 change_unimap(GtkTreeModel *m, const gchar *path,
1088 const gchar *ntext, gpointer data)
1091 GtkTreePath *p = gtk_tree_path_new_from_string(path);
1094 gtk_tree_model_get_iter(m, &iter, p);
1095 gtk_tree_model_get(m, &iter, 0, &ot, -1);
1098 gtk_list_store_set(GTK_LIST_STORE(m), &iter, 0, ntext, -1);
1102 add_mapping(GtkWidget *w, gpointer data)
1104 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1108 GtkTreeModel *model;
1112 v = gtk_entry_get_text(GTK_ENTRY(ge->ops.psf_input));
1115 * Insure that the value is in the form expected.
1117 n = (gulong) _bdf_atol((char *) v, 0, 16);
1119 sprintf(buffer1, "U+%04lX", n);
1121 sprintf(buffer1, "U+%06lX", n);
1122 v = (const gchar *) buffer1;
1124 model = gtk_tree_view_get_model(GTK_TREE_VIEW(ge->ops.psf_mappings));
1125 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
1126 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, v, -1);
1128 i = gtk_tree_model_get_string_from_iter(model, &iter);
1129 path = gtk_tree_path_new_from_string(i);
1131 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ge->ops.psf_mappings),
1132 path, 0, TRUE, 0.5, 0.0);
1133 gtk_tree_path_free(path);
1135 ge->ops.psf_modified = TRUE;
1137 gtk_entry_set_text(GTK_ENTRY(ge->ops.psf_input), "");
1138 gtk_widget_set_sensitive(ge->ops.psf_add, FALSE);
1139 gtk_widget_set_sensitive(ge->ops.apply, TRUE);
1143 enable_add(GtkWidget *w, gpointer data)
1145 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1146 const gchar *v = gtk_entry_get_text(GTK_ENTRY(ge->ops.psf_input));
1149 gtk_widget_set_sensitive(ge->ops.psf_add, FALSE);
1151 gtk_widget_set_sensitive(ge->ops.psf_add, TRUE);
1155 delete_unimap(GtkWidget *w, gpointer data)
1157 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1158 GtkTreeModel *model;
1159 GtkTreeSelection *sel;
1162 model = gtk_tree_view_get_model(GTK_TREE_VIEW(ge->ops.psf_mappings));
1163 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ge->ops.psf_mappings));
1165 if (gtk_tree_selection_get_selected(sel, 0, &iter)) {
1166 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
1167 ge->ops.psf_modified = TRUE;
1168 gtk_widget_set_sensitive(ge->ops.psf_add, FALSE);
1169 gtk_widget_set_sensitive(ge->ops.apply, TRUE);
1174 operations_dialog_populate(GlypheditRec *ge)
1176 bdf_psf_unimap_t *psf;
1179 GtkTreeModel *model;
1181 bdf_metrics_t metrics;
1184 * Populate the fields of the dialog with initial values.
1186 glyphedit_get_font_metrics(GLYPHEDIT(ge->gedit), &metrics);
1189 * The left bearing cannot be set when the font has character cell
1190 * spacing. But make sure it is enabled so the value from the font
1193 gtk_widget_set_sensitive(ge->ops.lbearing, TRUE);
1198 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ge->ops.lbearing),
1199 (gdouble) (-metrics.x_offset));
1200 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ge->ops.rbearing),
1201 (gdouble) (metrics.width + metrics.x_offset));
1202 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ge->ops.ascent),
1203 (gdouble) metrics.ascent);
1204 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ge->ops.descent),
1205 (gdouble) metrics.descent);
1206 if (metrics.font_spacing == BDF_CHARCELL)
1207 gtk_widget_set_sensitive(ge->ops.lbearing, FALSE);
1210 * Add the PSF mappings to the list.
1212 if ((psf = glyphedit_get_psf_mappings(GLYPHEDIT(ge->gedit)))) {
1214 * Erase the list store.
1216 model = gtk_tree_view_get_model(GTK_TREE_VIEW(ge->ops.psf_mappings));
1217 gtk_list_store_clear(GTK_LIST_STORE(model));
1219 mappings = _bdf_psf_unpack_mapping(psf, &nmappings);
1222 * Add the mappings to the list.
1224 for (i = 0; i < nmappings; i++) {
1225 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
1226 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
1227 0, mappings[i], -1);
1229 free((char *) mappings);
1232 gtk_entry_set_text(GTK_ENTRY(ge->ops.psf_input), "");
1233 gtk_widget_set_sensitive(ge->ops.psf_add, FALSE);
1236 * Make the "Apply" button insensitive until the user has modified
1239 gtk_widget_set_sensitive(ge->ops.apply, FALSE);
1241 ge->ops.degrees_modified = ge->ops.resize_modified =
1242 ge->ops.psf_modified = FALSE;
1246 operations_dialog_setup(GlypheditRec *ge)
1248 GtkWidget *nb, *label, *button, *hbox, *vbox, *frame, *swin;
1249 GtkListStore *store;
1250 GtkTreeViewColumn *column;
1251 GtkCellRenderer *cell_renderer;
1252 GtkTreeSelection *sel;
1254 if (ge->ops.dialog != 0)
1258 * Create the pixbufs if necessary.
1261 lb_image = gdk_pixbuf_new_from_xpm_data(lb_xpm);
1263 rb_image = gdk_pixbuf_new_from_xpm_data(rb_xpm);
1265 as_image = gdk_pixbuf_new_from_xpm_data(as_xpm);
1267 ds_image = gdk_pixbuf_new_from_xpm_data(ds_xpm);
1269 ge->ops.dialog = gtk_dialog_new();
1270 g_signal_connect(G_OBJECT(ge->ops.dialog), "response",
1271 G_CALLBACK(apply_operations),
1272 GUINT_TO_POINTER(ge->id));
1274 * The "delete_event" handling in the dialog doesn't seem to be
1275 * working with GTK+ version 2.7.4.
1277 g_signal_connect(G_OBJECT(ge->ops.dialog), "delete_event",
1278 G_CALLBACK(gtk_widget_hide), 0);
1279 ge->ops.apply = gtk_dialog_add_button(GTK_DIALOG(ge->ops.dialog),
1281 GTK_RESPONSE_APPLY);
1282 gtk_widget_set_sensitive(ge->ops.apply, FALSE);
1283 button = gtk_dialog_add_button(GTK_DIALOG(ge->ops.dialog),
1285 GTK_RESPONSE_CLOSE);
1287 nb = ge->ops.notebook = gtk_notebook_new();
1290 * 1. Create the rotate/shear tab.
1292 frame = gtk_frame_new(0);
1293 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
1295 vbox = gtk_vbox_new(FALSE, 10);
1297 hbox = gtk_hbox_new(FALSE, 0);
1298 ge->ops.rotate = gtk_radio_button_new_with_label(0, "Rotate");
1299 g_signal_connect(G_OBJECT(ge->ops.rotate), "toggled",
1300 G_CALLBACK(set_rotate_limits), GUINT_TO_POINTER(ge->id));
1302 gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ge->ops.rotate),
1304 g_signal_connect(G_OBJECT(ge->ops.shear), "toggled",
1305 G_CALLBACK(set_shear_limits), GUINT_TO_POINTER(ge->id));
1307 gtk_box_pack_start(GTK_BOX(hbox), ge->ops.rotate, FALSE, FALSE, 2);
1308 gtk_box_pack_start(GTK_BOX(hbox), ge->ops.shear, FALSE, FALSE, 2);
1310 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1312 ge->ops.rotate_adj =
1313 (GtkAdjustment *) gtk_adjustment_new(0.0, -359.0, 359.0, 1.0,
1316 * Do this so the adjustment doesn't get unref'ed out of existence
1317 * until we explicitly get rid of it later.
1319 g_object_ref(G_OBJECT(ge->ops.rotate_adj));
1320 /*gtk_object_sink(GTK_OBJECT(ge->ops.rotate_adj));*/
1323 (GtkAdjustment *) gtk_adjustment_new(0.0, -20.0, 20.0, 1.0,
1326 * Do this so the adjustment doesn't get unref'ed out of existence
1327 * until we explicitly get rid of it later.
1329 g_object_ref(G_OBJECT(ge->ops.shear_adj));
1330 /*gtk_object_sink(GTK_OBJECT(ge->ops.shear_adj));*/
1332 hbox = gtk_hbox_new(FALSE, 0);
1333 label = gtk_label_new("Degrees:");
1334 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1336 ge->ops.degrees = gtk_widget_new(gtk_spin_button_get_type(),
1338 "adjustment", ge->ops.rotate_adj,
1344 g_signal_connect(G_OBJECT(ge->ops.degrees), "changed",
1345 G_CALLBACK(degrees_changed), GUINT_TO_POINTER(ge->id));
1347 gtk_box_pack_start(GTK_BOX(hbox), ge->ops.degrees, FALSE, FALSE, 0);
1349 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
1351 gtk_container_add(GTK_CONTAINER(frame), vbox);
1354 * Add the frame to a notebook page.
1356 gtk_notebook_append_page(GTK_NOTEBOOK(nb), frame,
1357 gtk_label_new("Rotate/Shear"));
1360 * 2. Create the resize font bounding box tab.
1362 vbox = gtk_vbox_new(TRUE, 0);
1364 frame = gtk_frame_new("Left and Right Bearing");
1366 hbox = gtk_hbox_new(TRUE, 0);
1367 gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
1369 ge->ops.lbearing = gtk_spin_button_new_with_range(0.0, 1000.0, 1.0);
1370 g_signal_connect(G_OBJECT(ge->ops.lbearing), "changed",
1371 G_CALLBACK(resize_changed), GUINT_TO_POINTER(ge->id));
1372 label = labcon_new_pixbuf_defaults(lb_image, ge->ops.lbearing, 0);
1373 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1375 ge->ops.rbearing = gtk_spin_button_new_with_range(0.0, 1000.0, 1.0);
1376 g_signal_connect(G_OBJECT(ge->ops.rbearing), "changed",
1377 G_CALLBACK(resize_changed), GUINT_TO_POINTER(ge->id));
1378 label = labcon_new_pixbuf_defaults(rb_image, ge->ops.rbearing, label);
1379 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1381 gtk_container_add(GTK_CONTAINER(frame), hbox);
1383 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
1385 frame = gtk_frame_new("Ascent and Descent");
1387 hbox = gtk_hbox_new(TRUE, 0);
1388 gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
1390 ge->ops.ascent = gtk_spin_button_new_with_range(0.0, 1000.0, 1.0);
1391 g_signal_connect(G_OBJECT(ge->ops.ascent), "changed",
1392 G_CALLBACK(resize_changed), GUINT_TO_POINTER(ge->id));
1393 label = labcon_new_pixbuf_defaults(as_image, ge->ops.ascent, label);
1394 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1396 ge->ops.descent = gtk_spin_button_new_with_range(0.0, 1000.0, 1.0);
1397 g_signal_connect(G_OBJECT(ge->ops.descent), "changed",
1398 G_CALLBACK(resize_changed), GUINT_TO_POINTER(ge->id));
1399 label = labcon_new_pixbuf_defaults(ds_image, ge->ops.descent, label);
1400 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1402 gtk_container_add(GTK_CONTAINER(frame), hbox);
1404 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
1406 gtk_notebook_append_page(GTK_NOTEBOOK(nb), vbox,
1407 gtk_label_new("Resize BBX"));
1410 * 3. Create the PSF Unicode mapping tab.
1412 vbox = gtk_vbox_new(FALSE, 0);
1414 swin = gtk_scrolled_window_new(0, 0);
1415 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
1416 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
1417 gtk_container_set_border_width(GTK_CONTAINER(swin), 3);
1419 store = gtk_list_store_new(1, G_TYPE_STRING);
1420 ge->ops.psf_mappings =
1421 gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1422 g_object_unref(store);
1424 gtk_widget_set_size_request(ge->ops.psf_mappings, 150, 150);
1425 gtk_container_add(GTK_CONTAINER(swin), ge->ops.psf_mappings);
1428 cell_renderer = gtk_cell_renderer_text_new();
1429 g_object_set(G_OBJECT(cell_renderer), "editable", TRUE, NULL);
1430 g_signal_connect_object(G_OBJECT(cell_renderer), "edited",
1431 G_CALLBACK(change_unimap), (gpointer) store,
1433 column = gtk_tree_view_column_new_with_attributes("Unicode Mappings",
1438 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1439 gtk_tree_view_append_column(GTK_TREE_VIEW(ge->ops.psf_mappings), column);
1440 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ge->ops.psf_mappings));
1442 gtk_box_pack_start(GTK_BOX(vbox), swin, FALSE, FALSE, 0);
1444 hbox = gtk_hbox_new(FALSE, 0);
1446 ge->ops.psf_delete = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1447 gtk_box_pack_end(GTK_BOX(hbox), ge->ops.psf_delete, FALSE, FALSE, 5);
1448 g_signal_connect(G_OBJECT(ge->ops.psf_delete), "clicked",
1449 G_CALLBACK(delete_unimap), GUINT_TO_POINTER(ge->id));
1451 ge->ops.psf_add = gtk_button_new_from_stock(GTK_STOCK_ADD);
1452 gtk_box_pack_end(GTK_BOX(hbox), ge->ops.psf_add, FALSE, FALSE, 0);
1453 g_signal_connect(G_OBJECT(ge->ops.psf_add), "clicked",
1454 G_CALLBACK(add_mapping), GUINT_TO_POINTER(ge->id));
1456 ge->ops.psf_input = gtk_widget_new(gtk_entry_get_type(),
1457 "max_length", 8, NULL);
1458 g_signal_connect(G_OBJECT(ge->ops.psf_input), "activate",
1459 G_CALLBACK(add_mapping), GUINT_TO_POINTER(ge->id));
1460 g_signal_connect(G_OBJECT(ge->ops.psf_input), "changed",
1461 G_CALLBACK(enable_add), GUINT_TO_POINTER(ge->id));
1462 gtk_box_pack_end(GTK_BOX(hbox), ge->ops.psf_input, FALSE, FALSE, 0);
1464 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1466 gtk_notebook_append_page(GTK_NOTEBOOK(nb), vbox,
1467 gtk_label_new("PSF Unicode Mappings"));
1469 ge->unimap_page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(nb), 2);
1470 if (glyphedit_get_spacing(GLYPHEDIT(ge->gedit)) != BDF_PROPORTIONAL)
1471 gtk_widget_set_sensitive(ge->unimap_page, TRUE);
1473 gtk_widget_set_sensitive(ge->unimap_page, FALSE);
1476 * 4. Add the notebook to the dialog.
1478 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(ge->ops.dialog)->vbox), nb);
1480 gtk_window_set_transient_for(GTK_WINDOW(ge->ops.dialog),
1481 GTK_WINDOW(ge->shell));
1482 gtk_widget_show_all(GTK_DIALOG(ge->ops.dialog)->vbox);
1483 gtk_widget_show_all(GTK_DIALOG(ge->ops.dialog)->action_area);
1487 show_rotate_dialog(GtkWidget *w, gpointer data)
1489 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1491 operations_dialog_setup(ge);
1492 operations_dialog_populate(ge);
1495 * Make sure we turn to the first notebook page.
1497 gtk_notebook_set_current_page(GTK_NOTEBOOK(ge->ops.notebook), 0);
1499 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ge->ops.rotate), TRUE);
1502 * Move the focus to the spin box.
1504 gtk_widget_grab_focus(ge->ops.degrees);
1506 gtk_widget_show(ge->ops.dialog);
1510 show_shear_dialog(GtkWidget *w, gpointer data)
1512 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1514 operations_dialog_setup(ge);
1515 operations_dialog_populate(ge);
1518 * Make sure we turn to the first notebook page.
1520 gtk_notebook_set_current_page(GTK_NOTEBOOK(ge->ops.notebook), 0);
1522 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ge->ops.shear), TRUE);
1525 * Move the focus to the spin box.
1527 gtk_widget_grab_focus(ge->ops.degrees);
1529 gtk_widget_show(ge->ops.dialog);
1533 show_resize_dialog(GtkWidget *w, gpointer data)
1535 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1537 operations_dialog_setup(ge);
1538 operations_dialog_populate(ge);
1541 * Make sure we turn to the first notebook page.
1543 gtk_notebook_set_current_page(GTK_NOTEBOOK(ge->ops.notebook), 1);
1546 * Move the focus to the first sensitive spin box.
1548 if (GTK_WIDGET_SENSITIVE(ge->ops.lbearing))
1549 gtk_widget_grab_focus(ge->ops.lbearing);
1551 gtk_widget_grab_focus(ge->ops.rbearing);
1553 gtk_widget_show(ge->ops.dialog);
1557 embolden_glyph(GtkWidget *w, gpointer data)
1559 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1561 glyphedit_embolden_glyph(GLYPHEDIT(ge->gedit));
1565 show_unimap_dialog(GtkWidget *w, gpointer data)
1567 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1569 operations_dialog_setup(ge);
1570 operations_dialog_populate(ge);
1572 gtk_notebook_set_current_page(GTK_NOTEBOOK(ge->ops.notebook), 2);
1575 * Move the focus to the input field.
1577 gtk_widget_grab_focus(ge->ops.psf_input);
1579 gtk_widget_show(ge->ops.dialog);
1583 make_ops_menu(GlypheditRec *ge, GtkWidget *menubar)
1585 GtkWidget *ops, *menu, *mitem, *sep;
1588 * Create the Operations menu.
1590 ops = gtk_menu_item_new_with_mnemonic("_Operations");
1592 ge->ops_menu = menu = gtk_menu_new();
1593 g_signal_connect(G_OBJECT(menu), "map_event",
1594 G_CALLBACK(operations_menu_up), GUINT_TO_POINTER(ge->id));
1595 g_signal_connect(G_OBJECT(menu), "unmap_event",
1596 G_CALLBACK(operations_menu_down),
1597 GUINT_TO_POINTER(ge->id));
1599 mitem = make_accel_menu_item(menu, "_Draw",
1600 "<Control>D", ge->ag);
1601 g_signal_connect(G_OBJECT(mitem), "activate",
1602 G_CALLBACK(draw_operation),
1603 GUINT_TO_POINTER(ge->id));
1605 mitem = make_accel_menu_item(menu, "_Move",
1606 "<Control>M", ge->ag);
1607 g_signal_connect(G_OBJECT(mitem), "activate",
1608 G_CALLBACK(move_operation),
1609 GUINT_TO_POINTER(ge->id));
1611 mitem = make_accel_menu_item(menu, "_Copy",
1612 "<Control>Y", ge->ag);
1613 g_signal_connect(G_OBJECT(mitem), "activate",
1614 G_CALLBACK(copy_operation),
1615 GUINT_TO_POINTER(ge->id));
1620 sep = gtk_menu_item_new();
1621 gtk_widget_set_sensitive(sep, FALSE);
1622 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1624 mitem = make_accel_menu_item(menu, "_Rotate",
1625 "<Control>T", ge->ag);
1626 g_signal_connect(G_OBJECT(mitem), "activate",
1627 G_CALLBACK(show_rotate_dialog),
1628 GUINT_TO_POINTER(ge->id));
1630 mitem = make_accel_menu_item(menu, "_Shear",
1631 "<Control>E", ge->ag);
1632 g_signal_connect(G_OBJECT(mitem), "activate",
1633 G_CALLBACK(show_shear_dialog),
1634 GUINT_TO_POINTER(ge->id));
1636 mitem = make_accel_menu_item(menu, "_Embolden",
1637 "<Control>H", ge->ag);
1638 g_signal_connect(G_OBJECT(mitem), "activate",
1639 G_CALLBACK(embolden_glyph),
1640 GUINT_TO_POINTER(ge->id));
1642 gtk_menu_item_set_submenu(GTK_MENU_ITEM(ops), menu);
1647 sep = gtk_menu_item_new();
1648 gtk_widget_set_sensitive(sep, FALSE);
1649 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
1651 ge->resize = make_accel_menu_item(menu, "_Resize BBX",
1652 "<Control>R", ge->ag);
1653 g_signal_connect(G_OBJECT(ge->resize), "activate",
1654 G_CALLBACK(show_resize_dialog),
1655 GUINT_TO_POINTER(ge->id));
1657 ge->unimap = make_accel_menu_item(menu, "Edit PSF Unicode _Mappings",
1658 "<Control>F", ge->ag);
1659 g_signal_connect(G_OBJECT(ge->unimap), "activate",
1660 G_CALLBACK(show_unimap_dialog),
1661 GUINT_TO_POINTER(ge->id));
1667 pointer_moved(GtkWidget *w, gpointer cb, gpointer ged)
1669 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(ged);
1670 GlypheditSignalInfo *si = (GlypheditSignalInfo *) cb;
1671 bdf_glyph_grid_t *g;
1673 g = glyphedit_get_grid(GLYPHEDIT(ge->gedit));
1674 if (g->bpp == 1 || si->color == 0)
1675 sprintf(buffer1, "(%d,%d)", si->x, si->y);
1679 sprintf(buffer1, "(%d,%d,%d)", si->x, si->y,
1680 options.colors[si->color-1]);
1683 sprintf(buffer1, "(%d,%d,%d)", si->x, si->y,
1684 options.colors[si->color+4-1]);
1687 sprintf(buffer1, "(%d,%d,%d)", si->x, si->y, si->color);
1692 gtk_label_set_text(GTK_LABEL(ge->coords), buffer1);
1696 * Under certain circumstances, the glyphedit widget causes the operation to
1697 * change. Basically, when a bitmap is pasted, the widget goes into a MOVE
1698 * operation. All the operations are handled here just in case of future
1702 operation_changed(GtkWidget *w, gpointer cb, gpointer ged)
1704 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(ged);
1705 GlypheditSignalInfo *si = (GlypheditSignalInfo *) cb;
1707 if (si->operation == GLYPHEDIT_DRAW)
1708 gecontrol_change_operation(GECONTROL(ge->gectrl), GECONTROL_DRAW);
1709 else if (si->operation == GLYPHEDIT_MOVE)
1710 gecontrol_change_operation(GECONTROL(ge->gectrl), GECONTROL_MOVE);
1711 else if (si->operation == GLYPHEDIT_COPY)
1712 gecontrol_change_operation(GECONTROL(ge->gectrl), GECONTROL_COPY);
1716 color_changed(GtkWidget *w, gpointer cb, gpointer ged)
1718 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(ged);
1719 GlypheditSignalInfo *si = (GlypheditSignalInfo *) cb;
1721 gecontrol_change_color(GECONTROL(ge->gectrl), si->color);
1725 glyph_modified(GtkWidget *w, gpointer cb, gpointer ged)
1727 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(ged);
1728 gbdfed_editor_t *ed = editors + ge->owner;
1729 GlypheditSignalInfo *si = (GlypheditSignalInfo *) cb;
1730 gchar *prgname = g_get_prgname();
1732 if (si->metrics == 0)
1736 sprintf(buffer1, "%s - Glyph Edit: (unnamed%d) [modified]",
1739 sprintf(buffer1, "%s - Glyph Edit: %s [modified]", prgname, ed->file);
1741 gtk_window_set_title(GTK_WINDOW(ge->shell), buffer1);
1743 sprintf(buffer1, "width %hd height %hd\nascent %hd descent %hd",
1744 si->metrics->width, si->metrics->height,
1745 si->metrics->ascent, si->metrics->descent);
1746 gtk_label_set_text(GTK_LABEL(ge->metrics), buffer1);
1748 if (si->metrics->font_spacing == BDF_PROPORTIONAL) {
1749 sprintf(buffer1, "%hd", si->metrics->dwidth);
1750 g_signal_handler_block(G_OBJECT(ge->dwidth), ge->handler);
1751 gtk_entry_set_text(GTK_ENTRY(ge->dwidth), buffer1);
1752 g_signal_handler_unblock(G_OBJECT(ge->dwidth), ge->handler);
1756 * Update the glyph image on the Glyphedit control widget.
1758 gecontrol_update_glyph_image(GECONTROL(ge->gectrl), si->image);
1760 gtk_widget_set_sensitive(ge->update, TRUE);
1761 gtk_widget_set_sensitive(ge->update_next, TRUE);
1762 gtk_widget_set_sensitive(ge->update_prev, TRUE);
1763 gtk_widget_set_sensitive(ge->button_update, TRUE);
1764 gtk_widget_set_sensitive(ge->button_next, TRUE);
1765 gtk_widget_set_sensitive(ge->button_prev, TRUE);
1769 * This function will be a bit screwy until I can figure out how to make a
1770 * signal pass an enum as the first param after the widget.
1773 gectrl_activate(GtkWidget *w, gpointer info, gpointer data)
1775 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1776 GEControlActivateInfo *ai = (GEControlActivateInfo *) info;
1778 switch (ai->operation) {
1779 case GECONTROL_DRAW:
1780 glyphedit_change_operation(GLYPHEDIT(ge->gedit), GLYPHEDIT_DRAW);
1782 case GECONTROL_MOVE:
1783 glyphedit_change_operation(GLYPHEDIT(ge->gedit), GLYPHEDIT_MOVE);
1785 case GECONTROL_COPY:
1786 glyphedit_change_operation(GLYPHEDIT(ge->gedit), GLYPHEDIT_COPY);
1788 case GECONTROL_FLIP_HORIZONTAL:
1789 glyphedit_flip_glyph(GLYPHEDIT(ge->gedit), GTK_ORIENTATION_HORIZONTAL);
1791 case GECONTROL_FLIP_VERTICAL:
1792 glyphedit_flip_glyph(GLYPHEDIT(ge->gedit), GTK_ORIENTATION_VERTICAL);
1794 case GECONTROL_SHEAR:
1795 show_shear_dialog(w, data);
1797 case GECONTROL_ROTATE_LEFT_90:
1798 glyphedit_rotate_glyph(GLYPHEDIT(ge->gedit), -90);
1800 case GECONTROL_ROTATE_RIGHT_90:
1801 glyphedit_rotate_glyph(GLYPHEDIT(ge->gedit), 90);
1803 case GECONTROL_ROTATE:
1804 show_rotate_dialog(w, data);
1806 case GECONTROL_SHIFT_UP_LEFT:
1807 glyphedit_shift_glyph(GLYPHEDIT(ge->gedit), -1, -1);
1809 case GECONTROL_SHIFT_UP:
1810 glyphedit_shift_glyph(GLYPHEDIT(ge->gedit), 0, -1);
1812 case GECONTROL_SHIFT_UP_RIGHT:
1813 glyphedit_shift_glyph(GLYPHEDIT(ge->gedit), 1, -1);
1815 case GECONTROL_SHIFT_LEFT:
1816 glyphedit_shift_glyph(GLYPHEDIT(ge->gedit), -1, 0);
1818 case GECONTROL_SHIFT_RIGHT:
1819 glyphedit_shift_glyph(GLYPHEDIT(ge->gedit), 1, 0);
1821 case GECONTROL_SHIFT_DOWN_LEFT:
1822 glyphedit_shift_glyph(GLYPHEDIT(ge->gedit), -1, 1);
1824 case GECONTROL_SHIFT_DOWN:
1825 glyphedit_shift_glyph(GLYPHEDIT(ge->gedit), 0, 1);
1827 case GECONTROL_SHIFT_DOWN_RIGHT:
1828 glyphedit_shift_glyph(GLYPHEDIT(ge->gedit), 1, 1);
1830 case GECONTROL_COLOR_CHANGE:
1831 glyphedit_set_color(GLYPHEDIT(ge->gedit), ai->color);
1837 * This is called when the device width field is changed in any way.
1840 enable_update(GtkWidget *w, gpointer data)
1842 GlypheditRec *ge = glyph_editors + GPOINTER_TO_UINT(data);
1843 gbdfed_editor_t *ed = editors + ge->owner;
1846 sprintf(buffer1, "%s - Glyph Edit: (unnamed%d) [modified]",
1847 g_get_prgname(), ed->id);
1849 sprintf(buffer1, "%s - Glyph Edit: %s [modified]",
1850 g_get_prgname(), ed->file);
1852 gtk_window_set_title(GTK_WINDOW(ge->shell), buffer1);
1853 gtk_widget_set_sensitive(ge->update, TRUE);
1854 gtk_widget_set_sensitive(ge->update_next, TRUE);
1855 gtk_widget_set_sensitive(ge->update_prev, TRUE);
1856 gtk_widget_set_sensitive(ge->button_update, TRUE);
1860 _guigedit_build_editor(GlypheditRec *ge, bdf_glyph_grid_t *grid, guint base,
1861 gbdfed_editor_t *ed)
1863 GtkWidget *mb, *mitem, *frame, *vbox, *vbox1, *hbox, *img;
1867 sprintf(buffer1, "%s - Glyph Edit: (unnamed%d)", g_get_prgname(),
1870 sprintf(buffer1, "%s - Glyph Edit: %s", g_get_prgname(), ed->file);
1872 ge->shell = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1874 gtk_window_set_title(GTK_WINDOW(ge->shell), buffer1);
1876 gtk_window_set_resizable(GTK_WINDOW(ge->shell), TRUE);
1878 (void) g_signal_connect(G_OBJECT(ge->shell), "destroy_event",
1879 G_CALLBACK(close_glyph_editor),
1880 GUINT_TO_POINTER(ge->id));
1881 (void) g_signal_connect(G_OBJECT(ge->shell), "delete_event",
1882 G_CALLBACK(close_glyph_editor),
1883 GUINT_TO_POINTER(ge->id));
1885 vbox = gtk_vbox_new(FALSE, 0);
1886 gtk_container_add(GTK_CONTAINER(ge->shell), vbox);
1888 ge->ag = gtk_accel_group_new();
1890 mb = gtk_menu_bar_new();
1891 mitem = make_file_menu(ge, mb);
1892 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1894 mitem = make_edit_menu(ge, mb);
1895 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1897 mitem = make_ops_menu(ge, mb);
1898 gtk_menu_shell_append(GTK_MENU_SHELL(mb), mitem);
1900 gtk_box_pack_start(GTK_BOX(vbox), mb, FALSE, TRUE, 0);
1903 * Attach the accelerators to the editor.
1905 gtk_window_add_accel_group(GTK_WINDOW(ge->shell), ge->ag);
1908 * 1. Add the glyph name, next/previous buttons and encoding widgets.
1910 frame = gtk_frame_new(0);
1911 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
1912 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0);
1914 vbox1 = gtk_vbox_new(TRUE, 0);
1915 gtk_container_add(GTK_CONTAINER(frame), vbox1);
1917 hbox = gtk_hbox_new(FALSE, 0);
1918 gtk_box_pack_start(GTK_BOX(vbox1), hbox, TRUE, TRUE, 0);
1920 ge->name = gtk_widget_new(gtk_entry_get_type(), "max_length", 128, NULL);
1921 mitem = labcon_new_label_defaults("Glyph Name:", ge->name, 0);
1922 gtk_box_pack_start(GTK_BOX(hbox), mitem, TRUE, TRUE, 0);
1925 ge->button_update = gtk_button_new();
1926 guiutil_util_set_tooltip(ge->button_update, "Update Font");
1927 img = gtk_image_new_from_stock(GTK_STOCK_APPLY, GTK_ICON_SIZE_SMALL_TOOLBAR);
1928 gtk_button_set_image(GTK_BUTTON(ge->button_update), img);
1929 g_signal_connect(G_OBJECT(ge->button_update), "clicked",
1930 G_CALLBACK(update_font), NULL);
1931 gtk_box_pack_start(GTK_BOX(hbox), ge->button_update, FALSE, FALSE, 0);
1933 /* Previous button */
1934 ge->button_prev = gtk_button_new();
1935 guiutil_util_set_tooltip(ge->button_prev, "Previous Glyph");
1936 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PREVIOUS,
1937 GTK_ICON_SIZE_SMALL_TOOLBAR);
1938 gtk_button_set_image(GTK_BUTTON(ge->button_prev), img);
1939 g_signal_connect(G_OBJECT(ge->button_prev), "clicked",
1940 G_CALLBACK(previous_glyph), NULL);
1941 gtk_box_pack_start(GTK_BOX(hbox), ge->button_prev, FALSE, FALSE, 0);
1944 ge->button_next = gtk_button_new();
1945 guiutil_util_set_tooltip(ge->button_next, "Next Glyph");
1946 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_NEXT,
1947 GTK_ICON_SIZE_SMALL_TOOLBAR);
1948 gtk_button_set_image(GTK_BUTTON(ge->button_next), img);
1949 g_signal_connect(G_OBJECT(ge->button_next), "clicked",
1950 G_CALLBACK(next_glyph), NULL);
1951 gtk_box_pack_start(GTK_BOX(hbox), ge->button_next, FALSE, FALSE, 0);
1954 ge->encoding = gtk_label_new("0000");
1955 gtk_misc_set_alignment(GTK_MISC(ge->encoding), 0.0, 0.5);
1956 mitem = labcon_new_label_defaults("Encoding:", ge->encoding, mitem);
1957 gtk_box_pack_start(GTK_BOX(vbox1), mitem, TRUE, TRUE, 0);
1960 * 2. Add the device width and metrics widgets.
1962 frame = gtk_frame_new(0);
1963 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
1964 gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0);
1966 vbox1 = gtk_vbox_new(FALSE, 5);
1967 gtk_container_add(GTK_CONTAINER(frame), vbox1);
1969 ge->dwidth = gtk_widget_new(gtk_entry_get_type(),
1972 ge->handler = g_signal_connect(G_OBJECT(ge->dwidth), "changed",
1973 G_CALLBACK(enable_update),
1974 GUINT_TO_POINTER(ge->id));
1975 mitem = labcon_new_label_defaults("Device Width:", ge->dwidth, mitem);
1976 gtk_box_pack_start(GTK_BOX(vbox1), mitem, TRUE, TRUE, 0);
1978 ge->metrics = gtk_label_new("width 0 height 0\r\nascent 0 descent 0");
1979 gtk_misc_set_alignment(GTK_MISC(ge->metrics), 0.0, 0.5);
1980 mitem = labcon_new_label_defaults("Metrics:", ge->metrics, mitem);
1981 gtk_box_pack_start(GTK_BOX(vbox1), mitem, TRUE, TRUE, 0);
1983 hbox = gtk_hbox_new(FALSE, 0);
1985 vbox1 = gtk_vbox_new(FALSE, 0);
1988 * Create the coordinates label.
1990 ge->coords = gtk_label_new("(0,0)");
1991 gtk_misc_set_alignment(GTK_MISC(ge->coords), 0.5, 0.5);
1992 gtk_box_pack_start(GTK_BOX(vbox1), ge->coords, FALSE, TRUE, 0);
1995 * Create the glyph editor.
1997 ge->gedit = glyphedit_newv(grid, options.pixel_size, options.show_x_height,
1998 options.show_cap_height, options.colors);
1999 g_signal_connect(G_OBJECT(ge->gedit), "glyph-modified",
2000 G_CALLBACK(glyph_modified), GUINT_TO_POINTER(ge->id));
2001 g_signal_connect(G_OBJECT(ge->gedit), "pointer-moved",
2002 G_CALLBACK(pointer_moved), GUINT_TO_POINTER(ge->id));
2003 g_signal_connect(G_OBJECT(ge->gedit), "operation-change",
2004 G_CALLBACK(operation_changed), GUINT_TO_POINTER(ge->id));
2005 g_signal_connect(G_OBJECT(ge->gedit), "color-change",
2006 G_CALLBACK(color_changed), GUINT_TO_POINTER(ge->id));
2007 gtk_box_pack_start(GTK_BOX(vbox1), ge->gedit, TRUE, TRUE, 0);
2009 gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);
2011 vbox1 = gtk_vbox_new(FALSE, 0);
2013 ge->gectltips = gtk_label_new("");
2014 gtk_misc_set_alignment(GTK_MISC(ge->gectltips), 0.5, 0.5);
2015 gtk_box_pack_start(GTK_BOX(vbox1), ge->gectltips, FALSE, TRUE, 0);
2018 * Get the initial glyph image.
2020 glyphedit_get_image(GLYPHEDIT(ge->gedit), &image);
2021 ge->gectrl = gecontrol_newv(ge->gectltips, &image, options.colors);
2022 if (image.bytes > 0)
2024 g_signal_connect(G_OBJECT(ge->gectrl), "activate",
2025 G_CALLBACK(gectrl_activate), GUINT_TO_POINTER(ge->id));
2027 gtk_box_pack_start(GTK_BOX(vbox1), ge->gectrl, TRUE, TRUE, 0);
2029 gtk_box_pack_start(GTK_BOX(hbox), vbox1, FALSE, TRUE, 0);
2031 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
2035 guigedit_edit_glyph(gbdfed_editor_t *ed, FontgridSelectionInfo *si)
2040 bdf_glyph_grid_t *grid;
2043 font = fontgrid_get_font(FONTGRID(ed->fgrid));
2044 base = fontgrid_get_code_base(FONTGRID(ed->fgrid));
2047 grid = bdf_make_glyph_grid(font, si->start, 1);
2049 grid = bdf_make_glyph_grid(font, si->start, 0);
2051 ge = _guigedit_get_glyph_editor(ed->id);
2053 if (ge->name == 0) {
2054 _guigedit_build_editor(ge, grid, base, ed);
2057 sprintf(buffer1, "%s - Glyph Edit: (unnamed%d)", g_get_prgname(),
2060 sprintf(buffer1, "%s - Glyph Edit: %s", g_get_prgname(), ed->file);
2062 gtk_window_set_title(GTK_WINDOW(ge->shell), buffer1);
2063 glyphedit_set_grid(GLYPHEDIT(ge->gedit), grid);
2066 * Update the image in the glypheditor control panel.
2069 bdf_grid_image(grid, &image);
2070 gecontrol_set_glyph_image(GECONTROL(ge->gectrl), &image);
2071 if (image.bytes > 0)
2074 gecontrol_set_glyph_image(GECONTROL(ge->gectrl), 0);
2077 * Make sure the control has the most current list of colors.
2079 gecontrol_set_color_list(GECONTROL(ge->gectrl), options.colors);
2083 * Update the text fields and labels with the glyph info.
2085 gtk_entry_set_text(GTK_ENTRY(ge->name), grid->name);
2086 if (grid->unencoded)
2087 sprintf(buffer1, "-1");
2090 case 8: sprintf(buffer1, "%o", grid->encoding); break;
2091 case 10: sprintf(buffer1, "%d", grid->encoding); break;
2092 case 16: sprintf(buffer1, "%04X", grid->encoding); break;
2095 gtk_label_set_text(GTK_LABEL(ge->encoding), buffer1);
2097 gtk_widget_set_sensitive(ge->dwidth, TRUE);
2098 sprintf(buffer1, "%hd", grid->dwidth);
2100 g_signal_handler_block(G_OBJECT(ge->dwidth), ge->handler);
2101 gtk_entry_set_text(GTK_ENTRY(ge->dwidth), buffer1);
2102 g_signal_handler_unblock(G_OBJECT(ge->dwidth), ge->handler);
2104 if (grid->spacing != BDF_PROPORTIONAL)
2105 gtk_widget_set_sensitive(ge->dwidth, FALSE);
2107 sprintf(buffer1, "width %hd height %hd\r\nascent %hd descent %hd",
2108 grid->glyph_bbx.width, grid->glyph_bbx.height,
2109 grid->glyph_bbx.ascent, grid->glyph_bbx.descent);
2110 gtk_label_set_text(GTK_LABEL(ge->metrics), buffer1);
2112 if (grid->modified) {
2113 gtk_widget_set_sensitive(ge->update, TRUE);
2114 gtk_widget_set_sensitive(ge->button_update, TRUE);
2115 gtk_widget_set_sensitive(ge->update_next, TRUE);
2116 gtk_widget_set_sensitive(ge->update_prev, TRUE);
2118 gtk_widget_set_sensitive(ge->update, FALSE);
2119 gtk_widget_set_sensitive(ge->button_update, FALSE);
2120 gtk_widget_set_sensitive(ge->update_next, FALSE);
2121 gtk_widget_set_sensitive(ge->update_prev, FALSE);
2125 * Set the sensitivity of the next and previous buttons.
2127 if (glyphedit_get_encoding(GLYPHEDIT(ge->gedit)) == 0)
2128 gtk_widget_set_sensitive(ge->button_prev, FALSE);
2130 gtk_widget_set_sensitive(ge->button_prev, TRUE);
2132 if (glyphedit_get_encoding(GLYPHEDIT(ge->gedit)) == 0xffff)
2133 gtk_widget_set_sensitive(ge->button_next, FALSE);
2135 gtk_widget_set_sensitive(ge->button_next, TRUE);
2137 gtk_widget_show_all(ge->shell);
2140 * Force the focus to be on the glyph grid.
2142 gtk_widget_grab_focus(ge->gedit);
2146 * Routine to set the show_cap_height value for all the glyph editors.
2149 guigedit_show_cap_height(gboolean show)
2153 for (i = 0; i < num_glyph_editors; i++) {
2154 if (glyph_editors[i].owner != ~0)
2155 glyphedit_set_show_cap_height(GLYPHEDIT(glyph_editors[i].gedit),
2161 * Routine to set the show_cap_height value for all the glyph editors.
2164 guigedit_show_x_height(gboolean show)
2168 for (i = 0; i < num_glyph_editors; i++) {
2169 if (glyph_editors[i].owner != ~0)
2170 glyphedit_set_show_x_height(GLYPHEDIT(glyph_editors[i].gedit), show);
2175 * Routine to set the pixel size on all of the visible editors.
2178 guigedit_set_pixel_size(guint pixel_size)
2182 for (i = 0; i < num_glyph_editors; i++) {
2183 if (glyph_editors[i].owner != ~0)
2184 glyphedit_set_pixel_size(GLYPHEDIT(glyph_editors[i].gedit),
2190 * Routine to set the spacing and device width on all of the visible editors.
2193 guigedit_set_font_spacing(gint spacing, guint16 monowidth)
2197 for (i = 0; i < num_glyph_editors; i++) {
2198 if (glyph_editors[i].owner != ~0)
2199 glyphedit_set_spacing(GLYPHEDIT(glyph_editors[i].gedit), spacing,
2205 * Routine to set the code base on all the glyph editors that are active.
2208 guigedit_set_code_base(gint base)
2212 for (i = 0; i < num_glyph_editors; i++) {
2213 if (glyph_editors[i].owner != ~0) {
2214 enc = (guint) glyphedit_get_encoding(GLYPHEDIT(glyph_editors[i].gedit));
2217 sprintf(buffer1, "%o", enc);
2220 sprintf(buffer1, "%d", enc);
2223 sprintf(buffer1, "%04X", enc);
2226 gtk_label_set_text(GTK_LABEL(glyph_editors[i].encoding), buffer1);
2232 * Routine to clean up everything that was allocated here.
2235 guigedit_cleanup(void)
2240 * Cycle through all the glyph editors and check if they have been
2241 * modified and if they need to be saved.
2243 for (i = 0; i < num_glyph_editors; i++) {
2244 if (glyph_editors[i].id != ~0)
2245 close_glyph_editor(0, 0, GUINT_TO_POINTER(i));
2249 * Unreference all the pixbufs so they go away.
2252 g_object_unref(G_OBJECT(lb_image));
2254 g_object_unref(G_OBJECT(rb_image));
2256 g_object_unref(G_OBJECT(as_image));
2258 g_object_unref(G_OBJECT(ds_image));
2260 lb_image = rb_image = as_image = ds_image = 0;
2263 * GTK will take care of the widgets in the glyph editors.
2265 if (num_glyph_editors > 0)
2266 g_free(glyph_editors);