1 /*
2  *	  latex.c - Plugin to let Geany better work together with LaTeX
3  *
4  *	  Copyright 2007-2015 Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
5  *	  Copyright 2005-2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
6  *	  Copyright 2006-2009 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
7  *
8  *	  For long list of friendly supporters please have a look at THANKS.
9  *
10  *	  This program is free software; you can redistribute it and/or modify
11  *	  it under the terms of the GNU General Public License as published by
12  *	  the Free Software Foundation; either version 2 of the License, or
13  *	  (at your option) any later version.
14  *
15  *	  This program is distributed in the hope that it will be useful,
16  *	  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *	  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *	  GNU General Public License for more details.
19  *
20  *	  You should have received a copy of the GNU General Public License
21  *	  along with this program; if not, write to the Free Software
22  *	  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  */
24 
25 /* LaTeX plugin */
26 /* This plugin improves the work with LaTeX and Geany.*/
27 
28 
29 #ifdef HAVE_CONFIG_H
30 	#include "config.h" /* for the gettext domain */
31 #endif
32 
33 #include <glib/gstdio.h>
34 #include "latex.h"
35 #include "ctype.h"
36 
37 PLUGIN_VERSION_CHECK(224)
38 
39 PLUGIN_SET_TRANSLATABLE_INFO(
40 	LOCALEDIR,
41 	GETTEXT_PACKAGE,
42 	_("LaTeX"),
43 	_("Extends LaTeX support"),
44 	"0.7",
45 	"Frank Lanitz <frank@frank.uvena.de>")
46 
47 GeanyPlugin	 *geany_plugin;
48 GeanyData	   *geany_data;
49 
50 /* Widgets for plugin */
51 static GtkWidget *menu_latex = NULL;
52 static GtkWidget *menu_bibtex = NULL;
53 static GtkWidget *menu_bibtex_menu = NULL;
54 static GtkWidget *menu_latex_menu = NULL;
55 static GtkWidget *menu_latex_wizard = NULL;
56 static GtkWidget *menu_latex_menu_special_char = NULL;
57 static GtkWidget *menu_latex_menu_special_char_submenu = NULL;
58 static GtkWidget *menu_latex_ref = NULL;
59 static GtkWidget *menu_latex_label = NULL;
60 static GtkWidget *menu_latex_bibtex = NULL;
61 static GtkWidget *menu_latex_bibtex_submenu = NULL;
62 static GtkWidget *menu_latex_insert_bibtex_cite = NULL;
63 static GtkWidget *menu_latex_format_insert = NULL;
64 static GtkWidget *menu_latex_format_insert_submenu = NULL;
65 static GtkWidget *menu_latex_fontsize = NULL;
66 static GtkWidget *menu_latex_fontsize_submenu = NULL;
67 static GtkWidget *menu_latex_insert_environment = NULL;
68 static GtkWidget *menu_latex_insert_usepackage = NULL;
69 static GtkWidget *menu_latex_insert_command = NULL;
70 static GtkWidget *menu_latex_replacement = NULL;
71 static GtkWidget *menu_latex_replacement_submenu = NULL;
72 static GtkWidget *menu_latex_replace_selection = NULL;
73 static GtkWidget *menu_latex_replace_toggle = NULL;
74 static GtkWidget *menu_latex_toolbar_wizard = NULL;
75 
76 /* Options for plugin */
77 static gboolean glatex_set_koma_active = FALSE;
78 static gboolean glatex_deactivate_toolbaritems_with_non_latex = TRUE;
79 static gboolean glatex_deactivate_menubarentry_with_non_latex = TRUE;
80 static gboolean glatex_add_menu_on_startup;
81 static gchar *glatex_ref_chapter_string = NULL;
82 static gchar *glatex_ref_page_string = NULL;
83 static gchar *glatex_ref_all_string = NULL;
84 static gboolean glatex_set_toolbar_active = FALSE;
85 static gboolean glatex_capitalize_sentence_starts = FALSE;
86 static gboolean glatex_wizard_to_generic_toolbar = FALSE;
87 
88 /* We want to keep this deactivated by default as the
89  * user needs to know what he is doing here.... */
90 static gboolean glatex_autocompletion_active = FALSE;
91 /* Value how many line should be search for autocompletion of \end{}
92  * and \endgroup{}. */
93 static gint glatex_autocompletion_context_size;
94 static gboolean glatex_autocompletion_only_for_latex;
95 gboolean glatex_autobraces_active = TRUE;
96 gboolean glatex_lowercase_on_smallcaps = FALSE;
97 
98 
99 /* Function will be deactivated, when only loaded */
100 static gboolean toggle_active = FALSE;
101 
102 static GtkUIManager *uim;
103 static GtkActionGroup *group;
104 static GtkWidget *glatex_toolbar = NULL;
105 static GtkWidget *box = NULL;
106 
107 static GtkToolItem *glatex_wizard_generic_toolbar_item = NULL;
108 
109 /* Configuration file */
110 static gchar *config_file = NULL;
111 
112 LaTeXWizard glatex_wizard;
113 
114 const GtkActionEntry format_icons[] =
115 {
116 	{ "Wizard", GTK_STOCK_NEW, NULL, NULL, N_("Runs LaTeX wizard"), G_CALLBACK(glatex_kbwizard) },
117 	{ "Italic", GTK_STOCK_ITALIC, NULL, NULL, N_("Marks selected text as italic"), G_CALLBACK(glatex_kb_format_italic) },
118 	{ "Bold", GTK_STOCK_BOLD, NULL, NULL, N_("Marks selected text as bold"), G_CALLBACK(glatex_kb_format_bold) },
119 	{ "Underline", GTK_STOCK_UNDERLINE, NULL, NULL, N_("Underlines selected text"), G_CALLBACK(glatex_kb_format_typewriter) },
120 	{ "Centered", GTK_STOCK_JUSTIFY_CENTER, NULL, NULL, N_("Centered"), G_CALLBACK(glatex_kb_format_centering) },
121 	{ "Left", GTK_STOCK_JUSTIFY_LEFT, NULL, NULL, N_("Left side oriented"), G_CALLBACK(glatex_kb_format_left) },
122 	{ "Right", GTK_STOCK_JUSTIFY_RIGHT, NULL, NULL, N_("Right side oriented"), G_CALLBACK(glatex_kb_format_right) },
123 };
124 
125 const guint ui_entries_n = G_N_ELEMENTS(format_icons);
126 
127 
128 /* fallback UI definition */
129 static const gchar *toolbar_markup =
130 "<ui>"
131 	"<toolbar name='glatex_format_toolbar'>"
132 		"<toolitem action='Wizard'/>"
133 		"<separator/>"
134 		"<toolitem action='Italic'/>"
135 		"<toolitem action='Bold'/>"
136 		"<toolitem action='Underline'/>"
137 		"<separator/>"
138 		"<toolitem action='Centered' />"
139 		"<toolitem action='Left' />"
140 		"<toolitem action='Right'/>"
141 	"</toolbar>"
142 "</ui>";
143 
144 static struct
145 {
146 	GtkWidget *koma_active;
147 	GtkWidget *toolbar_active;
148 	GtkWidget *glatex_autocompletion_active;
149 	GtkWidget *glatex_capitalize_sentence;
150 	GtkWidget *wizard_to_generic_toolbar;
151 	GtkWidget *lower_selection_on_smallcaps;
152 }
153 config_widgets;
154 
155 /* Some functions*/
156 static void toggle_toolbar_items_by_file_type(gint id);
157 static void add_menu_to_menubar(void);
158 static void remove_menu_from_menubar(void);
159 static void add_wizard_to_generic_toolbar(void);
160 static void remove_wizard_from_generic_toolbar(void);
161 
162 
init_toolbar(void)163 static GtkWidget *init_toolbar(void)
164 {
165 	GtkWidget *toolbar = NULL;
166 
167 	box = ui_lookup_widget(geany->main_widgets->window, "vbox1");
168 	uim = gtk_ui_manager_new();
169 	group = gtk_action_group_new("glatex_format_toolbar");
170 	gtk_action_group_set_translation_domain(group, GETTEXT_PACKAGE);
171 	gtk_action_group_add_actions(group, format_icons, ui_entries_n, NULL);
172 	gtk_ui_manager_insert_action_group(uim, group, 0);
173 	if (gtk_ui_manager_add_ui_from_string(uim, toolbar_markup, -1, NULL) > 0)
174 	{
175 		toolbar = gtk_ui_manager_get_widget(uim, "/ui/glatex_format_toolbar");
176 		gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(toolbar), FALSE, TRUE, 0);
177 		gtk_box_reorder_child(GTK_BOX(box), toolbar, 2);
178 	}
179 	/* TODO maybe more error handling */
180 
181 	return toolbar;
182 }
183 
184 
185 /* Move "geanyLaTex/general.conf" to "LaTex/general.conf"
186    if it still exists. */
187 static void
move_old_config_file(void)188 move_old_config_file(void)
189 {
190 	gchar *filename_old, *filename_new, *dir_new;
191 	GFile *file_old, *file_new;
192 
193 	filename_old = g_strconcat(geany->app->configdir,
194 		G_DIR_SEPARATOR_S, "plugins", G_DIR_SEPARATOR_S,
195 		"geanyLaTeX", G_DIR_SEPARATOR_S, "general.conf", NULL);
196 
197 	if (g_file_test(filename_old, G_FILE_TEST_EXISTS))
198 	{
199 		filename_new = g_strconcat(geany->app->configdir,
200 			G_DIR_SEPARATOR_S, "plugins", G_DIR_SEPARATOR_S,
201 			"LaTeX", G_DIR_SEPARATOR_S, "general.conf", NULL);
202 
203 		dir_new = g_path_get_dirname(filename_new);
204 		if (!g_file_test(dir_new, G_FILE_TEST_IS_DIR)
205 			&& utils_mkdir(dir_new, TRUE) != 0)
206 		{
207 			dialogs_show_msgbox(GTK_MESSAGE_ERROR,
208 				_("Plugin configuration directory could not be created."));
209 		}
210 
211 		file_old = g_file_new_for_path(filename_old);
212 		file_new = g_file_new_for_path(filename_new);
213 
214 		g_file_move(file_old, file_new, 0, NULL, NULL, NULL, NULL);
215 
216 		g_object_unref(file_old);
217 		g_object_unref(file_new);
218 
219 		if (!g_file_test(filename_old, G_FILE_TEST_EXISTS))
220 		{
221 			gchar *dir_old;
222 
223 			/* File move successful, remove old dir. */
224 			dir_old = g_path_get_dirname(filename_old);
225 			g_rmdir(dir_old);
226 			g_free(dir_old);
227 		}
228 
229 		g_free(filename_new);
230 		g_free(dir_new);
231 	}
232 
233 	g_free(filename_old);
234 }
235 
236 
237 static void
on_configure_response(G_GNUC_UNUSED GtkDialog * dialog,gint response,G_GNUC_UNUSED gpointer user_data)238 on_configure_response(G_GNUC_UNUSED GtkDialog *dialog, gint response,
239 					  G_GNUC_UNUSED gpointer user_data)
240 {
241 	if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
242 	{
243 		GKeyFile *config = g_key_file_new();
244 		gchar *data;
245 		gchar *config_dir = g_path_get_dirname(config_file);
246 		gint glatex_autocompletion_active_response;
247 
248 		config_file = g_strconcat(geany->app->configdir,
249 			G_DIR_SEPARATOR_S, "plugins", G_DIR_SEPARATOR_S,
250 			"LaTeX", G_DIR_SEPARATOR_S, "general.conf", NULL);
251 		glatex_set_koma_active =
252 			gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_widgets.koma_active));
253 		glatex_set_toolbar_active =
254 			gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_widgets.toolbar_active));
255 		glatex_capitalize_sentence_starts =
256 			gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_widgets.glatex_capitalize_sentence));
257 		glatex_wizard_to_generic_toolbar =
258 			gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_widgets.wizard_to_generic_toolbar));
259 		glatex_lowercase_on_smallcaps =
260 			gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_widgets.lower_selection_on_smallcaps));
261 
262 		/* Check the response code for LaTeX's autocompletion functions.
263 		 * Due compatibility with oder Geany versions cass 0 will be treated
264 		 * as FALSE, which means autocompletion is deactivated. */
265 		glatex_autocompletion_active_response = gtk_combo_box_get_active(
266 			GTK_COMBO_BOX(config_widgets.glatex_autocompletion_active));
267 		if (glatex_autocompletion_active_response == 0)
268 			glatex_autocompletion_active = FALSE;
269 		else
270 			glatex_autocompletion_active = TRUE;
271 
272 		/* write stuff to file */
273 		g_key_file_load_from_file(config, config_file, G_KEY_FILE_NONE, NULL);
274 
275 		g_key_file_set_boolean(config, "general", "glatex_set_koma_active",
276 			glatex_set_koma_active);
277 		g_key_file_set_boolean(config, "general", "glatex_set_toolbar_active",
278 			glatex_set_toolbar_active);
279 		g_key_file_set_boolean(config, "general", "glatex_set_autocompletion",
280 			glatex_autocompletion_active);
281 		g_key_file_set_boolean(config, "general", "glatex_lowercase_on_smallcaps",
282 			glatex_lowercase_on_smallcaps);
283 		g_key_file_set_boolean(config, "autocompletion",
284 			"glatex_capitalize_sentence_starts", glatex_capitalize_sentence_starts);
285 		g_key_file_set_boolean(config, "toolbar", "glatex_wizard_to_generic_toolbar",
286 			glatex_wizard_to_generic_toolbar);
287 
288 
289 		if (!g_file_test(config_dir, G_FILE_TEST_IS_DIR)
290 			&& utils_mkdir(config_dir, TRUE) != 0)
291 		{
292 			dialogs_show_msgbox(GTK_MESSAGE_ERROR,
293 				_("Plugin configuration directory could not be created."));
294 		}
295 		else
296 		{
297 			/* write config to file */
298 			data = g_key_file_to_data(config, NULL, NULL);
299 			utils_write_file(config_file, data);
300 			g_free(data);
301 		}
302 
303 		g_free(config_dir);
304 		g_key_file_free(config);
305 
306 		/* Apply changes to Geany */
307 		/* Add toolbar if requested */
308 		if (glatex_set_toolbar_active == TRUE)
309 		{
310 			if (glatex_toolbar == NULL)
311 			{
312 				glatex_toolbar = init_toolbar();
313 			}
314 			else
315 			{
316 				gtk_widget_show(glatex_toolbar);
317 			}
318 		}
319 		/* Hide toolbar */
320 		else if (glatex_set_toolbar_active == FALSE && glatex_toolbar != NULL)
321 		{
322 			gtk_widget_hide(glatex_toolbar);
323 		}
324 
325 		/* Add wizard to generic toolbar if requested */
326 		if (glatex_wizard_to_generic_toolbar == TRUE &&
327 			glatex_wizard_generic_toolbar_item == NULL)
328 		{
329 			add_wizard_to_generic_toolbar();
330 		}
331 		else if (glatex_wizard_to_generic_toolbar == FALSE &&
332 				 glatex_wizard_generic_toolbar_item != NULL)
333 		{
334 			remove_wizard_from_generic_toolbar();
335 		}
336 	}
337 }
338 
339 GtkWidget *
plugin_configure(GtkDialog * dialog)340 plugin_configure(GtkDialog * dialog)
341 {
342 	GtkWidget   *vbox;
343 	GtkWidget   *hbox_autocompletion;
344 	GtkWidget   *label_autocompletion = NULL;
345 	gint		tmp;
346 
347 	vbox = gtk_vbox_new(FALSE, 6);
348 
349 	config_widgets.koma_active = gtk_check_button_new_with_label(
350 		_("Use KOMA script by default"));
351 	config_widgets.toolbar_active = gtk_check_button_new_with_label(
352 		_("Show extra plugin toolbar"));
353 	config_widgets.glatex_capitalize_sentence = gtk_check_button_new_with_label(
354 		_("Capitalize sentence on typing"));
355 	config_widgets.wizard_to_generic_toolbar = gtk_check_button_new_with_label(
356 		_("Add a wizard icon to Geany's main toolbar"));
357 	config_widgets.lower_selection_on_smallcaps = gtk_check_button_new_with_label(
358 		_("Lower selection when formatting smallcaps (\\textsc{})"));
359 
360 	config_widgets.glatex_autocompletion_active = gtk_combo_box_text_new();
361 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(config_widgets.glatex_autocompletion_active), 0,
362 		_("Don't care about this inside plugin"));
363 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(config_widgets.glatex_autocompletion_active), 1,
364 		_("Always perform autocompletion on LaTeX"));
365 
366 	/* Configuration for auto completion feature */
367 	hbox_autocompletion = gtk_hbox_new(FALSE, 3);
368 
369 	/* Dirty workarround for transferring boolean into a valid interger value */
370 	if (glatex_autocompletion_active == TRUE)
371 		tmp = 1;
372 	else
373 		tmp = 0;
374 
375 	gtk_combo_box_set_active(GTK_COMBO_BOX(config_widgets.glatex_autocompletion_active), tmp);
376 
377 	label_autocompletion = gtk_label_new(_("Modus of autocompletion"));
378 
379 	gtk_box_pack_start(GTK_BOX(hbox_autocompletion), label_autocompletion, FALSE, FALSE, 3);
380 	gtk_box_pack_start(GTK_BOX(hbox_autocompletion), config_widgets.glatex_autocompletion_active, TRUE, TRUE, 3);
381 
382 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_widgets.koma_active),
383 		glatex_set_koma_active);
384 	gtk_box_pack_start(GTK_BOX(vbox), config_widgets.koma_active, FALSE, FALSE, 2);
385 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_widgets.toolbar_active),
386 		glatex_set_toolbar_active);
387 	gtk_box_pack_start(GTK_BOX(vbox), config_widgets.toolbar_active, FALSE, FALSE, 2);
388 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_widgets.glatex_capitalize_sentence),
389 		glatex_capitalize_sentence_starts);
390 	gtk_box_pack_start(GTK_BOX(vbox), config_widgets.glatex_capitalize_sentence, FALSE, FALSE, 2);
391 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_widgets.wizard_to_generic_toolbar),
392 		glatex_wizard_to_generic_toolbar);
393 	gtk_box_pack_start(GTK_BOX(vbox), config_widgets.lower_selection_on_smallcaps, FALSE, FALSE, 2);
394 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_widgets.lower_selection_on_smallcaps),
395 		glatex_lowercase_on_smallcaps);
396 	gtk_box_pack_start(GTK_BOX(vbox), config_widgets.wizard_to_generic_toolbar, FALSE, FALSE, 2);
397 	gtk_box_pack_start(GTK_BOX(vbox), hbox_autocompletion, FALSE, FALSE, 2);
398 
399 	gtk_widget_show_all(vbox);
400 	g_signal_connect(dialog, "response", G_CALLBACK(on_configure_response), NULL);
401 	return vbox;
402 }
403 
404 /* Functions to toggle the status of plugin */
glatex_set_latextoggle_status(gboolean new_status)405 static void glatex_set_latextoggle_status(gboolean new_status)
406 {
407 	/* No more function at the moment.*/
408 	if (toggle_active != new_status)
409 		toggle_active = new_status;
410 }
411 
glatex_toggle_status(G_GNUC_UNUSED GtkMenuItem * menuitem)412 static void glatex_toggle_status(G_GNUC_UNUSED GtkMenuItem * menuitem)
413 {
414 	if (toggle_active == TRUE)
415 		glatex_set_latextoggle_status(FALSE);
416 	else
417 		glatex_set_latextoggle_status(TRUE);
418 }
419 
toggle_toolbar_item(const gchar * path,gboolean new_status)420 static void toggle_toolbar_item(const gchar *path, gboolean new_status)
421 {
422 	if (gtk_action_get_sensitive(gtk_ui_manager_get_action(uim, path)) != new_status)
423 	{
424 		gtk_action_set_sensitive(gtk_ui_manager_get_action(uim, path), new_status);
425 	}
426 }
427 
428 static void
check_for_menu(gint ft_id)429 check_for_menu(gint ft_id)
430 {
431 	/* We don't check whether the menu has been added here, as this
432 	 * will is checked by add_menu_to_menubar() anyway */
433 	if (ft_id == GEANY_FILETYPES_LATEX)
434 	{
435 		add_menu_to_menubar();
436 	}
437 	if (ft_id != GEANY_FILETYPES_LATEX)
438 	{
439 		if (glatex_deactivate_menubarentry_with_non_latex == TRUE)
440 		{
441 			remove_menu_from_menubar();
442 		}
443 	}
444 }
445 
446 
activate_toolbar_items(void)447 static void activate_toolbar_items(void)
448 {
449 	if (uim == NULL)
450 	{
451 		return;
452 	}
453 
454 	toggle_toolbar_item("/ui/glatex_format_toolbar/Bold", TRUE);
455 	toggle_toolbar_item("/ui/glatex_format_toolbar/Underline", TRUE);
456 	toggle_toolbar_item("/ui/glatex_format_toolbar/Centered", TRUE);
457 	toggle_toolbar_item("/ui/glatex_format_toolbar/Italic", TRUE);
458 	toggle_toolbar_item("/ui/glatex_format_toolbar/Left", TRUE);
459 	toggle_toolbar_item("/ui/glatex_format_toolbar/Right", TRUE);
460 	gtk_ui_manager_ensure_update(uim);
461 }
462 
deactivate_toolbar_items(void)463 static void deactivate_toolbar_items(void)
464 {
465 	if (uim == NULL)
466 	{
467 		return;
468 	}
469 
470 	toggle_toolbar_item("/ui/glatex_format_toolbar/Bold", FALSE);
471 	toggle_toolbar_item("/ui/glatex_format_toolbar/Underline", FALSE);
472 	toggle_toolbar_item("/ui/glatex_format_toolbar/Centered", FALSE);
473 	toggle_toolbar_item("/ui/glatex_format_toolbar/Italic", FALSE);
474 	toggle_toolbar_item("/ui/glatex_format_toolbar/Left", FALSE);
475 	toggle_toolbar_item("/ui/glatex_format_toolbar/Right", FALSE);
476 	gtk_ui_manager_ensure_update(uim);
477 }
478 
479 
toggle_toolbar_items_by_file_type(gint id)480 static void toggle_toolbar_items_by_file_type(gint id)
481 {
482 	if (glatex_set_toolbar_active == TRUE)
483 	{
484 		if (id == GEANY_FILETYPES_LATEX ||
485 			glatex_deactivate_toolbaritems_with_non_latex == FALSE)
486 		{
487 			activate_toolbar_items();
488 		}
489 		else
490 		{
491 			deactivate_toolbar_items();
492 		}
493 	}
494 }
495 
496 
on_document_activate(G_GNUC_UNUSED GObject * object,GeanyDocument * doc,G_GNUC_UNUSED gpointer data)497 static void on_document_activate(G_GNUC_UNUSED GObject *object,
498 								 GeanyDocument *doc, G_GNUC_UNUSED gpointer data)
499 {
500 	g_return_if_fail(doc != NULL);
501 
502 	if (main_is_realized() == TRUE)
503 	{
504 		toggle_toolbar_items_by_file_type(doc->file_type->id);
505 		check_for_menu(doc->file_type->id);
506 	}
507 }
508 
509 
on_document_new(G_GNUC_UNUSED GObject * object,GeanyDocument * doc,G_GNUC_UNUSED gpointer data)510 static void on_document_new(G_GNUC_UNUSED GObject *object, GeanyDocument *doc,
511 							G_GNUC_UNUSED gpointer data)
512 {
513 	g_return_if_fail(doc != NULL);
514 
515 	if (main_is_realized() == TRUE)
516 	{
517 		toggle_toolbar_items_by_file_type(doc->file_type->id);
518 	}
519 }
520 
521 
522 static void
on_geany_startup_complete(G_GNUC_UNUSED GObject * obj,G_GNUC_UNUSED gpointer user_data)523 on_geany_startup_complete(G_GNUC_UNUSED GObject *obj,
524 						  G_GNUC_UNUSED gpointer user_data)
525 {
526 	GeanyDocument *doc = NULL;
527 
528 	doc = document_get_current();
529 	if (doc != NULL)
530 	{
531 		toggle_toolbar_items_by_file_type(doc->file_type->id);
532 		if (glatex_add_menu_on_startup == TRUE||
533 			doc->file_type->id == GEANY_FILETYPES_LATEX)
534 		{
535 			add_menu_to_menubar();
536 		}
537 	}
538 
539 }
540 
541 
on_document_filetype_set(G_GNUC_UNUSED GObject * obj,GeanyDocument * doc,G_GNUC_UNUSED GeanyFiletype * filetype_old,G_GNUC_UNUSED gpointer user_data)542 static void on_document_filetype_set(G_GNUC_UNUSED GObject *obj, GeanyDocument *doc,
543 									 G_GNUC_UNUSED GeanyFiletype *filetype_old,
544 									 G_GNUC_UNUSED gpointer user_data)
545 {
546 	g_return_if_fail(doc != NULL);
547 
548 	if (main_is_realized() == TRUE)
549 	{
550 		toggle_toolbar_items_by_file_type(doc->file_type->id);
551 		check_for_menu(doc->file_type->id);
552 	}
553 }
554 
555 
get_position_relative(ScintillaObject * sci,gint pos,gint n)556 static gint get_position_relative(ScintillaObject *sci, gint pos, gint n)
557 {
558 	return (gint) scintilla_send_message(sci, SCI_POSITIONRELATIVE, (uptr_t) pos, n);
559 }
560 
561 
get_char_relative(ScintillaObject * sci,gint pos,gint n)562 static gint get_char_relative(ScintillaObject *sci, gint pos, gint n)
563 {
564 	return sci_get_char_at(sci, get_position_relative(sci, pos, n));
565 }
566 
567 
on_editor_notify(G_GNUC_UNUSED GObject * object,GeanyEditor * editor,SCNotification * nt,G_GNUC_UNUSED gpointer data)568 static gboolean on_editor_notify(G_GNUC_UNUSED GObject *object, GeanyEditor *editor,
569 									SCNotification *nt, G_GNUC_UNUSED gpointer data)
570 {
571 	ScintillaObject* sci;
572 	gint pos;
573 
574 	g_return_val_if_fail(editor != NULL, FALSE);
575 	sci = editor->sci;
576 	/* Autocompletion for LaTeX specific stuff:
577 	 * Introducing \end{} or \endgroup{} after a \begin{}
578 
579 	 * Function is based on function which was inside
580 	 * Geany's core under terms of GPLv2+
581 	 * EXtended for LaTeX with some more autocompletion features
582 	 * for e.g. _{} and ^{}.*/
583 
584 	if (glatex_autocompletion_active == TRUE &&
585 		!(glatex_autocompletion_only_for_latex == TRUE &&
586 		editor->document->file_type->id != GEANY_FILETYPES_LATEX))
587 	{
588 		pos = sci_get_current_position(sci);
589 
590 		if (nt->nmhdr.code == SCN_CHARADDED)
591 		{
592 			switch (nt->ch)
593 			{
594 				case '\n':
595 				case '\r':
596 				{
597 					if (sci_get_char_at(sci, pos - (editor_get_eol_char_len (editor) + 1)) == '}'||
598 						sci_get_char_at(sci, pos - (editor_get_eol_char_len (editor) + 1)) == ']')
599 					{
600 						gchar *buf, *construct;
601 						/* TODO: Make possible to have longer than a 50 chars environment */
602 						gchar env[50];
603 						gint line = sci_get_line_from_position(sci, pos - (editor_get_eol_char_len (editor) + 1));
604 						gint line_len = sci_get_line_length(sci, line);
605 						gint i, start;
606 						gint indent;
607 						GeanyIndentPrefs* indent_prefs = editor_get_indent_prefs(editor);
608 
609 						/* get the line */
610 						buf = sci_get_line(sci, line);
611 
612 						/* get to the first non-blank char (some kind of ltrim()) */
613 						start = 0;
614 						while (isspace(buf[start]) && buf[start] != '\0')
615 							start++;
616 
617 						/* check for begin for autocompletion of \end{} and \endgr*/
618 						if (strncmp(buf + start, "\\begin", 6) == 0)
619 						{
620 							gchar full_cmd[15];
621 							guint j = 0;
622 
623 							/* take also "\begingroup" (or whatever there can be) and
624 							 * append "\endgroup" and so on. */
625 							i = start + 6;
626 							while (i < line_len && buf[i] != '{' && j < (sizeof(full_cmd) - 1))
627 							{
628 								/* copy all between "\begin" and "{" to full_cmd */
629 								full_cmd[j] = buf[i];
630 								i++;
631 								j++;
632 							}
633 							full_cmd[j] = '\0';
634 
635 							/* go through the line and get the environment */
636 							for (i = start + j; i < line_len; i++)
637 							{
638 								if (buf[i] == '{')
639 								{
640 									j = 0;
641 									i++;
642 									while (buf[i] != '}' && j < (sizeof(env) - 1))
643 									{   /* this could be done in a shorter way,
644 									 	 * but so it remains readable ;-) */
645 										env[j] = buf[i];
646 										j++;
647 										i++;
648 									}
649 									env[j] = '\0';
650 									break;
651 								}
652 							}
653 							/* Search whether the environment is closed within the next
654 							 * lines. We assume, no \end is needed in such cases */
655 							/* TODO using sci_find_text() should be way faster than getting
656 							 *	  the line buffer and performing string comparisons */
657 							for (i = 1; i < glatex_autocompletion_context_size; i++)
658 							{
659 								gchar *tmp;
660 								gchar *end_construct;
661 								tmp = sci_get_line(sci, line + i);
662 
663 								end_construct = g_strdup_printf("\\end%s{%s}", full_cmd, env);
664 								if (strstr(tmp, end_construct) != NULL)
665 								{
666 									/* Clean up everything and quit as nothing
667 									 * needs to be done */
668 									g_free(tmp);
669 									g_free(buf);
670 									g_free(end_construct);
671 									return FALSE;
672 								}
673 								g_free(tmp);
674 								g_free(end_construct);
675 							}
676 
677 							/* After we have this, we need to ensure basic
678 							 * indent is getting applied on closing command */
679 							indent = sci_get_line_indentation(sci, line);
680 
681 							/* Now we build up closing string and insert
682 							 * it into document */
683 							construct = g_strdup_printf("\t\n\\end%s{%s}", full_cmd, env);
684 							editor_insert_text_block(editor, construct, pos,
685 								1, -1, TRUE);
686 							/* ... and setting the indention */
687 							/* If user pressed carriage return, we end up in a new line. This line
688 							 * should be indented one level further than the previous indentation */
689 							sci_set_line_indentation(sci, sci_get_current_line(sci),
690 								indent + indent_prefs->width);
691 							/* Set the cursor position to the end of the new line we're in which
692 							 * has just been indented */
693 							sci_set_current_position(sci, sci_get_line_end_position(sci, sci_get_current_line(sci)), 1);
694 							/* Indentation of the \end{} command, which is now in the next line,
695 							 * should be the same as the previous indentation */
696 							sci_set_line_indentation(sci, sci_get_current_line(sci) + 1,
697 								indent);
698 							g_free(construct);
699 						}
700 						g_free(buf);
701 					}
702 
703 					/* Now we are handling the case, a new line has been inserted
704 					* but no closing braces */
705 					else if (glatex_autobraces_active == TRUE)
706 					{
707 						gint line;
708 
709 						gint line_len;
710 						gint i;
711 						gchar *buf;
712 
713 						line = sci_get_line_from_position(sci, pos -
714 									(editor_get_eol_char_len (editor) + 1));
715 						line_len = sci_get_line_length(sci, line) -
716 									editor_get_eol_char_len (editor);
717 
718 
719 						/* Catching current line which has been 'finished'*/
720 						buf = sci_get_line(sci, line);
721 
722 						/* Searching for either \ or " ", {, } from end of
723 						 * line back to start */
724 						for (i = line_len; i >= 0 ; i--)
725 						{
726 							if (buf[i] == '\\')
727 							{
728 								if ((i > 0 && buf[i-1] != '\\') ||
729 									(i == 0))
730 								{
731 									sci_insert_text(sci,
732 										pos - (editor_get_eol_char_len (editor)), "{}");
733 								}
734 								/* We will stop here in any case */
735 								break;
736 							}
737 							/* Else we want to stop once we found a space,
738 							 * some closing braces somewhere before as we
739 							 * are assuming, manipulating something here
740 							 * would cause a bigger mess. */
741 							else if (buf[i] == ' ' ||
742 									 buf[i] == '}' ||
743 									 buf[i] == '{' ||
744 									 buf[i] == '"')
745 							{
746 								break;
747 							}
748 						}
749 						g_free(buf);
750 					}
751 					break;
752 				} /* Closing case \r or \n */
753 				case '_':
754 				case '^':
755 				{
756 					if (glatex_autobraces_active == TRUE)
757 					{
758 						sci_insert_text(sci, -1, "{}");
759 						sci_set_current_position(sci, pos + 1, TRUE);
760 					}
761 					break;
762 				}
763 				default:
764 				{
765 					if (glatex_capitalize_sentence_starts == TRUE &&
766 						g_ascii_isspace(get_char_relative(sci, pos, -2)))
767 					{
768 						gint prevNonWhite = 0;
769 						gint i;
770 
771 						/* find the previous non-white character */
772 						i = get_position_relative(sci, pos, -3);
773 						while (g_ascii_isspace((prevNonWhite = sci_get_char_at(sci, i))))
774 						{
775 							/* no need to bother about multi-byte characters here since
776 							 * we only check for ASCII space characters anyway */
777 							--i;
778 						}
779 
780 						if (prevNonWhite == '.' ||
781 							prevNonWhite == '!' ||
782 							prevNonWhite == '?')
783 						{
784 							gchar *upperLtr = NULL;
785 							gchar *selection = NULL;
786 
787 							sci_set_selection_start(sci, get_position_relative(sci, pos, -1));
788 							sci_set_selection_end(sci, pos);
789 
790 							selection = sci_get_selection_contents(sci);
791 							upperLtr = g_utf8_strup(selection, -1);
792 							sci_replace_sel(sci, upperLtr);
793 
794 							g_free(upperLtr);
795 							g_free(selection);
796 						}
797 					}
798 					break;
799 				}
800 			} /* Closing switch  */
801 			/* later there could be some else ifs for other keywords */
802 		}
803 	} /* End of latex autocpletion */
804 
805 	/* Toggle special characters on input */
806 	if (editor->document->file_type->id == GEANY_FILETYPES_LATEX &&
807 		toggle_active == TRUE)
808 	{
809 		if (nt->nmhdr.code == SCN_CHARADDED)
810 		{
811 			gchar buf[7];
812 			gint len;
813 			sci = editor->sci;
814 
815 			len = g_unichar_to_utf8(nt->ch, buf);
816 			if (len > 0)
817 			{
818 				const gchar *entity;
819 
820 				buf[len] = '\0';
821 				entity = glatex_get_entity(buf);
822 
823 				if (entity != NULL)
824 				{
825 					pos = sci_get_current_position(sci);
826 
827 					sci_set_selection_start(editor->sci, pos - len);
828 					sci_set_selection_end(editor->sci, pos);
829 
830 					sci_replace_sel(editor->sci, entity);
831 				}
832 			}
833 		}
834 	}
835 	return FALSE;
836 }
837 
838 
on_document_close(G_GNUC_UNUSED GObject * obj,GeanyDocument * doc,G_GNUC_UNUSED gpointer user_data)839 static void on_document_close(G_GNUC_UNUSED GObject *obj, GeanyDocument *doc,
840 					   G_GNUC_UNUSED gpointer user_data)
841 {
842 	g_return_if_fail(doc != NULL);
843 
844 	if (doc->index < 2)
845 		deactivate_toolbar_items();
846 	if (doc->index < 1 &&
847 		glatex_deactivate_menubarentry_with_non_latex == TRUE)
848 		remove_menu_from_menubar();
849 }
850 
851 
852 /* Called when keys were pressed */
glatex_kblatex_toggle(G_GNUC_UNUSED guint key_id)853 static void glatex_kblatex_toggle(G_GNUC_UNUSED guint key_id)
854 {
855 	if (toggle_active == TRUE)
856 		glatex_set_latextoggle_status(FALSE);
857 	else
858 		glatex_set_latextoggle_status(TRUE);
859 }
860 
861 
862 PluginCallback plugin_callbacks[] =
863 {
864 	{ "editor-notify", (GCallback) &on_editor_notify, FALSE, NULL },
865 	{ "document-activate", (GCallback) &on_document_activate, FALSE, NULL },
866 	{ "document-filetype-set", (GCallback) &on_document_filetype_set, FALSE, NULL },
867 	{ "document-new", (GCallback) &on_document_new, FALSE, NULL},
868 	{ "geany-startup-complete", (GCallback) &on_geany_startup_complete, FALSE, NULL },
869 	{ "document-close", (GCallback) &on_document_close, FALSE, NULL},
870 	{ NULL, NULL, FALSE, NULL }
871 };
872 
873 
874 static inline const gchar*
get_latex_command(gint tab_index)875 get_latex_command(gint tab_index)
876 {
877 	return glatex_char_array[tab_index].latex;
878 }
879 
880 
881 static void
char_insert_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,G_GNUC_UNUSED gpointer gdata)882 char_insert_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,
883 					  G_GNUC_UNUSED gpointer gdata)
884 {
885 	glatex_insert_string(get_latex_command(GPOINTER_TO_INT(gdata)), TRUE);
886 }
887 
888 
889 void
glatex_insert_label_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,G_GNUC_UNUSED gpointer gdata)890 glatex_insert_label_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,
891 					   G_GNUC_UNUSED gpointer gdata)
892 {
893 	gchar *input = NULL;
894 
895 	input = dialogs_show_input(_("Insert Label"),
896 								GTK_WINDOW(geany->main_widgets->window),
897 								_("Label name:"),
898 								NULL);
899 
900 	if (input)
901 	{
902 		gchar *label_str = NULL;
903 
904 		label_str = g_strconcat("\\label{",input , "}", NULL);
905 		glatex_insert_string(label_str, TRUE);
906 		g_free(input);
907 		g_free(label_str);
908 	}
909 }
910 
911 
912 void
glatex_insert_command_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,G_GNUC_UNUSED gpointer gdata)913 glatex_insert_command_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,
914 					 G_GNUC_UNUSED gpointer gdata)
915 {
916 
917 	gchar *input = NULL;
918 
919 	input = dialogs_show_input(_("Insert Command"),
920 								GTK_WINDOW(geany->main_widgets->window),
921 								_("Command name:"),
922 								NULL);
923 
924 	if (input)
925 	{
926 		gchar *cmd_str = NULL;
927 
928 		GeanyDocument *doc = document_get_current();
929 
930 		sci_start_undo_action(doc->editor->sci);
931 
932 		cmd_str = g_strdup_printf("\\%s{", input);
933 		glatex_insert_string(cmd_str, TRUE);
934 		/* This shall put the cursor inside the braces */
935 		glatex_insert_string("}", FALSE);
936 
937 		sci_end_undo_action(doc->editor->sci);
938 		g_free(input);
939 		g_free(cmd_str);
940 	}
941 }
942 
943 
944 void
glatex_insert_ref_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,G_GNUC_UNUSED gpointer gdata)945 glatex_insert_ref_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,
946 					 G_GNUC_UNUSED gpointer gdata)
947 {
948 	GtkWidget *dialog;
949 	GtkWidget *vbox = NULL;
950 	GtkWidget *label_ref = NULL;
951 	GtkWidget *textbox_ref = NULL;
952 	GtkWidget *table = NULL;
953 	GtkWidget *radio1 = NULL;
954 	GtkWidget *radio2 = NULL;
955 	GtkWidget *radio3 = NULL;
956 	GtkWidget *tmp_entry = NULL;
957 	GtkTreeModel *model = NULL;
958 	GeanyDocument *doc = NULL;
959 	GSList *file_list = NULL;
960 	gchar *dir;
961 
962 	doc = document_get_current();
963 
964 	dialog = gtk_dialog_new_with_buttons(_("Insert Reference"),
965 						 GTK_WINDOW(geany->main_widgets->window),
966 						 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL,
967 						 GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
968 						 NULL);
969 	vbox = ui_dialog_vbox_new(GTK_DIALOG(dialog));
970 	gtk_widget_set_name(dialog, "GeanyDialog");
971 	gtk_box_set_spacing(GTK_BOX(vbox), 10);
972 
973 	table = gtk_table_new(1, 2, FALSE);
974 	gtk_table_set_col_spacings(GTK_TABLE(table), 6);
975 	gtk_table_set_row_spacings(GTK_TABLE(table), 6);
976 
977 	label_ref = gtk_label_new(_("Reference name:"));
978 	textbox_ref = gtk_combo_box_text_new_with_entry();
979 
980 	if (doc->real_path != NULL)
981 	{
982 		dir = g_path_get_dirname(doc->real_path);
983 		file_list = utils_get_file_list_full(dir, TRUE, TRUE, NULL);
984 		glatex_add_Labels(textbox_ref, file_list);
985 		model = gtk_combo_box_get_model(GTK_COMBO_BOX(textbox_ref));
986 		gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),
987 			0, GTK_SORT_ASCENDING);
988 		g_slist_foreach(file_list, (GFunc) g_free, NULL);
989 		g_slist_free(file_list);
990 		if (dir != NULL)
991 			g_free(dir);
992 	}
993 
994 
995 	gtk_misc_set_alignment(GTK_MISC(label_ref), 0, 0.5);
996 
997 	gtk_table_attach_defaults(GTK_TABLE(table), label_ref, 0, 1, 0, 1);
998 	gtk_table_attach_defaults(GTK_TABLE(table), textbox_ref, 1, 2, 0, 1);
999 	gtk_container_add(GTK_CONTAINER(vbox), table);
1000 
1001 	radio1 = gtk_radio_button_new_with_mnemonic(NULL,
1002 		_("_Standard Reference"));
1003 	gtk_button_set_focus_on_click(GTK_BUTTON(radio1), FALSE);
1004 	gtk_container_add(GTK_CONTAINER(vbox), radio1);
1005 
1006 	radio2 = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio1),
1007 		_("_Page Reference"));
1008 	gtk_button_set_focus_on_click(GTK_BUTTON(radio2), FALSE);
1009 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio2), FALSE);
1010 	gtk_container_add(GTK_CONTAINER(vbox), radio2);
1011 
1012 	radio3 = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio1), _("_Add both"));
1013 	gtk_button_set_focus_on_click(GTK_BUTTON(radio3), FALSE);
1014 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio3), FALSE);
1015 	gtk_container_add(GTK_CONTAINER(vbox), radio3);
1016 
1017 	tmp_entry =  gtk_bin_get_child(GTK_BIN(textbox_ref));
1018 	g_signal_connect(G_OBJECT(tmp_entry), "activate",
1019 		G_CALLBACK(glatex_enter_key_pressed_in_entry), dialog);
1020 
1021 
1022 	gtk_widget_show_all(vbox);
1023 
1024 
1025 	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1026 	{
1027 		gchar *ref_string = NULL;
1028 		GString *template_string = NULL;
1029 
1030 		ref_string = g_strdup(gtk_combo_box_text_get_active_text(
1031 			GTK_COMBO_BOX_TEXT(textbox_ref)));
1032 
1033 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio1)) == TRUE)
1034 		{
1035 			template_string = g_string_new(glatex_ref_chapter_string);
1036 		}
1037 		else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio2))== TRUE)
1038 		{
1039 			template_string = g_string_new(glatex_ref_page_string);
1040 		}
1041 		else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio3))== TRUE)
1042 		{
1043 			template_string = g_string_new(glatex_ref_all_string);
1044 		}
1045 
1046 		if (ref_string != NULL && template_string != NULL)
1047 		{
1048 			gchar *tmp;
1049 			utils_string_replace_all(template_string, "{{reference}}", ref_string);
1050 			tmp = g_string_free(template_string, FALSE);
1051 			glatex_insert_string(tmp, TRUE);
1052 			g_free(ref_string);
1053 			g_free(tmp);
1054 		}
1055 		else
1056 		{
1057 			if (ref_string != NULL)
1058 				g_free(ref_string);
1059 			if (template_string != NULL)
1060 				g_string_free(template_string, TRUE);
1061 		}
1062 	}
1063 
1064 	gtk_widget_destroy(dialog);
1065 }
1066 
1067 
glatex_character_create_menu_item(GtkWidget * menu,const gchar * label,gint letter,MenuCallback callback)1068 static void glatex_character_create_menu_item(GtkWidget *menu, const gchar *label,
1069 									   gint letter, MenuCallback callback)
1070 {
1071 	GtkWidget *tmp;
1072 
1073 	tmp = gtk_menu_item_new_with_label(label);
1074 	gtk_widget_show(tmp);
1075 	gtk_container_add(GTK_CONTAINER(menu), tmp);
1076 	g_signal_connect(tmp, "activate",
1077 		G_CALLBACK(callback), GINT_TO_POINTER(letter));
1078 }
1079 
1080 
1081 /* returns -1, if there are more than gint can work with or any other error
1082  * returns 0, if categorie is empty
1083  * if gint categorie is -1, function will count every element.
1084  * Useful, if there is no need for a categorie check.*/
1085 gint
glatex_count_menu_entries(SubMenuTemplate * tmp,gint categorie)1086 glatex_count_menu_entries(SubMenuTemplate *tmp, gint categorie)
1087 {
1088 	/* TODO: Reset max value to stop before it's too late */
1089 	gint i;
1090 	gint count = 0;
1091 
1092 	if (categorie == -1)
1093 	{
1094 		for (i =1; tmp[i].label != NULL; i++)
1095 		{
1096 			count = count + 1;
1097 		}
1098 	}
1099 	else
1100 	{
1101 		for (i = 1; tmp[i].label != NULL; i++)
1102 		{
1103 			if (tmp[i].cat == categorie)
1104 			{
1105 				count = count + 1;
1106 			}
1107 			if (i >= 256)
1108 			{
1109 				count = -1;
1110 				break;
1111 			}
1112 		}
1113 	}
1114 	return count + 1;
1115 }
1116 
1117 static gint
count_menu_cat_entries(CategoryName * tmp)1118 count_menu_cat_entries(CategoryName *tmp)
1119 {
1120 	gint i;
1121 
1122 	for (i = 0; tmp[i].label != NULL; i++);
1123 	return i;
1124 }
1125 
1126 
glatex_sub_menu_init(GtkWidget * base_menu,SubMenuTemplate * menu_template,CategoryName * category_name,MenuCallback callback_function)1127 static void glatex_sub_menu_init(GtkWidget *base_menu, SubMenuTemplate *menu_template,
1128 				   CategoryName *category_name,
1129 				   MenuCallback callback_function)
1130 {
1131 	gint i;
1132 	gint j;
1133 	gint categories = count_menu_cat_entries(category_name);
1134 	GtkWidget *sub_menu = NULL;
1135 	GtkWidget *sub_menu_cat[categories][2];
1136 	GtkWidget *active_submenu = NULL;
1137 
1138 	/* Creates sub menus based on information from letter.h */
1139 	for (i = 0; i < categories; i++)
1140 	{
1141 		if (glatex_count_menu_entries(menu_template, i) > 0)
1142 		{
1143 			create_sub_menu(base_menu, sub_menu_cat[i][0],
1144 			 sub_menu_cat[i][1], category_name[i].label);
1145 		}
1146 	}
1147 
1148 	/* Searching for all categories */
1149 	for (i = 0; i < categories; i++)
1150 	{
1151 		gboolean split = FALSE;
1152 		gboolean last_sub_menu = FALSE;
1153 		gboolean sorted = category_name[i].sorted;
1154 		/* To check whether we need to build up a new sub sub menu. */
1155 		gint local_count = 0;
1156 		gint item_count = glatex_count_menu_entries(menu_template, i);
1157 
1158 		if (item_count < 1)
1159 			continue;
1160 
1161 		/*  Default is, not to split anything to make menu not */
1162 		/*  deeper than realy needed.  */
1163 		if (item_count > MAX_MENU_ENTRIES)
1164 		{
1165 			split = TRUE;
1166 		}
1167 
1168 		/*  Setting active sub menu to sub menu of category */
1169 		sub_menu = sub_menu_cat[i][0];
1170 		active_submenu = sub_menu;
1171 		/*  Finding entries for each category */
1172 
1173 		for (j = 0; menu_template[j].latex != NULL; j++)
1174 		{
1175 			if (menu_template[j].cat == i)
1176 			{
1177 				/*  Creates a new sub sub menu if needed */
1178 				if (split == TRUE && (local_count % MAX_MENU_ENTRIES) == 0)
1179 				{
1180 					gint next_split_point = 0;
1181 					GtkWidget *tmp = NULL;
1182 					GtkWidget *tmp_item = NULL;
1183 
1184 					sub_menu = active_submenu;
1185 
1186 					for (next_split_point = 0;
1187 						next_split_point < MAX_MENU_ENTRIES ; next_split_point ++)
1188 					{
1189 						if (menu_template[j+next_split_point].cat != i)
1190 						{
1191 							last_sub_menu = TRUE;
1192 							break;
1193 						}
1194 
1195 					}
1196 
1197 					if (sorted == TRUE)
1198 					{
1199 						create_sub_menu(sub_menu_cat[i][0], tmp, tmp_item,
1200 						g_strconcat(menu_template[j].label, " ... ",
1201 						menu_template[j + next_split_point-1].label, NULL));
1202 
1203 						sub_menu = tmp;
1204 					}
1205 					else if (sorted == FALSE)
1206 					{
1207 						if (last_sub_menu == FALSE)
1208 						{
1209 							create_sub_menu(sub_menu, tmp, tmp_item, _("More"));
1210 							sub_menu = active_submenu;
1211 							active_submenu = tmp;
1212 						}
1213 					}
1214 				}
1215 
1216 				/*  Sets the counter to keep in track if a new ,,
1217 				 *  submenu needs to be build up */
1218 				local_count = local_count + 1;
1219 				glatex_character_create_menu_item(sub_menu, g_strconcat(
1220 					menu_template[j].label, "\t", menu_template[j].latex,
1221 					NULL), j, callback_function);
1222 			}
1223 		}
1224 	}
1225 }
1226 
1227 static int
find_latex_enc(gint l_geany_enc)1228 find_latex_enc(gint l_geany_enc)
1229 {
1230 	guint i;
1231 	for (i = 0; i < LATEX_ENCODINGS_MAX; i++)
1232 	{
1233 		if (latex_encodings[i].geany_enc == l_geany_enc)
1234 			return i;
1235 	}
1236 	return LATEX_ENCODING_NONE;
1237 }
1238 
1239 
1240 static void
show_output(const gchar * output,const gchar * name,const gint local_enc)1241 show_output(const gchar * output, const gchar * name, const gint local_enc)
1242 {
1243 	GeanyDocument *doc = NULL;
1244 	GeanyFiletype *ft = filetypes_lookup_by_name("LaTeX");
1245 
1246 	if (output)
1247 	{
1248 		doc = document_new_file(name, ft, output);
1249 		document_set_encoding(doc, encodings_get_charset_from_index
1250 			(latex_encodings[local_enc].geany_enc));
1251 	}
1252 }
1253 
glatex_insert_usepackage_dialog(G_GNUC_UNUSED GtkMenuItem * menuitem,G_GNUC_UNUSED gpointer gdata)1254 void glatex_insert_usepackage_dialog(G_GNUC_UNUSED GtkMenuItem * menuitem,
1255 									 G_GNUC_UNUSED gpointer gdata)
1256 {
1257 	GtkWidget *dialog = NULL;
1258 	GtkWidget *vbox = NULL;
1259 	GtkWidget *label = NULL;
1260 	GtkWidget *textbox = NULL;
1261 	GtkWidget *table = NULL;
1262 	GtkWidget *label_options = NULL;
1263 	GtkWidget *textbox_options = NULL;
1264 
1265 	dialog = gtk_dialog_new_with_buttons(_("Add additional package"),
1266 						 GTK_WINDOW(geany->main_widgets->window),
1267 						 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL,
1268 						 GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1269 						 NULL);
1270 	vbox = ui_dialog_vbox_new(GTK_DIALOG(dialog));
1271 	gtk_widget_set_name(dialog, "GeanyDialog");
1272 	gtk_box_set_spacing(GTK_BOX(vbox), 10);
1273 
1274 	table = gtk_table_new(1, 2, FALSE);
1275 	gtk_table_set_col_spacings(GTK_TABLE(table), 6);
1276 	gtk_table_set_row_spacings(GTK_TABLE(table), 6);
1277 
1278 	label = gtk_label_new(_("Package name:"));
1279 	textbox = gtk_entry_new();
1280 
1281 	label_options = gtk_label_new(_("Package options:"));
1282 	textbox_options = gtk_entry_new();
1283 
1284 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1285 	gtk_misc_set_alignment(GTK_MISC(label_options), 0, 0.5);
1286 
1287 	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1288 	gtk_table_attach_defaults(GTK_TABLE(table), textbox, 1, 2, 0, 1);
1289 	gtk_table_attach_defaults(GTK_TABLE(table), label_options, 0, 1, 1, 2);
1290 	gtk_table_attach_defaults(GTK_TABLE(table), textbox_options, 1, 2, 1, 2);
1291 
1292 	gtk_container_add(GTK_CONTAINER(vbox), table);
1293 
1294 	g_signal_connect(G_OBJECT(textbox), "activate",
1295 		G_CALLBACK(glatex_enter_key_pressed_in_entry), dialog);
1296 	g_signal_connect(G_OBJECT(textbox_options), "activate",
1297 		G_CALLBACK(glatex_enter_key_pressed_in_entry), dialog);
1298 
1299 	gtk_widget_show_all(vbox);
1300 
1301 	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1302 	{
1303 		const gchar *pkg = NULL;
1304 		const gchar *option = NULL;
1305 		pkg = gtk_entry_get_text(GTK_ENTRY(textbox));
1306 		option = gtk_entry_get_text(GTK_ENTRY(textbox_options));
1307 		glatex_usepackage(pkg, option);
1308 	}
1309 
1310 	gtk_widget_destroy(dialog);
1311 
1312 }
1313 
1314 void
on_insert_bibtex_dialog_activate(G_GNUC_UNUSED GtkMenuItem * menuitem,G_GNUC_UNUSED gpointer gdata)1315 on_insert_bibtex_dialog_activate(G_GNUC_UNUSED GtkMenuItem *menuitem,
1316 								 G_GNUC_UNUSED gpointer gdata)
1317 {
1318 	GtkWidget *dialog;
1319 	GtkWidget *vbox = NULL;
1320 	GtkWidget *label= NULL;
1321 	GtkWidget *textbox = NULL;
1322 	GtkWidget *table = NULL;
1323 	GtkWidget *tmp_entry = NULL;
1324 	GtkTreeModel *model = NULL;
1325 	GeanyDocument *doc = NULL;
1326 
1327 	doc = document_get_current();
1328 
1329 	dialog = gtk_dialog_new_with_buttons(_("Insert BibTeX Reference"),
1330 						 GTK_WINDOW(geany->main_widgets->window),
1331 						 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL,
1332 						 GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1333 						 NULL);
1334 	vbox = ui_dialog_vbox_new(GTK_DIALOG(dialog));
1335 	gtk_widget_set_name(dialog, "GeanyDialog");
1336 	gtk_box_set_spacing(GTK_BOX(vbox), 10);
1337 
1338 	table = gtk_table_new(1, 2, FALSE);
1339 	gtk_table_set_col_spacings(GTK_TABLE(table), 6);
1340 	gtk_table_set_row_spacings(GTK_TABLE(table), 6);
1341 
1342 	label = gtk_label_new(_("BibTeX reference name:"));
1343 	textbox = gtk_combo_box_text_new_with_entry();
1344 
1345 	if (doc->real_path != NULL)
1346 	{
1347 		GDir *dir;
1348 		gchar *tmp_dir;
1349 		const gchar *filename = NULL;
1350 
1351 		tmp_dir = g_path_get_dirname(doc->real_path);
1352 		dir = g_dir_open(tmp_dir, 0, NULL);
1353 
1354 		if(dir == NULL)
1355 			g_free(tmp_dir);
1356 		g_return_if_fail(dir != NULL);
1357 
1358 		foreach_dir(filename, dir)
1359 		{
1360 			gchar *fullpath = NULL;
1361 			fullpath = g_build_path(G_DIR_SEPARATOR_S, tmp_dir, filename, NULL);
1362 
1363 			glatex_parse_bib_file(fullpath, textbox);
1364 			g_free(fullpath);
1365 		}
1366 		g_free(tmp_dir);
1367 		g_dir_close(dir);
1368 		model = gtk_combo_box_get_model(GTK_COMBO_BOX(textbox));
1369 		gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),
1370 			0, GTK_SORT_ASCENDING);
1371 	}
1372 
1373 
1374 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1375 
1376 	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1377 	gtk_table_attach_defaults(GTK_TABLE(table), textbox, 1, 2, 0, 1);
1378 	gtk_container_add(GTK_CONTAINER(vbox), table);
1379 
1380 	tmp_entry = gtk_bin_get_child(GTK_BIN(textbox));
1381 	g_signal_connect(G_OBJECT(tmp_entry), "activate",
1382 		G_CALLBACK(glatex_enter_key_pressed_in_entry), dialog);
1383 
1384 	gtk_widget_show_all(vbox);
1385 
1386 	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1387 	{
1388 		gchar *ref_string = NULL;
1389 		GString *template_string = NULL;
1390 
1391 		ref_string = g_strdup(gtk_combo_box_text_get_active_text(
1392 			GTK_COMBO_BOX_TEXT(textbox)));
1393 
1394 		if (ref_string != NULL)
1395 		{
1396 			glatex_bibtex_insert_cite(ref_string, NULL);
1397 			g_free(ref_string);
1398 		}
1399 		else
1400 		{
1401 			g_free(ref_string);
1402 			g_free(template_string);
1403 		}
1404 	}
1405 
1406 	gtk_widget_destroy(dialog);
1407 }
1408 
1409 
1410 static void
on_wizard_response(G_GNUC_UNUSED GtkDialog * dialog,gint response,G_GNUC_UNUSED gpointer user_data)1411 on_wizard_response(G_GNUC_UNUSED GtkDialog *dialog, gint response,
1412 				   G_GNUC_UNUSED gpointer user_data)
1413 {
1414 	GString *code = NULL;
1415 	gchar *author = NULL;
1416 	gchar *date = NULL;
1417 	gchar *output = NULL;
1418 	gchar *classoptions = NULL;
1419 	gchar *title = NULL;
1420 	gchar *enc_latex_char = NULL;
1421 	gchar *documentclass_str = NULL;
1422 	gchar *papersize = NULL;
1423 	gchar *draft = NULL;
1424 	gchar *fontsize = NULL;
1425 	gchar *orientation_string = NULL;
1426 	gboolean KOMA_active = FALSE;
1427 	gboolean draft_active = FALSE;
1428 	guint template_int;
1429 	gint documentclass_int;
1430 	gint encoding_int;
1431 	gint papersize_int;
1432 	gint paperorientation_int;
1433 
1434 	if (response == GTK_RESPONSE_OK ||
1435 		response == GTK_RESPONSE_APPLY ||
1436 		response == GTK_RESPONSE_ACCEPT)
1437 	{
1438 		KOMA_active = gtk_toggle_button_get_active(
1439 			GTK_TOGGLE_BUTTON(glatex_wizard.checkbox_KOMA));
1440 		draft_active = gtk_toggle_button_get_active(
1441 			GTK_TOGGLE_BUTTON(glatex_wizard.checkbox_draft));
1442 		documentclass_int = gtk_combo_box_get_active(
1443 			GTK_COMBO_BOX(glatex_wizard.documentclass_combobox));
1444 		template_int = gtk_combo_box_get_active(
1445 			GTK_COMBO_BOX(glatex_wizard.template_combobox));
1446 		encoding_int = gtk_combo_box_get_active(
1447 			GTK_COMBO_BOX(glatex_wizard.encoding_combobox));
1448 		/* We don't want to set an encoding, if there is none choosen */
1449 		if (encoding_int != LATEX_ENCODINGS_MAX)
1450 		{
1451 			enc_latex_char = g_strconcat("\\usepackage[",
1452 				latex_encodings[encoding_int].latex,"]{inputenc}\n", NULL);
1453 		}
1454 		fontsize = gtk_combo_box_text_get_active_text(
1455 			GTK_COMBO_BOX_TEXT(glatex_wizard.fontsize_combobox));
1456 		author = g_strdup(gtk_entry_get_text(GTK_ENTRY(glatex_wizard.author_textbox)));
1457 		date = g_strdup(gtk_entry_get_text(GTK_ENTRY(glatex_wizard.date_textbox)));
1458 		title = g_strdup(gtk_entry_get_text(GTK_ENTRY(glatex_wizard.title_textbox)));
1459 		papersize_int = gtk_combo_box_get_active(
1460 			GTK_COMBO_BOX(glatex_wizard.papersize_combobox));
1461 		paperorientation_int = gtk_combo_box_get_active(
1462 			GTK_COMBO_BOX(glatex_wizard.orientation_combobox));
1463 
1464 		if (KOMA_active == TRUE)
1465 		{
1466 			switch (papersize_int)
1467 			{
1468 				case 0:
1469 				{
1470 					papersize = g_utf8_casefold("paper=a4", -1);
1471 					break;
1472 				}
1473 				case 1:
1474 				{
1475 					papersize = g_utf8_casefold("paper=a5", -1);
1476 					break;
1477 				}
1478 				case 2:
1479 				{
1480 					papersize = g_utf8_casefold("paper=a6", -1);
1481 					break;
1482 				}
1483 			}
1484 
1485 		}
1486 		else
1487 		{
1488 			switch (papersize_int)
1489 			{
1490 				case 0:
1491 				{
1492 					papersize = g_utf8_casefold("a4paper", -1);
1493 					break;
1494 				}
1495 				case 1:
1496 				{
1497 					papersize = g_utf8_casefold("a5paper", -1);
1498 					break;
1499 				}
1500 				case 2:
1501 				{
1502 					papersize = g_utf8_casefold("a6paper", -1);
1503 					break;
1504 				}
1505 			}
1506 		}
1507 
1508 		if (papersize != NULL)
1509 		{
1510 			classoptions = g_strdup(papersize);
1511 			g_free(papersize);
1512 		}
1513 
1514 		switch (paperorientation_int)
1515 		{
1516 			case 2:
1517 			{
1518 				if (KOMA_active == TRUE)
1519 				{
1520 					orientation_string = g_utf8_casefold("paper=landscape", -1);
1521 				}
1522 				else
1523 				{
1524 					orientation_string = g_utf8_casefold("landscape", -1);
1525 				}
1526 				break;
1527 			}
1528 			/* 1 and default currently not handled differently, but
1529 			 * already inside for future use. Dear future me, sorry */
1530 			case 1:
1531 			default:
1532 			{
1533 				orientation_string = g_utf8_casefold("", -1);
1534 				break;
1535 			}
1536 		}
1537 		if (classoptions != NULL && !EMPTY(orientation_string))
1538 		{
1539 			classoptions = g_strconcat(classoptions, ",", orientation_string, NULL);
1540 			g_free(orientation_string);
1541 		}
1542 
1543 		if (classoptions != NULL && draft_active == TRUE)
1544 		{
1545 			draft = g_utf8_casefold("draft", -1);
1546 			classoptions = g_strconcat(classoptions,",", draft, NULL);
1547 			g_free(draft);
1548 		}
1549 		else if (classoptions == NULL && draft_active == TRUE)
1550 		{
1551 			draft = g_utf8_casefold("draft", -1);
1552 			classoptions = g_strconcat(draft, NULL);
1553 			g_free(draft);
1554 		}
1555 		if (classoptions != NULL && !EMPTY(fontsize))
1556 		{
1557 			classoptions = g_strconcat(classoptions, ",", fontsize, NULL);
1558 		}
1559 		else if (classoptions == NULL && !EMPTY(fontsize))
1560 		{
1561 			classoptions = g_strdup(fontsize);
1562 		}
1563 		g_free(fontsize);
1564 
1565 
1566 		switch (documentclass_int)
1567 		{
1568 			case 0:
1569 			{
1570 				documentclass_str = g_utf8_casefold("book", -1);
1571 				break;
1572 			}
1573 			case 1:
1574 			{
1575 				documentclass_str = g_utf8_casefold("article", -1);
1576 				break;
1577 			}
1578 			case 2:
1579 			{
1580 				documentclass_str = g_utf8_casefold("report", -1);
1581 				break;
1582 			}
1583 			case 3:
1584 			{
1585 				documentclass_str = g_utf8_casefold("letter", -1);
1586 				break;
1587 			}
1588 			case 4:
1589 			{
1590 				documentclass_str = g_utf8_casefold("beamer", -1);
1591 			}
1592 		}
1593 
1594 		if (KOMA_active)
1595 		{
1596 			switch (documentclass_int)
1597 			{
1598 				case 0:
1599 				{
1600 					documentclass_str = g_utf8_casefold("scrbook", -1);
1601 					break;
1602 				}
1603 				case 1:
1604 				{
1605 					documentclass_str = g_utf8_casefold("scrartcl", -1);
1606 					break;
1607 				}
1608 				case 2:
1609 				{
1610 					documentclass_str = g_utf8_casefold("scrreprt", -1);
1611 					break;
1612 				}
1613 			}
1614 
1615 		}
1616 
1617 		/*  Get the correct template */
1618 		/*  First check whether its a build in one or a custom one than
1619 		 *  assign the wished template */
1620 		if (template_int < LATEX_WIZARD_TEMPLATE_END ||
1621 			glatex_wizard.template_list == NULL)
1622 		{
1623 			if (template_int == LATEX_WIZARD_TEMPLATE_DEFAULT)
1624 				code = g_string_new(TEMPLATE_LATEX);
1625 			else if (documentclass_int == 3)
1626 				code = g_string_new(TEMPLATE_LATEX_LETTER);
1627 			else if (documentclass_int == 4)
1628 				code = g_string_new(TEMPLATE_LATEX_BEAMER);
1629 			else
1630 				code = g_string_new(TEMPLATE_LATEX);
1631 		}
1632 		else
1633 		{
1634 			TemplateEntry *tmp = NULL;
1635 
1636 			/* Return if the value choose is for some uknown reason to high */
1637 			if (template_int > (glatex_wizard.template_list->len + LATEX_WIZARD_TEMPLATE_END))
1638 				return;
1639 
1640 			tmp = g_ptr_array_index(glatex_wizard.template_list, template_int - LATEX_WIZARD_TEMPLATE_END);
1641 			code = glatex_get_template_from_file(tmp->filepath);
1642 
1643 			/* Cleaning up template array as there is no usage for anymore */
1644 			g_ptr_array_foreach (glatex_wizard.template_list, (GFunc)glatex_free_template_entry, NULL);
1645 			g_ptr_array_free(glatex_wizard.template_list, TRUE);
1646 		}
1647 
1648 		if (code != NULL)
1649 		{
1650 			if (classoptions != NULL)
1651 			{
1652 				utils_string_replace_all(code, "{CLASSOPTION}", classoptions);
1653 				g_free(classoptions);
1654 			}
1655 			if (documentclass_str != NULL)
1656 			{
1657 				utils_string_replace_all(code, "{DOCUMENTCLASS}", documentclass_str);
1658 				g_free(documentclass_str);
1659 			}
1660 			if (enc_latex_char != NULL)
1661 			{
1662 				utils_string_replace_all(code, "{ENCODING}", enc_latex_char);
1663 				g_free(enc_latex_char);
1664 			}
1665 			else
1666 			/* If there is no encoding proberly set but {ENCODING} is set inside
1667 			 * the template, replace it with nothing */
1668 			{
1669 				utils_string_replace_all(code, "{ENCODING}", "");
1670 			}
1671 			switch (paperorientation_int){
1672 				case 2:
1673 				{
1674 					utils_string_replace_all(code, "{GEOMETRY}",
1675 						"\\usepackage[landscape]{geometry}\n");
1676 					break;
1677 				}
1678 				default:
1679 				{
1680 					utils_string_replace_all(code, "{GEOMETRY}", "");
1681 					break;
1682 				}
1683 			}
1684 			if (!EMPTY(author))
1685 			{
1686 				gchar* author_string = NULL;
1687 				if (documentclass_int == 3)
1688 				{
1689 					author_string = g_strconcat("\\signature{", author, "}\n", NULL);
1690 				}
1691 				else
1692 				{
1693 					author_string = g_strconcat("\\author{", author, "}\n", NULL);
1694 				}
1695 				utils_string_replace_all(code, "{AUTHOR}", author_string);
1696 				g_free(author);
1697 				g_free(author_string);
1698 			}
1699 			else
1700 			{
1701 				gchar* author_string = NULL;
1702 				if (documentclass_int == 3)
1703 				{
1704 					utils_string_replace_all(code, "{AUTHOR}", "% \\signature{}\n");
1705 				}
1706 				else
1707 				{
1708 					utils_string_replace_all(code, "{AUTHOR}", "% \\author{}\n");
1709 				}
1710 				utils_string_replace_all(code, "{AUTHOR}", author_string);
1711 				if (author != NULL)
1712 				{
1713 					g_free(author);
1714 				}
1715 				g_free(author_string);
1716 			}
1717 
1718 			if (!EMPTY(date))
1719 			{
1720 				gchar *date_string = NULL;
1721 				date_string = g_strconcat("\\date{", date, "}\n", NULL);
1722 				utils_string_replace_all(code, "{DATE}", date_string);
1723 				g_free(date);
1724 				g_free(date_string);
1725 			}
1726 			else
1727 			{
1728 				utils_string_replace_all(code, "{DATE}", "% \\date{}\n");
1729 				if (date != NULL)
1730 				{
1731 					g_free(date);
1732 				}
1733 			}
1734 
1735 			if (title != NULL)
1736 			{
1737 				gchar *title_string = NULL;
1738 				if (documentclass_int == 3)
1739 				{
1740 					title_string = g_strconcat("\\subject{", title, "}\n", NULL);
1741 				}
1742 				else
1743 				{
1744 					title_string = g_strconcat("\\title{", title, "}\n", NULL);
1745 				}
1746 
1747 				utils_string_replace_all(code, "{TITLE}", title_string);
1748 				g_free(title);
1749 				g_free(title_string);
1750 			}
1751 			else
1752 			{
1753 				if (documentclass_int == 3)
1754 				{
1755 					utils_string_replace_all(code, "{TITLE}", "% \\subject{} \n");
1756 				}
1757 				else
1758 				{
1759 					utils_string_replace_all(code, "{TITLE}", "% \\title{} \n");
1760 				}
1761 				if (title != NULL)
1762 				{
1763 					g_free(title);
1764 				}
1765 			}
1766 			utils_string_replace_all(code, "{OPENING}", _("Dear Sir or Madame"));
1767 			utils_string_replace_all(code, "{CLOSING}", _("With kind regards"));
1768 
1769 			output = g_string_free(code, FALSE);
1770 			show_output(output, NULL, encoding_int);
1771 			g_free(output);
1772 		}
1773 		else
1774 		{
1775 			g_warning(_("No template assigned. Aborting"));
1776 		}
1777 	}
1778 	gtk_widget_destroy(GTK_WIDGET(dialog));
1779 }
1780 
1781 void
glatex_wizard_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,G_GNUC_UNUSED gpointer gdata)1782 glatex_wizard_activated(G_GNUC_UNUSED GtkMenuItem * menuitem,
1783 				 G_GNUC_UNUSED gpointer gdata)
1784 {
1785 	gint i;
1786 	gchar *author;
1787 	GtkWidget *dialog = NULL;
1788 	GtkWidget *vbox = NULL;
1789 	GtkWidget *label_documentclass = NULL;
1790 	GtkWidget *label_encoding = NULL;
1791 	GtkWidget *label_fontsize = NULL;
1792 	GtkWidget *table = NULL;
1793 	GtkWidget *label_author = NULL;
1794 	GtkWidget *label_date = NULL;
1795 	GtkWidget *label_title = NULL;
1796 	GtkWidget *label_papersize = NULL;
1797 	GtkWidget *label_template = NULL;
1798 	GtkWidget *label_orientation = NULL;
1799 	GtkWidget *fontsize_entry = NULL;
1800 
1801 	/*  Building the wizard-dialog and showing it */
1802 	dialog = gtk_dialog_new_with_buttons(_("LaTeX-Wizard"),
1803 				GTK_WINDOW(geany->main_widgets->window),
1804 				GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL,
1805 				GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1806 				NULL);
1807 	gtk_widget_set_name(dialog, "GeanyDialog");
1808 
1809 	/*  Creating and formatting table */
1810 	table = gtk_table_new(2, 6, FALSE);
1811 	gtk_table_set_col_spacings(GTK_TABLE(table), 6);
1812 	gtk_table_set_row_spacings(GTK_TABLE(table), 6);
1813 
1814 	/*  Templates
1815 	 *  Adds custom templates if there are any. If there are none just
1816 	 *  adds default one */
1817 	label_template = gtk_label_new(_("Template:"));
1818 
1819 	glatex_wizard.template_combobox = gtk_combo_box_text_new();
1820 	gtk_widget_set_tooltip_text(glatex_wizard.template_combobox,
1821 		_("Set the template which should be used for creating the new document"));
1822 	gtk_misc_set_alignment(GTK_MISC(label_template), 0, 0.5);
1823 
1824 	gtk_table_attach_defaults(GTK_TABLE(table), label_template, 0, 1, 0, 1);
1825 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.template_combobox, 1, 2, 0, 1);
1826 
1827 	/*  Adding default/build in templates to pull down and set the generic
1828 	 * 	one as default */
1829 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.template_combobox),
1830 		LATEX_WIZARD_TEMPLATE_DEFAULT, _("Default"));
1831 	gtk_combo_box_set_active(GTK_COMBO_BOX(glatex_wizard.template_combobox),
1832 		LATEX_WIZARD_TEMPLATE_DEFAULT);
1833 
1834 	/*  Checking whether some custom template are available and adding
1835 	 *  if so.
1836 	 *  Also init array with templates available. */
1837 	glatex_wizard.template_list = glatex_init_custom_templates();
1838 	glatex_add_templates_to_combobox(glatex_wizard.template_list, glatex_wizard.template_combobox);
1839 
1840 	/*  Documentclass */
1841 	label_documentclass = gtk_label_new(_("Documentclass:"));
1842 	glatex_wizard.documentclass_combobox = gtk_combo_box_text_new();
1843 	gtk_widget_set_tooltip_text(glatex_wizard.documentclass_combobox,
1844 		_("Choose the kind of document you want to write"));
1845 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.documentclass_combobox), 0,
1846 		_("Book"));
1847 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.documentclass_combobox), 1,
1848 		_("Article"));
1849 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.documentclass_combobox), 2,
1850 		_("Report"));
1851 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.documentclass_combobox), 3,
1852 		_("Letter"));
1853 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.documentclass_combobox), 4,
1854 		_("Presentation"));
1855 
1856 	gtk_combo_box_set_active(GTK_COMBO_BOX(glatex_wizard.documentclass_combobox), 0);
1857 
1858 	gtk_misc_set_alignment(GTK_MISC(label_documentclass), 0, 0.5);
1859 
1860 	gtk_table_attach_defaults(GTK_TABLE(table), label_documentclass, 0, 1, 1, 2);
1861 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.documentclass_combobox, 1, 2, 1, 2);
1862 
1863 	/*  Encoding */
1864 	label_encoding = gtk_label_new(_("Encoding:"));
1865 
1866 	glatex_wizard.encoding_combobox = gtk_combo_box_text_new();
1867 	gtk_widget_set_tooltip_text(glatex_wizard.encoding_combobox,
1868 		_("Set the encoding for your new document"));
1869 	for (i = 0; i < LATEX_ENCODINGS_MAX; i++)
1870 	{
1871 		gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.encoding_combobox), i,
1872 					  latex_encodings[i].name);
1873 	}
1874 
1875 	gtk_combo_box_set_active(GTK_COMBO_BOX(glatex_wizard.encoding_combobox),
1876 		find_latex_enc(geany_data->file_prefs->default_new_encoding));
1877 
1878 	gtk_misc_set_alignment(GTK_MISC(label_encoding), 0, 0.5);
1879 
1880 	gtk_table_attach_defaults(GTK_TABLE(table), label_encoding, 0, 1, 2, 3);
1881 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.encoding_combobox, 1, 2, 2, 3);
1882 
1883 	/*  fontsize */
1884 	label_fontsize = gtk_label_new(_("Font size"));
1885 	glatex_wizard.fontsize_combobox = gtk_combo_box_text_new_with_entry();
1886 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(glatex_wizard.fontsize_combobox),"10pt");
1887 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(glatex_wizard.fontsize_combobox),"11pt");
1888 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(glatex_wizard.fontsize_combobox),"12pt");
1889 	gtk_widget_set_tooltip_text(glatex_wizard.fontsize_combobox,
1890 		_("Set the default font size of your new document"));
1891 
1892 	gtk_misc_set_alignment(GTK_MISC(label_fontsize), 0, 0.5);
1893 
1894 	gtk_table_attach_defaults(GTK_TABLE(table), label_fontsize, 0, 1, 3, 4);
1895 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.fontsize_combobox, 1, 2, 3, 4);
1896 
1897 	fontsize_entry =  gtk_bin_get_child(GTK_BIN(glatex_wizard.fontsize_combobox));
1898 	g_signal_connect(G_OBJECT(fontsize_entry), "activate",
1899 		G_CALLBACK(glatex_enter_key_pressed_in_entry), dialog);
1900 
1901 	/*  Author */
1902 	label_author = gtk_label_new(_("Author:"));
1903 	glatex_wizard.author_textbox = gtk_entry_new();
1904 	gtk_widget_set_tooltip_text(glatex_wizard.author_textbox,
1905 		_("Sets the value of the \\author command. In most cases this should be your name"));
1906 	if (geany_data->template_prefs->developer != NULL)
1907 	{
1908 		author = geany_data->template_prefs->developer;
1909 		gtk_entry_set_text(GTK_ENTRY(glatex_wizard.author_textbox), author);
1910 	}
1911 	gtk_misc_set_alignment(GTK_MISC(label_author), 0, 0.5);
1912 	gtk_table_attach_defaults(GTK_TABLE(table), label_author, 0, 1, 4, 5);
1913 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.author_textbox, 1, 2, 4, 5);
1914 
1915 	g_signal_connect(G_OBJECT(glatex_wizard.author_textbox), "activate",
1916 		G_CALLBACK(glatex_enter_key_pressed_in_entry), dialog);
1917 
1918 	/*  Date */
1919 	label_date = gtk_label_new(_("Date:"));
1920 	glatex_wizard.date_textbox = gtk_entry_new();
1921 	gtk_widget_set_tooltip_text(glatex_wizard.date_textbox,
1922 		_("Sets the value of the \\date command inside header of your "
1923 		 "new created LaTeX-document. Keeping it at \\today is a good "
1924 		 "decision if you don't need any fixed date."));
1925 	gtk_entry_set_text(GTK_ENTRY(glatex_wizard.date_textbox), "\\today");
1926 	gtk_misc_set_alignment(GTK_MISC(label_date), 0, 0.5);
1927 	gtk_table_attach_defaults(GTK_TABLE(table), label_date, 0, 1, 5, 6);
1928 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.date_textbox, 1, 2, 5, 6);
1929 
1930 	g_signal_connect(G_OBJECT(glatex_wizard.date_textbox), "activate",
1931 		G_CALLBACK(glatex_enter_key_pressed_in_entry), dialog);
1932 
1933 	/*  Title of the new document */
1934 	label_title = gtk_label_new(_("Title:"));
1935 	glatex_wizard.title_textbox = gtk_entry_new();
1936 	gtk_widget_set_tooltip_text(glatex_wizard.title_textbox,
1937 		_("Sets the title of your new document."));
1938 	gtk_misc_set_alignment(GTK_MISC(label_title), 0, 0.5);
1939 	gtk_table_attach_defaults(GTK_TABLE(table), label_title, 0, 1, 6, 7);
1940 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.title_textbox, 1, 2, 6, 7);
1941 
1942 	g_signal_connect(G_OBJECT(glatex_wizard.title_textbox), "activate",
1943 		G_CALLBACK(glatex_enter_key_pressed_in_entry), dialog);
1944 
1945 	/*  Papersize */
1946 	label_papersize = gtk_label_new(_("Paper size:"));
1947 	glatex_wizard.papersize_combobox = gtk_combo_box_text_new();
1948 	gtk_widget_set_tooltip_text(glatex_wizard.papersize_combobox,
1949 		_("Choose the paper format for the newly created document"));
1950 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.papersize_combobox), 0, "A4");
1951 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.papersize_combobox), 1, "A5");
1952 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.papersize_combobox), 2, "A6");
1953 
1954 	gtk_combo_box_set_active(GTK_COMBO_BOX(glatex_wizard.papersize_combobox), 0);
1955 
1956 	gtk_misc_set_alignment(GTK_MISC(label_papersize), 0, 0.5);
1957 
1958 	gtk_table_attach_defaults(GTK_TABLE(table), label_papersize, 0, 1, 7, 8);
1959 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.papersize_combobox, 1, 2, 7, 8);
1960 
1961 	/* Paper direction */
1962 	label_orientation = gtk_label_new(_("Paper Orientation:"));
1963 	glatex_wizard.orientation_combobox = gtk_combo_box_text_new();
1964 	gtk_widget_set_tooltip_text(glatex_wizard.orientation_combobox,
1965 		_("Choose the paper orientation for the newly created document"));
1966 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.orientation_combobox), 0, "Default");
1967 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.orientation_combobox), 1, "Portrait");
1968 	gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(glatex_wizard.orientation_combobox), 2, "Landscape");
1969 
1970 	gtk_combo_box_set_active(GTK_COMBO_BOX(glatex_wizard.orientation_combobox), 0);
1971 
1972 	gtk_misc_set_alignment(GTK_MISC(label_orientation), 0, 0.5);
1973 
1974 	gtk_table_attach_defaults(GTK_TABLE(table), label_orientation, 0, 1, 8, 9);
1975 	gtk_table_attach_defaults(GTK_TABLE(table), glatex_wizard.orientation_combobox, 1, 2, 8, 9);
1976 
1977 
1978 	/* Doing the rest .... */
1979 	gtk_widget_show_all(table);
1980 
1981 	vbox = ui_dialog_vbox_new(GTK_DIALOG(dialog));
1982 	gtk_box_set_spacing(GTK_BOX(vbox), 10);
1983 	gtk_container_add(GTK_CONTAINER(vbox), table);
1984 
1985 	glatex_wizard.checkbox_KOMA = gtk_check_button_new_with_label(
1986 		_("Use KOMA-script classes if possible"));
1987 	gtk_widget_set_tooltip_text(glatex_wizard.checkbox_KOMA,
1988 		_("Uses the KOMA-script classes by Markus Kohm.\n"
1989 		"Keep in mind: To compile your document these classes "
1990 		"have to be installed before."));
1991 	gtk_button_set_focus_on_click(GTK_BUTTON(glatex_wizard.checkbox_KOMA), FALSE);
1992 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(glatex_wizard.checkbox_KOMA), glatex_set_koma_active);
1993 	gtk_box_pack_start(GTK_BOX(vbox), glatex_wizard.checkbox_KOMA, FALSE, FALSE, 5);
1994 
1995 	glatex_wizard.checkbox_draft = gtk_check_button_new_with_label(_("Use draft mode"));
1996 	gtk_widget_set_tooltip_text(glatex_wizard.checkbox_draft,
1997 		_("Set the draft flag inside new created documents to get "
1998 		"documents with a number of debugging helpers"));
1999 	gtk_button_set_focus_on_click(GTK_BUTTON(glatex_wizard.checkbox_draft), FALSE);
2000 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(glatex_wizard.checkbox_draft), FALSE);
2001 	gtk_box_pack_start(GTK_BOX(vbox), glatex_wizard.checkbox_draft, FALSE, FALSE, 5);
2002 	g_signal_connect(dialog, "response", G_CALLBACK(on_wizard_response), NULL);
2003 
2004 	gtk_widget_show_all(dialog);
2005 }
2006 
init_keybindings(void)2007 static void init_keybindings(void)
2008 {
2009 	GeanyKeyGroup *key_group;
2010 
2011 	/* init keybindings */
2012 	key_group = plugin_set_key_group(geany_plugin, "latex", COUNT_KB, NULL);
2013 	keybindings_set_item(key_group, KB_LATEX_WIZARD, glatex_kbwizard,
2014 		0, 0, "run_latex_wizard", _("Run LaTeX-Wizard"), menu_latex_wizard);
2015 	keybindings_set_item(key_group, KB_LATEX_INSERT_LABEL, glatex_kblabel_insert,
2016 		0, 0, "insert_latex_label", _("Insert \\label"), menu_latex_label);
2017 	keybindings_set_item(key_group, KB_LATEX_INSERT_REF, glatex_kbref_insert,
2018 		0, 0, "insert_latex_ref", _("Insert \\ref"), menu_latex_ref);
2019 	keybindings_set_item(key_group, KB_LATEX_INSERT_NEWLINE, glatex_kb_insert_newline,
2020 		0, 0, "insert_new_line", _("Insert linebreak \\\\ "), NULL);
2021 	keybindings_set_item(key_group, KB_LATEX_INSERT_COMMAND,
2022 		glatex_kb_insert_command_dialog, 0, 0, "latex_insert_command",
2023 		_("Insert command"), menu_latex_insert_command);
2024 	keybindings_set_item(key_group, KB_LATEX_TOGGLE_ACTIVE, glatex_kblatex_toggle,
2025 		0, 0, "latex_toggle_status", _("Turn input replacement on/off"),
2026 		menu_latex_replace_toggle);
2027 	keybindings_set_item(key_group, KB_LATEX_REPLACE_SPECIAL_CHARS,
2028 		glatex_kb_replace_special_chars, 0, 0, "latex_replace_chars",
2029 		_("Replace special characters"), NULL);
2030 	keybindings_set_item(key_group, KB_LATEX_ENVIRONMENT_INSERT,
2031 		glatex_kbref_insert_environment, 0, 0, "latex_insert_environment",
2032 		_("Run insert environment dialog"), menu_latex_insert_environment);
2033 	keybindings_set_item(key_group, KB_LATEX_INSERT_NEWITEM,
2034 		glatex_kb_insert_newitem, 0, 0, "latex_insert_item", _("Insert \\item"), NULL);
2035 	keybindings_set_item(key_group, KB_LATEX_FORMAT_BOLD, glatex_kb_format_bold,
2036 		0, 0, "format_bold", _("Format selection in bold font face"), NULL);
2037 	keybindings_set_item(key_group, KB_LATEX_FORMAT_ITALIC, glatex_kb_format_italic,
2038 		0, 0, "format_italic", _("Format selection in italic font face"), NULL);
2039 	keybindings_set_item(key_group, KB_LATEX_FORMAT_TYPEWRITER, glatex_kb_format_typewriter,
2040 		0, 0, "format_typewriter", _("Format selection in typewriter font face"), NULL);
2041 	keybindings_set_item(key_group, KB_LATEX_FORMAT_CENTER, glatex_kb_format_centering,
2042 		0, 0, "format_center", _("Format selection centered"), NULL);
2043 	keybindings_set_item(key_group, KB_LATEX_FORMAT_LEFT, glatex_kb_format_left,
2044 		0, 0, "format_left", _("Format selection left-aligned"), NULL);
2045 	keybindings_set_item(key_group, KB_LATEX_FORMAT_RIGHT, glatex_kb_format_right,
2046 		0, 0, "format_right", _("Format selection right-aligned"), NULL);
2047 	keybindings_set_item(key_group, KB_LATEX_ENVIRONMENT_INSERT_DESCRIPTION,
2048 		glatex_kb_insert_description_list, 0, 0, "insert_description_list",
2049 		_("Insert description list"), NULL);
2050 	keybindings_set_item(key_group, KB_LATEX_ENVIRONMENT_INSERT_ITEMIZE,
2051 		glatex_kb_insert_itemize_list, 0, 0, "insert_itemize_list",
2052 		_("Insert itemize list"), NULL);
2053 	keybindings_set_item(key_group, KB_LATEX_ENVIRONMENT_INSERT_ENUMERATE,
2054 		glatex_kb_insert_enumerate_list, 0, 0, "insert_enumerate_list",
2055 		_("Insert enumerate list"), NULL);
2056 	keybindings_set_item(key_group, KB_LATEX_STRUCTURE_LVLUP,
2057 		glatex_kb_structure_lvlup, 0, 0, "structure_lvl_up",
2058 		_("Set selection one level up"), NULL);
2059 	keybindings_set_item(key_group, KB_LATEX_STRUCTURE_LVLDOWN,
2060 		glatex_kb_structure_lvldown, 0, 0, "structure_lvl_down",
2061 		_("Set selection one level down"), NULL);
2062 	keybindings_set_item(key_group, KB_LATEX_USEPACKAGE_DIALOG,
2063 		glatex_kb_usepackage_dialog, 0, 0, "usepackage_dialog",
2064 		_("Insert \\usepackage{}"), menu_latex_insert_usepackage);
2065 	keybindings_set_item(key_group, KB_LATEX_INSERT_CITE,
2066 		glatex_kb_insert_bibtex_cite, 0, 0, "insert_cite_dialog",
2067 		_("Insert BibTeX reference dialog"), menu_latex_insert_bibtex_cite);
2068 }
2069 
2070 
plugin_help(void)2071 void plugin_help(void)
2072 {
2073 	dialogs_show_msgbox(GTK_MESSAGE_INFO,
2074 		_("LaTeX is a plugin to improve support for LaTeX in Geany."
2075 		"\n\nPlease report all bugs or feature requests to one of the "
2076 		"authors."));
2077 }
2078 
2079 
glatex_init_configuration(void)2080 static void glatex_init_configuration(void)
2081 {
2082 	GKeyFile *config = g_key_file_new();
2083 
2084 	/* loading configurations from file ...*/
2085 	config_file = g_strconcat(geany->app->configdir, G_DIR_SEPARATOR_S,
2086 	"plugins", G_DIR_SEPARATOR_S,
2087 	"LaTeX", G_DIR_SEPARATOR_S, "general.conf", NULL);
2088 
2089 	/* ... and Initialising options from config file */
2090 	g_key_file_load_from_file(config, config_file, G_KEY_FILE_NONE, NULL);
2091 
2092 	glatex_set_koma_active = utils_get_setting_boolean(config, "general",
2093 		"glatex_set_koma_active", FALSE);
2094 	glatex_set_toolbar_active = utils_get_setting_boolean(config, "general",
2095 		"glatex_set_toolbar_active", FALSE);
2096 	glatex_autocompletion_active = utils_get_setting_boolean(config, "general",
2097 		"glatex_set_autocompletion", TRUE);
2098 	glatex_autobraces_active = utils_get_setting_boolean(config, "autocompletion",
2099 		"glatex_set_autobraces", TRUE);
2100 	glatex_lowercase_on_smallcaps = utils_get_setting_boolean(config, "general",
2101 		"glatex_lowercase_on_smallcaps", FALSE);
2102 
2103 	/* Hidden preferences. Can be set directly via configuration file*/
2104 	glatex_autocompletion_context_size = utils_get_setting_integer(config, "autocompletion",
2105 		"glatex_set_autocompletion_contextsize", 5);
2106 
2107 	/* Doing some input validation */
2108 	if (glatex_autocompletion_active == TRUE &&
2109 		glatex_autocompletion_context_size <= 0)
2110 	{
2111 		glatex_autocompletion_context_size = 5;
2112 		g_warning(_("glatex_set_autocompletion_contextsize has been "
2113 					"initialized with an invalid value. Default value taken. "
2114 					"Please check your configuration file"));
2115 	}
2116 	/* Increase value by an offset as we add a new line so 2 really means 2 */
2117 	glatex_autocompletion_context_size = glatex_autocompletion_context_size + 2;
2118 
2119 	glatex_autocompletion_only_for_latex = utils_get_setting_boolean(config, "autocompletion",
2120 		"glatex_autocompletion_only_for_latex", TRUE);
2121 	glatex_capitalize_sentence_starts = utils_get_setting_boolean(config, "autocompletion",
2122 		"glatex_capitalize_sentence_starts", FALSE);
2123 
2124 	glatex_deactivate_toolbaritems_with_non_latex = utils_get_setting_boolean(config, "toolbar",
2125 		"glatex_deactivate_toolbaritems_with_non_latex", TRUE);
2126 	glatex_wizard_to_generic_toolbar = utils_get_setting_boolean(config, "toolbar",
2127 		"glatex_wizard_to_generic_toolbar", TRUE);
2128 	glatex_deactivate_menubarentry_with_non_latex = utils_get_setting_boolean(config, "menu",
2129 		"glatex_deactivate_menubarentry_with_non_latex", TRUE);
2130 	glatex_add_menu_on_startup = utils_get_setting_boolean(config, "menu",
2131 		"glatex_add_menu_on_startup", FALSE);
2132 
2133 	glatex_ref_page_string = utils_get_setting_string(config, "reference",
2134 		"glatex_reference_page", _("page \\pageref{{{reference}}}"));
2135 	glatex_ref_chapter_string = utils_get_setting_string(config, "reference",
2136 		"glatex_reference_chapter", "\\ref{{{reference}}}");
2137 	glatex_ref_all_string = utils_get_setting_string(config, "reference",
2138 		"glatex_reference_all", _("\\ref{{{reference}}}, page \\pageref{{{reference}}}"));
2139 
2140 	glatex_ref_page_string = utils_get_setting_string(config, "reference",
2141 		"glatex_reference_page", _("page \\pageref{{{reference}}}"));
2142 	glatex_ref_chapter_string = utils_get_setting_string(config, "reference",
2143 		"glatex_reference_chapter", "\\ref{{{reference}}}");
2144 	glatex_ref_all_string = utils_get_setting_string(config, "reference",
2145 		"glatex_reference_all", _("\\ref{{{reference}}}, page \\pageref{{{reference}}}"));
2146 
2147 	g_key_file_free(config);
2148 }
2149 
2150 
2151 static void
add_wizard_to_generic_toolbar(void)2152 add_wizard_to_generic_toolbar(void)
2153 {
2154 	if (glatex_wizard_generic_toolbar_item == NULL)
2155 	{
2156 		/* TODO: Find a better icon as this one is used way too often */
2157 		glatex_wizard_generic_toolbar_item =
2158 			gtk_tool_button_new_from_stock(GTK_STOCK_NEW);
2159 		plugin_add_toolbar_item(geany_plugin, glatex_wizard_generic_toolbar_item);
2160 		gtk_widget_show_all(GTK_WIDGET(glatex_wizard_generic_toolbar_item));
2161 		g_signal_connect(glatex_wizard_generic_toolbar_item, "clicked",
2162 				G_CALLBACK(glatex_wizard_activated), NULL);
2163 	}
2164 }
2165 
2166 
2167 static void
remove_wizard_from_generic_toolbar(void)2168 remove_wizard_from_generic_toolbar(void)
2169 {
2170 	if (glatex_wizard_generic_toolbar_item != NULL)
2171 	{
2172 		gtk_widget_destroy(GTK_WIDGET(glatex_wizard_generic_toolbar_item));
2173 		glatex_wizard_generic_toolbar_item = NULL;
2174 	}
2175 }
2176 
2177 
2178 static void
add_menu_to_menubar(void)2179 add_menu_to_menubar(void)
2180 {
2181 	GtkWidget *tmp = NULL;
2182 	gint i;
2183 	GtkMenuShell *menubar;
2184 	GList *menubar_children;
2185 
2186 	/* First we check for the menubar where to add the LaTeX menu */
2187 	menubar = GTK_MENU_SHELL(
2188 				ui_lookup_widget(geany->main_widgets->window, "menubar1"));
2189 
2190 	/* First we check whether the LaTeX menu entry already exists */
2191 	if (menu_latex == NULL)
2192 	{
2193 		/* Build up menu for menubar */
2194 		menu_latex = gtk_menu_item_new_with_mnemonic(_("_LaTeX"));
2195 		menubar_children = gtk_container_get_children(GTK_CONTAINER(menubar));
2196 		gtk_menu_shell_insert(
2197 			menubar, menu_latex, g_list_length(menubar_children)-1);
2198 
2199 		menu_latex_menu = gtk_menu_new();
2200 		gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_latex), menu_latex_menu);
2201 
2202 		/* Filling up menubar menus */
2203 		/* LaTeX menu */
2204 		menu_latex_wizard = ui_image_menu_item_new(GTK_STOCK_NEW, _("LaTeX-_Wizard"));
2205 		gtk_container_add(GTK_CONTAINER(menu_latex_menu), menu_latex_wizard);
2206 		gtk_widget_set_tooltip_text(menu_latex_wizard,
2207 					 _("Starts a Wizard to easily create LaTeX-documents"));
2208 
2209 		g_signal_connect(menu_latex_wizard, "activate",
2210 				 G_CALLBACK(glatex_wizard_activated), NULL);
2211 
2212 		menu_latex_menu_special_char = gtk_menu_item_new_with_mnemonic(_("I_nsert Special Character"));
2213 		gtk_widget_set_tooltip_text(menu_latex_menu_special_char,
2214 					 _("Helps to use some not very common letters and signs"));
2215 		gtk_container_add(GTK_CONTAINER(menu_latex_menu),
2216 			menu_latex_menu_special_char);
2217 
2218 		menu_latex_menu_special_char_submenu = gtk_menu_new();
2219 		gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_latex_menu_special_char),
2220 			menu_latex_menu_special_char_submenu);
2221 		glatex_sub_menu_init(menu_latex_menu_special_char_submenu,
2222 			glatex_char_array, glatex_cat_names, char_insert_activated);
2223 
2224 		menu_latex_ref = gtk_menu_item_new_with_mnemonic(_("Insert _Reference"));
2225 		gtk_widget_set_tooltip_text(menu_latex_ref,
2226 			_("Inserting references to the document"));
2227 		gtk_container_add(GTK_CONTAINER(menu_latex_menu), menu_latex_ref);
2228 		g_signal_connect(menu_latex_ref, "activate",
2229 			G_CALLBACK(glatex_insert_ref_activated), NULL);
2230 
2231 		menu_latex_label = gtk_menu_item_new_with_mnemonic(_("Insert _Label"));
2232 		gtk_widget_set_tooltip_text(menu_latex_label,
2233 			_("Helps at inserting labels to a document"));
2234 		gtk_container_add(GTK_CONTAINER(menu_latex_menu), menu_latex_label);
2235 		g_signal_connect(menu_latex_label, "activate",
2236 			G_CALLBACK(glatex_insert_label_activated), NULL);
2237 
2238 		menu_latex_insert_environment = gtk_menu_item_new_with_mnemonic(
2239 			_("Insert _Environment"));
2240 		gtk_widget_set_tooltip_text(menu_latex_insert_environment,
2241 			 _("Helps at inserting an environment a document"));
2242 		gtk_container_add(GTK_CONTAINER(menu_latex_menu), menu_latex_insert_environment);
2243 		g_signal_connect(menu_latex_insert_environment, "activate",
2244 			G_CALLBACK(glatex_insert_environment_dialog), NULL);
2245 
2246 		menu_latex_insert_usepackage = gtk_menu_item_new_with_mnemonic(
2247 			_("Insert P_ackage"));
2248 		gtk_widget_set_tooltip_text(menu_latex_insert_usepackage,
2249 			 _("A small dialog to insert \\usepackage{} into header of current file"));
2250 		gtk_container_add(GTK_CONTAINER(menu_latex_menu), menu_latex_insert_usepackage);
2251 		g_signal_connect(menu_latex_insert_usepackage, "activate",
2252 			G_CALLBACK(glatex_insert_usepackage_dialog), NULL);
2253 
2254 		menu_latex_format_insert = gtk_menu_item_new_with_mnemonic(_("_Format"));
2255 		gtk_container_add(GTK_CONTAINER(menu_latex_menu), menu_latex_format_insert);
2256 
2257 		menu_latex_format_insert_submenu = gtk_menu_new();
2258 		gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_latex_format_insert),
2259 			menu_latex_format_insert_submenu);
2260 
2261 		for (i = 0; i < LATEX_STYLES_END; i++)
2262 		{
2263 			tmp = NULL;
2264 			tmp = gtk_menu_item_new_with_mnemonic(_(glatex_format_labels[i]));
2265 			gtk_container_add(GTK_CONTAINER(menu_latex_format_insert_submenu), tmp);
2266 			g_signal_connect(tmp, "activate",
2267 				G_CALLBACK(glatex_insert_latex_format), GINT_TO_POINTER(i));
2268 		}
2269 
2270 		/* Add font size menu */
2271 		menu_latex_fontsize = gtk_menu_item_new_with_mnemonic(_("F_ont size"));
2272 		gtk_container_add(GTK_CONTAINER(menu_latex_menu), menu_latex_fontsize);
2273 
2274 		menu_latex_fontsize_submenu = gtk_menu_new();
2275 		gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_latex_fontsize),
2276 			menu_latex_fontsize_submenu);
2277 
2278 		for (i = 0; i < LATEX_FONTSIZE_END; i++)
2279 		{
2280 			tmp = NULL;
2281 			tmp = gtk_menu_item_new_with_mnemonic(_(glatex_fontsize_labels[i]));
2282 			gtk_container_add(GTK_CONTAINER(menu_latex_fontsize_submenu), tmp);
2283 			g_signal_connect(tmp, "activate",
2284 				G_CALLBACK(glatex_insert_latex_fontsize), GINT_TO_POINTER(i));
2285 		}
2286 
2287 		/* Add menuitem for LaTeX replacement functions*/
2288 		menu_latex_replacement = gtk_menu_item_new_with_mnemonic(
2289 			_("_Special Character Replacement"));
2290 		menu_latex_replacement_submenu = gtk_menu_new();
2291 		gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_latex_replacement),
2292 			menu_latex_replacement_submenu);
2293 		gtk_container_add(GTK_CONTAINER(menu_latex_menu), menu_latex_replacement);
2294 
2295 		/* Add menuitem for bulk replacment */
2296 		menu_latex_replace_selection = gtk_menu_item_new_with_mnemonic(
2297 			_("Bulk _Replace Special Characters"));
2298 		gtk_widget_set_tooltip_text(menu_latex_replace_selection,
2299 			_("_Replace selected special characters with TeX substitutes"));
2300 		gtk_container_add(GTK_CONTAINER(menu_latex_replacement_submenu),
2301 			menu_latex_replace_selection);
2302 		g_signal_connect(menu_latex_replace_selection, "activate",
2303 			G_CALLBACK(glatex_replace_special_character), NULL);
2304 
2305 		/* Add menu entry for toggling input replacment */
2306 		menu_latex_replace_toggle = gtk_check_menu_item_new_with_mnemonic(
2307 			_("Toggle _Special Character Replacement"));
2308 		gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_latex_replace_toggle),
2309 										toggle_active);
2310 		gtk_container_add(GTK_CONTAINER(menu_latex_replacement_submenu),
2311 			menu_latex_replace_toggle);
2312 
2313 		g_signal_connect(menu_latex_replace_toggle, "activate",
2314 						 G_CALLBACK(glatex_toggle_status), NULL);
2315 
2316 		/* Add menu entry for inserting a command */
2317 		menu_latex_insert_command = gtk_menu_item_new_with_mnemonic(
2318 			_("Insert _Command"));
2319 		gtk_widget_set_tooltip_text(menu_latex_ref,
2320 			_("Inserting customized command to document"));
2321 		gtk_container_add(GTK_CONTAINER(menu_latex_menu),
2322 			menu_latex_insert_command);
2323 		g_signal_connect(menu_latex_insert_command, "activate",
2324 			G_CALLBACK(glatex_insert_command_activated), NULL);
2325 
2326 		/* Switch document sitiveness for menu entries */
2327 		ui_add_document_sensitive(menu_latex_menu_special_char);
2328 		ui_add_document_sensitive(menu_latex_ref);
2329 		ui_add_document_sensitive(menu_latex_label);
2330 		ui_add_document_sensitive(menu_latex_format_insert);
2331 		ui_add_document_sensitive(menu_latex_insert_environment);
2332 		ui_add_document_sensitive(menu_latex_insert_usepackage);
2333 		ui_add_document_sensitive(menu_latex_insert_command);
2334 		ui_add_document_sensitive(menu_latex_fontsize);
2335 		ui_add_document_sensitive(menu_latex_replacement);
2336 
2337 
2338 		gtk_widget_show_all(menu_latex);
2339 	} /* only execute if menuitem "LaTeX" has not already been inserted
2340 	     into menubar before */
2341 
2342 	/* BibTeX menu */
2343 	if (menu_bibtex == NULL)
2344 	{
2345 		menu_bibtex = gtk_menu_item_new_with_mnemonic(_("_BibTeX"));
2346 		menubar_children = gtk_container_get_children(GTK_CONTAINER(menubar));
2347 		gtk_menu_shell_insert(
2348 			menubar, menu_bibtex, g_list_length(menubar_children)-1);
2349 
2350 		menu_bibtex_menu = gtk_menu_new();
2351 		gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_bibtex), menu_bibtex_menu);
2352 
2353 		menu_latex_insert_bibtex_cite =
2354 			gtk_menu_item_new_with_mnemonic(_("Insert B_ibTeX reference"));
2355 		gtk_widget_set_tooltip_text(menu_latex_insert_bibtex_cite,
2356 			_("Helps to insert a reference out of BibTeX files"));
2357 		gtk_container_add(GTK_CONTAINER(menu_bibtex_menu), menu_latex_insert_bibtex_cite);
2358 		g_signal_connect(menu_latex_insert_bibtex_cite, "activate",
2359 			G_CALLBACK(on_insert_bibtex_dialog_activate), NULL);
2360 
2361 		menu_latex_bibtex = gtk_menu_item_new_with_mnemonic(_("_BibTeX entries"));
2362 		gtk_container_add(GTK_CONTAINER(menu_bibtex_menu), menu_latex_bibtex);
2363 
2364 		menu_latex_bibtex_submenu = gtk_menu_new();
2365 		gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_latex_bibtex),
2366 			menu_latex_bibtex_submenu);
2367 
2368 		for (i = 0; i < GLATEX_BIBTEX_N_TYPES; i++)
2369 		{
2370 			tmp = NULL;
2371 			tmp = gtk_menu_item_new_with_mnemonic(_(glatex_bibtex_types[i].label));
2372 			gtk_container_add(GTK_CONTAINER(menu_latex_bibtex_submenu), tmp);
2373 			g_signal_connect(tmp, "activate",
2374 				G_CALLBACK(glatex_insert_bibtex_entry), GINT_TO_POINTER(i));
2375 		}
2376 
2377 		/* Switch document sensitivness */
2378 		ui_add_document_sensitive(menu_latex_bibtex);
2379 
2380 		gtk_widget_show_all(menu_bibtex);
2381 	} /* Only insert BibTeX menu if not already done. */
2382 }
2383 
2384 /* Removes the menubar menus from menubar if requested and available */
remove_menu_from_menubar(void)2385 static void remove_menu_from_menubar(void)
2386 {
2387 	if (menu_latex != NULL)
2388 	{
2389 		gtk_widget_destroy(menu_latex);
2390 		menu_latex = NULL;
2391 	}
2392 	if (menu_bibtex != NULL)
2393 	{
2394 		gtk_widget_destroy(menu_bibtex);
2395 		menu_bibtex = NULL;
2396 	}
2397 }
2398 
2399 
2400 static void
remove_menu_from_tools_menu(void)2401 remove_menu_from_tools_menu(void)
2402 {
2403 	if (menu_latex_toolbar_wizard != NULL)
2404 	{
2405 		gtk_widget_destroy(menu_latex_toolbar_wizard);
2406 		menu_latex_toolbar_wizard = NULL;
2407 	}
2408 }
2409 
2410 
2411 static void
add_wizard_to_tools_menu(void)2412 add_wizard_to_tools_menu(void)
2413 {
2414 	if (menu_latex_toolbar_wizard == NULL)
2415 	{
2416 		menu_latex_toolbar_wizard = ui_image_menu_item_new(GTK_STOCK_NEW,
2417 			_("LaTeX-_Wizard"));
2418 		gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), menu_latex_toolbar_wizard);
2419 		gtk_widget_set_tooltip_text(menu_latex_toolbar_wizard,
2420 					 _("Starts a Wizard to easily create LaTeX-documents"));
2421 		gtk_widget_show_all(menu_latex_toolbar_wizard);
2422 		g_signal_connect(menu_latex_toolbar_wizard, "activate",
2423 				 G_CALLBACK(glatex_wizard_activated), NULL);
2424 	}
2425 }
2426 
2427 
2428 void
plugin_init(G_GNUC_UNUSED GeanyData * data)2429 plugin_init(G_GNUC_UNUSED GeanyData * data)
2430 {
2431 	GeanyDocument *doc = NULL;
2432 
2433 	doc = document_get_current();
2434 
2435 	glatex_init_configuration();
2436 	glatex_init_encodings_latex();
2437 
2438 	add_wizard_to_tools_menu();
2439 
2440 	init_keybindings();
2441 
2442 	/* Check whether the toolbar should be shown or not and do so*/
2443 	if (glatex_set_toolbar_active == TRUE)
2444 	{
2445 		glatex_toolbar = init_toolbar();
2446 	}
2447 	else
2448 	{
2449 		glatex_toolbar = NULL;
2450 	}
2451 
2452 	if (glatex_wizard_to_generic_toolbar == TRUE)
2453 	{
2454 		add_wizard_to_generic_toolbar();
2455 	}
2456 	else
2457 	{
2458 		glatex_wizard_generic_toolbar_item = NULL;
2459 	}
2460 
2461 	if (doc != NULL)
2462 	{
2463 		if (glatex_add_menu_on_startup == TRUE||
2464 			doc->file_type->id == GEANY_FILETYPES_LATEX)
2465 		{
2466 			add_menu_to_menubar();
2467 		}
2468 	}
2469 
2470 	move_old_config_file();
2471 }
2472 
2473 void
plugin_cleanup(void)2474 plugin_cleanup(void)
2475 {
2476 	if (glatex_toolbar != NULL)
2477 		gtk_widget_destroy(glatex_toolbar);
2478 	remove_menu_from_menubar();
2479 	remove_menu_from_tools_menu();
2480 	remove_wizard_from_generic_toolbar();
2481 	g_free(config_file);
2482 	g_free(glatex_ref_chapter_string);
2483 	g_free(glatex_ref_page_string);
2484 	g_free(glatex_ref_all_string);
2485 }
2486