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 static GtkWidget *help_dialog;
27 static GtkWidget *help_text;
28 static GtkWidget *help_topics;
36 static helpmap_t topics[] = {
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},
51 static guint ntopics = sizeof(topics) / sizeof(topics[0]);
53 /**************************************************************
55 * Routines for parsing the markup for the help text buffer.
57 **************************************************************/
59 #define HTEXT_BULLET 0x0001
60 #define HTEXT_UL 0x0002
65 const gchar *tag_name;
69 static htext_parse_t hp;
71 static const gchar *bullet = "•";
74 help_parse_start(GMarkupParseContext *ctx, const gchar *tag,
75 const gchar **attr_names, const gchar **attr_vals,
76 gpointer data, GError **err)
78 if (strcmp(tag, "bullet") == 0) {
79 gtk_text_buffer_insert_with_tags_by_name(hp.text, &hp.iter,
82 "large_bullet", NULL);
83 hp.flags |= HTEXT_BULLET;
85 } else if (strcmp(tag, "help") == 0)
92 help_parse_text(GMarkupParseContext *ctx, const gchar *txt, gsize txtlen,
93 gpointer data, GError **err)
96 gtk_text_buffer_insert_with_tags_by_name(hp.text, &hp.iter,
100 if (hp.flags & HTEXT_BULLET)
101 gtk_text_buffer_insert_with_tags_by_name(hp.text, &hp.iter,
108 gtk_text_buffer_insert(hp.text, &hp.iter, txt, txtlen);
113 help_parse_end(GMarkupParseContext *ctx, const gchar *tag,
114 gpointer data, GError **err)
116 if (strcmp(tag, "bullet") == 0)
117 hp.flags &= ~HTEXT_BULLET;
122 help_parse_error(GMarkupParseContext *ctx, GError *err, gpointer data)
126 static GMarkupParser markup_funcs = {
134 static GMarkupParseContext *markup_context = NULL;
137 * Creates all the markup tags.
140 help_init_markup(void)
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",
154 "weight", PANGO_WEIGHT_BOLD,
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);
169 tabs = pango_tab_array_new_with_positions(2, TRUE,
172 gtk_text_buffer_create_tag(hp.text, "tabs",
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);
186 /**************************************************************
190 **************************************************************/
193 help_free_list_item(gpointer data, gpointer user_data)
195 gtk_tree_path_free((GtkTreePath *) data);
199 help_on(GtkTreeSelection *sel, gpointer data)
206 * Because this is called before the help text widget is created,
207 * simply return if the help text widget is NULL.
213 * Sorta complicated, but can't see any other way around it at the moment
216 rowlist = gtk_tree_selection_get_selected_rows(sel, NULL);
218 gtk_tree_path_get_indices((GtkTreePath *) g_list_nth_data(rowlist, 0));
222 * Clear out the rows that were returned.
224 g_list_foreach(rowlist, help_free_list_item, 0);
227 * Set the dialog title.
229 sprintf(buffer1, "Help: %s", topics[row].help_topic);
230 gtk_window_set_title(GTK_WINDOW(help_dialog), buffer1);
233 * Clear the text buffer.
235 gtk_text_buffer_set_text(hp.text, "", 0);
238 * Get the iterator at the start of the buffer.
240 gtk_text_buffer_get_start_iter(hp.text, &hp.iter);
243 * Parse the help text.
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);
251 guihelp_show_help(GtkWidget *w, gpointer data)
254 GtkWidget *hbox, *sw, *button;
257 GtkTreeViewColumn *column;
258 GtkCellRenderer *cell_renderer;
259 GtkTreeSelection *sel;
263 if (help_dialog == 0) {
265 * Store the help text into the array.
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;
280 help_dialog = gtk_dialog_new();
283 * Force the help dialog to center over the first editor that
286 (void) g_signal_connect(G_OBJECT(help_dialog), "delete_event",
287 G_CALLBACK(gtk_widget_hide), NULL);
289 hbox = gtk_hbox_new(FALSE, 5);
292 * Create the list that will be used for the help topics.
294 store = gtk_list_store_new(1, G_TYPE_STRING);
297 * Add the topics to the list.
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);
303 help_topics = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
305 cell_renderer = gtk_cell_renderer_text_new();
306 column = gtk_tree_view_column_new_with_attributes ("Help Topics",
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);
313 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(help_topics));
314 gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
316 (void) g_signal_connect(G_OBJECT(sel), "changed",
317 G_CALLBACK(help_on), NULL);
319 gtk_box_pack_start(GTK_BOX(hbox), help_topics, FALSE, FALSE, 0);
321 g_object_unref(store);
323 gtk_box_pack_start(GTK_BOX(hbox), gtk_vseparator_new(),
327 * Create the text widget that will display the help text.
329 sw = gtk_scrolled_window_new(NULL, NULL);
330 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
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);
340 gtk_container_add(GTK_CONTAINER(sw), help_text);
342 gtk_box_pack_start(GTK_BOX(hbox), sw, TRUE, TRUE, 0);
345 * Add the table to the dialog widget.
347 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(help_dialog)->vbox),
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,
356 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(help_dialog)->action_area),
358 gtk_widget_show_all(GTK_DIALOG(help_dialog)->vbox);
359 gtk_widget_show_all(GTK_DIALOG(help_dialog)->action_area);
362 * Create all the markup tags the text buffer will use.
370 * Create the context for the parser.
372 markup_context = g_markup_parse_context_new(&markup_funcs, 0,
377 * Select the row specified in the callback.
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);
384 * Show the help dialog and force it to the top.
386 guiutil_show_dialog_centered(help_dialog, editors[0].shell);
387 gdk_window_raise(help_dialog->window);
391 guihelp_cleanup(void)
393 if (markup_context != NULL)
394 g_markup_parse_context_free(markup_context);
395 markup_context = NULL;