Revision: 1811 http://geany.svn.sourceforge.net/geany/?rev=1811&view=rev Author: eht16 Date: 2007-08-19 10:40:19 -0700 (Sun, 19 Aug 2007)
Log Message: ----------- New plugin: Export as HTML and LaTeX. Add some functions to the plugin API needed by the Export plugin.
Modified Paths: -------------- trunk/ChangeLog trunk/plugins/Makefile.am trunk/plugins/makefile.win32 trunk/po/POTFILES.in trunk/src/plugindata.h trunk/src/plugins.c
Added Paths: ----------- trunk/plugins/export.c
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-17 14:50:55 UTC (rev 1810) +++ trunk/ChangeLog 2007-08-19 17:40:19 UTC (rev 1811) @@ -1,3 +1,11 @@ +2007-08-19 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + + * plugins/export.c, plugins/Makefile.am, plugins/makefile.win32, + po/POTFILES.in, src/plugins.c, src/plugindata.h: + New plugin: Export as HTML and LaTeX. + Add some functions to the plugin API needed by the Export plugin. + + 2007-08-17 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
* src/plugins.c:
Modified: trunk/plugins/Makefile.am =================================================================== --- trunk/plugins/Makefile.am 2007-08-17 14:50:55 UTC (rev 1810) +++ trunk/plugins/Makefile.am 2007-08-19 17:40:19 UTC (rev 1811) @@ -14,6 +14,7 @@ demoplugin_la_LDFLAGS = -module -avoid-version classbuilder_la_LDFLAGS = -module -avoid-version htmlchars_la_LDFLAGS = -module -avoid-version +export_la_LDFLAGS = -module -avoid-version
if PLUGINS
@@ -21,7 +22,8 @@ plugin_LTLIBRARIES = \ demoplugin.la \ classbuilder.la \ - htmlchars.la + htmlchars.la \ + export.la
# Plugins not to be installed #noinst_LTLIBRARIES = \ @@ -30,10 +32,12 @@ demoplugin_la_SOURCES = demoplugin.c classbuilder_la_SOURCES = classbuilder.c htmlchars_la_SOURCES = htmlchars.c +export_la_SOURCES = export.c
demoplugin_la_LIBADD = $(GTK_LIBS) classbuilder_la_LIBADD = $(GTK_LIBS) htmlchars_la_LIBADD = $(GTK_LIBS) +export_la_LIBADD = $(GTK_LIBS)
endif # PLUGINS
Added: trunk/plugins/export.c =================================================================== --- trunk/plugins/export.c (rev 0) +++ trunk/plugins/export.c 2007-08-19 17:40:19 UTC (rev 1811) @@ -0,0 +1,663 @@ +/* + * export.c - this file is part of Geany, a fast and lightweight IDE + * + * Copyright 2007 Enrico Tröger enrico.troeger@uvena.de + * Copyright 2007 Nick Treleaven nick.treleaven@btinternet.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: demoplugin.c 1749 2007-07-27 10:37:22Z ntrel $ + */ + +/* Export plugin. */ + +#include "geany.h" +#include "support.h" +#include "plugindata.h" +#include "editor.h" +#include "document.h" +#include <ctype.h> + + +PluginFields *plugin_fields; +GeanyData *geany_data; + +VERSION_CHECK(10) +PLUGIN_INFO(_("Export"), _("Exports the current file into different formats.")) + +#define doc_array geany_data->doc_array +#define scintilla geany_data->sci +#define utils geany_data->utils +#define support geany_data->support +#define dialogs geany_data->dialogs +#define msgwin geany_data->msgwindow + +#define ROTATE_RGB(color) \ + (((color) & 0xFF0000) >> 16) + ((color) & 0x00FF00) + (((color) & 0x0000FF) << 16) +#define TEMPLATE_HTML "\ +<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\ + \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\ +<html xmlns="http://www.w3.org/1999/xhtml%5C" xml:lang="en" lang="en">\n\ +\n\ +<head>\n\ + <title>{export_filename}</title>\n\ + <meta http-equiv="content-type" content="text/html;charset=utf-8" />\n\ + <meta name="generator" content="Geany " VERSION "" />\n\ + <style type="text/css">\n\ +{export_styles}\n\ + </style>\n\ +</head>\n\ +\n\ +<body>\n\ +<p>\n\ +{export_content}\n\ +</p>\n\ +</body>\n\ +</html>\n" + +#define TEMPLATE_LATEX "\ +\documentclass[a4paper]{article}\n\ +\usepackage[a4paper,margin=2cm]{geometry}\n\ +\usepackage[utf8x]{inputenc}\n\ +\usepackage[T1]{fontenc}\n\ +\usepackage{color}\n\ +{export_styles}\n\ +\begin{document}\ +\n\ +\noindent\n\ +\ttfamily\n\ +\setlength{\fboxrule}{0pt}\n\ +\setlength{\fboxsep}{0pt}\n\ +{export_content}\ +\end{document}\n" + + +enum +{ + FORE = 0, + BACK, + BOLD, + ITALIC, + USED, + MAX_TYPES +}; + +typedef void (*ExportFunc) (gint idx, const gchar *filename, gboolean use_zoom); +typedef struct +{ + gint idx; + gboolean have_zoom_level_checkbox; + ExportFunc export_func; +} ExportInfo; + +static void on_file_save_dialog_response(GtkDialog *dialog, gint response, gpointer user_data); +static void write_html_file(gint idx, const gchar *filename, gboolean use_zoom); +static void write_latex_file(gint idx, const gchar *filename, gboolean use_zoom); + + +/* converts a RGB colour into a LaTeX compatible representation, taken from SciTE */ +static gchar* get_tex_rgb(gint rgb_colour) +{ + //texcolor[rgb]{0,0.5,0}{....} + gdouble rf = (rgb_colour % 256) / 256.0; + gdouble gf = ((rgb_colour & - 16711936) / 256) / 256.0; + gdouble bf = ((rgb_colour & 0xff0000) / 65536) / 256.0; + gint r = (gint) (rf * 10 + 0.5); + gint g = (gint) (gf * 10 + 0.5); + gint b = (gint) (bf * 10 + 0.5); + + return g_strdup_printf("%d.%d, %d.%d, %d.%d", r / 10, r % 10, g / 10, g % 10, b / 10, b % 10); +} + + +// convert a style number (0..127) into a string representation (aa, ab, .., ba, bb, .., zy, zz) +static gchar *get_tex_style(gint style) +{ + static gchar buf[4]; + int i = 0; + + do + { + buf[i] = (style % 26) + 'a'; + style /= 26; + i++; + } while (style > 0); + buf[i] = '\0'; + + return buf; +} + + +static void create_file_save_as_dialog(const gchar *extension, ExportFunc func, + gboolean show_zoom_level_checkbox) +{ + gint idx; + GtkWidget *dialog; + GtkTooltips *tooltips; + ExportInfo *exi; + + if (extension == NULL) + return; + + idx = geany_data->document->get_cur_idx(); + tooltips = GTK_TOOLTIPS(support->lookup_widget(geany_data->app->window, "tooltips")); + + exi = g_new(ExportInfo, 1); + exi->idx = idx; + exi->export_func = func; + exi->have_zoom_level_checkbox = FALSE; + + dialog = gtk_file_chooser_dialog_new(_("Export File"), GTK_WINDOW(geany_data->app->window), + GTK_FILE_CHOOSER_ACTION_SAVE, NULL, NULL); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE); + gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_widget_set_name(dialog, "GeanyExportDialog"); + + gtk_dialog_add_buttons(GTK_DIALOG(dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + + if (show_zoom_level_checkbox) + { + GtkWidget *vbox, *check_zoom_level; + + vbox = gtk_vbox_new(FALSE, 0); + check_zoom_level = gtk_check_button_new_with_mnemonic(_("_Use current zoom level")); + gtk_tooltips_set_tip(tooltips, check_zoom_level, + _("Renders the font size of the document together with the current zoom level."), NULL); + gtk_box_pack_start(GTK_BOX(vbox), check_zoom_level, FALSE, FALSE, 0); + gtk_widget_show_all(vbox); + gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dialog), vbox); + + g_object_set_data_full(G_OBJECT(dialog), "check_zoom_level", + gtk_widget_ref(check_zoom_level), (GDestroyNotify) gtk_widget_unref); + + exi->have_zoom_level_checkbox = TRUE; + } + + g_signal_connect((gpointer) dialog, "delete_event", + G_CALLBACK(gtk_widget_hide_on_delete), NULL); + g_signal_connect((gpointer) dialog, "response", + G_CALLBACK(on_file_save_dialog_response), exi); + + gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(geany_data->app->window)); + + // if the current document has a filename we use it as the default. + gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(dialog)); + if (doc_list[idx].file_name != NULL) + { + gchar *base_name = g_path_get_basename(doc_list[idx].file_name); + gchar *short_name = utils->remove_ext_from_filename(base_name); + gchar *file_name = g_strconcat(short_name, extension, NULL); + gchar *locale_filename = utils->get_locale_from_utf8(doc_list[idx].file_name); + gchar *locale_dirname = g_path_get_dirname(locale_filename); + // set the current name to base_name.html which probably doesn't exist yet so + // gtk_file_chooser_set_filename() can't be used and we need + // gtk_file_chooser_set_current_folder() additionally + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_dirname); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), file_name); + g_free(locale_filename); + g_free(short_name); + g_free(file_name); + g_free(base_name); + } + else + { + gchar *fname = g_strconcat(GEANY_STRING_UNTITLED, extension, NULL); + + gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(dialog)); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), fname); + + // use default startup directory(if set) if no files are open + if (geany_data->app->default_open_path != NULL && + *(geany_data->app->default_open_path) != '\0') + { + if (g_path_is_absolute(geany_data->app->default_open_path)) + { + gchar *def_path = utils->get_locale_from_utf8(geany_data->app->default_open_path); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), def_path); + g_free(def_path); + } + } + g_free(fname); + } + gtk_dialog_run(GTK_DIALOG(dialog)); +} + + +static void on_menu_create_latex_activate(gint idx, const gchar *filename, gboolean use_zoom) +{ + create_file_save_as_dialog(".tex", write_latex_file, FALSE); +} + + +static void on_menu_create_html_activate(gint idx, const gchar *filename, gboolean use_zoom) +{ + create_file_save_as_dialog(".html", write_html_file, TRUE); +} + + +static void write_data(const gchar *filename, const gchar *data) +{ + gint error_nr = utils->write_file(filename, data); + gchar *utf8_filename = utils->get_utf8_from_locale(filename); + + if (error_nr == 0) + msgwin->status_add(_("Document successfully exported as '%s'."), utf8_filename); + else + msgwin->status_add(_("File '%s' could not be written (%s)."), + utf8_filename, g_strerror(error_nr)); + + g_free(utf8_filename); +} + + +static void on_file_save_dialog_response(GtkDialog *dialog, gint response, gpointer user_data) +{ + ExportInfo *exi = user_data; + + if (response == GTK_RESPONSE_ACCEPT && exi != NULL) + { + gchar *new_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + gchar *utf8_filename; + gboolean use_zoom_level = FALSE; + + if (exi->have_zoom_level_checkbox) + { + use_zoom_level = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + support->lookup_widget(GTK_WIDGET(dialog), "check_zoom_level"))); + } + + utf8_filename = utils->get_utf8_from_locale(new_filename); + + // check if file exists and ask whether to overwrite or not + if (g_file_test(new_filename, G_FILE_TEST_EXISTS)) + { + if (dialogs->show_question( + _("The file '%s' already exists. Do you want to overwrite it?"), + utf8_filename) == FALSE) + return; + } + + exi->export_func(exi->idx, new_filename, use_zoom_level); + + g_free(utf8_filename); + g_free(new_filename); + } + g_free(exi); + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + + +static void write_latex_file(gint idx, const gchar *filename, gboolean use_zoom) +{ + gint i, style = -1, old_style = 0, column = 0; + gchar c, c_next, *tmp; + // 0 - fore, 1 - back, 2 - bold, 3 - italic, 4 - font size, 5 - used(0/1) + gint styles[STYLE_MAX + 1][MAX_TYPES]; + gchar *latex; + gboolean block_open = FALSE; + GString *body; + GString *cmds; + + // first read all styles from Scintilla + for (i = 0; i <= STYLE_MAX; i++) + { + styles[i][FORE] = scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETFORE, i, 0); + styles[i][BACK] = scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETBACK, i, 0); + styles[i][BOLD] = scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETBOLD, i, 0); + styles[i][ITALIC] = scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETITALIC, i, 0); + styles[i][USED] = 0; + } + + // read the document and write the LaTeX code + body = g_string_new(""); + for (i = 0; i < scintilla->get_length(doc_list[idx].sci); i++) + { + style = scintilla->get_style_at(doc_list[idx].sci, i); + c = scintilla->get_char_at(doc_list[idx].sci, i); + c_next = scintilla->get_char_at(doc_list[idx].sci, i + 1); + + if (style != old_style || ! block_open) + { + old_style = style; + styles[style][USED] = 1; + if (block_open) + { + g_string_append(body, "}\n"); + block_open = FALSE; + } + g_string_append_printf(body, "\style%s{", get_tex_style(style)); + + block_open = TRUE; + } + // escape the current character if necessary else just add it + switch (c) + { + case '\r': + case '\n': + { + if (c == '\r' && c_next == '\n') + continue; // when using CR/LF skip CR and add the line break with LF + + if (block_open) + { + g_string_append(body, "}"); + block_open = FALSE; + } + g_string_append(body, " \\\n"); + column = -1; + break; + } + case '\t': + { + gint tab_stop = geany_data->editor_prefs->tab_width - + (column % geany_data->editor_prefs->tab_width); + + column += tab_stop - 1; // -1 because we add 1 at the end of the loop + g_string_append_printf(body, "\hspace*{%dem}", tab_stop); + break; + } + case ' ': + { + if (c_next == ' ') + g_string_append(body, "{\hspace*{1em}}"); + else + g_string_append_c(body, ' '); + break; + } + case '{': + case '}': + case '_': + case '&': + case '$': + case '#': + case '%': + { + g_string_append_printf(body, "\%c", c); + break; + } + case '\': + { + g_string_append(body, "\textbackslash"); + break; + } + case '~': + { + g_string_append(body, "\symbol{126}"); + break; + } + case '^': + { + g_string_append(body, "\symbol{92}"); + break; + } + case '-': // mask "--" + { + if (c_next == '-') + g_string_append(body, "-\@-"); + break; + } + default: g_string_append_c(body, c); + } + column++; + } + if (block_open) + { + g_string_append(body, "}\n"); + block_open = FALSE; + } + + // force writing of style 0 (used at least for line breaks) + styles[0][USED] = 1; + + // write used styles in the header + cmds = g_string_new(""); + for (i = 0; i <= STYLE_MAX; i++) + { + if (styles[i][USED]) + { + g_string_append_printf(cmds, + "\newcommand{\style%s}[1]{\noindent{", get_tex_style(i)); + if (styles[i][BOLD]) + g_string_append(cmds, "\textbf{"); + if (styles[i][ITALIC]) + g_string_append(cmds, "\textit{"); + + tmp = get_tex_rgb(styles[i][FORE]); + g_string_append_printf(cmds, "\textcolor[rgb]{%s}{", tmp); + g_free(tmp); + tmp = get_tex_rgb(styles[i][BACK]); + g_string_append_printf(cmds, "\fcolorbox[rgb]{0, 0, 0}{%s}{", tmp); + g_string_append(cmds, "#1}}"); + g_free(tmp); + + if (styles[i][BOLD]) + g_string_append_c(cmds, '}'); + if (styles[i][ITALIC]) + g_string_append_c(cmds, '}'); + g_string_append(cmds, "}}\n"); + } + } + + // write all + latex = g_strdup(TEMPLATE_LATEX); + latex = utils->str_replace(latex, "{export_content}", body->str); + latex = utils->str_replace(latex, "{export_styles}", cmds->str); + // {export_filename} is currently unused but maybe someone want to use it + if (doc_list[idx].file_name == NULL) + latex = utils->str_replace(latex, "{export_filename}", GEANY_STRING_UNTITLED); + else + latex = utils->str_replace(latex, "{export_filename}", doc_list[idx].file_name); + + write_data(filename, latex); + + g_string_free(body, TRUE); + g_string_free(cmds, TRUE); + g_free(latex); +} + + +static void write_html_file(gint idx, const gchar *filename, gboolean use_zoom) +{ + gint i, style = -1, old_style = 0, column = 0; + gchar c, c_next; + // 0 - fore, 1 - back, 2 - bold, 3 - italic, 4 - font size, 5 - used(0/1) + gint styles[STYLE_MAX + 1][MAX_TYPES]; + gboolean span_open = FALSE; + gchar *html; + const gchar *font_name; + gint font_size; + PangoFontDescription *font_desc; + GString *body; + GString *css; + + // first read all styles from Scintilla + for (i = 0; i <= STYLE_MAX; i++) + { + styles[i][FORE] = ROTATE_RGB(scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETFORE, i, 0)); + styles[i][BACK] = ROTATE_RGB(scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETBACK, i, 0)); + styles[i][BOLD] = scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETBOLD, i, 0); + styles[i][ITALIC] = scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETITALIC, i, 0); + styles[i][USED] = 0; + } + + // read Geany's font and font size + font_desc = pango_font_description_from_string(geany_data->app->editor_font); + font_name = pango_font_description_get_family(font_desc); + //font_size = pango_font_description_get_size(font_desc) / PANGO_SCALE; + // take the zoom level also into account + font_size = scintilla->send_message(doc_list[idx].sci, SCI_STYLEGETSIZE, 0, 0); + if (use_zoom) + font_size += scintilla->get_zoom(doc_list[idx].sci); + + // read the document and write the HTML body + body = g_string_new(""); + for (i = 0; i < scintilla->get_length(doc_list[idx].sci); i++) + { + style = scintilla->get_style_at(doc_list[idx].sci, i); + c = scintilla->get_char_at(doc_list[idx].sci, i); + // scintilla->get_char_at() takes care of index boundaries and return 0 if i is too high + c_next = scintilla->get_char_at(doc_list[idx].sci, i + 1); + + if ((style != old_style || ! span_open) && ! isspace(c)) + { + old_style = style; + styles[style][USED] = 1; + if (span_open) + { + g_string_append(body, "</span>"); + } + g_string_append_printf(body, "<span class="style_%d">", style); + + span_open = TRUE; + } + // escape the current character if necessary else just add it + switch (c) + { + case '\r': + case '\n': + { + if (c == '\r' && c_next == '\n') + continue; // when using CR/LF skip CR and add the line break with LF + + if (span_open) + { + g_string_append(body, "</span>"); + span_open = FALSE; + } + g_string_append(body, "<br />\n"); + column = -1; + break; + } + case '\t': + { + gint j; + gint tab_stop = geany_data->editor_prefs->tab_width - + (column % geany_data->editor_prefs->tab_width); + + column += tab_stop - 1; // -1 because we add 1 at the end of the loop + for (j = 0; j < tab_stop; j++) + { + g_string_append(body, " "); + } + break; + } + case ' ': + { + g_string_append(body, " "); + break; + } + case '<': + { + g_string_append(body, "<"); + break; + } + case '>': + { + g_string_append(body, ">"); + break; + } + case '&': + { + g_string_append(body, "&"); + break; + } + default: g_string_append_c(body, c); + } + column++; + } + if (span_open) + { + g_string_append(body, "</span>"); + span_open = FALSE; + } + + // write used styles in the header + css = g_string_new(""); + g_string_append_printf(css, + "\tbody\n\t{\n\t\tfont-family: %s, monospace;\n\t\tfont-size: %dpt;\n\t}\n", + font_name, font_size); + + for (i = 0; i <= STYLE_MAX; i++) + { + if (styles[i][USED]) + { + g_string_append_printf(css, + "\t.style_%d\n\t{\n\t\tcolor: #%06x;\n\t\tbackground-color: #%06x;\n%s%s\t}\n", + i, styles[i][FORE], styles[i][BACK], + (styles[i][BOLD]) ? "\t\tfont-weight: bold;\n" : "", + (styles[i][ITALIC]) ? "\t\tfont-style: italic;\n" : ""); + } + } + + // write all + html = g_strdup(TEMPLATE_HTML); + html = utils->str_replace(html, "{export_content}", body->str); + html = utils->str_replace(html, "{export_styles}", css->str); + if (doc_list[idx].file_name == NULL) + html = utils->str_replace(html, "{export_filename}", GEANY_STRING_UNTITLED); + else + html = utils->str_replace(html, "{export_filename}", doc_list[idx].file_name); + + write_data(filename, html); + + pango_font_description_free(font_desc); + g_string_free(body, TRUE); + g_string_free(css, TRUE); + g_free(html); +} + + +void init(GeanyData *data) +{ + GtkWidget *menu_export; + GtkWidget *menu_export_menu; + GtkWidget *menu_create_html; + GtkWidget *menu_create_latex; + + menu_export = gtk_image_menu_item_new_with_mnemonic(_("_Export")); + gtk_container_add(GTK_CONTAINER(data->tools_menu), menu_export); + + menu_export_menu = gtk_menu_new (); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_export), menu_export_menu); + + // HTML + menu_create_html = gtk_menu_item_new_with_mnemonic(_("As HTML")); + gtk_container_add(GTK_CONTAINER (menu_export_menu), menu_create_html); + + g_signal_connect((gpointer) menu_create_html, "activate", + G_CALLBACK(on_menu_create_html_activate), NULL); + + // LaTeX + menu_create_latex = gtk_menu_item_new_with_mnemonic(_("As LaTeX")); + gtk_container_add(GTK_CONTAINER (menu_export_menu), menu_create_latex); + + g_signal_connect((gpointer) menu_create_latex, "activate", + G_CALLBACK(on_menu_create_latex_activate), NULL); + + gtk_widget_show_all(menu_export); + + plugin_fields->menu_item = menu_export; +} + + +void cleanup() +{ + gtk_widget_destroy(plugin_fields->menu_item); +}
Modified: trunk/plugins/makefile.win32 =================================================================== --- trunk/plugins/makefile.win32 2007-08-17 14:50:55 UTC (rev 1810) +++ trunk/plugins/makefile.win32 2007-08-19 17:40:19 UTC (rev 1811) @@ -43,7 +43,8 @@ plugins: \ htmlchars.dll \ demoplugin.dll \ - classbuilder.dll + classbuilder.dll \ + export.dll
clean: -$(RM) deps.mak *.o *.dll
Modified: trunk/po/POTFILES.in =================================================================== --- trunk/po/POTFILES.in 2007-08-17 14:50:55 UTC (rev 1810) +++ trunk/po/POTFILES.in 2007-08-19 17:40:19 UTC (rev 1811) @@ -36,3 +36,4 @@ src/win32.c plugins/classbuilder.c plugins/htmlchars.c +plugins/export.c
Modified: trunk/src/plugindata.h =================================================================== --- trunk/src/plugindata.h 2007-08-17 14:50:55 UTC (rev 1810) +++ trunk/src/plugindata.h 2007-08-19 17:40:19 UTC (rev 1811) @@ -68,7 +68,7 @@
/* The API version should be incremented whenever any plugin data types below are * modified. */ -static const gint api_version = 11; +static const gint api_version = 12;
/* The ABI version should be incremented whenever existing fields in the plugin * data types below have to be changed or reordered. It should stay the same if fields @@ -144,6 +144,8 @@ struct UtilsFuncs *utils; struct UIUtilsFuncs *ui; struct SupportFuncs *support; + struct DialogFuncs *dialogs; + struct MsgWinFuncs *msgwindow; } GeanyData;
@@ -205,6 +207,9 @@ void (*ensure_line_is_visible) (struct _ScintillaObject* sci, gint line); void (*scroll_caret) (struct _ScintillaObject* sci); gint (*find_bracematch) (struct _ScintillaObject* sci, gint pos); + gint (*get_style_at) (struct _ScintillaObject *sci, gint position); + gchar (*get_char_at) (struct _ScintillaObject *sci, gint pos); + gint (*get_zoom) (struct _ScintillaObject * sci); } ScintillaFuncs;
@@ -219,6 +224,10 @@ gboolean (*str_equal) (const gchar *a, const gchar *b); gchar* (*str_replace) (gchar *haystack, const gchar *needle, const gchar *replacement); GSList* (*get_file_list) (const gchar *path, guint *length, GError **error); + gint (*write_file) (const gchar *filename, const gchar *text); + gchar* (*get_locale_from_utf8) (const gchar *utf8_text); + gchar* (*get_utf8_from_locale) (const gchar *locale_text); + gchar* (*remove_ext_from_filename) (const gchar *filename); } UtilsFuncs;
@@ -229,6 +238,13 @@ } UIUtilsFuncs;
+typedef struct DialogFuncs +{ + gboolean (*show_question) (const gchar *text, ...); + void (*show_msgbox) (gint type, const gchar *text, ...); +} +DialogFuncs; + typedef struct SupportFuncs { GtkWidget* (*lookup_widget) (GtkWidget *widget, const gchar *widget_name); @@ -236,6 +252,13 @@ SupportFuncs;
+typedef struct MsgWinFuncs +{ + void (*status_add) (const gchar *format, ...); +} +MsgWinFuncs; + + typedef struct GeanyCallback { gchar *signal_name;
Modified: trunk/src/plugins.c =================================================================== --- trunk/src/plugins.c 2007-08-17 14:50:55 UTC (rev 1810) +++ trunk/src/plugins.c 2007-08-19 17:40:19 UTC (rev 1811) @@ -43,6 +43,8 @@ #include "sciwrappers.h" #include "ui_utils.h" #include "editor.h" +#include "dialogs.h" +#include "msgwindow.h" #include "geanyobject.h"
#ifdef G_OS_WIN32 @@ -109,7 +111,10 @@ &sci_get_line_is_visible, &sci_ensure_line_is_visible, &sci_scroll_caret, - &sci_find_bracematch + &sci_find_bracematch, + &sci_get_style_at, + &sci_get_char_at, + &sci_get_zoom };
static TemplateFuncs template_funcs = { @@ -119,7 +124,11 @@ static UtilsFuncs utils_funcs = { &utils_str_equal, &utils_str_replace, - &utils_get_file_list + &utils_get_file_list, + &utils_write_file, + &utils_get_locale_from_utf8, + &utils_get_utf8_from_locale, + &utils_remove_ext_from_filename };
static UIUtilsFuncs uiutils_funcs = { @@ -127,11 +136,20 @@ &ui_frame_new_with_alignment };
+static DialogFuncs dialog_funcs = { + &dialogs_show_question, + &dialogs_show_msgbox +}; + static SupportFuncs support_funcs = { &lookup_widget };
+static MsgWinFuncs msgwin_funcs = { + &msgwin_status_add +};
+ static GeanyData geany_data = { NULL, NULL, @@ -144,7 +162,9 @@ &template_funcs, &utils_funcs, &uiutils_funcs, - &support_funcs + &support_funcs, + &dialog_funcs, + &msgwin_funcs };
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.