SF.net SVN: geany: [1811] trunk
eht16 at users.sourceforge.net
eht16 at xxxxx
Sun Aug 19 17:40:19 UTC 2007
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 at uvena.de>
+ * Copyright 2007 Nick Treleaven <nick.treleaven at 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\" 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.
More information about the Commits
mailing list