1 /* Bluefish HTML Editor
2  * htmlbar.c - plugin for html toolbar
3  *
4  * Copyright (C) 2002-2011 Olivier Sessink
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 /*#define DEBUG*/
20 
21 #include <string.h>
22 
23 #include "htmlbar.h"
24 #include <gmodule.h>
25 #include "../plugins.h"
26 #include "../rcfile.h"
27 #include "../bfwin_uimanager.h" /* bfwin_set_menu_toggle_item() */
28 #include "../document.h"
29 #include "../gtk_easy.h"
30 #include "../stringlist.h"
31 #include "../pixmap.h"
32 #include "htmlbar_uimanager.h"
33 #include "htmlbar_stock_icons.h"
34 #include "rpopup.h"
35 #include "prefs.h"
36 
37 Thtmlbar htmlbar_v = {NULL, NULL, 0, 0, 1};
38 
39 static void
htmlbar_doc_view_populate_popup(GtkTextView * textview,GtkMenu * menu,Tdocument * doc)40 htmlbar_doc_view_populate_popup(GtkTextView * textview, GtkMenu * menu, Tdocument * doc)
41 {
42 	GtkWidget *menuitem;
43 	DEBUG_MSG("htmlbar_doc_view_populate_popup, called\n");
44 
45 	menuitem = gtk_image_menu_item_new_with_label(_("Edit color"));
46 	gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), GTK_WIDGET(menuitem));
47 	if (rpopup_doc_located_color(doc)) {
48 		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(rpopup_edit_color_cb), doc);
49 	} else {
50 		gtk_widget_set_sensitive(menuitem, FALSE);
51 	}
52 
53 	menuitem = gtk_image_menu_item_new_with_label(_("Edit tag"));
54 	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
55 								  gtk_image_new_from_stock(BF_STOCK_EDIT_TAG, GTK_ICON_SIZE_MENU));
56 	gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), GTK_WIDGET(menuitem));
57 	if (rpopup_doc_located_tag(doc)) {
58 		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(rpopup_edit_tag_cb), doc);
59 	} else {
60 		gtk_widget_set_sensitive(menuitem, FALSE);
61 	}
62 }
63 
64 static void
htmlbar_doc_view_button_press(GtkWidget * widget,GdkEventButton * bevent,Tdocument * doc)65 htmlbar_doc_view_button_press(GtkWidget * widget, GdkEventButton * bevent, Tdocument * doc)
66 {
67 	DEBUG_MSG("htmlbar_doc_view_button_press, called\n");
68 	if (bevent->button == 3) {
69 		rpopup_bevent_in_html_code(doc);
70 	}
71 }
72 
73 static void
htmlbar_sidepanel_initgui(Tbfwin * bfwin)74 htmlbar_sidepanel_initgui(Tbfwin *bfwin)
75 {
76 	DEBUG_MSG("htmlbar_sidepanel_initgui, in_sidepanel=%d\n",htmlbar_v.in_sidepanel);
77 	if (htmlbar_v.in_sidepanel && bfwin->leftpanel_notebook) {
78 		Thtmlbarwin *hbw;
79 		Thtmlbarsession *hbs;
80 		GtkWidget *html_notebook;
81 		GtkWidget *image;
82 
83 		hbs = g_hash_table_lookup(htmlbar_v.lookup, bfwin->session);
84 		hbw = g_hash_table_lookup(htmlbar_v.lookup, bfwin);
85 		if (!hbw || !hbs) {
86 			g_warning("htmlbar, no hbw/hbs when creating sidebar, please report");
87 			return;
88 		}
89 
90 		image = gtk_image_new_from_stock(BF_STOCK_BROWSER_PREVIEW, GTK_ICON_SIZE_LARGE_TOOLBAR);
91 		html_notebook = htmlbar_toolbar_create(hbw, hbs);
92 		DEBUG_MSG("htmlbar_sidepanel_initgui, html_notebook=%p\n",html_notebook);
93 		gtk_notebook_set_tab_pos(GTK_NOTEBOOK(html_notebook), GTK_POS_LEFT);
94 		gtk_widget_show_all(html_notebook);
95 		DEBUG_MSG("htmlbar_sidepanel_initgui, append html_notebook=%p to leftpanel_notebook %p and image %p\n",html_notebook, bfwin->leftpanel_notebook, image);
96 		gtk_notebook_append_page_menu(GTK_NOTEBOOK(bfwin->leftpanel_notebook),html_notebook,image,gtk_label_new(_("Htmlbar")));
97 		DEBUG_MSG("handlebox=%p\n",hbw->handlebox);
98 		if (hbw->handlebox) {
99 			DEBUG_MSG("htmlbar_sidepanel_initgui, destroy hbw->handlebox %p\n",hbw->handlebox);
100 			gtk_widget_destroy(hbw->handlebox);
101 			hbw->handlebox = NULL;
102 		}
103 
104 	}
105 }
106 
107 /*static void
108 htmlbar_sidepanel_destroygui(Tbfwin *bfwin)
109 {
110 
111 }
112 */
113 static void
htmlbar_init(void)114 htmlbar_init(void)
115 {
116 #ifdef ENABLE_NLS
117 	DEBUG_MSG("htmlbar_init, gettext domain-name=%s\n", PACKAGE "_plugin_htmlbar");
118 	bindtextdomain(PACKAGE "_plugin_htmlbar", LOCALEDIR);
119 	bind_textdomain_codeset(PACKAGE "_plugin_htmlbar", "UTF-8");
120 #endif
121 	htmlbar_v.quickbar_items = NULL;
122 	htmlbar_v.in_sidepanel = 0;
123 	htmlbar_v.lowercase_tags = 1;
124 
125 	htmlbar_v.lookup = g_hash_table_new_full(NULL /* == g_direct_hash() */ ,
126 											 NULL /* == g_direct_equal() */ ,
127 											 NULL, g_free);
128 	DEBUG_MSG("htmlbar_init, will add doc_view_button_press %p\n", htmlbar_doc_view_button_press);
129 	main_v->doc_view_populate_popup_cbs =
130 		g_slist_prepend(main_v->doc_view_populate_popup_cbs, htmlbar_doc_view_populate_popup);
131 	main_v->doc_view_button_press_cbs =
132 		g_slist_prepend(main_v->doc_view_button_press_cbs, htmlbar_doc_view_button_press);
133 	main_v->pref_initgui =
134 		g_slist_prepend(main_v->pref_initgui, htmlbar_pref_initgui);
135 	main_v->pref_apply =
136 		g_slist_prepend(main_v->pref_apply, htmlbar_pref_apply);
137 	main_v->sidepanel_initgui = g_slist_prepend(main_v->sidepanel_initgui,htmlbar_sidepanel_initgui);
138 /*	main_v->sidepanel_destroygui = g_slist_prepend(main_v->sidepanel_destroygui,htmlbar_sidepanel_destroygui);*/
139 	DEBUG_MSG("htmlbar_init, finished\n");
140 }
141 
142 static void
htmlbar_initgui(Tbfwin * bfwin)143 htmlbar_initgui(Tbfwin * bfwin)
144 {
145 	Thtmlbarwin *hbw;
146 	Thtmlbarsession *hbs;
147 	GtkAction *action;
148 
149 	hbw = g_new0(Thtmlbarwin, 1);
150 	hbw->bfwin = bfwin;
151 	if (g_hash_table_size(htmlbar_v.lookup)==1) { /* the first entry is the global session, so we make sure now we run this code only once! */
152 		htmlbar_register_stock_icons();
153 	}
154 
155 	g_hash_table_insert(htmlbar_v.lookup, bfwin, hbw);
156 	DEBUG_MSG("htmlbar_initgui, adding hbw %p to hashtable %p with key %p\n", hbw, htmlbar_v.lookup, bfwin);
157 	hbs = g_hash_table_lookup(htmlbar_v.lookup, bfwin->session);
158 	if (!hbs) {
159 		hbs = g_new0(Thtmlbarsession, 1);
160 		hbs->view_htmlbar = TRUE;
161 		DEBUG_MSG("htmlbar_initgui, adding hbs %p to hashtable %p with key %p\n", hbs, htmlbar_v.lookup,
162 				  bfwin->session);
163 		g_hash_table_insert(htmlbar_v.lookup, bfwin->session, hbs);
164 	}
165 	DEBUG_MSG("htmlbar_initgui, created hbw=%p and hbs=%p, will call htmlbar_load_ui\n",hbw,hbs);
166 	htmlbar_load_ui(hbw);
167 	htmlbar_menu_create(hbw);
168 	action = gtk_ui_manager_get_action(bfwin->uimanager, "/MainMenu/ViewMenu/ViewHTMLToolbar");
169 	if (!htmlbar_v.in_sidepanel) {
170 		htmlbar_toolbar_show(hbw, hbs, hbs->view_htmlbar);
171 		gtk_action_set_visible(action, TRUE);
172 	} else {
173 		gtk_action_set_visible(action, FALSE);
174 	}
175 	DEBUG_MSG("htmlbar_initgui, finished\n");
176 }
177 
178 static void
htmlbar_enforce_session(Tbfwin * bfwin)179 htmlbar_enforce_session(Tbfwin * bfwin)
180 {
181 	Thtmlbarsession *hbs;
182 	Thtmlbarwin *hbw;
183 	DEBUG_MSG("htmlbar_enforce_session, started for session %p\n", bfwin->session);
184 	hbs = g_hash_table_lookup(htmlbar_v.lookup, bfwin->session);
185 	hbw = g_hash_table_lookup(htmlbar_v.lookup, bfwin);
186 	if (!hbs || !hbw) {
187 		return;
188 	}
189 	if (!htmlbar_v.in_sidepanel) {
190 		htmlbar_toolbar_show(hbw, hbs, hbs->view_htmlbar);
191 		bfwin_set_menu_toggle_item(hbw->actiongroup, "ViewHTMLToolbar", hbs->view_htmlbar);
192 	}
193 }
194 
195 static void
htmlbar_cleanup(void)196 htmlbar_cleanup(void)
197 {
198 	GList *tmplist = g_list_first(gtk_window_list_toplevels());
199 	while (tmplist) {
200 		if (GTK_IS_WIDGET(tmplist->data)) {
201 			const gchar *role = gtk_window_get_role((GtkWindow *) tmplist->data);
202 			if (role && strcmp(role, "html_dialog") == 0) {
203 				gtk_widget_hide(GTK_WIDGET(tmplist->data));
204 				window_destroy(GTK_WIDGET(tmplist->data));
205 			}
206 		}
207 		tmplist = g_list_next(tmplist);
208 	}
209 
210 	free_stringlist(htmlbar_v.quickbar_items);
211 	g_hash_table_unref(htmlbar_v.lookup);
212 	main_v->doc_view_populate_popup_cbs =
213 		g_slist_remove(main_v->doc_view_populate_popup_cbs, htmlbar_doc_view_populate_popup);
214 	main_v->doc_view_button_press_cbs =
215 		g_slist_remove(main_v->doc_view_button_press_cbs, htmlbar_doc_view_button_press);
216 
217 }
218 
219 static void
htmlbar_cleanup_gui(Tbfwin * bfwin)220 htmlbar_cleanup_gui(Tbfwin * bfwin)
221 {
222 	/* BUG: clean the keys and structures in the hashtable */
223 	DEBUG_MSG("htmlbar_cleanup_gui, cleanup bfwin %p\n",bfwin);
224 	g_hash_table_remove(htmlbar_v.lookup, bfwin);
225 }
226 
227 static GHashTable *
htmlbar_register_globses_config(GHashTable * configlist)228 htmlbar_register_globses_config(GHashTable * configlist)
229 {
230 	DEBUG_MSG("htmlbar_register_globses_config, started\n");
231 	configlist = make_config_list_item(configlist, &htmlbar_v.in_sidepanel, 'i', "htmlbar_in_sidepanel:", 0);
232 	configlist = make_config_list_item(configlist, &htmlbar_v.quickbar_items, 'l', "htmlbar_quickbar:", 0);
233 	configlist = make_config_list_item(configlist, &htmlbar_v.lowercase_tags, 'i', "lowercase_tags:", 0);
234 	configlist = make_config_list_item(configlist, &htmlbar_v.transient_htdialogs, 'i', "htmlbar_transient:", 0);
235 	return configlist;
236 }
237 
238 static GHashTable *
htmlbar_register_session_config(GHashTable * configlist,Tsessionvars * session)239 htmlbar_register_session_config(GHashTable * configlist, Tsessionvars * session)
240 {
241 	Thtmlbarsession *hbs;
242 	DEBUG_MSG("htmlbar_register_session_config, started for %p\n", session);
243 	hbs = g_hash_table_lookup(htmlbar_v.lookup, session);
244 	if (!hbs) {
245 		hbs = g_new0(Thtmlbarsession, 1);
246 		hbs->view_htmlbar = TRUE;
247 		hbs->thumbnailwidth = 300;
248 		g_hash_table_insert(htmlbar_v.lookup, session, hbs);
249 		DEBUG_MSG("htmlbar_register_session_config, adding hbs %p to hashtable %p with key %p\n", hbs,
250 				  htmlbar_v.lookup, session);
251 	}
252 	configlist = make_config_list_item(configlist, &hbs->view_htmlbar, 'i', "htmlbar_view:", 0);
253 	configlist = make_config_list_item(configlist, &hbs->notebooktab, 'i', "htmlbar_notebooktab:", 0);
254 	configlist = make_config_list_item(configlist, &hbs->thumbnailwidth, 'i', "htmlbar_thumbnailwidth:", 0);
255 	return configlist;
256 }
257 
258 static void
htmlbar_session_cleanup(Tsessionvars * session)259 htmlbar_session_cleanup(Tsessionvars * session)
260 {
261 	DEBUG_MSG("htmlbar_session_cleanup, cleanup session %p\n", session);
262 	g_hash_table_remove(htmlbar_v.lookup, session);
263 }
264 
265 
266 static TBluefishPlugin bfplugin = {
267 	N_("HTML Features"),
268 	BFPLUGIN_VERSION,
269 	GTK_MAJOR_VERSION,
270 	sizeof(Tdocument),
271 	sizeof(Tsessionvars),
272 	sizeof(Tglobalsession),
273 	sizeof(Tbfwin),
274 	sizeof(Tproject),
275 	sizeof(Tmain),
276 	sizeof(Tproperties),
277 	BFPLUGIN_PRIORITY_DEFAULT,
278 	1,
279 	NULL,						/* private */
280 	htmlbar_init,				/* init */
281 	htmlbar_initgui,
282 	htmlbar_enforce_session,
283 	htmlbar_cleanup,
284 	htmlbar_cleanup_gui,
285 	htmlbar_register_globses_config,
286 	htmlbar_register_session_config,
287 	htmlbar_session_cleanup,
288 	NULL,						/* binary compatibility */
289 	NULL,
290 	NULL
291 };
292 
293 G_MODULE_EXPORT TBluefishPlugin *
getplugin(void)294 getplugin(void)
295 {
296 	return &bfplugin;
297 }
298