]> git.karo-electronics.de Git - gbdfed.git/blob - guihelp.c
Fixup several compile faults due to changes in recent distributions,
[gbdfed.git] / guihelp.c
1 /*
2  * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include "gbdfed.h"
24 #include "htext.h"
25
26 static GtkWidget *help_dialog;
27 static GtkWidget *help_text;
28 static GtkWidget *help_topics;
29
30 typedef struct {
31     int mnemonic;
32     gchar *help_topic;
33     gchar *help_text;
34 } helpmap_t;
35
36 static helpmap_t topics[] = {
37     {'A', "About",               0},
38     {'P', "The Program",         0},
39     {'F', "Font Grid",           0},
40     {'G', "Glyph Editor",        0},
41     {'C', "Configuration File",  0},
42     {'r', "Preferences Dialog",  0},
43     {'W', "Windows Font Notes",  0},
44     {'O', "OpenType Font Notes", 0},
45     {'P', "PSF Font Notes",      0},
46     {'H', "HEX Font Notes",      0},
47     {'o', "Color Notes",         0},
48     {'i', "Tips",                0},
49 };
50
51 static guint ntopics = sizeof(topics) / sizeof(topics[0]);
52
53 /**************************************************************
54  *
55  * Routines for parsing the markup for the help text buffer.
56  *
57  **************************************************************/
58
59 #define HTEXT_BULLET 0x0001
60 #define HTEXT_UL     0x0002
61
62 typedef struct {
63     guint flags;
64     GtkTextBuffer *text;
65     const gchar *tag_name;
66     GtkTextIter iter;
67 } htext_parse_t;
68
69 static htext_parse_t hp;
70
71 static const gchar *bullet = "•";
72
73 void
74 help_parse_start(GMarkupParseContext *ctx, const gchar *tag,
75                  const gchar **attr_names, const gchar **attr_vals,
76                  gpointer data, GError **err)
77 {
78     if (strcmp(tag, "bullet") == 0) {
79         gtk_text_buffer_insert_with_tags_by_name(hp.text, &hp.iter,
80                                                  bullet, 3,
81                                                  "margin",
82                                                  "large_bullet", NULL);
83         hp.flags |= HTEXT_BULLET;
84         hp.tag_name = 0;
85     } else if (strcmp(tag, "help") == 0)
86       hp.tag_name = 0;
87     else
88       hp.tag_name = tag;
89 }
90
91 void
92 help_parse_text(GMarkupParseContext *ctx, const gchar *txt, gsize txtlen,
93                 gpointer data, GError **err)
94 {
95     if (hp.tag_name != 0)
96       gtk_text_buffer_insert_with_tags_by_name(hp.text, &hp.iter,
97                                                txt, txtlen,
98                                                hp.tag_name, NULL);
99     else {
100         if (hp.flags & HTEXT_BULLET)
101           gtk_text_buffer_insert_with_tags_by_name(hp.text, &hp.iter,
102                                                    txt, txtlen,
103                                                    "tabs", NULL);
104         else
105           /*
106            * Plain text insert.
107            */
108           gtk_text_buffer_insert(hp.text, &hp.iter, txt, txtlen);
109     }
110 }
111
112 void
113 help_parse_end(GMarkupParseContext *ctx, const gchar *tag,
114                gpointer data, GError **err)
115 {
116     if (strcmp(tag, "bullet") == 0)
117       hp.flags &= ~HTEXT_BULLET;
118     hp.tag_name = 0;
119 }
120
121 void
122 help_parse_error(GMarkupParseContext *ctx, GError *err, gpointer data)
123 {
124 }
125
126 static GMarkupParser markup_funcs = {
127     help_parse_start,
128     help_parse_end,
129     help_parse_text,
130     0,
131     help_parse_error,
132 };
133
134 static GMarkupParseContext *markup_context = NULL;
135
136 /*
137  * Creates all the markup tags.
138  */
139 static void
140 help_init_markup(void)
141 {
142     PangoTabArray *tabs;
143
144     gtk_text_buffer_create_tag(hp.text, "center",
145                                "justification", GTK_JUSTIFY_CENTER, NULL);
146     gtk_text_buffer_create_tag(hp.text, "margin",
147                                "left_margin", 20, NULL);
148     gtk_text_buffer_create_tag(hp.text, "margin1",
149                                "left_margin", 30, NULL);
150     gtk_text_buffer_create_tag(hp.text, "margin2",
151                                "left_margin", 45, NULL);
152     gtk_text_buffer_create_tag(hp.text, "margin1.5",
153                                "left_margin", 30,
154                                "weight", PANGO_WEIGHT_BOLD,
155                                NULL);
156     gtk_text_buffer_create_tag(hp.text, "margin3",
157                                "left_margin", 60, NULL);
158     gtk_text_buffer_create_tag(hp.text, "large_bullet",
159                                "scale", PANGO_SCALE_X_LARGE, NULL);
160     gtk_text_buffer_create_tag(hp.text, "param",
161                                "weight", PANGO_WEIGHT_BOLD,
162                                "left_margin", 10, NULL);
163     gtk_text_buffer_create_tag(hp.text, "ul",
164                                "underline", PANGO_UNDERLINE_SINGLE, NULL);
165     gtk_text_buffer_create_tag(hp.text, "bul",
166                                "underline", PANGO_UNDERLINE_SINGLE,
167                                "weight", PANGO_WEIGHT_BOLD, NULL);
168
169     tabs = pango_tab_array_new_with_positions(2, TRUE,
170                                               PANGO_TAB_LEFT, 50,
171                                               PANGO_TAB_LEFT, 70);
172     gtk_text_buffer_create_tag(hp.text, "tabs",
173                                "tabs", tabs,
174                                "left_margin", 10,
175                                NULL);
176
177     gtk_text_buffer_create_tag(hp.text, "i",
178                                "style", PANGO_STYLE_ITALIC, NULL);
179     gtk_text_buffer_create_tag(hp.text, "b",
180                                "weight", PANGO_WEIGHT_BOLD, NULL);
181     gtk_text_buffer_create_tag(hp.text, "bi",
182                                "style", PANGO_STYLE_ITALIC,
183                                "weight", PANGO_WEIGHT_BOLD, NULL);
184 }
185
186 /**************************************************************
187  *
188  * API functions.
189  *
190  **************************************************************/
191
192 static void
193 help_free_list_item(gpointer data, gpointer user_data)
194 {
195     gtk_tree_path_free((GtkTreePath *) data);
196 }
197
198 static void
199 help_on(GtkTreeSelection *sel, gpointer data)
200 {
201     GList *rowlist;
202     gint row = 1, *rows;
203     GError *err = 0;
204
205     /*
206      * Because this is called before the help text widget is created,
207      * simply return if the help text widget is NULL.
208      */
209     if (help_text == 0)
210       return;
211
212     /*
213      * Sorta complicated, but can't see any other way around it at the moment
214      * with gtk 2.2.4.
215      */
216     rowlist = gtk_tree_selection_get_selected_rows(sel, NULL);
217     rows =
218         gtk_tree_path_get_indices((GtkTreePath *) g_list_nth_data(rowlist, 0));
219     row = rows[0];
220
221     /*
222      * Clear out the rows that were returned.
223      */
224     g_list_foreach(rowlist, help_free_list_item, 0);
225
226     /*
227      * Set the dialog title.
228      */
229     sprintf(buffer1, "Help: %s", topics[row].help_topic);
230     gtk_window_set_title(GTK_WINDOW(help_dialog), buffer1);
231
232     /*
233      * Clear the text buffer.
234      */
235     gtk_text_buffer_set_text(hp.text, "", 0);
236
237     /*
238      * Get the iterator at the start of the buffer.
239      */
240     gtk_text_buffer_get_start_iter(hp.text, &hp.iter);
241
242     /*
243      * Parse the help text.
244      */
245     if (g_markup_parse_context_parse(markup_context,
246                                      topics[row].help_text, -1, &err) == FALSE)
247       fprintf(stderr, "guihelp.c:%s\n", err->message);
248 }
249
250 void
251 guihelp_show_help(GtkWidget *w, gpointer data)
252 {
253     guint i;
254     GtkWidget *hbox, *sw, *button;
255     GtkTextBuffer *text;
256     GtkListStore *store;
257     GtkTreeViewColumn *column;
258     GtkCellRenderer *cell_renderer;
259     GtkTreeSelection *sel;
260     GtkTreePath *tpath;
261     GtkTreeIter iter;
262
263     if (help_dialog == 0) {
264         /*
265          * Store the help text into the array.
266          */
267         topics[GUIHELP_ABOUT].help_text = about_text;
268         topics[GUIHELP_PROGRAM].help_text = program_text;
269         topics[GUIHELP_FONTGRID].help_text = fgrid_text;
270         topics[GUIHELP_GLYPH_EDITOR].help_text = gedit_text;
271         topics[GUIHELP_CONFIG_FILE].help_text = conf_text;
272         topics[GUIHELP_PREFERENCES].help_text = preferences_text;
273         topics[GUIHELP_FNT].help_text = fnt_text;
274         topics[GUIHELP_OTF].help_text = otf_text;
275         topics[GUIHELP_PSF].help_text = psf_text;
276         topics[GUIHELP_HEX].help_text = hex_text;
277         topics[GUIHELP_COLOR].help_text = color_text;
278         topics[GUIHELP_TIPS].help_text = tips_text;
279
280         help_dialog = gtk_dialog_new();
281
282         /*
283          * Force the help dialog to center over the first editor that
284          * was created.
285          */
286         (void) g_signal_connect(G_OBJECT(help_dialog), "delete_event",
287                                 G_CALLBACK(gtk_widget_hide), NULL);
288
289         hbox = gtk_hbox_new(FALSE, 5);
290
291         /*
292          * Create the list that will be used for the help topics.
293          */
294         store = gtk_list_store_new(1, G_TYPE_STRING);
295
296         /*
297          * Add the topics to the list.
298          */
299         for (i = 0; i < ntopics; i++) {
300             gtk_list_store_append(store, &iter);
301             gtk_list_store_set(store, &iter, 0, topics[i].help_topic, -1);
302         }
303         help_topics = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
304
305         cell_renderer = gtk_cell_renderer_text_new();
306         column = gtk_tree_view_column_new_with_attributes ("Help Topics",
307                                                            cell_renderer,
308                                                            "text", 0,
309                                                            NULL);
310         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
311         gtk_tree_view_append_column (GTK_TREE_VIEW(help_topics), column);
312
313         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(help_topics));
314         gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
315
316         (void) g_signal_connect(G_OBJECT(sel), "changed",
317                                 G_CALLBACK(help_on), NULL);
318
319         gtk_box_pack_start(GTK_BOX(hbox), help_topics, FALSE, FALSE, 0);
320
321         g_object_unref(store);
322
323         gtk_box_pack_start(GTK_BOX(hbox), gtk_vseparator_new(),
324                            FALSE, FALSE, 0);
325
326         /*
327          * Create the text widget that will display the help text.
328          */
329         sw = gtk_scrolled_window_new(NULL, NULL);
330         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
331                                        GTK_POLICY_NEVER,
332                                        GTK_POLICY_ALWAYS);
333
334         text = gtk_text_buffer_new(NULL);
335         help_text = gtk_text_view_new_with_buffer(text);
336         gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(help_text), GTK_WRAP_WORD);
337         gtk_text_view_set_editable(GTK_TEXT_VIEW(help_text), FALSE);
338         gtk_widget_set_size_request(help_text, 550, 300);
339
340         gtk_container_add(GTK_CONTAINER(sw), help_text);
341
342         gtk_box_pack_start(GTK_BOX(hbox), sw, TRUE, TRUE, 0);
343
344         /*
345          * Add the table to the dialog widget.
346          */
347         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(help_dialog)->vbox),
348                           hbox);
349
350         button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
351         (void) g_signal_connect_object(G_OBJECT(button), "clicked",
352                                        G_CALLBACK(gtk_widget_hide),
353                                        (gpointer) help_dialog,
354                                        G_CONNECT_SWAPPED);
355
356         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(help_dialog)->action_area),
357                           button);
358         gtk_widget_show_all(GTK_DIALOG(help_dialog)->vbox);
359         gtk_widget_show_all(GTK_DIALOG(help_dialog)->action_area);
360
361         /*
362          * Create all the markup tags the text buffer will use.
363          */
364         hp.flags = 0;
365         hp.text = text;
366         hp.tag_name = "";
367         help_init_markup();
368
369         /*
370          * Create the context for the parser.
371          */
372         markup_context = g_markup_parse_context_new(&markup_funcs, 0,
373                                                     NULL, NULL);
374     }
375
376     /*
377      * Select the row specified in the callback.
378      */
379     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(help_topics));
380     tpath = gtk_tree_path_new_from_indices(GPOINTER_TO_INT(data), -1);
381     gtk_tree_selection_select_path(sel, tpath);
382
383     /*
384      * Show the help dialog and force it to the top.
385      */
386     guiutil_show_dialog_centered(help_dialog, editors[0].shell);
387     gdk_window_raise(help_dialog->window);
388 }
389
390 void
391 guihelp_cleanup(void)
392 {
393     if (markup_context != NULL)
394       g_markup_parse_context_free(markup_context);
395     markup_context = NULL;
396 }