diff options
-rw-r--r-- | src-old/colloquium.c | 476 | ||||
-rw-r--r-- | src-old/colloquium.h | 45 | ||||
-rw-r--r-- | src-old/debugger.c | 229 | ||||
-rw-r--r-- | src-old/debugger.h | 32 | ||||
-rw-r--r-- | src-old/frame.c | 1820 | ||||
-rw-r--r-- | src-old/frame.h | 194 | ||||
-rw-r--r-- | src-old/presentation.c | 362 | ||||
-rw-r--r-- | src-old/presentation.h | 83 | ||||
-rw-r--r-- | src-old/render.c | 332 | ||||
-rw-r--r-- | src-old/render.h | 62 | ||||
-rw-r--r-- | src-old/sc_editor.c | 2197 | ||||
-rw-r--r-- | src-old/sc_editor.h | 199 | ||||
-rw-r--r-- | src-old/sc_interp.c | 1148 | ||||
-rw-r--r-- | src-old/sc_interp.h | 80 | ||||
-rw-r--r-- | src-old/sc_parse.c | 856 | ||||
-rw-r--r-- | src-old/sc_parse.h | 85 | ||||
-rw-r--r-- | src-old/slide_window.c | 282 | ||||
-rw-r--r-- | src-old/slide_window.h | 37 | ||||
-rw-r--r-- | src-old/stylesheet.c | 288 | ||||
-rw-r--r-- | src-old/stylesheet.h | 54 | ||||
-rw-r--r-- | src-old/stylesheet_editor.c | 794 | ||||
-rw-r--r-- | src-old/stylesheet_editor.h | 128 | ||||
-rw-r--r-- | src-old/utils.c | 137 | ||||
-rw-r--r-- | src-old/utils.h | 47 |
24 files changed, 0 insertions, 9967 deletions
diff --git a/src-old/colloquium.c b/src-old/colloquium.c deleted file mode 100644 index 02ffa0a..0000000 --- a/src-old/colloquium.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * colloquium.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gtk/gtk.h> -#include <getopt.h> -#include <string.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <glib.h> -#include <glib/gstdio.h> - -#include "colloquium.h" -#include "presentation.h" -#include "narrative_window.h" -#include "utils.h" - - -struct _colloquium -{ - GtkApplication parent_instance; - GtkBuilder *builder; - char *mydir; - int first_run; - char *imagestore; - int hidepointer; -}; - - -typedef GtkApplicationClass ColloquiumClass; - - -G_DEFINE_TYPE(Colloquium, colloquium, GTK_TYPE_APPLICATION) - - -static void colloquium_activate(GApplication *papp) -{ - Colloquium *app = COLLOQUIUM(papp); - if ( !app->first_run ) { - struct presentation *p; - p = new_presentation(app->imagestore); - narrative_window_new(p, papp); - } -} - - -static void new_sig(GSimpleAction *action, GVariant *parameter, gpointer vp) -{ - GApplication *app = vp; - g_application_activate(app); -} - - -static void open_intro_doc(Colloquium *app) -{ - GFile *file = g_file_new_for_uri("resource:///uk/me/bitwiz/Colloquium/demo.sc"); - g_application_open(G_APPLICATION(app), &file, 1, ""); - g_object_unref(file); -} - - -static void intro_sig(GSimpleAction *action, GVariant *parameter, gpointer vp) -{ - GApplication *app = vp; - open_intro_doc(COLLOQUIUM(app)); -} - - -void open_about_dialog(GtkWidget *parent) -{ - GtkWidget *window; - - const gchar *authors[] = { - "Thomas White <taw@bitwiz.org.uk>", - NULL - }; - - window = gtk_about_dialog_new(); - gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(parent)); - - gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(window), - "Colloquium"); - gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(window), - "colloquium"); - gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(window), - PACKAGE_VERSION); - gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(window), - "© 2017-2018 Thomas White <taw@bitwiz.me.uk>"); - gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(window), - /* Description of the program */ - _("Narrative-based presentation system")); - gtk_about_dialog_set_license_type(GTK_ABOUT_DIALOG(window), GTK_LICENSE_GPL_3_0); - gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(window), - "https://www.bitwiz.me.uk/"); - gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(window), - "https://www.bitwiz.me.uk/"); - gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(window), authors); - gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(window), - _("translator-credits")); - - g_signal_connect(window, "response", G_CALLBACK(gtk_widget_destroy), - NULL); - - gtk_widget_show_all(window); -} - - -static void quit_sig(GSimpleAction *action, GVariant *parameter, gpointer vp) -{ - GApplication *app = vp; - g_application_quit(app); -} - - -static GFile **gslist_to_array(GSList *item, int *n) -{ - int i = 0; - int len = g_slist_length(item); - GFile **files = malloc(len * sizeof(GFile *)); - - if ( files == NULL ) return NULL; - - while ( item != NULL ) { - if ( i == len ) { - fprintf(stderr, "WTF? Too many files\n"); - break; - } - files[i++] = item->data; - item = item->next; - } - - *n = len; - return files; -} - - -static gint open_response_sig(GtkWidget *d, gint response, GApplication *papp) -{ - if ( response == GTK_RESPONSE_ACCEPT ) { - - GSList *files; - int n_files = 0; - GFile **files_array; - int i; - - files = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(d)); - files_array = gslist_to_array(files, &n_files); - if ( files_array == NULL ) { - fprintf(stderr, "Failed to convert file list\n"); - return 0; - } - g_slist_free(files); - g_application_open(papp, files_array, n_files, ""); - - for ( i=0; i<n_files; i++ ) { - g_object_unref(files_array[i]); - } - - } - - gtk_widget_destroy(d); - - return 0; -} - - -static void open_sig(GSimpleAction *action, GVariant *parameter, gpointer vp) -{ - GtkWidget *d; - GApplication *app = vp; - - d = gtk_file_chooser_dialog_new(_("Open Presentation"), - gtk_application_get_active_window(GTK_APPLICATION(app)), - GTK_FILE_CHOOSER_ACTION_OPEN, - _("_Cancel"), GTK_RESPONSE_CANCEL, - _("_Open"), GTK_RESPONSE_ACCEPT, - NULL); - - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(d), TRUE); - - g_signal_connect(G_OBJECT(d), "response", - G_CALLBACK(open_response_sig), app); - - gtk_widget_show_all(d); -} - - -GActionEntry app_entries[] = { - - { "new", new_sig, NULL, NULL, NULL }, - { "open", open_sig, NULL, NULL, NULL }, - { "intro", intro_sig, NULL, NULL, NULL }, - { "quit", quit_sig, NULL, NULL, NULL }, -}; - - -static void colloquium_open(GApplication *papp, GFile **files, gint n_files, - const gchar *hint) -{ - int i; - Colloquium *app = COLLOQUIUM(papp); - - for ( i = 0; i<n_files; i++ ) { - struct presentation *p; - p = new_presentation(app->imagestore); - if ( load_presentation(p, files[i]) == 0 ) { - narrative_window_new(p, papp); - } else { - char *uri = g_file_get_uri(files[i]); - fprintf(stderr, _("Failed to load presentation '%s'\n"), - uri); - g_free(uri); - } - } -} - - -static void colloquium_finalize(GObject *object) -{ - G_OBJECT_CLASS(colloquium_parent_class)->finalize(object); -} - - -static void create_config(const char *filename) -{ - - FILE *fh; - fh = fopen(filename, "w"); - if ( fh == NULL ) { - fprintf(stderr, _("Failed to create config\n")); - return; - } - - fprintf(fh, "imagestore: %s\n", - g_get_user_special_dir(G_USER_DIRECTORY_PICTURES)); - fprintf(fh, "hidepointer: no\n"); - - fclose(fh); -} - - -static int yesno(const char *a) -{ - if ( a == NULL ) return 0; - - if ( strcmp(a, "1") == 0 ) return 1; - if ( strcasecmp(a, "yes") == 0 ) return 1; - if ( strcasecmp(a, "true") == 0 ) return 1; - - if ( strcasecmp(a, "0") == 0 ) return 0; - if ( strcasecmp(a, "no") == 0 ) return 0; - if ( strcasecmp(a, "false") == 0 ) return 0; - - fprintf(stderr, "Don't understand '%s', assuming false\n", a); - return 0; -} - - -static void read_config(const char *filename, Colloquium *app) -{ - FILE *fh; - char line[1024]; - - fh = fopen(filename, "r"); - if ( fh == NULL ) { - fprintf(stderr, _("Failed to open config %s\n"), filename); - return; - } - - do { - - if ( fgets(line, 1024, fh) == NULL ) break; - chomp(line); - - if ( strncmp(line, "imagestore: ", 11) == 0 ) { - app->imagestore = strdup(line+12); - } - - if ( strncmp(line, "hidepointer: ", 12) == 0 ) { - app->hidepointer = yesno(line+13); - } - } while ( !feof(fh) ); - - fclose(fh); -} - - -const char *colloquium_get_imagestore(Colloquium *app) -{ - return app->imagestore; -} - - -int colloquium_get_hidepointer(Colloquium *app) -{ - return app->hidepointer; -} - - -static void colloquium_startup(GApplication *papp) -{ - Colloquium *app = COLLOQUIUM(papp); - const char *configdir; - char *tmp; - - G_APPLICATION_CLASS(colloquium_parent_class)->startup(papp); - - g_action_map_add_action_entries(G_ACTION_MAP(app), app_entries, - G_N_ELEMENTS(app_entries), app); - - app->builder = gtk_builder_new_from_resource("/uk/me/bitwiz/Colloquium/menus.ui"); - gtk_builder_add_from_resource(app->builder, "/uk/me/bitwiz/Colloquium/windows.ui", NULL); - gtk_application_set_menubar(GTK_APPLICATION(app), - G_MENU_MODEL(gtk_builder_get_object(app->builder, "menubar"))); - - if ( gtk_application_prefers_app_menu(GTK_APPLICATION(app)) ) { - /* Set the application menu only if it will be shown by the - * desktop environment. All the entries are already in the - * normal menus, so don't let GTK create a fallback menu in the - * menu bar. */ - GMenuModel *mmodel = G_MENU_MODEL(gtk_builder_get_object(app->builder, "app-menu")); - gtk_application_set_app_menu(GTK_APPLICATION(app), mmodel); - } - - configdir = g_get_user_config_dir(); - app->mydir = malloc(strlen(configdir)+14); - strcpy(app->mydir, configdir); - strcat(app->mydir, "/colloquium"); - - if ( !g_file_test(app->mydir, G_FILE_TEST_IS_DIR) ) { - - /* Folder not created yet */ - open_intro_doc(app); - app->first_run = 1; - - if ( g_mkdir(app->mydir, S_IRUSR | S_IWUSR | S_IXUSR) ) { - fprintf(stderr, _("Failed to create config folder\n")); - } - } - - /* Read config file */ - tmp = malloc(strlen(app->mydir)+32); - if ( tmp != NULL ) { - - tmp[0] = '\0'; - strcat(tmp, app->mydir); - strcat(tmp, "/config"); - - /* Create default config file if it doesn't exist */ - if ( !g_file_test(tmp, G_FILE_TEST_EXISTS) ) { - create_config(tmp); - } - - read_config(tmp, app); - free(tmp); - } -} - - -static void colloquium_shutdown(GApplication *app) -{ - G_APPLICATION_CLASS(colloquium_parent_class)->shutdown(app); -} - - -static void colloquium_class_init(ColloquiumClass *class) -{ - GApplicationClass *app_class = G_APPLICATION_CLASS(class); - GObjectClass *object_class = G_OBJECT_CLASS(class); - - app_class->startup = colloquium_startup; - app_class->shutdown = colloquium_shutdown; - app_class->activate = colloquium_activate; - app_class->open = colloquium_open; - - object_class->finalize = colloquium_finalize; -} - - -static void colloquium_init(Colloquium *app) -{ - app->imagestore = NULL; - app->hidepointer = 0; -} - - -static Colloquium *colloquium_new() -{ - Colloquium *app; - - g_set_application_name("Colloquium"); - app = g_object_new(colloquium_get_type(), - "application-id", "uk.org.bitwiz.Colloquium", - "flags", G_APPLICATION_HANDLES_OPEN, - "register-session", TRUE, - NULL); - - app->first_run = 0; /* Will be updated at "startup" if appropriate */ - - return app; -} - - -static void show_help(const char *s) -{ - printf(_("Syntax: %s [options] [<file.sc>]\n\n"), s); - printf(_("Narrative-based presentation system.\n\n" - " -h, --help Display this help message.\n")); -} - - -int main(int argc, char *argv[]) -{ - int c; - int status; - Colloquium *app; - - /* Long options */ - const struct option longopts[] = { - {"help", 0, NULL, 'h'}, - {0, 0, NULL, 0} - }; - - /* Short options */ - while ((c = getopt_long(argc, argv, "h", longopts, NULL)) != -1) { - - switch (c) - { - case 'h' : - show_help(argv[0]); - return 0; - - case 0 : - break; - - default : - return 1; - } - - } - -#if !GLIB_CHECK_VERSION(2,36,0) - g_type_init(); -#endif - - bindtextdomain("colloquium", LOCALEDIR); - textdomain("colloquium"); - - app = colloquium_new(); - status = g_application_run(G_APPLICATION(app), argc, argv); - g_object_unref(app); - return status; -} diff --git a/src-old/colloquium.h b/src-old/colloquium.h deleted file mode 100644 index 89f600f..0000000 --- a/src-old/colloquium.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * colloquium.h - * - * Copyright © 2014-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef COLLOQUIUM_H -#define COLLOQUIUM_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib-object.h> - - -typedef struct _colloquium Colloquium; - -#define COLLOQUIUM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ - GTK_TYPE_APPLICATION, Colloquium)) - - -extern const char *colloquium_get_imagestore(Colloquium *app); -extern int colloquium_get_hidepointer(Colloquium *app); - -extern void open_about_dialog(GtkWidget *parent); - - -#endif /* COLLOQUIUM_H */ diff --git a/src-old/debugger.c b/src-old/debugger.c deleted file mode 100644 index f15478a..0000000 --- a/src-old/debugger.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * print.c - * - * Copyright © 2017-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gtk/gtk.h> -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -#include "presentation.h" -#include "narrative_window.h" -#include "render.h" -#include "frame.h" -#include "utils.h" - - -#define MAX_DEBUG_RUNS (1024) - -struct debugwindow -{ - GtkWidget *window; - GtkWidget *drawingarea; - struct frame *fr; - guint timeout; -}; - - -static void plot_hr(cairo_t *cr, double *ypos, double width) -{ - cairo_move_to(cr, 10.0, *ypos+5.5); - cairo_line_to(cr, width-20.0, *ypos+5.5); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - *ypos += 10.0; -} - - -static void plot_text(cairo_t *cr, double *ypos, PangoFontDescription *fontdesc, - const char *tmp) -{ - PangoLayout *layout; - PangoRectangle ext; - - cairo_move_to(cr, 10.0, *ypos); - - layout = pango_cairo_create_layout(cr); - pango_layout_set_text(layout, tmp, -1); - pango_layout_set_font_description(layout, fontdesc); - - pango_layout_get_extents(layout, NULL, &ext); - *ypos += ext.height/PANGO_SCALE; - - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); - pango_cairo_show_layout(cr, layout); - - g_object_unref(layout); -} - - -static const char *str_type(enum para_type t) -{ - switch ( t ) { - - /* Text paragraph */ - case PARA_TYPE_TEXT : return "text"; - - /* Callback paragraph */ - case PARA_TYPE_CALLBACK : return "callback"; - - /* Unknown paragraph type */ - default : return "unknown"; - } -} - -static void debug_text_para(Paragraph *para, cairo_t *cr, double *ypos, - PangoFontDescription *fontdesc) -{ - int i, nrun; - char tmp[256]; - - nrun = para_debug_num_runs(para); - /* How many text runs */ - snprintf(tmp, 255, " %i runs", nrun); - plot_text(cr, ypos, fontdesc, tmp); - - for ( i=0; i<nrun; i++ ) { - SCBlock *scblock; - if ( para_debug_run_info(para, i, &scblock) ) { - /* Failed to get debug info for paragraph */ - plot_text(cr, ypos, fontdesc, "Error"); - } else { - snprintf(tmp, 255, " Run %i: SCBlock %p", i, scblock); - plot_text(cr, ypos, fontdesc, tmp); - } - } - - snprintf(tmp, 255, "Newline at end: %p", - para_debug_get_newline_at_end(para)); - plot_text(cr, ypos, fontdesc, tmp); -} - - -static gboolean dbg_draw_sig(GtkWidget *da, cairo_t *cr, struct debugwindow *dbgw) -{ - int width, height; - char tmp[256]; - PangoFontDescription *fontdesc; - int i; - double ypos = 10.0; - - /* Background */ - width = gtk_widget_get_allocated_width(GTK_WIDGET(da)); - height = gtk_widget_get_allocated_height(GTK_WIDGET(da)); - cairo_set_source_rgba(cr, 1.0, 0.8, 0.8, 1.0); - cairo_rectangle(cr, 0.0, 0.0, width, height); - cairo_fill(cr); - - if ( dbgw->fr == NULL ) return FALSE; - - fontdesc = pango_font_description_new(); - pango_font_description_set_family_static(fontdesc, "Serif"); - pango_font_description_set_style(fontdesc, PANGO_STYLE_ITALIC); - pango_font_description_set_absolute_size(fontdesc, 15*PANGO_SCALE); - - snprintf(tmp, 255, "Frame %p has %i paragraphs", dbgw->fr, dbgw->fr->n_paras); - plot_text(cr, &ypos, fontdesc, tmp); - - for ( i=0; i<dbgw->fr->n_paras; i++ ) { - - enum para_type t = para_type(dbgw->fr->paras[i]); - SCBlock *scblock = para_scblock(dbgw->fr->paras[i]); - - plot_hr(cr, &ypos, width); - snprintf(tmp, 255, "Paragraph %i: type %s", i, str_type(t)); - plot_text(cr, &ypos, fontdesc, tmp); - - snprintf(tmp, 255, "SCBlock %p", scblock); - plot_text(cr, &ypos, fontdesc, tmp); - - if ( t == PARA_TYPE_TEXT ) { - debug_text_para(dbgw->fr->paras[i], cr, &ypos, fontdesc); - } - - plot_text(cr, &ypos, fontdesc, ""); - - } - - pango_font_description_free(fontdesc); - - return FALSE; -} - - -static gboolean queue_redraw(void *vp) -{ - struct debugwindow *dbgw = vp; - gint w, h; - w = gtk_widget_get_allocated_width(GTK_WIDGET(dbgw->drawingarea)); - h = gtk_widget_get_allocated_height(GTK_WIDGET(dbgw->drawingarea)); - gtk_widget_queue_draw_area(GTK_WIDGET(dbgw->drawingarea), 0, 0, w, h); - return TRUE; -} - - -static gboolean close_sig(GtkWidget *widget, GdkEvent *event, struct debugwindow *dbgw) -{ - g_source_remove(dbgw->timeout); - free(dbgw); - return FALSE; -} - - -void open_debugger(struct frame *fr) -{ - struct debugwindow *dbgw; - GtkWidget *scroll; - - if ( fr == NULL ) return; - - dbgw = calloc(1, sizeof(struct debugwindow)); - if ( dbgw == NULL ) return; - - dbgw->fr = fr; - - dbgw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(dbgw->window), "debugger"); - gtk_window_set_title(GTK_WINDOW(dbgw->window), "Colloquium debugger"); - - scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_container_add(GTK_CONTAINER(dbgw->window), scroll); - - dbgw->drawingarea = gtk_drawing_area_new(); - gtk_container_add(GTK_CONTAINER(scroll), dbgw->drawingarea); - gtk_widget_set_size_request(dbgw->drawingarea, 100, 8000); - - g_signal_connect(G_OBJECT(dbgw->drawingarea), "draw", - G_CALLBACK(dbg_draw_sig), dbgw); - - g_signal_connect(G_OBJECT(dbgw->window), "delete-event", - G_CALLBACK(close_sig), dbgw); - - dbgw->timeout = g_timeout_add(1000, queue_redraw, dbgw); - - gtk_widget_show_all(dbgw->window); -} diff --git a/src-old/debugger.h b/src-old/debugger.h deleted file mode 100644 index d6191bf..0000000 --- a/src-old/debugger.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * debugger.h - * - * Copyright © 2017-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef DEBUGGER_H -#define DEBUGGER_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -extern void open_debugger(struct frame *fr); - -#endif /* DEBUGGER_H */ diff --git a/src-old/frame.c b/src-old/frame.c deleted file mode 100644 index 08b8fd9..0000000 --- a/src-old/frame.c +++ /dev/null @@ -1,1820 +0,0 @@ -/* - * frame.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include "sc_parse.h" -#include "frame.h" -#include "imagestore.h" -#include "utils.h" - -struct text_run -{ - SCBlock *scblock; - char *real_text; /* Usually NULL */ - PangoFontDescription *fontdesc; - double col[4]; -}; - -struct _paragraph -{ - enum para_type type; - double height; - float space[4]; - SCBlock *newline_at_end; - int empty; - - /* For PARA_TYPE_TEXT */ - int n_runs; - struct text_run *runs; - PangoLayout *layout; - PangoAlignment alignment; - - /* For anything other than PARA_TYPE_TEXT - * (for text paragraphs, these things are in the runs) */ - SCBlock *scblock; - - /* For PARA_TYPE_IMAGE */ - char *filename; - double image_w; - double image_h; - int image_real_w; - int image_real_h; - - /* For PARA_TYPE_CALLBACK */ - double cb_w; - double cb_h; - SCCallbackDrawFunc draw_func; - SCCallbackClickFunc click_func; - void *bvp; - void *vp; -}; - - -/* Returns the height of the paragraph including all spacing, padding etc */ -double paragraph_height(Paragraph *para) -{ - return para->height + para->space[2] + para->space[3]; -} - - -static int alloc_ro(struct frame *fr) -{ - struct frame **new_ro; - - new_ro = realloc(fr->children, - fr->max_children*sizeof(struct frame *)); - if ( new_ro == NULL ) return 1; - - fr->children = new_ro; - - return 0; -} - - -struct frame *frame_new() -{ - struct frame *n; - - n = calloc(1, sizeof(struct frame)); - if ( n == NULL ) return NULL; - - n->children = NULL; - n->max_children = 32; - if ( alloc_ro(n) ) { - fprintf(stderr, "Couldn't allocate children\n"); - free(n); - return NULL; - } - n->num_children = 0; - - n->scblocks = NULL; - n->n_paras = 0; - n->paras = NULL; - - return n; -} - - -static void free_paragraph(Paragraph *para) -{ - int i; - - for ( i=0; i<para->n_runs; i++ ) { - pango_font_description_free(para->runs[i].fontdesc); - free(para->runs[i].real_text); /* free(NULL) is OK */ - } - free(para->runs); - if ( para->layout != NULL ) g_object_unref(para->layout); - free(para); -} - - -void frame_free(struct frame *fr) -{ - int i; - - if ( fr == NULL ) return; - - /* Free paragraphs */ - if ( fr->paras != NULL ) { - for ( i=0; i<fr->n_paras; i++ ) { - free_paragraph(fr->paras[i]); - } - free(fr->paras); - } - - /* Free all children */ - for ( i=0; i<fr->num_children; i++ ) { - frame_free(fr->children[i]); - } - free(fr->children); - - free(fr); -} - - -struct frame *add_subframe(struct frame *fr) -{ - struct frame *n; - - n = frame_new(); - if ( n == NULL ) return NULL; - - if ( fr->num_children == fr->max_children ) { - fr->max_children += 32; - if ( alloc_ro(fr) ) return NULL; - } - - fr->children[fr->num_children++] = n; - - return n; -} - - -void show_frame_hierarchy(struct frame *fr, const char *t) -{ - int i; - char tn[1024]; - - strcpy(tn, t); - strcat(tn, " "); - - printf("%s%p (%.2f x %.2f)\n", t, fr, fr->w, fr->h); - - for ( i=0; i<fr->num_children; i++ ) { - show_frame_hierarchy(fr->children[i], tn); - } - -} - - -struct frame *find_frame_with_scblocks(struct frame *fr, SCBlock *scblocks) -{ - int i; - - if ( fr->scblocks == scblocks ) return fr; - - for ( i=0; i<fr->num_children; i++ ) { - struct frame *tt; - tt = find_frame_with_scblocks(fr->children[i], scblocks); - if ( tt != NULL ) return tt; - } - - return NULL; -} - - -static const char *text_for_run(const struct text_run *run) -{ - if ( run == NULL ) { - fprintf(stderr, "NULL run passed to text_for_run\n"); - return 0; - } - - if ( run->scblock == NULL ) { - fprintf(stderr, "NULL scblock in text_for_run\n"); - return 0; - } - - if ( run->real_text != NULL ) { - return run->real_text; - } - - return sc_block_contents(run->scblock); -} - - -static size_t run_text_len(const struct text_run *run) -{ - if ( run == NULL ) { - fprintf(stderr, "NULL run passed to run_text_len\n"); - return 0; - } - - if ( run->scblock == NULL ) { - fprintf(stderr, "NULL scblock in run_text_len\n"); - return 0; - } - - if ( run->real_text != NULL ) { - return strlen(run->real_text); - } - - if ( sc_block_contents(run->scblock) == NULL ) { - fprintf(stderr, "NULL scblock contents in run_text_len\n"); - return 0; - } - - return strlen(sc_block_contents(run->scblock)); -} - - -void wrap_paragraph(Paragraph *para, PangoContext *pc, double w, - size_t sel_start, size_t sel_end) -{ - size_t total_len = 0; - int i; - char *text; - PangoAttrList *attrs; - PangoRectangle rect; - size_t pos = 0; - - w -= para->space[0] + para->space[1]; - - if ( para->type == PARA_TYPE_IMAGE ) { - if ( para->image_w < 0.0 ) { - para->image_w = w; - para->image_h = w*((float)para->image_real_h/para->image_real_w); - } - para->height = para->image_h; - return; - } - - if ( para->type != PARA_TYPE_TEXT ) return; - - for ( i=0; i<para->n_runs; i++ ) { - total_len += run_text_len(¶->runs[i]); - } - - /* Allocate the complete text */ - text = malloc(total_len+1); - if ( text == NULL ) { - fprintf(stderr, "Couldn't allocate combined text (%lli)\n", - (long long int)total_len); - return; - } - - /* Allocate the attributes */ - attrs = pango_attr_list_new(); - - /* Put all of the text together */ - text[0] = '\0'; - for ( i=0; i<para->n_runs; i++ ) { - - PangoAttribute *attr; - const char *run_text; - size_t run_len; - guint16 r, g, b; - - run_text = text_for_run(¶->runs[i]); - run_len = strlen(run_text); - - attr = pango_attr_font_desc_new(para->runs[i].fontdesc); - attr->start_index = pos; - attr->end_index = pos + run_len; - pango_attr_list_insert(attrs, attr); - - r = para->runs[i].col[0] * 65535; - g = para->runs[i].col[1] * 65535; - b = para->runs[i].col[2] * 65535; - attr = pango_attr_foreground_new(r, g, b); - attr->start_index = pos; - attr->end_index = pos + run_len; - pango_attr_list_insert(attrs, attr); - - pos += run_len; - strncat(text, run_text, run_len); - - } - - /* Add attributes for selected text */ - if ( sel_start > 0 || sel_end > 0 ) { - PangoAttribute *attr; - attr = pango_attr_background_new(42919, 58853, 65535); - attr->start_index = sel_start; - attr->end_index = sel_end; - pango_attr_list_insert(attrs, attr); - } - - if ( para->layout == NULL ) { - para->layout = pango_layout_new(pc); - } - pango_layout_set_width(para->layout, pango_units_from_double(w)); - pango_layout_set_text(para->layout, text, total_len); - pango_layout_set_alignment(para->layout, para->alignment); - pango_layout_set_attributes(para->layout, attrs); - free(text); - pango_attr_list_unref(attrs); - - pango_layout_get_extents(para->layout, NULL, &rect); - para->height = pango_units_to_double(rect.height); -} - -static SCBlock *get_newline_at_end(Paragraph *para) -{ - return para->newline_at_end; -} - - -SCBlock *para_debug_get_newline_at_end(Paragraph *para) -{ - return get_newline_at_end(para); -} - - -void set_newline_at_end(Paragraph *para, SCBlock *bl) -{ - para->newline_at_end = bl; -} - - -void add_run(Paragraph *para, SCBlock *scblock, - PangoFontDescription *fdesc, double col[4], const char *real_text) -{ - struct text_run *runs_new; - - runs_new = realloc(para->runs, - (para->n_runs+1)*sizeof(struct text_run)); - if ( runs_new == NULL ) { - fprintf(stderr, "Failed to add run.\n"); - return; - } - - para->runs = runs_new; - para->runs[para->n_runs].scblock = scblock; - if ( real_text != NULL ) { - para->runs[para->n_runs].real_text = strdup(real_text); - } else { - para->runs[para->n_runs].real_text = NULL; - } - para->runs[para->n_runs].fontdesc = pango_font_description_copy(fdesc); - para->runs[para->n_runs].col[0] = col[0]; - para->runs[para->n_runs].col[1] = col[1]; - para->runs[para->n_runs].col[2] = col[2]; - para->runs[para->n_runs].col[3] = col[3]; - para->empty = 0; - para->n_runs++; -} - - -Paragraph *create_paragraph(struct frame *fr, SCBlock *bl) -{ - Paragraph **paras_new; - Paragraph *pnew; - - paras_new = realloc(fr->paras, (fr->n_paras+1)*sizeof(Paragraph *)); - if ( paras_new == NULL ) return NULL; - - pnew = calloc(1, sizeof(struct _paragraph)); - if ( pnew == NULL ) return NULL; - - fr->paras = paras_new; - fr->paras[fr->n_paras++] = pnew; - - /* For now, assume the paragraph is going to be for text. - * However, this can easily be changed */ - pnew->type = PARA_TYPE_TEXT; - pnew->scblock = bl; - pnew->n_runs = 0; - pnew->runs = NULL; - pnew->layout = NULL; - pnew->height = 0.0; - pnew->alignment = PANGO_ALIGN_LEFT; - pnew->empty = 1; - - return pnew; -} - - -/* Create a new paragraph in 'fr' just after paragraph 'pos' */ -Paragraph *insert_paragraph(struct frame *fr, int pos) -{ - Paragraph **paras_new; - Paragraph *pnew; - int i; - - if ( pos >= fr->n_paras ) { - fprintf(stderr, "insert_paragraph(): pos too high!\n"); - return NULL; - } - - paras_new = realloc(fr->paras, (fr->n_paras+1)*sizeof(Paragraph *)); - if ( paras_new == NULL ) return NULL; - - pnew = calloc(1, sizeof(struct _paragraph)); - if ( pnew == NULL ) return NULL; - - fr->paras = paras_new; - fr->n_paras++; - - for ( i=fr->n_paras-1; i>pos; i-- ) { - fr->paras[i] = fr->paras[i-1]; - } - fr->paras[pos+1] = pnew; - - return pnew; -} - - -Paragraph *add_callback_para(struct frame *fr, SCBlock *bl, double w, double h, - SCCallbackDrawFunc draw_func, - SCCallbackClickFunc click_func, void *bvp, - void *vp) -{ - Paragraph *pnew; - - if ( (fr->n_paras > 0) && (fr->paras[fr->n_paras-1]->empty) ) { - pnew = fr->paras[fr->n_paras-1]; - } else { - pnew = create_paragraph(fr, bl); - if ( pnew == NULL ) { - fprintf(stderr, "Failed to add callback paragraph\n"); - return NULL; - } - } - - pnew->type = PARA_TYPE_CALLBACK; - pnew->scblock = bl; - pnew->cb_w = w; - pnew->cb_h = h; - pnew->draw_func = draw_func; - pnew->click_func = click_func; - pnew->bvp = bvp; - pnew->vp = vp; - pnew->height = h; - pnew->empty = 0; - - return pnew; -} - - -void add_image_para(struct frame *fr, SCBlock *scblock, - const char *filename, - ImageStore *is, double w, double h, int editable) -{ - Paragraph *pnew; - int wi, hi; - - if ( is == NULL ) { - fprintf(stderr, "Adding image without ImageStore!\n"); - return; - } - - if ( (fr->n_paras > 0) && (fr->paras[fr->n_paras-1]->empty) ) { - pnew = fr->paras[fr->n_paras-1]; - } else { - pnew = create_paragraph(fr, scblock); - if ( pnew == NULL ) { - fprintf(stderr, "Failed to add image paragraph\n"); - return; - } - } - - if ( imagestore_get_size(is, filename, &wi, &hi) ) { - fprintf(stderr, _("Couldn't determine size of image '%s'\n"), - filename); - wi = 100; - hi = 100; - } - - pnew->type = PARA_TYPE_IMAGE; - pnew->scblock = scblock; - pnew->filename = strdup(filename); - pnew->image_w = w; - pnew->image_h = h; - pnew->image_real_w = wi; - pnew->image_real_h = hi; - pnew->height = h; - pnew->space[0] = 0.0; - pnew->space[1] = 0.0; - pnew->space[2] = 0.0; - pnew->space[3] = 0.0; - pnew->empty = 0; -} - - -double total_height(struct frame *fr) -{ - int i; - double t = 0.0; - for ( i=0; i<fr->n_paras; i++ ) { - t += paragraph_height(fr->paras[i]); - } - return t; -} - - -Paragraph *last_para(struct frame *fr) -{ - if ( fr == NULL ) return NULL; - if ( fr->paras == NULL ) return NULL; - return fr->paras[fr->n_paras-1]; -} - - -static void render_from_surf(cairo_surface_t *surf, cairo_t *cr, - double w, double h, int border) -{ - double x, y; - int sw, sh; - - x = 0.0; y = 0.0; - cairo_user_to_device(cr, &x, &y); - x = rint(x); y = rint(y); - cairo_device_to_user(cr, &x, &y); - - sw = cairo_image_surface_get_width(surf); - sh = cairo_image_surface_get_height(surf); - - cairo_save(cr); - cairo_scale(cr, w/sw, h/sh); - cairo_new_path(cr); - cairo_rectangle(cr, x, y, sw, sh); - cairo_set_source_surface(cr, surf, 0.0, 0.0); - cairo_pattern_t *patt = cairo_get_source(cr); - cairo_pattern_set_extend(patt, CAIRO_EXTEND_PAD); - cairo_pattern_set_filter(patt, CAIRO_FILTER_BEST); - cairo_fill(cr); - cairo_restore(cr); - - if ( border ) { - cairo_new_path(cr); - cairo_rectangle(cr, x+0.5, y+0.5, w, h); - cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - } -} - - -void render_paragraph(cairo_t *cr, Paragraph *para, ImageStore *is) -{ - cairo_surface_t *surf; - cairo_surface_type_t type; - double w, h; - - cairo_translate(cr, para->space[0], para->space[2]); - - type = cairo_surface_get_type(cairo_get_target(cr)); - - switch ( para->type ) { - - case PARA_TYPE_TEXT : - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); - pango_cairo_update_layout(cr, para->layout); - pango_cairo_show_layout(cr, para->layout); - cairo_fill(cr); - break; - - case PARA_TYPE_IMAGE : - w = para->image_w; - h = para->image_h; - cairo_user_to_device_distance(cr, &w, &h); - surf = lookup_image(is, para->filename, w); - if ( surf != NULL ) { - render_from_surf(surf, cr, para->image_w, para->image_h, 0); - } else { - printf("surf = NULL!\n"); - } - break; - - case PARA_TYPE_CALLBACK : - w = para->cb_w; - h = para->cb_h; - cairo_user_to_device_distance(cr, &w, &h); - if ( type == CAIRO_SURFACE_TYPE_PDF ) { - w *= 6; h *= 6; - } - surf = para->draw_func(w, h, - para->bvp, para->vp); - render_from_surf(surf, cr, para->cb_w, para->cb_h, 1); - cairo_surface_destroy(surf); /* FIXME: Cache like crazy */ - break; - - } -} - - -static size_t end_offset_of_para(struct frame *fr, int pn) -{ - int i; - size_t total = 0; - for ( i=0; i<fr->paras[pn]->n_runs; i++ ) { - total += run_text_len(&fr->paras[pn]->runs[i]); - } - return total; -} - - -/* Local x,y in paragraph -> text offset */ -static size_t text_para_pos(Paragraph *para, double x, double y, int *ptrail) -{ - int idx; - pango_layout_xy_to_index(para->layout, pango_units_from_double(x), - pango_units_from_double(y), &idx, ptrail); - return idx; -} - - -void show_edit_pos(struct edit_pos a) -{ - printf("para %i, pos %li, trail %i\n", a.para, (long int)a.pos, a.trail); -} - - -int positions_equal(struct edit_pos a, struct edit_pos b) -{ - if ( a.para != b.para ) return 0; - if ( a.pos != b.pos ) return 0; - if ( a.trail != b.trail ) return 0; - return 1; -} - - -void sort_positions(struct edit_pos *a, struct edit_pos *b) -{ - if ( a->para > b->para ) { - size_t tpos; - int tpara, ttrail; - tpara = b->para; tpos = b->pos; ttrail = b->trail; - b->para = a->para; b->pos = a->pos; b->trail = a->trail; - a->para = tpara; a->pos = tpos; a->trail = ttrail; - } - - if ( (a->para == b->para) && (a->pos > b->pos) ) - { - size_t tpos = b->pos; - int ttrail = b->trail; - b->pos = a->pos; b->trail = a->trail; - a->pos = tpos; a->trail = ttrail; - } -} - - -static PangoFontDescription *last_font_desc_and_col(struct frame *fr, int pn, double *col) -{ - int i; - - for ( i=pn-1; i>=0; i-- ) { - if ( fr->paras[i]->type != PARA_TYPE_TEXT ) continue; - if ( fr->paras[i]->n_runs == 0 ) continue; - col[0] = fr->paras[i]->runs[fr->paras[i]->n_runs-1].col[0]; - col[1] = fr->paras[i]->runs[fr->paras[i]->n_runs-1].col[1]; - col[2] = fr->paras[i]->runs[fr->paras[i]->n_runs-1].col[2]; - col[3] = fr->paras[i]->runs[fr->paras[i]->n_runs-1].col[3]; - return fr->paras[i]->runs[fr->paras[i]->n_runs-1].fontdesc; - } - - /* No previous text at all, so use the default text style - * (which is valid for new text in the frame, so this is OK) */ - col[0] = fr->col[0]; - col[1] = fr->col[1]; - col[2] = fr->col[2]; - col[3] = fr->col[3]; - return fr->fontdesc; -} - - -void ensure_run(struct frame *fr, struct edit_pos cpos) -{ - SCBlock *bl; - Paragraph *para; - PangoFontDescription *fontdesc; - double col[4]; - - para = fr->paras[cpos.para]; - - if ( para->n_runs > 0 ) return; - - if ( para->type != PARA_TYPE_TEXT ) return; - - if ( para->scblock != NULL ) { - - bl = sc_block_prepend(para->scblock, fr->scblocks); - if ( bl == NULL ) { - fprintf(stderr, "Couldn't prepend block\n"); - return; - } - sc_block_set_contents(bl, strdup("")); - - } else { - - /* If the paragraph's SCBlock is NULL, it means this paragraph - * is right at the end of the document. The last thing in the - * document is something like \newpara. */ - bl = sc_block_append_inside(fr->scblocks, NULL, NULL, strdup("")); - - } - - para->scblock = bl; - - fontdesc = last_font_desc_and_col(fr, cpos.para, col); - add_run(para, bl, fontdesc, col, NULL); - wrap_paragraph(para, NULL, fr->w - fr->pad_l - fr->pad_r, 0, 0); -} - - -int find_cursor(struct frame *fr, double x, double y, struct edit_pos *pos) -{ - double pad; - int i; - - if ( fr == NULL ) { - fprintf(stderr, "Cursor frame is NULL.\n"); - return 1; - } - - pad = fr->pad_t; - - for ( i=0; i<fr->n_paras; i++ ) { - double npos = pad + paragraph_height(fr->paras[i]); - if ( npos > y ) { - pos->para = i; - if ( fr->paras[i]->type == PARA_TYPE_TEXT ) { - pos->pos = text_para_pos(fr->paras[i], - x - fr->pad_l - fr->paras[i]->space[0], - y - pad - fr->paras[i]->space[2], - &pos->trail); - } else { - pos->pos = 0; - } - return 0; - } - pad = npos; - } - - if ( fr->n_paras == 0 ) { - printf("No paragraphs in frame.\n"); - return 1; - } - - /* Pretend it's in the last paragraph */ - pad -= fr->paras[fr->n_paras-1]->height; - pos->para = fr->n_paras - 1; - pos->pos = text_para_pos(fr->paras[fr->n_paras-1], - x - fr->pad_l, y - pad, &pos->trail); - return 0; -} - - -int get_para_highlight(struct frame *fr, int cursor_para, - double *cx, double *cy, double *cw, double *ch) -{ - Paragraph *para; - int i; - double py = 0.0; - - if ( fr == NULL ) { - fprintf(stderr, "Cursor frame is NULL.\n"); - return 1; - } - - if ( cursor_para >= fr->n_paras ) { - fprintf(stderr, "Highlight paragraph number is too high!\n"); - return 1; - } - - para = fr->paras[cursor_para]; - for ( i=0; i<cursor_para; i++ ) { - py += paragraph_height(fr->paras[i]); - } - - *cx = fr->pad_l; - *cy = fr->pad_t + py; - *cw = fr->w - fr->pad_l - fr->pad_r; - *ch = paragraph_height(para); - return 0; -} - - -int get_cursor_pos(struct frame *fr, int cursor_para, int cursor_pos, - double *cx, double *cy, double *ch) -{ - Paragraph *para; - PangoRectangle rect; - int i; - double py = 0.0; - - if ( fr == NULL ) { - fprintf(stderr, "Cursor frame is NULL.\n"); - return 1; - } - - if ( cursor_para >= fr->n_paras ) { - fprintf(stderr, "Cursor paragraph number is too high!\n"); - return 1; - } - - para = fr->paras[cursor_para]; - for ( i=0; i<cursor_para; i++ ) { - py += paragraph_height(fr->paras[i]); - } - - if ( para->type != PARA_TYPE_TEXT ) { - return 1; - } - - pango_layout_get_cursor_pos(para->layout, cursor_pos, &rect, NULL); - - *cx = pango_units_to_double(rect.x) + fr->pad_l + para->space[0]; - *cy = pango_units_to_double(rect.y) + fr->pad_t + py + para->space[2]; - *ch = pango_units_to_double(rect.height); - return 0; -} - - -//void cursor_moveh(struct frame *fr, int *cpara, size_t *cpos, int *ctrail, -void cursor_moveh(struct frame *fr, struct edit_pos *cp, signed int dir) -{ - Paragraph *para = fr->paras[cp->para]; - int np = cp->pos; - - pango_layout_move_cursor_visually(para->layout, 1, cp->pos, cp->trail, - dir, &np, &cp->trail); - if ( np == -1 ) { - if ( cp->para > 0 ) { - size_t end_offs; - cp->para--; - end_offs = end_offset_of_para(fr, cp->para); - if ( end_offs > 0 ) { - cp->pos = end_offs - 1; - cp->trail = 1; - } else { - /* Jumping into an empty paragraph */ - cp->pos = 0; - cp->trail = 0; - } - return; - } else { - /* Can't move any further */ - return; - } - } - - if ( np == G_MAXINT ) { - if ( cp->para < fr->n_paras-1 ) { - cp->para++; - cp->pos = 0; - cp->trail = 0; - return; - } else { - /* Can't move any further */ - return; - } - } - - cp->pos = np; -} - - -void check_callback_click(struct frame *fr, int para) -{ - Paragraph *p = fr->paras[para]; - if ( p->type == PARA_TYPE_CALLBACK ) { - p->click_func(0.0, 0.0, p->bvp, p->vp); - } -} - - -static int get_paragraph_offset(Paragraph *para, int nrun) -{ - int i; - size_t t = 0; - - for ( i=0; i<nrun; i++ ) { - struct text_run *run = ¶->runs[i]; - t += run_text_len(run); - } - return t; -} - - -static int which_run(Paragraph *para, size_t offs) -{ - int i; - size_t t = 0; - - for ( i=0; i<para->n_runs; i++ ) { - struct text_run *run = ¶->runs[i]; - t += run_text_len(run); - if ( t > offs ) return i; - } - - /* Maybe offs points exactly to the end of the last run? */ - if ( t == offs ) return para->n_runs-1; - - return para->n_runs; -} - - -size_t pos_trail_to_offset(Paragraph *para, size_t offs, int trail) -{ - glong char_offs; - size_t run_offs; - const char *run_text; - struct text_run *run; - int nrun; - char *ptr; - size_t para_offset_of_run; - - nrun = which_run(para, offs); - - if ( nrun == para->n_runs ) { - fprintf(stderr, "pos_trail_to_offset: Offset too high\n"); - return 0; - } - - if ( para->n_runs == 0 ) { - return 0; - } - - run = ¶->runs[nrun]; - - if ( para->type != PARA_TYPE_TEXT ) return 0; - - if ( run == NULL ) { - fprintf(stderr, "pos_trail_to_offset: No run\n"); - return 0; - } - - if ( run->scblock == NULL ) { - fprintf(stderr, "pos_trail_to_offset: SCBlock = NULL?\n"); - return 0; - } - - /* Get the text for the run */ - run_text = text_for_run(run); - if ( run_text == NULL ) { - fprintf(stderr, "pos_trail_to_offset: No contents " - "(%p name=%s, options=%s)\n", - run->scblock, sc_block_name(run->scblock), - sc_block_options(run->scblock)); - return 0; - } - - - /* Turn the paragraph offset into a run offset */ - para_offset_of_run = get_paragraph_offset(para, nrun); - run_offs = offs - para_offset_of_run; - - char_offs = g_utf8_pointer_to_offset(run_text, run_text+run_offs); - char_offs += trail; - - if ( char_offs > g_utf8_strlen(run_text, -1) ) { - printf("Offset outside string! '%s'\n" - "char_offs %li offs %li len %li\n", - run_text, (long int)char_offs, (long int)offs, - (long int)g_utf8_strlen(run_text, -1)); - } - - ptr = g_utf8_offset_to_pointer(run_text, char_offs); - return ptr - run_text + para_offset_of_run; -} - - -int position_editable(struct frame *fr, struct edit_pos cp) -{ - Paragraph *para; - int run; - size_t paraoffs; - - if ( fr == NULL ) { - fprintf(stderr, "Frame is NULL.\n"); - return 0; - } - - if ( cp.para >= fr->n_paras ) { - fprintf(stderr, "Paragraph number is too high!\n"); - return 0; - } - - para = fr->paras[cp.para]; - - if ( para->type != PARA_TYPE_TEXT ) { - fprintf(stderr, "Paragraph is not text.\n"); - return 0; - } - - paraoffs = pos_trail_to_offset(para, cp.pos, cp.trail); - run = which_run(para, paraoffs); - if ( run == para->n_runs ) { - fprintf(stderr, "Couldn't find run!\n"); - return 0; - } - - if ( para->runs[run].real_text != NULL ) return 0; - - return 1; -} - - -void insert_text_in_paragraph(Paragraph *para, size_t offs, const char *t) -{ - int nrun; - - /* Find which run we are in */ - nrun = which_run(para, offs); - if ( nrun == para->n_runs ) { - fprintf(stderr, "Couldn't find run to insert into.\n"); - return; - } - - if ( para->n_runs == 0 ) { - printf("No runs in paragraph?\n"); - } else { - struct text_run *run; - size_t run_offs; - run = ¶->runs[nrun]; - run_offs = offs - get_paragraph_offset(para, nrun); - sc_insert_text(run->scblock, run_offs, t); - } -} - - -static SCBlock *pos_to_scblock(struct frame *fr, struct edit_pos p, - enum para_type *type) -{ - int run; - size_t paraoffs; - Paragraph *para; - - para = fr->paras[p.para]; - if ( type != NULL ) { - *type = para->type; - } - - if ( para->type != PARA_TYPE_TEXT ) { - return para->scblock; - } - - paraoffs = pos_trail_to_offset(para, p.pos, p.trail); - - run = which_run(para, paraoffs); - assert(run < para->n_runs); - - return para->runs[run].scblock; -} - - -static size_t pos_to_offset(struct frame *fr, struct edit_pos p) -{ - int run; - size_t paraoffs; - Paragraph *para; - - para = fr->paras[p.para]; - if ( para->type != PARA_TYPE_TEXT ) { - return 0; - } - - /* Offset of this position into the paragraph */ - paraoffs = pos_trail_to_offset(para, p.pos, p.trail); - - run = which_run(para, paraoffs); - assert(run < para->n_runs); - - /* Offset of this position into the run - * (and therefore into the SCBlock) */ - return paraoffs - get_paragraph_offset(para, run); -} - - -static int pos_to_run_number(struct frame *fr, struct edit_pos p) -{ - int run; - size_t paraoffs; - Paragraph *para; - - para = fr->paras[p.para]; - if ( para->type != PARA_TYPE_TEXT ) { - return 0; - } - - paraoffs = pos_trail_to_offset(para, p.pos, p.trail); - - run = which_run(para, paraoffs); - assert(run < para->n_runs); - - return run; -} - - -static void delete_run(Paragraph *para, int nrun) -{ - printf("deleting run %i of %i from para %p\n", nrun, para->n_runs, para); - memmove(¶->runs[nrun], ¶->runs[nrun+1], - (para->n_runs-nrun-1)*sizeof(struct text_run)); - para->n_runs--; -} - - -static Paragraph *scan_runs_for_scblock(struct frame *fr, int pn1, int pn2, - SCBlock *bl, int *run) -{ - int i; - - for ( i=pn1; i<=pn2; i++ ) { - - int j; - - /* Non-text paragraph - just one thing to check */ - if ( fr->paras[i]->scblock == bl ) { - *run = 0; - return fr->paras[i]; - } - - /* Check all runs */ - for ( j=0; j<fr->paras[i]->n_runs; j++ ) { - if ( fr->paras[i]->runs[j].scblock == bl ) { - *run = j; - return fr->paras[i]; - } - } - } - return NULL; -} - - -static Paragraph *find_run_for_scblock_next(struct frame *fr, int pn1, int pn2, - SCBlock *bl, int *run) -{ - if ( sc_block_child(bl) != NULL ) { - Paragraph *para; - para = find_run_for_scblock_next(fr, pn1, pn2, - sc_block_child(bl), run); - if ( para != NULL ) return para; - } - - do { - Paragraph *para; - para = scan_runs_for_scblock(fr, pn1, pn2, bl, run); - if ( para != NULL ) return para; - bl = sc_block_next(bl); - } while ( bl != NULL ); - - return NULL; -} - - -/* Find the run which contains the text from "bl", - * taking into account that it might be a child block, for example: - * {some text} - * \italic <---- bl points here - * {more text} <---- but this block is referenced by the run - * {final text} - */ -static Paragraph *find_run_for_scblock(struct frame *fr, int pn1, int pn2, - SCBlock *bl, int *run) -{ - Paragraph *para; - - show_sc_block(bl, "searching "); - para = scan_runs_for_scblock(fr, pn1, pn2, bl, run); - if ( para != NULL ) return para; - - if ( sc_block_child(bl) != NULL ) { - para = find_run_for_scblock_next(fr, pn1, pn2, sc_block_child(bl), run); - if ( para != NULL ) return para; - } - - return NULL; -} - - -static int paragraph_number(struct frame *fr, Paragraph *p, int *err) -{ - int i; - for ( i=0; i<fr->n_paras; i++ ) { - if ( fr->paras[i] == p ) return i; - } - fprintf(stderr, "Couldn't find paragraph %p\n", p); - *err = 1; - return 0; -} - - -static int find_para(struct frame *fr, Paragraph *para) -{ - int i; - - for ( i=0; i<fr->n_paras; i++ ) { - if ( fr->paras[i] == para ) return i; - } - - return fr->n_paras; -} - - -static void delete_paragraph(struct frame *fr, Paragraph *para, int *pnp) -{ - int pn = find_para(fr, para); - if ( pn == fr->n_paras ) { - fprintf(stderr, "Couldn't find paragraph to delete (%p)\n", para); - return; - } - - printf("deleting paragraph %i (%p)\n", pn, para); - - memmove(&fr->paras[pn], &fr->paras[pn+1], - (fr->n_paras-pn-1)*sizeof(Paragraph *)); - fr->n_paras--; - - if ( (pnp != NULL) && (*pnp > pn) ) { - (*pnp)--; - } -} - - -static void delete_run_for_scblock(struct frame *fr, - Paragraph *p1, Paragraph *p2, SCBlock *bl, - int *pnp) -{ - int pn1, pn2; - int err = 0; - Paragraph *para; - int run; - - pn1 = paragraph_number(fr, p1, &err); - pn2 = paragraph_number(fr, p2, &err); - if ( err ) return; - - para = find_run_for_scblock(fr, pn1, pn2, bl, &run); - if ( para == NULL ) { - fprintf(stderr, "Couldn't find block %p between paragraphs %p and %p\n", - bl, p1, p2); - return; - } - - if ( (run==0) && (para->scblock == bl ) ) { - delete_paragraph(fr, para, pnp); - } else { - delete_run(para, run); - } -} - - -static signed int merge_paragraph_runs(Paragraph *p1, Paragraph *p2) -{ - struct text_run *runs_new; - int i, spos; - - /* All the runs from p2 get added to p1 */ - runs_new = realloc(p1->runs, - (p1->n_runs+p2->n_runs)*sizeof(struct text_run)); - if ( runs_new == NULL ) { - fprintf(stderr, "Failed to allocate merged runs.\n"); - return -1; - } - p1->runs = runs_new; - - spos = p1->n_runs; - - /* The end of the united paragraph should now be the end of the - * second one */ - set_newline_at_end(p1, get_newline_at_end(p2)); - - for ( i=0; i<p2->n_runs; i++ ) { - p1->runs[p1->n_runs] = p2->runs[i]; - p1->n_runs++; - } - free(p2->runs); - free(p2); - - return spos; -} - - -static void merge_paragraphs_by_newpara(struct frame *fr, SCBlock *np) -{ - int i; - Paragraph *p1; - Paragraph *p2; - - for ( i=0; i<fr->n_paras-1; i++ ) { - if ( fr->paras[i]->newline_at_end == np ) { - - int j; - signed int spos; - - p1 = fr->paras[i]; - p2 = fr->paras[i+1]; - - printf("-------------------------------\n"); - show_para(p1); - printf("---x--------x------------------\n"); - show_para(p2); - spos = merge_paragraph_runs(p1, p2); - if ( spos < 0 ) { - fprintf(stderr, "Failed to merge paragraphs\n"); - return; - } - printf("-------------------------------\n"); - show_para(p1); - - for ( j=i+1; j<fr->n_paras-1; j++ ) { - fr->paras[j] = fr->paras[j+1]; - } - fr->n_paras--; - - return; - - } - } - - fprintf(stderr, "Couldn't find paragraphs to merge by newpara\n"); -} - - -static int find_block_inside(SCBlock *needle, SCBlock *bl) -{ - if ( needle == bl ) return 1; - - if ( sc_block_child(bl) != NULL ) { - if ( find_block_inside(needle, sc_block_child(bl)) ) return 1; - } - - if ( sc_block_next(bl) != NULL ) { - if ( find_block_inside(needle, sc_block_next(bl)) ) return 1; - } - - return 0; -} - - -/* Return true if "top" either IS "child", or contains "child" somewhere - * underneath, even if via a macro expansion */ -static int block_is_under(SCBlock *needle, SCBlock *top) -{ - if ( needle == top ) return 1; - - if ( sc_block_child(top) != NULL ) { - if ( find_block_inside(needle, sc_block_child(top)) ) return 1; - } - - /* Do not look at top->next here */ - - return 0; -} - - -void delete_text_from_frame(struct frame *fr, struct edit_pos p1, struct edit_pos p2, - double wrapw) -{ - int i; - SCBlock *p1scblock, *p2scblock; - enum para_type type1, type2; - size_t p2offs; - SCBlock *scblock; - int wrap_end; - - sort_positions(&p1, &p2); - - /* To make sure there are no nasty surprises ahead, run through the - * paragraphs we're about to touch, and make sure they all have at least - * an empty dummy run */ - for ( i=p1.para; i<=p2.para; i++ ) { - struct edit_pos ep; - ep.para = i; - ep.pos = 0; - ep.trail = 0; - ensure_run(fr, ep); - } - - if ( !position_editable(fr, p1) || !position_editable(fr, p2) ) { - fprintf(stderr, "Delete outside editable region\n"); - return; - } - - /* Find SC positions for start and end */ - p1scblock = pos_to_scblock(fr, p1, &type1); - p2scblock = pos_to_scblock(fr, p2, &type2); - p2offs = pos_to_offset(fr, p2); - wrap_end = p2.para; - - printf("SCBlocks %p to %p\n", p1scblock, p2scblock); - if ( p1scblock == NULL ) { - fprintf(stderr, "Starting block NULL. Not deleting.\n"); - return; - } - if ( p2scblock == NULL ) { - fprintf(stderr, "Ending block NULL. Not deleting.\n"); - return; - } - //show_sc_blocks(p1scblock); - - if ( (p1scblock == p2scblock) && (type1 == PARA_TYPE_TEXT) ) { - - size_t p1offs; - printf("Simple case, one SCBlock\n"); - - assert(type1 == type2); - - /* Remove the text and update the run length */ - p1offs = pos_to_offset(fr, p1); - scblock_delete_text(p1scblock, p1offs, p2offs); - - wrap_paragraph(fr->paras[p1.para], NULL, wrapw, 0, 0); - - return; - } - - /* Starting point for iteration over blocks in middle of range. - * Record this now, because p1scblock might be about to get deleted */ - scblock = sc_block_next(p1scblock); - - /* First SCBlock in range: delete whole thing or second half */ - printf("First block %p\n", p1scblock); - if ( type1 == PARA_TYPE_TEXT ) { - - size_t p1offs = pos_to_offset(fr, p1); - int p1run = pos_to_run_number(fr, p1); - printf(" offs %li\n", (long int)p1offs); - if ( p1offs != 0 ) { - printf("Partial delete\n"); - printf("contents '%s'\n", sc_block_contents(p1scblock)); - printf("from offs %li\n", (long int)p1offs); - scblock_delete_text(p1scblock, p1offs, -1); - } else { - printf("Deleting the whole text SCBlock\n"); - sc_block_delete(&fr->scblocks, p1scblock); - delete_run(fr->paras[p1.para], p1run); - } - - } else { - printf("Deleting the whole non-text SCBlock\n"); - sc_block_delete(&fr->scblocks, p1scblock); - } - - /* Delete all the complete SCBlocks in the middle of the range */ - if ( !block_is_under(p2scblock, scblock) ) { - do { - - SCBlock *next; - - /* For each SC block in middle of range: */ - printf("Deleting %p\n", scblock); - if ( scblock == NULL ) { - fprintf(stderr, "nothing?\n"); - break; - } - printf("name is '%s'\n", sc_block_name(scblock)); - - if ( (sc_block_name(scblock) != NULL) - && (strcmp(sc_block_name(scblock), "newpara") == 0) ) - { - /* Deleting newpara block, merge the paragraphs */ - merge_paragraphs_by_newpara(fr, scblock); - p2.para--; - } - - next = sc_block_next(scblock); - delete_run_for_scblock(fr, fr->paras[p1.para], - fr->paras[p2.para], scblock, - &p2.para); - sc_block_delete(&fr->scblocks, scblock); - - scblock = next; - - } while ( !block_is_under(p2scblock, scblock) ); - } - - /* Last SCBlock in range: delete whole thing or first half */ - printf("Last block %p (%s)\n", p2scblock, sc_block_name(p2scblock)); - if ( type2 == PARA_TYPE_TEXT ) { - size_t len; - printf(" offs %li\n", (long int)p2offs); - if ( sc_block_contents(p2scblock) != NULL ) { - len = strlen(sc_block_contents(p2scblock)); - } else { - len = 0; - } - printf(" len %li\n", (long int)len); - if ( (len > 0) && (p2offs == len) ) { - printf("Deleting the whole text SCBlock\n"); - printf("deleting block %p\n", p2scblock); - show_sc_block(p2scblock, ""); - sc_block_delete(&fr->scblocks, p2scblock); - delete_run_for_scblock(fr, fr->paras[p1.para], - fr->paras[p2.para], p2scblock, - NULL); - } else if ( p2offs > 0 ) { - printf("Partial delete\n"); - printf("contents '%s'\n", sc_block_contents(p2scblock)); - printf("up to offs %li\n", (long int)p2offs); - scblock_delete_text(p2scblock, 0, p2offs); - } /* else do nothing */ - } else { - printf("Deleting the whole non-text SCBlock\n"); - sc_block_delete(&fr->scblocks, p2scblock); - } - - /* If any paragraphs have been deleted, this will wrap too many - * paragraphs, but it doesn't matter as long as we don't wrap - * past the end of the frame's contents. */ - for ( i=p1.para; i<=wrap_end; i++ ) { - if ( i >= fr->n_paras ) break; - printf("Wrapping para %i (%p)\n", i, fr->paras[i]); - wrap_paragraph(fr->paras[i], NULL, wrapw, 0, 0); - } - printf("All done.\n"); -} - - -void show_para(Paragraph *p) -{ - printf("Paragraph %p\n", p); - - if ( p->type == PARA_TYPE_TEXT ) { - - int i; - - printf("%i runs:\n", p->n_runs); - for ( i=0; i<p->n_runs; i++ ) { - printf(" Run %2i: SCBlock %p %s '%s'\n", - i, p->runs[i].scblock, - pango_font_description_to_string(p->runs[i].fontdesc), - sc_block_contents(p->runs[i].scblock)); - } - - } else if ( p->type == PARA_TYPE_IMAGE ) { - printf(" Image: %s\n", p->filename); - } else { - printf(" Other paragraph type\n"); - } -} - - -static SCBlock *split_text_paragraph(struct frame *fr, int pn, size_t pos, - PangoContext *pc) -{ - Paragraph *pnew; - int i; - SCBlock *nnp; - size_t run_offs; - int run; - Paragraph *para = fr->paras[pn]; - struct text_run *rr; - - pnew = insert_paragraph(fr, pn); - if ( pnew == NULL ) { - fprintf(stderr, "Failed to insert paragraph\n"); - return NULL; - } - - /* Determine which run the cursor is in */ - run = which_run(para, pos); - - /* Create the new (second) paragraph */ - pnew->type = PARA_TYPE_TEXT; - pnew->n_runs = 0; - pnew->runs = NULL; - for ( i=0; i<4; i++ ) pnew->space[i] = para->space[i]; - - rr = ¶->runs[run]; - run_offs = pos - get_paragraph_offset(para, run); - printf("split at run %i\n", run); - - /* Easy case: splitting at a run boundary */ - if ( run_offs == run_text_len(rr) ) { - - /* Even easier case: splitting at the end of the paragraph */ - if ( run == para->n_runs-1 ) { - - SCBlock *np; - SCBlock *end; - - printf("Simple new para\n"); - - if ( get_newline_at_end(para) == NULL ) { - - /* The current paragraph doesn't have - * a \newpara yet */ - - np = sc_block_append(rr->scblock, - strdup("newpara"), NULL, - NULL, NULL); - set_newline_at_end(para, np); - - } else { - - SCBlock *op; - - /* If the current paragraph did have \newpara, - * then the new one needs one too */ - np = sc_block_append(rr->scblock, - strdup("newpara"), - NULL, NULL, NULL); - op = get_newline_at_end(para); - set_newline_at_end(para, np); - set_newline_at_end(pnew, op); - - - } - - /* Add an empty run + SCBlock to type into */ - end = sc_block_append(np, NULL, NULL, strdup(""), NULL); - - pnew->n_runs = 0; - add_run(pnew, end, rr->fontdesc, rr->col, NULL); - pnew->scblock = end; - - wrap_paragraph(pnew, pc, fr->w - fr->pad_l - fr->pad_r, 0, 0); - - return end; - - } - - } else { - - /* Split the run (and SCBlock) into two */ - double col[4] = {0,0,0,0}; - struct text_run *rn; - - printf("Splitting run %i. Before:\n", run); - show_para(para); - - add_run(para, NULL, NULL, col, NULL); - /* -2 here because add_run increased para->n_runs by 1 */ - memmove(¶->runs[run+2], ¶->runs[run+1], - (para->n_runs - run - 2)*sizeof(struct text_run)); - - rr = ¶->runs[run]; /* Because add_run realloced the runs */ - rn = ¶->runs[run+1]; - - rn->scblock = sc_block_split(rr->scblock, run_offs); - - rn->fontdesc = pango_font_description_copy(rr->fontdesc); - rn->col[0] = rr->col[0]; - rn->col[1] = rr->col[1]; - rn->col[2] = rr->col[2]; - rn->col[3] = rr->col[3]; - - printf("After:\n"); - show_para(para); - - } - - /* All later runs just get moved to the new paragraph */ - for ( i=run+1; i<para->n_runs; i++ ) { - double col[4] = {0,0,0,0}; - printf("Moving run %i to pos %i\n", i, pnew->n_runs); - add_run(pnew, NULL, NULL, col, NULL); - pnew->runs[pnew->n_runs-1] = para->runs[i]; - } - pnew->scblock = pnew->runs[0].scblock; - - /* Truncate the first paragraph at the appropriate position */ - para->n_runs = run+1; - - printf("Final paragraphs:\n"); - printf("First:\n"); - show_para(para); - printf("Second:\n"); - show_para(pnew); - - /* Add a \newpara after the end of the first paragraph's SC */ - nnp = sc_block_append(rr->scblock, strdup("newpara"), NULL, NULL, NULL); - set_newline_at_end(pnew, get_newline_at_end(para)); - set_newline_at_end(para, nnp); - - wrap_paragraph(para, pc, fr->w - fr->pad_l - fr->pad_r, 0, 0); - wrap_paragraph(pnew, pc, fr->w - fr->pad_l - fr->pad_r, 0, 0); - - return sc_block_next(nnp); -} - - -SCBlock *split_paragraph(struct frame *fr, int pn, size_t pos, PangoContext *pc) -{ - Paragraph *para = fr->paras[pn]; - - if ( para->type == PARA_TYPE_TEXT ) { - return split_text_paragraph(fr, pn, pos, pc); - } else { - /* Other types can't be split */ - return NULL; - } -} - - -SCBlock *block_at_cursor(struct frame *fr, int pn, size_t pos) -{ - Paragraph *para = fr->paras[pn]; - - if ( para->type != PARA_TYPE_CALLBACK ) return NULL; - - return para->scblock; -} - - -int get_sc_pos(struct frame *fr, int pn, size_t pos, - SCBlock **bl, size_t *ppos) -{ - Paragraph *para = fr->paras[pn]; - int nrun; - struct text_run *run; - - nrun = which_run(para, pos); - if ( nrun == para->n_runs ) { - fprintf(stderr, "Couldn't find run to insert into.\n"); - return 1; - } - run = ¶->runs[nrun]; - - *ppos = pos - get_paragraph_offset(para, nrun); - *bl = run->scblock; - - return 0; -} - - -void set_para_spacing(Paragraph *para, float space[4]) -{ - if ( para == NULL ) return; - para->space[0] = space[0]; - para->space[1] = space[1]; - para->space[2] = space[2]; - para->space[3] = space[3]; -} - - -void set_para_alignment(Paragraph *para, PangoAlignment align) -{ - if ( para == NULL ) return; - para->alignment = align; -} - - -void *get_para_bvp(Paragraph *para) -{ - if ( para->type != PARA_TYPE_CALLBACK ) return NULL; - return para->bvp; -} - - -SCBlock *para_scblock(Paragraph *para) -{ - return para->scblock; -} - - -enum para_type para_type(Paragraph *para) -{ - return para->type; -} - - -int para_debug_num_runs(Paragraph *para) -{ - if ( para->type != PARA_TYPE_TEXT ) return 0; - return para->n_runs; -} - - -int para_debug_run_info(Paragraph *para, int i, SCBlock **scblock) -{ - if ( para->type != PARA_TYPE_TEXT ) return 1; - if ( i >= para->n_runs ) return 1; - - *scblock = para->runs[i].scblock; - return 0; -} diff --git a/src-old/frame.h b/src-old/frame.h deleted file mode 100644 index d0525f8..0000000 --- a/src-old/frame.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * frame.h - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef FRAME_H -#define FRAME_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <pango/pango.h> -#include <cairo.h> - - -typedef enum -{ - GRAD_NONE, - GRAD_HORIZ, - GRAD_VERT -} GradientType; - -enum para_type -{ - PARA_TYPE_TEXT, - PARA_TYPE_IMAGE, - PARA_TYPE_CALLBACK -}; - -typedef struct _paragraph Paragraph; - -#include "sc_parse.h" -#include "sc_interp.h" -#include "imagestore.h" - - -struct edit_pos -{ - int para; /* Paragraph number */ - size_t pos; /* Byte position within paragraph - * Yes, really. See pango_layout_xy_to_index */ - int trail; -}; - - -struct frame -{ - struct frame **children; - int num_children; - int max_children; - - SCBlock *scblocks; - - Paragraph **paras; - int n_paras; - int max_paras; - - /* The font which will be used by default for this frame */ - PangoFontDescription *fontdesc; - double col[4]; - - /* The rectangle allocated to this frame, determined by the renderer */ - double x; - double y; - double w; - double h; - - double pad_t; - double pad_b; - double pad_l; - double pad_r; - - /* Background properties for this frame */ - double bgcol[4]; - double bgcol2[4]; - GradientType grad; - - /* True if this frame should be deleted on the next mouse click */ - int empty; - - /* True if the aspect ratio of this frame should be maintained */ - int is_image; - - /* True if this frame can be resized and moved */ - int resizable; -}; - - -extern struct frame *frame_new(void); -extern void frame_free(struct frame *fr); -extern struct frame *add_subframe(struct frame *fr); -extern struct frame *find_frame_with_scblocks(struct frame *top, - SCBlock *scblocks); - -extern double total_height(struct frame *fr); - -extern Paragraph *last_para(struct frame *fr); -extern void show_para(Paragraph *p); -extern void set_para_spacing(Paragraph *para, float space[4]); -extern void set_para_alignment(Paragraph *para, PangoAlignment align); - -extern double paragraph_height(Paragraph *para); -extern void render_paragraph(cairo_t *cr, Paragraph *para, ImageStore *is); - -extern void set_newline_at_end(Paragraph *para, SCBlock *bl); -extern void show_edit_pos(struct edit_pos a); - -extern void add_run(Paragraph *para, SCBlock *scblock, - PangoFontDescription *fdesc, double col[4], - const char *real_text); - -extern Paragraph *insert_paragraph(struct frame *fr, int pos); - -extern Paragraph *add_callback_para(struct frame *fr, SCBlock *scblock, - double w, double h, - SCCallbackDrawFunc draw_func, - SCCallbackClickFunc click_func, void *bvp, - void *vp); - -extern void add_image_para(struct frame *fr, SCBlock *scblock, - const char *filename, - ImageStore *is, double w, double h, int editable); - -extern void wrap_paragraph(Paragraph *para, PangoContext *pc, double w, - size_t sel_start, size_t sel_end); - -extern int find_cursor(struct frame *fr, double x, double y, - struct edit_pos *pos); - -extern void sort_positions(struct edit_pos *a, struct edit_pos *b); - -extern void ensure_run(struct frame *fr, struct edit_pos cpos); - -extern int positions_equal(struct edit_pos a, struct edit_pos b); - -extern int get_para_highlight(struct frame *fr, int cursor_para, - double *cx, double *cy, double *cw, double *ch); - -extern int position_editable(struct frame *fr, struct edit_pos cp); - -extern int get_cursor_pos(struct frame *fr, int cursor_para, int cursor_pos, - double *cx, double *cy, double *ch); - -extern void cursor_moveh(struct frame *fr, struct edit_pos *cp, signed int dir); - -extern void check_callback_click(struct frame *fr, int para); - -extern size_t pos_trail_to_offset(Paragraph *para, size_t offs, int trail); - -extern void insert_text_in_paragraph(Paragraph *para, size_t offs, - const char *t); - -extern void delete_text_from_frame(struct frame *fr, struct edit_pos p1, struct edit_pos p2, - double wrap_w); - -extern SCBlock *split_paragraph(struct frame *fr, int pn, size_t pos, - PangoContext *pc); -extern SCBlock *block_at_cursor(struct frame *fr, int para, size_t pos); - -extern void show_frame_hierarchy(struct frame *fr, const char *t); - -extern int get_sc_pos(struct frame *fr, int pn, size_t pos, - SCBlock **bl, size_t *ppos); - -extern void *get_para_bvp(Paragraph *para); - -extern Paragraph *create_paragraph(struct frame *fr, SCBlock *bl); - -extern enum para_type para_type(Paragraph *para); -extern SCBlock *para_scblock(Paragraph *para); - -extern SCBlock *para_debug_get_newline_at_end(Paragraph *para); -extern int para_debug_num_runs(Paragraph *para); -extern int para_debug_run_info(Paragraph *para, int i, SCBlock **scblock); - -#endif /* FRAME_H */ diff --git a/src-old/presentation.c b/src-old/presentation.c deleted file mode 100644 index d7d9c08..0000000 --- a/src-old/presentation.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * presentation.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <gtk/gtk.h> - -#include "presentation.h" -#include "slide_window.h" -#include "frame.h" -#include "imagestore.h" -#include "render.h" -#include "sc_interp.h" -#include "utils.h" - - -void free_presentation(struct presentation *p) -{ - /* FIXME: Loads of stuff leaks here */ - g_object_unref(p->file); - g_object_unref(p->stylesheet_from); - imagestore_destroy(p->is); - free(p); -} - - -char *get_titlebar_string(struct presentation *p) -{ - if ( p == NULL || p->file == NULL ) { - return strdup(_("(untitled)")); - } else { - char *bn = g_file_get_basename(p->file); - return bn; - } -} - - -static void find_and_load_stylesheet(struct presentation *p, GFile *file) -{ - GFile *ssfile; - - if ( file != NULL ) { - - /* First choice: /same/directory/<presentation>.ss */ - gchar *ssuri = g_file_get_uri(file); - if ( ssuri != NULL ) { - size_t l = strlen(ssuri); - if ( ssuri[l-3] == '.' && ssuri[l-2] == 's' && ssuri[l-1] =='c' ) { - ssuri[l-1] = 's'; - ssfile = g_file_new_for_uri(ssuri); - p->stylesheet = stylesheet_load(ssfile); - p->stylesheet_from = ssfile; - g_free(ssuri); - } - } - - /* Second choice: /same/directory/stylesheet.ss */ - if ( p->stylesheet == NULL ) { - GFile *parent = g_file_get_parent(file); - if ( parent != NULL ) { - ssfile = g_file_get_child(parent, "stylesheet.ss"); - if ( ssfile != NULL ) { - p->stylesheet = stylesheet_load(ssfile); - p->stylesheet_from = ssfile; - } - g_object_unref(parent); - } - } - - } - - /* Third choice: <cwd>/stylesheet.ss */ - if ( p->stylesheet == NULL ) { - ssfile = g_file_new_for_path("./stylesheet.ss"); - p->stylesheet = stylesheet_load(ssfile); - p->stylesheet_from = ssfile; - } - - /* Fourth choice: internal default stylesheet */ - if ( p->stylesheet == NULL ) { - ssfile = g_file_new_for_uri("resource:///uk/me/bitwiz/Colloquium/default.ss"); - p->stylesheet = stylesheet_load(ssfile); - p->stylesheet_from = NULL; - g_object_unref(ssfile); - } - - /* Last resort is NULL stylesheet and SCInterpreter's defaults */ - /* We keep a reference to the GFile */ -} - - -struct presentation *new_presentation(const char *imagestore) -{ - struct presentation *new; - - new = calloc(1, sizeof(struct presentation)); - if ( new == NULL ) return NULL; - - new->file = NULL; - new->stylesheet_from = NULL; - - new->scblocks = NULL; - - /* Default slide size */ - new->slide_width = 1024.0; - new->slide_height = 768.0; - - new->completely_empty = 1; - new->saved = 1; - new->stylesheet = NULL; - new->is = imagestore_new(imagestore); - - new->lang = pango_language_get_default(); - - find_and_load_stylesheet(new, NULL); - - return new; -} - - -int save_presentation(struct presentation *p, GFile *file, GFile *ssfile) -{ - GFileOutputStream *fh; - int r; - int sr; - GError *error = NULL; - - fh = g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error); - if ( fh == NULL ) { - fprintf(stderr, _("Open failed: %s\n"), error->message); - return 1; - } - r = save_sc_block(G_OUTPUT_STREAM(fh), p->scblocks); - if ( r ) { - fprintf(stderr, _("Couldn't save presentation\n")); - } - g_object_unref(fh); - - if ( ssfile != NULL ) { - char *uri = g_file_get_uri(ssfile); - printf(_("Saving stylesheet to %s\n"), uri); - g_free(uri); - sr = stylesheet_save(p->stylesheet, ssfile); - if ( sr ) { - fprintf(stderr, _("Couldn't save stylesheet\n")); - } - if ( p->stylesheet_from != ssfile ) { - if ( p->stylesheet_from != NULL ) { - g_object_unref(p->stylesheet_from); - } - p->stylesheet_from = ssfile; - g_object_ref(p->stylesheet_from); - } - } else { - fprintf(stderr, _("Not saving the stylesheet\n")); - sr = 0; - } - - if ( r || sr ) return 1; - - imagestore_set_parent(p->is, g_file_get_parent(file)); - - if ( p->file != file ) { - if ( p->file != NULL ) g_object_unref(p->file); - p->file = file; - g_object_ref(p->file); - } - p->saved = 1; - update_titlebar(p->narrative_window); - return 0; -} - - -int slide_number(struct presentation *p, SCBlock *sl) -{ - SCBlock *bl = p->scblocks; - int n = 0; - - while ( bl != NULL ) { - if ( safe_strcmp(sc_block_name(bl), "slide") == 0 ) { - n++; - if ( bl == sl ) return n; - } - bl = sc_block_next(bl); - } - - return 0; -} - - -int num_slides(struct presentation *p) -{ - SCBlock *bl = p->scblocks; - int n = 0; - - while ( bl != NULL ) { - if ( safe_strcmp(sc_block_name(bl), "slide") == 0 ) { - n++; - } - bl = sc_block_next(bl); - } - - return n; -} - - -SCBlock *first_slide(struct presentation *p) -{ - SCBlock *bl = p->scblocks; - - while ( bl != NULL ) { - if ( safe_strcmp(sc_block_name(bl), "slide") == 0 ) { - return bl; - } - bl = sc_block_next(bl); - } - - fprintf(stderr, "Couldn't find first slide!\n"); - return NULL; -} - - -SCBlock *last_slide(struct presentation *p) -{ - SCBlock *bl = p->scblocks; - SCBlock *l = NULL; - - while ( bl != NULL ) { - if ( safe_strcmp(sc_block_name(bl), "slide") == 0 ) { - l = bl; - } - bl = sc_block_next(bl); - } - - if ( l == NULL ) { - fprintf(stderr, "Couldn't find last slide!\n"); - } - return l; -} - - -SCBlock *next_slide(struct presentation *p, SCBlock *sl) -{ - SCBlock *bl = sl; - int found = 0; - - while ( bl != NULL ) { - if ( safe_strcmp(sc_block_name(bl), "slide") == 0 ) { - if ( found ) return bl; - } - if ( bl == sl ) { - found = 1; - } - bl = sc_block_next(bl); - } - - fprintf(stderr, "Couldn't find next slide!\n"); - return NULL; -} - - -SCBlock *prev_slide(struct presentation *p, SCBlock *sl) -{ - SCBlock *bl = p->scblocks; - SCBlock *l = NULL; - - while ( bl != NULL ) { - if ( bl == sl ) { - if ( l == NULL ) return sl; /* Already on first slide */ - return l; - } - if ( safe_strcmp(sc_block_name(bl), "slide") == 0 ) { - l = bl; - } - bl = sc_block_next(bl); - } - - fprintf(stderr, "Couldn't find prev slide!\n"); - return NULL; -} - - -static void set_slide_size_from_stylesheet(struct presentation *p) -{ - char *result; - - result = stylesheet_lookup(p->stylesheet, "$.slide", "size"); - if ( result != NULL ) { - float v[2]; - if ( parse_double(result, v) == 0 ) { - p->slide_width = v[0]; - p->slide_height = v[1]; - } - } -} - - -int load_presentation(struct presentation *p, GFile *file) -{ - int r = 0; - char *everything; - - assert(p->completely_empty); - - if ( !g_file_load_contents(file, NULL, &everything, NULL, NULL, NULL) ) { - fprintf(stderr, _("Failed to load '%s'\n"), g_file_get_uri(file)); - return 1; - } - - p->scblocks = sc_parse(everything); - g_free(everything); - - p->lang = pango_language_get_default(); - - if ( p->scblocks == NULL ) r = 1; - - if ( r ) { - p->completely_empty = 1; - fprintf(stderr, _("Parse error.\n")); - return r; /* Error */ - } - - p->stylesheet = NULL; - - find_and_load_stylesheet(p, file); - - set_slide_size_from_stylesheet(p); - - assert(p->file == NULL); - p->file = file; - g_object_ref(file); - - imagestore_set_parent(p->is, g_file_get_parent(file)); - - return 0; -} - diff --git a/src-old/presentation.h b/src-old/presentation.h deleted file mode 100644 index b288d8e..0000000 --- a/src-old/presentation.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * presentation.h - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef PRESENTATION_H -#define PRESENTATION_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -struct presentation; - -#include "imagestore.h" -#include "sc_parse.h" -#include "slideshow.h" -#include "narrative_window.h" -#include "slide_window.h" -#include "stylesheet.h" - -struct menu_pl; - -struct presentation -{ - GFile *file; - GFile *stylesheet_from; - int completely_empty; - int saved; - PangoLanguage *lang; - - ImageStore *is; - - NarrativeWindow *narrative_window; - - struct pr_clock *clock; - - /* This is the "native" size of the slide. It only exists to give - * font size some meaning in the context of a somewhat arbitrary DPI */ - double slide_width; - double slide_height; - - SCBlock *scblocks; - Stylesheet *stylesheet; -}; - - -extern struct presentation *new_presentation(const char *imagestore); -extern void free_presentation(struct presentation *p); - -extern char *get_titlebar_string(struct presentation *p); - -extern int slide_number(struct presentation *p, SCBlock *sl); -extern int num_slides(struct presentation *p); -extern SCBlock *first_slide(struct presentation *p); -extern SCBlock *last_slide(struct presentation *p); -extern SCBlock *next_slide(struct presentation *p, SCBlock *sl); -extern SCBlock *prev_slide(struct presentation *p, SCBlock *sl); - -extern int load_presentation(struct presentation *p, GFile *file); -extern int save_presentation(struct presentation *p, GFile *file, GFile *ssfile); - -#define UNUSED __attribute__((unused)) - - -#endif /* PRESENTATION_H */ diff --git a/src-old/render.c b/src-old/render.c deleted file mode 100644 index 6ac09fc..0000000 --- a/src-old/render.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * render.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <cairo.h> -#include <cairo-pdf.h> -#include <pango/pangocairo.h> -#include <assert.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gdk/gdk.h> - -#include "sc_parse.h" -#include "sc_interp.h" -#include "presentation.h" -#include "frame.h" -#include "render.h" -#include "imagestore.h" -#include "utils.h" - - -static void do_background(cairo_t *cr, struct frame *fr) -{ - cairo_pattern_t *patt = NULL; - - cairo_new_path(cr); - cairo_rectangle(cr, 0.0, 0.0, fr->w, fr->h); - - switch ( fr->grad ) { - - case GRAD_NONE: - cairo_set_source_rgba(cr, fr->bgcol[0], - fr->bgcol[1], - fr->bgcol[2], - fr->bgcol[3]); - break; - - case GRAD_VERT: - patt = cairo_pattern_create_linear(0.0, 0.0, - 0.0, fr->h); - cairo_pattern_add_color_stop_rgba(patt, 0.0, fr->bgcol[0], - fr->bgcol[1], - fr->bgcol[2], - fr->bgcol[3]); - cairo_pattern_add_color_stop_rgba(patt, 1.0, fr->bgcol2[0], - fr->bgcol2[1], - fr->bgcol2[2], - fr->bgcol2[3]); - cairo_set_source(cr, patt); - break; - - case GRAD_HORIZ: - patt = cairo_pattern_create_linear(0.0, 0.0, - fr->w, 0.0); - cairo_pattern_add_color_stop_rgba(patt, 0.0, fr->bgcol[0], - fr->bgcol[1], - fr->bgcol[2], - fr->bgcol[3]); - cairo_pattern_add_color_stop_rgba(patt, 1.0, fr->bgcol2[0], - fr->bgcol2[1], - fr->bgcol2[2], - fr->bgcol2[3]); - cairo_set_source(cr, patt); - break; - - } - - cairo_fill(cr); - if ( patt != NULL ) cairo_pattern_destroy(patt); -} - - -static int draw_frame(cairo_t *cr, struct frame *fr, ImageStore *is, - double min_y, double max_y) -{ - int i; - double hpos = 0.0; - - cairo_save(cr); - do_background(cr, fr); - - /* Actually render the contents */ - cairo_translate(cr, fr->pad_l, fr->pad_t); - for ( i=0; i<fr->n_paras; i++ ) { - - double cur_h = paragraph_height(fr->paras[i]); - - cairo_save(cr); - cairo_translate(cr, 0.0, hpos); - - if ( (hpos + cur_h > min_y) && (hpos < max_y) ) { - render_paragraph(cr, fr->paras[i], is); - } /* else paragraph is not visible */ - - hpos += cur_h; - cairo_restore(cr); - - } - cairo_restore(cr); - - return 0; -} - - -int recursive_draw(struct frame *fr, cairo_t *cr, - ImageStore *is, - double min_y, double max_y) -{ - int i; - - draw_frame(cr, fr, is, min_y, max_y); - - for ( i=0; i<fr->num_children; i++ ) { - cairo_save(cr); - cairo_translate(cr, fr->children[i]->x, fr->children[i]->y); - recursive_draw(fr->children[i], cr, is, - min_y - fr->children[i]->y, - max_y - fr->children[i]->y); - cairo_restore(cr); - } - - return 0; -} - - -void wrap_frame(struct frame *fr, PangoContext *pc) -{ - int i; - double w; - - w = fr->w - fr->pad_l - fr->pad_r; - - for ( i=0; i<fr->n_paras; i++ ) { - wrap_paragraph(fr->paras[i], pc, w, 0, 0); - } -} - - -int recursive_wrap(struct frame *fr, PangoContext *pc) -{ - int i; - - wrap_frame(fr, pc); - - for ( i=0; i<fr->num_children; i++ ) { - recursive_wrap(fr->children[i], pc); - } - - return 0; -} - - -struct frame *interp_and_shape(SCBlock *scblocks, Stylesheet *stylesheet, - SCCallbackList *cbl, ImageStore *is, - int slide_number, - PangoContext *pc, double w, double h, - PangoLanguage *lang) -{ - SCInterpreter *scin; - char snum[64]; - struct frame *top; - - top = frame_new(); - top->resizable = 0; - top->x = 0.0; - top->y = 0.0; - top->w = w; - top->h = h; - top->scblocks = scblocks; - - scin = sc_interp_new(pc, lang, is, top); - if ( scin == NULL ) { - fprintf(stderr, "Failed to set up interpreter.\n"); - frame_free(top); - return NULL; - } - - sc_interp_set_callbacks(scin, cbl); - - snprintf(snum, 63, "%i", slide_number); - sc_interp_set_constant(scin, SCCONST_SLIDENUMBER, snum); - - top->fontdesc = pango_font_description_copy(sc_interp_get_fontdesc(scin)); - top->col[0] = sc_interp_get_fgcol(scin)[0]; - top->col[1] = sc_interp_get_fgcol(scin)[1]; - top->col[2] = sc_interp_get_fgcol(scin)[2]; - top->col[3] = sc_interp_get_fgcol(scin)[3]; - - sc_interp_add_block(scin, scblocks, stylesheet); - - sc_interp_destroy(scin); - - return top; -} - - -static struct frame *render_sc_with_context(SCBlock *scblocks, - cairo_t *cr, double log_w, double log_h, - Stylesheet *stylesheet, SCCallbackList *cbl, - ImageStore *is, - int slide_number, PangoLanguage *lang, - PangoContext *pc) -{ - struct frame *top; - - cairo_rectangle(cr, 0.0, 0.0, log_w, log_h); - cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - cairo_fill(cr); - - top = interp_and_shape(scblocks, stylesheet, cbl, is, - slide_number, pc, log_w, log_h, lang); - - recursive_wrap(top, pc); - - recursive_draw(top, cr, is, 0.0, log_h); - - return top; -} - - -cairo_surface_t *render_sc(SCBlock *scblocks, int w, int h, - double log_w, double log_h, - Stylesheet *stylesheet, SCCallbackList *cbl, - ImageStore *is, - int slide_number, struct frame **ptop, - PangoLanguage *lang) -{ - cairo_surface_t *surf; - cairo_t *cr; - struct frame *top; - PangoContext *pc; - - surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); - cr = cairo_create(surf); - pc = pango_cairo_create_context(cr); - cairo_scale(cr, w/log_w, h/log_h); - top = render_sc_with_context(scblocks, cr, log_w, log_h, - stylesheet, cbl, is, slide_number, - lang, pc); - g_object_unref(pc); - cairo_destroy(cr); - - *ptop = top; - - return surf; -} - - -int export_pdf(struct presentation *p, const char *filename) -{ - double r; - double w = 2048.0; - double scale; - cairo_surface_t *surf; - cairo_t *cr; - SCBlock *bl; - int i; - PangoContext *pc; - - r = p->slide_height / p->slide_width; - - surf = cairo_pdf_surface_create(filename, w, w*r); - if ( cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS ) { - fprintf(stderr, _("Couldn't create Cairo surface\n")); - return 1; - } - - cr = cairo_create(surf); - scale = w / p->slide_width; - pc = pango_cairo_create_context(cr); - - i = 1; - bl = p->scblocks; - while ( bl != NULL ) { - - if ( safe_strcmp(sc_block_name(bl), "slide") != 0 ) { - bl = sc_block_next(bl); - continue; - } - - cairo_save(cr); - - cairo_scale(cr, scale, scale); - - cairo_rectangle(cr, 0.0, 0.0, p->slide_width, p->slide_height); - cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - cairo_fill(cr); - - render_sc_with_context(bl, cr, p->slide_width, - p->slide_height, p->stylesheet, NULL, - p->is, i, p->lang, pc); - - cairo_restore(cr); - - cairo_show_page(cr); - - bl = sc_block_next(bl); - i++; - - } - - g_object_unref(pc); - cairo_surface_finish(surf); - cairo_destroy(cr); - - return 0; -} diff --git a/src-old/render.h b/src-old/render.h deleted file mode 100644 index 0cfae26..0000000 --- a/src-old/render.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * render.h - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef RENDER_H -#define RENDER_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "presentation.h" -#include "imagestore.h" -#include "sc_interp.h" -#include "frame.h" - -/* Convienience function to run the entire pipeline */ -extern cairo_surface_t *render_sc(SCBlock *scblocks, int w, int h, - double log_w, double log_h, - Stylesheet *stylesheet, SCCallbackList *cbl, - ImageStore *is, - int slide_number, struct frame **ptop, - PangoLanguage *lang); - -/* Interpret StoryCode and measure boxes. - * Needs to be followed by: wrap_contents() (recursively) - * recursive_draw() - */ -extern struct frame *interp_and_shape(SCBlock *scblocks, Stylesheet *stylesheet, - SCCallbackList *cbl, - ImageStore *is, - int slide_number, PangoContext *pc, - double w, double h, PangoLanguage *lang); - -extern void wrap_frame(struct frame *fr, PangoContext *pc); -extern int recursive_wrap(struct frame *fr, PangoContext *pc); - -extern int export_pdf(struct presentation *p, const char *filename); - -extern int recursive_draw(struct frame *fr, cairo_t *cr, - ImageStore *is, - double min_y, double max_y); - -#endif /* RENDER_H */ diff --git a/src-old/sc_editor.c b/src-old/sc_editor.c deleted file mode 100644 index 8e79fd8..0000000 --- a/src-old/sc_editor.c +++ /dev/null @@ -1,2197 +0,0 @@ -/* - * sc_editor.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <gtk/gtk.h> -#include <assert.h> -#include <gdk/gdkkeysyms.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <math.h> - -#include "colloquium.h" -#include "presentation.h" -#include "slide_window.h" -#include "render.h" -#include "frame.h" -#include "sc_parse.h" -#include "sc_interp.h" -#include "sc_editor.h" -#include "slideshow.h" -#include "debugger.h" -#include "utils.h" - - -static void scroll_interface_init(GtkScrollable *iface) -{ -} - - -enum -{ - SCEDITOR_0, - SCEDITOR_VADJ, - SCEDITOR_HADJ, - SCEDITOR_VPOL, - SCEDITOR_HPOL, -}; - - -G_DEFINE_TYPE_WITH_CODE(SCEditor, sc_editor, GTK_TYPE_DRAWING_AREA, - G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, - scroll_interface_init)) - -static void debug_paragraphs(SCEditor *e) -{ - struct frame *fr = e->cursor_frame; - int i; - - printf("Paragraphs in current frame:\n"); - for ( i=0; i<fr->n_paras; i++ ) { - show_para(fr->paras[i]); - } -} - - -static void horizontal_adjust(GtkAdjustment *adj, SCEditor *e) -{ - e->h_scroll_pos = gtk_adjustment_get_value(adj); - sc_editor_redraw(e); -} - - -static void set_horizontal_params(SCEditor *e) -{ - if ( e->hadj == NULL ) return; - gtk_adjustment_configure(e->hadj, e->h_scroll_pos, 0, e->w, 100, - e->visible_width, e->visible_width); -} - - -static void vertical_adjust(GtkAdjustment *adj, SCEditor *e) -{ - e->scroll_pos = gtk_adjustment_get_value(adj); - sc_editor_redraw(e); -} - - -static void set_vertical_params(SCEditor *e) -{ - double page; - - if ( e->vadj == NULL ) return; - - /* Ensure we do not scroll off the top of the document */ - if ( e->scroll_pos < 0.0 ) e->scroll_pos = 0.0; - - /* Ensure we do not scroll off the bottom of the document */ - if ( e->scroll_pos > e->h - e->visible_height ) { - e->scroll_pos = e->h - e->visible_height; - } - - /* If we can show the whole document, show it at the top */ - if ( e->h < e->visible_height ) { - e->scroll_pos = 0.0; - } - - if ( e->h > e->visible_height ) { - page = e->visible_height; - } else { - page = e->h; - } - - gtk_adjustment_configure(e->vadj, e->scroll_pos, 0, e->h, 100, - e->visible_height, page); -} - - -static void update_size(SCEditor *e) -{ - if ( e->flow ) { - - double total = total_height(e->top); - - e->w = e->top->w; - e->h = total + e->top->pad_t + e->top->pad_b; - - e->log_w = e->w; - e->log_h = e->h; - e->top->h = e->h; - } else { - e->top->w = e->log_w; - e->top->h = e->log_h; - } - - if ( e->flow && (e->top->h < e->visible_height) ) { - e->top->h = e->visible_height; - } - - set_vertical_params(e); - set_horizontal_params(e); -} - - -static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event, - SCEditor *e) -{ - PangoContext *pc; - - pc = gdk_pango_context_get(); - - if ( e->scale ) { - - double sx, sy; - double aw, ah; - - e->w = event->width; - e->h = event->height; - sx = (double)e->w / e->log_w; - sy = (double)e->h / e->log_h; - e->view_scale = (sx < sy) ? sx : sy; - - /* Actual size (in device units) */ - aw = e->view_scale * e->log_w; - ah = e->view_scale * e->log_h; - - e->border_offs_x = (event->width - aw)/2.0; - e->border_offs_y = (event->height - ah)/2.0; - - } - - e->visible_height = event->height; - e->visible_width = event->width; - - /* Interpret and shape, if not already done */ - if ( e->top == NULL ) { - double w, h; - if ( e->flow ) { - w = event->width; - h = 0.0; - } else { - w = e->log_w; - h = e->log_h; - } - e->top = interp_and_shape(e->scblocks, e->stylesheet, e->cbl, - e->is, e->slidenum, pc, - w, h, e->lang); - e->top->scblocks = e->scblocks; - recursive_wrap(e->top, pc); - } - - if ( e->flow ) { - /* Wrap using current width */ - e->top->w = event->width; - e->top->h = 0.0; /* To be updated in a moment */ - e->top->x = 0.0; - e->top->y = 0.0; - /* Only the top level needs to be wrapped */ - wrap_frame(e->top, pc); - } - - update_size(e); - - g_object_unref(pc); - - return FALSE; -} - - -static void emit_change_sig(SCEditor *e) -{ - g_signal_emit_by_name(e, "changed"); -} - - -void sc_editor_set_flow(SCEditor *e, int flow) -{ - e->flow = flow; -} - - -static void sc_editor_set_property(GObject *obj, guint id, const GValue *val, - GParamSpec *spec) -{ - SCEditor *e = SC_EDITOR(obj); - - switch ( id ) { - - case SCEDITOR_VPOL : - e->vpol = g_value_get_enum(val); - break; - - case SCEDITOR_HPOL : - e->hpol = g_value_get_enum(val); - break; - - case SCEDITOR_VADJ : - e->vadj = g_value_get_object(val); - set_vertical_params(e); - if ( e->vadj != NULL ) { - g_signal_connect(G_OBJECT(e->vadj), "value-changed", - G_CALLBACK(vertical_adjust), e); - } - break; - - case SCEDITOR_HADJ : - e->hadj = g_value_get_object(val); - set_horizontal_params(e); - if ( e->hadj != NULL ) { - g_signal_connect(G_OBJECT(e->hadj), "value-changed", - G_CALLBACK(horizontal_adjust), e); - } - break; - - default : - printf("setting %i\n", id); - break; - - } -} - - -static void sc_editor_get_property(GObject *obj, guint id, GValue *val, - GParamSpec *spec) -{ - SCEditor *e = SC_EDITOR(obj); - - switch ( id ) { - - case SCEDITOR_VADJ : - g_value_set_object(val, e->vadj); - break; - - case SCEDITOR_HADJ : - g_value_set_object(val, e->hadj); - break; - - case SCEDITOR_VPOL : - g_value_set_enum(val, e->vpol); - break; - - case SCEDITOR_HPOL : - g_value_set_enum(val, e->hpol); - break; - - default : - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, spec); - break; - - } -} - - -static GtkSizeRequestMode get_request_mode(GtkWidget *widget) -{ - return GTK_SIZE_REQUEST_CONSTANT_SIZE; -} - - -static void get_preferred_width(GtkWidget *widget, gint *min, gint *natural) -{ - SCEditor *e = SC_EDITOR(widget); - if ( e->flow ) { - *min = 100; - *natural = 640; - } else { - *min = e->w; - *natural = e->w; - } -} - - -static void get_preferred_height(GtkWidget *widget, gint *min, gint *natural) -{ - SCEditor *e = SC_EDITOR(widget); - if ( e->flow ) { - *min = 1000; - *natural = 1000; - } else { - *min = e->h; - *natural = e->h; - } -} - - -static void sc_editor_class_init(SCEditorClass *klass) -{ - GObjectClass *goc = G_OBJECT_CLASS(klass); - goc->set_property = sc_editor_set_property; - goc->get_property = sc_editor_get_property; - g_object_class_override_property(goc, SCEDITOR_VADJ, "vadjustment"); - g_object_class_override_property(goc, SCEDITOR_HADJ, "hadjustment"); - g_object_class_override_property(goc, SCEDITOR_VPOL, "vscroll-policy"); - g_object_class_override_property(goc, SCEDITOR_HPOL, "hscroll-policy"); - - GTK_WIDGET_CLASS(klass)->get_request_mode = get_request_mode; - GTK_WIDGET_CLASS(klass)->get_preferred_width = get_preferred_width; - GTK_WIDGET_CLASS(klass)->get_preferred_height = get_preferred_height; - GTK_WIDGET_CLASS(klass)->get_preferred_height_for_width = NULL; - - g_signal_new("changed", SC_TYPE_EDITOR, G_SIGNAL_RUN_LAST, 0, - NULL, NULL, NULL, G_TYPE_NONE, 0); -} - - -static void sc_editor_init(SCEditor *e) -{ - e->vpol = GTK_SCROLL_NATURAL; - e->hpol = GTK_SCROLL_NATURAL; - e->vadj = gtk_adjustment_new(0, 0, 100, 1, 10, 10); - e->hadj = gtk_adjustment_new(0, 0, 100, 1, 10, 10); -} - - -void sc_editor_set_background(SCEditor *e, double r, double g, double b) -{ - e->bgcol[0] = r; - e->bgcol[1] = g; - e->bgcol[2] = b; -} - - -void sc_editor_ensure_cursor(SCEditor *e) -{ - if ( e->cursor_frame != NULL ) return; - e->cursor_frame = e->top; - e->cpos.para = 0; - e->cpos.pos = 0; - e->cpos.trail = 0; - e->selection = NULL; -} - - -static void sc_editor_remove_cursor(SCEditor *e) -{ - e->cursor_frame = NULL; - e->cpos.para = 0; - e->cpos.pos = 0; - e->cpos.trail = 0; - e->selection = NULL; -} - - -/* (Re-)run the entire rendering pipeline. - * NB "full" means "full". All frame, line and box handles will become - * invalid. The cursor position will be unset. */ -static void full_rerender(SCEditor *e) -{ - PangoContext *pc; - - frame_free(e->top); - sc_editor_remove_cursor(e); - - pc = gdk_pango_context_get(); - - e->top = interp_and_shape(e->scblocks, e->stylesheet, e->cbl, - e->is, e->slidenum, - pc, e->log_w, 0.0, e->lang); - - e->top->x = 0.0; - e->top->y = 0.0; - e->top->w = e->w; - e->top->h = 0.0; /* To be updated in a moment */ - - recursive_wrap(e->top, pc); - update_size(e); - - sc_editor_redraw(e); - - g_object_unref(pc); -} - - -void sc_editor_redraw(SCEditor *e) -{ - gint w, h; - - w = gtk_widget_get_allocated_width(GTK_WIDGET(e)); - h = gtk_widget_get_allocated_height(GTK_WIDGET(e)); - - gtk_widget_queue_draw_area(GTK_WIDGET(e), 0, 0, w, h); -} - - -static void paste_storycode_received(GtkClipboard *cb, GtkSelectionData *seldata, - gpointer vp) -{ - SCEditor *e = vp; - SCBlock *nf; - const guchar *t; - - t = gtk_selection_data_get_data(seldata); - - printf("received storycode paste\n"); - printf("'%s'\n", t); - if ( t == NULL ) return; - - /* FIXME: It might not be a new frame */ - nf = sc_parse((char *)t); - show_sc_blocks(nf); - sc_block_append_block(sc_block_child(e->scblocks), nf); - full_rerender(e); -} - - -static void paste_text_received(GtkClipboard *cb, GtkSelectionData *seldata, - gpointer vp) -{ - SCEditor *e = vp; - SCBlock *bl; - guchar *t; - SCBlock *cur_bl; - size_t cur_sc_pos; - size_t offs; - Paragraph *para; - - t = gtk_selection_data_get_text(seldata); - - printf("received text paste\n"); - printf("'%s'\n", t); - if ( t == NULL ) return; - - bl = sc_parse((char *)t); - - if ( e->cursor_frame == NULL ) { - fprintf(stderr, _("No frame selected for paste\n")); - return; - } - - para = e->cursor_frame->paras[e->cpos.para]; - offs = pos_trail_to_offset(para, e->cpos.pos, e->cpos.trail); - - get_sc_pos(e->cursor_frame, e->cpos.para, offs, &cur_bl, &cur_sc_pos); - sc_insert_block(cur_bl, cur_sc_pos, bl); - full_rerender(e); -} - - -static void paste_targets_received(GtkClipboard *cb, GdkAtom *targets, - gint n_targets, gpointer vp) -{ - SCEditor *e = vp; - int i; - int have_sc = 0; - int index_sc, index_text; - int have_text = 0; - - if ( targets == NULL ) { - fprintf(stderr, "No paste targets offered.\n"); - return; - } - - for ( i=0; i<n_targets; i++ ) { - gchar *name = gdk_atom_name(targets[i]); - if ( g_strcmp0(name, "text/x-storycode") == 0 ) { - have_sc = 1; - index_sc = i; - } - if ( g_strcmp0(name, "text/plain") == 0 ) { - have_text = 1; - index_text = i; - } - g_free(name); - } - - if ( have_sc ) { - printf("storycode is offered\n"); - gtk_clipboard_request_contents(cb, targets[index_sc], - paste_storycode_received, e); - } else if ( have_text ) { - printf("text is offered\n"); - gtk_clipboard_request_contents(cb, targets[index_text], - paste_text_received, e); - } else { - printf("nothing useful is offered\n"); - } -} - - -void sc_editor_paste(SCEditor *e) -{ - GtkClipboard *cb; - GdkAtom atom; - - printf("pasting\n"); - - atom = gdk_atom_intern("CLIPBOARD", FALSE); - if ( atom == GDK_NONE ) return; - cb = gtk_clipboard_get(atom); - gtk_clipboard_request_targets(cb, paste_targets_received, e); -} - - -void sc_editor_add_storycode(SCEditor *e, const char *sc) -{ - SCBlock *nf; - nf = sc_parse(sc); - sc_block_append_block(sc_block_child(e->scblocks), nf); - full_rerender(e); -} - - -static void clipboard_get(GtkClipboard *cb, GtkSelectionData *seldata, - guint info, gpointer data) -{ - char *t = data; - - printf("clipboard get\n"); - - if ( info == 0 ) { - printf("sending SC frame\n"); - gtk_selection_data_set(seldata, - gtk_selection_data_get_target(seldata), - 8, (const guchar *)t, strlen(t)+1); - } else { - GdkAtom target; - gchar *name; - target = gtk_selection_data_get_target(seldata); - name = gdk_atom_name(target); - fprintf(stderr, "Don't know what to send for %s\n", name); - g_free(name); - } -} - - -static void clipboard_clear(GtkClipboard *cb, gpointer data) -{ - free(data); -} - - -void sc_editor_copy_selected_frame(SCEditor *e) -{ - char *t; - GtkClipboard *cb; - GdkAtom atom; - GtkTargetEntry targets[1]; - - if ( e->selection == NULL ) return; - - atom = gdk_atom_intern("CLIPBOARD", FALSE); - if ( atom == GDK_NONE ) return; - - cb = gtk_clipboard_get(atom); - - targets[0].target = "text/x-storycode"; - targets[0].flags = 0; - targets[0].info = 0; - - /* FIXME: Offer image, PDF etc? */ - - printf("copying frame\n"); - - t = serialise_sc_block(e->selection->scblocks); - - gtk_clipboard_set_with_data(cb, targets, 1, - clipboard_get, clipboard_clear, t); -} - - -static void copy_selection(SCEditor *e) -{ - char *t; - GtkClipboard *cb; - GdkAtom atom; - GtkTargetEntry targets[1]; - SCBlock *bl; - - if ( e->selection == NULL ) return; - - atom = gdk_atom_intern("CLIPBOARD", FALSE); - if ( atom == GDK_NONE ) return; - - cb = gtk_clipboard_get(atom); - - - targets[0].target = "text/x-storycode"; - targets[0].flags = 0; - targets[0].info = 0; - - printf("copying selection\n"); - - bl = block_at_cursor(e->cursor_frame, e->cpos.para, 0); - if ( bl == NULL ) return; - - t = serialise_sc_block(bl); - - gtk_clipboard_set_with_data(cb, targets, 1, - clipboard_get, clipboard_clear, t); -} - - -void sc_editor_delete_selected_frame(SCEditor *e) -{ - SCBlock *scb_old = e->scblocks; - sc_block_delete(&e->scblocks, e->selection->scblocks); - assert(scb_old == e->scblocks); - full_rerender(e); - emit_change_sig(e); -} - - -static gint destroy_sig(GtkWidget *window, SCEditor *e) -{ - return 0; -} - - -static void draw_editing_box(cairo_t *cr, struct frame *fr) -{ - const double dash[] = {2.0, 2.0}; - double xmin, ymin, width, height; - double ptot_w, ptot_h; - - xmin = fr->x; - ymin = fr->y; - width = fr->w; - height = fr->h; - - cairo_new_path(cr); - cairo_rectangle(cr, xmin, ymin, width, height); - cairo_set_source_rgb(cr, 0.0, 0.69, 1.0); - cairo_set_line_width(cr, 0.5); - cairo_stroke(cr); - - cairo_new_path(cr); - ptot_w = fr->pad_l + fr->pad_r; - ptot_h = fr->pad_t + fr->pad_b; - cairo_rectangle(cr, xmin+fr->pad_l, ymin+fr->pad_t, - width-ptot_w, height-ptot_h); - cairo_set_dash(cr, dash, 2, 0.0); - cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); - cairo_set_line_width(cr, 0.1); - cairo_stroke(cr); - - cairo_set_dash(cr, NULL, 0, 0.0); -} - - -static void draw_para_highlight(cairo_t *cr, struct frame *fr, int cursor_para) -{ - double cx, cy, w, h; - - if ( get_para_highlight(fr, cursor_para, &cx, &cy, &w, &h) != 0 ) { - return; - } - - cairo_new_path(cr); - cairo_rectangle(cr, cx+fr->x, cy+fr->y, w, h); - cairo_set_source_rgba(cr, 0.7, 0.7, 1.0, 0.5); - cairo_set_line_width(cr, 5.0); - cairo_stroke(cr); -} - - -static void draw_caret(cairo_t *cr, struct frame *fr, struct edit_pos cpos, - int hgh) -{ - double cx, clow, chigh, h; - const double t = 1.8; - size_t offs; - Paragraph *para; - - if ( hgh ) { - draw_para_highlight(cr, fr, cpos.para); - return; - } - - assert(fr != NULL); - - para = fr->paras[cpos.para]; - if ( para_type(para) != PARA_TYPE_TEXT ) { - draw_para_highlight(cr, fr, cpos.para); - return; - } - - offs = pos_trail_to_offset(para, cpos.pos, cpos.trail); - get_cursor_pos(fr, cpos.para, offs, &cx, &clow, &h); - - cx += fr->x; - clow += fr->y; - chigh = clow + h; - - cairo_move_to(cr, cx, clow); - cairo_line_to(cr, cx, chigh); - - cairo_move_to(cr, cx-t, clow-t); - cairo_line_to(cr, cx, clow); - cairo_move_to(cr, cx+t, clow-t); - cairo_line_to(cr, cx, clow); - - cairo_move_to(cr, cx-t, chigh+t); - cairo_line_to(cr, cx, chigh); - cairo_move_to(cr, cx+t, chigh+t); - cairo_line_to(cr, cx, chigh); - - cairo_set_source_rgb(cr, 0.86, 0.0, 0.0); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); -} - - -static void draw_resize_handle(cairo_t *cr, double x, double y) -{ - cairo_new_path(cr); - cairo_rectangle(cr, x, y, 20.0, 20.0); - cairo_set_source_rgba(cr, 0.9, 0.9, 0.9, 0.5); - cairo_fill(cr); -} - - -static void draw_overlay(cairo_t *cr, SCEditor *e) -{ - if ( e->selection != NULL ) { - - double x, y, w, h; - - draw_editing_box(cr, e->selection); - - x = e->selection->x; - y = e->selection->y; - w = e->selection->w; - h = e->selection->h; - - if ( e->selection->resizable ) { - /* Draw resize handles */ - draw_resize_handle(cr, x, y+h-20.0); - draw_resize_handle(cr, x+w-20.0, y); - draw_resize_handle(cr, x, y); - draw_resize_handle(cr, x+w-20.0, y+h-20.0); - } - - draw_caret(cr, e->cursor_frame, e->cpos, e->para_highlight); - - } - - if ( (e->drag_status == DRAG_STATUS_DRAGGING) - && ((e->drag_reason == DRAG_REASON_CREATE) - || (e->drag_reason == DRAG_REASON_IMPORT)) ) - { - cairo_new_path(cr); - cairo_rectangle(cr, e->start_corner_x, e->start_corner_y, - e->drag_corner_x - e->start_corner_x, - e->drag_corner_y - e->start_corner_y); - cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); - cairo_set_line_width(cr, 0.5); - cairo_stroke(cr); - } - - if ( (e->drag_status == DRAG_STATUS_DRAGGING) - && ((e->drag_reason == DRAG_REASON_RESIZE) - || (e->drag_reason == DRAG_REASON_MOVE)) ) - { - cairo_new_path(cr); - cairo_rectangle(cr, e->box_x, e->box_y, - e->box_width, e->box_height); - cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); - cairo_set_line_width(cr, 0.5); - cairo_stroke(cr); - } -} - - -static gboolean draw_sig(GtkWidget *da, cairo_t *cr, SCEditor *e) -{ - /* Ultimate background */ - if ( e->bg_pixbuf != NULL ) { - gdk_cairo_set_source_pixbuf(cr, e->bg_pixbuf, 0.0, 0.0); - cairo_pattern_t *patt = cairo_get_source(cr); - cairo_pattern_set_extend(patt, CAIRO_EXTEND_REPEAT); - cairo_paint(cr); - } else { - cairo_set_source_rgba(cr, 0.8, 0.8, 1.0, 1.0); - cairo_paint(cr); - } - - cairo_translate(cr, e->border_offs_x, e->border_offs_y); - cairo_translate(cr, -e->h_scroll_pos, -e->scroll_pos); - cairo_scale(cr, e->view_scale, e->view_scale); - - /* Rendering background */ - cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); - cairo_rectangle(cr, 0.0, 0.0, e->log_w, e->log_h); - cairo_fill(cr); - - /* Contents */ - recursive_draw(e->top, cr, e->is, - e->scroll_pos/e->view_scale, - (e->scroll_pos + e->visible_height)/e->view_scale); - - /* Editing overlay */ - draw_overlay(cr, e); - - return FALSE; -} - - -SCBlock *split_paragraph_at_cursor(SCEditor *e) -{ - size_t offs; - Paragraph *para; - - if ( e->cursor_frame == NULL ) return NULL; - - para = e->cursor_frame->paras[e->cpos.para]; - offs = pos_trail_to_offset(para, e->cpos.pos, e->cpos.trail); - return split_paragraph(e->cursor_frame, e->cpos.para, offs, e->pc); -} - - -static void check_cursor_visible(SCEditor *e) -{ - double x, y, h; - size_t offs; - Paragraph *para; - - if ( e->cursor_frame == NULL ) return; - - para = e->cursor_frame->paras[e->cpos.para]; - offs = pos_trail_to_offset(para, e->cpos.pos, e->cpos.trail); - get_cursor_pos(e->cursor_frame, e->cpos.para, offs, &x, &y, &h); - - /* Off the bottom? */ - if ( y - e->scroll_pos + h > e->visible_height ) { - e->scroll_pos = y + h - e->visible_height; - e->scroll_pos += e->cursor_frame->pad_b; - } - - /* Off the top? */ - if ( y < e->scroll_pos ) { - e->scroll_pos = y - e->cursor_frame->pad_t; - } -} - - -static void do_backspace(struct frame *fr, SCEditor *e) -{ - double wrapw = e->cursor_frame->w - e->cursor_frame->pad_l - e->cursor_frame->pad_r; - - if ( e->sel_active ) { - - /* Delete the selected block */ - delete_text_from_frame(e->cursor_frame, e->sel_start, e->sel_end, wrapw); - - /* Cursor goes at start of deletion */ - sort_positions(&e->sel_start, &e->sel_end); - e->cpos = e->sel_start; - e->sel_active = 0; - - } else { - - if ( para_type(e->cursor_frame->paras[e->cpos.para]) == PARA_TYPE_TEXT ) { - - /* Delete one character */ - struct edit_pos p1, p2; - - p1 = e->cpos; - - p2 = p1; - - cursor_moveh(e->cursor_frame, &p2, -1); - show_edit_pos(p1); - show_edit_pos(p2); - - delete_text_from_frame(e->cursor_frame, p1, p2, wrapw); - e->cpos = p2; - - } else { - - /* FIXME: Implement this */ - fprintf(stderr, "Deleting non-text paragraph\n"); - - } - - } - - emit_change_sig(e); - sc_editor_redraw(e); -} - - -static void insert_text(char *t, SCEditor *e) -{ - Paragraph *para; - - if ( e->cursor_frame == NULL ) return; - - if ( e->sel_active ) { - do_backspace(e->cursor_frame, e); - } - - if ( strcmp(t, "\n") == 0 ) { - split_paragraph_at_cursor(e); - if ( e->flow ) update_size(e); - cursor_moveh(e->cursor_frame, &e->cpos, +1); - check_cursor_visible(e); - emit_change_sig(e); - sc_editor_redraw(e); - return; - } - - para = e->cursor_frame->paras[e->cpos.para]; - - /* Is this paragraph even a text one? */ - if ( para_type(para) == PARA_TYPE_TEXT ) { - - size_t off; - - /* Yes. The "easy" case */ - - if ( !position_editable(e->cursor_frame, e->cpos) ) { - fprintf(stderr, "Position not editable\n"); - return; - } - - off = pos_trail_to_offset(para, e->cpos.pos, e->cpos.trail); - insert_text_in_paragraph(para, off, t); - wrap_paragraph(para, NULL, - e->cursor_frame->w - e->cursor_frame->pad_l - - e->cursor_frame->pad_r, 0, 0); - if ( e->flow ) update_size(e); - - cursor_moveh(e->cursor_frame, &e->cpos, +1); - - } else { - - SCBlock *bd; - SCBlock *ad; - Paragraph *pnew; - - bd = para_scblock(para); - if ( bd == NULL ) { - fprintf(stderr, "No SCBlock for para\n"); - return; - } - - /* No. Create a new text paragraph straight afterwards */ - ad = sc_block_insert_after(bd, NULL, NULL, strdup(t)); - if ( ad == NULL ) { - fprintf(stderr, "Failed to add SCBlock\n"); - return; - } - - pnew = insert_paragraph(e->cursor_frame, e->cpos.para); - if ( pnew == NULL ) { - fprintf(stderr, "Failed to insert paragraph\n"); - return; - } - add_run(pnew, ad, e->cursor_frame->fontdesc, - e->cursor_frame->col, NULL); - - wrap_frame(e->cursor_frame, e->pc); - - e->cpos.para += 1; - e->cpos.pos = 0; - e->cpos.trail = 1; - - } - - emit_change_sig(e); - check_cursor_visible(e); - sc_editor_redraw(e); -} - - -static gboolean im_commit_sig(GtkIMContext *im, gchar *str, - SCEditor *e) -{ - insert_text(str, e); - return FALSE; -} - - -static int within_frame(struct frame *fr, double x, double y) -{ - if ( fr == NULL ) return 0; - if ( x < fr->x ) return 0; - if ( y < fr->y ) return 0; - if ( x > fr->x + fr->w ) return 0; - if ( y > fr->y + fr->h ) return 0; - return 1; -} - - -static struct frame *find_frame_at_position(struct frame *fr, - double x, double y) -{ - int i; - - for ( i=0; i<fr->num_children; i++ ) { - - if ( within_frame(fr->children[i], x, y) ) { - return find_frame_at_position(fr->children[i], x, y); - } - - } - - if ( within_frame(fr, x, y) ) return fr; - return NULL; -} - - -static enum corner which_corner(double xp, double yp, struct frame *fr) -{ - double x, y; /* Relative to object position */ - - x = xp - fr->x; - y = yp - fr->y; - - if ( x < 0.0 ) return CORNER_NONE; - if ( y < 0.0 ) return CORNER_NONE; - if ( x > fr->w ) return CORNER_NONE; - if ( y > fr->h ) return CORNER_NONE; - - /* Top left? */ - if ( (x<20.0) && (y<20.0) ) return CORNER_TL; - if ( (x>fr->w-20.0) && (y<20.0) ) return CORNER_TR; - if ( (x<20.0) && (y>fr->h-20.0) ) return CORNER_BL; - if ( (x>fr->w-20.0) && (y>fr->h-20.0) ) return CORNER_BR; - - return CORNER_NONE; -} - - -static void calculate_box_size(struct frame *fr, SCEditor *e, - double x, double y) -{ - double ddx, ddy, dlen, mult; - double vx, vy, dbx, dby; - - ddx = x - e->start_corner_x; - ddy = y - e->start_corner_y; - - if ( !fr->is_image ) { - - switch ( e->drag_corner ) { - - case CORNER_BR : - e->box_x = fr->x; - e->box_y = fr->y; - e->box_width = fr->w + ddx; - e->box_height = fr->h + ddy; - break; - - case CORNER_BL : - e->box_x = fr->x + ddx; - e->box_y = fr->y; - e->box_width = fr->w - ddx; - e->box_height = fr->h + ddy; - break; - - case CORNER_TL : - e->box_x = fr->x + ddx; - e->box_y = fr->y + ddy; - e->box_width = fr->w - ddx; - e->box_height = fr->h - ddy; - break; - - case CORNER_TR : - e->box_x = fr->x; - e->box_y = fr->y + ddy; - e->box_width = fr->w + ddx; - e->box_height = fr->h - ddy; - break; - - case CORNER_NONE : - break; - - } - return; - - - } - - switch ( e->drag_corner ) { - - case CORNER_BR : - vx = fr->w; - vy = fr->h; - break; - - case CORNER_BL : - vx = -fr->w; - vy = fr->h; - break; - - case CORNER_TL : - vx = -fr->w; - vy = -fr->h; - break; - - case CORNER_TR : - vx = fr->w; - vy = -fr->h; - break; - - case CORNER_NONE : - default: - vx = 0.0; - vy = 0.0; - break; - - } - - dlen = (ddx*vx + ddy*vy) / e->diagonal_length; - mult = (dlen+e->diagonal_length) / e->diagonal_length; - - e->box_width = fr->w * mult; - e->box_height = fr->h * mult; - dbx = e->box_width - fr->w; - dby = e->box_height - fr->h; - - if ( e->box_width < 40.0 ) { - mult = 40.0 / fr->w; - } - if ( e->box_height < 40.0 ) { - mult = 40.0 / fr->h; - } - e->box_width = fr->w * mult; - e->box_height = fr->h * mult; - dbx = e->box_width - fr->w; - dby = e->box_height - fr->h; - - switch ( e->drag_corner ) { - - case CORNER_BR : - e->box_x = fr->x; - e->box_y = fr->y; - break; - - case CORNER_BL : - e->box_x = fr->x - dbx; - e->box_y = fr->y; - break; - - case CORNER_TL : - e->box_x = fr->x - dbx; - e->box_y = fr->y - dby; - break; - - case CORNER_TR : - e->box_x = fr->x; - e->box_y = fr->y - dby; - break; - - case CORNER_NONE : - break; - - } -} - - -static void check_paragraph(struct frame *fr, PangoContext *pc, - SCBlock *scblocks) -{ - if ( fr->n_paras > 0 ) return; - Paragraph *para = last_para(fr); - - if ( scblocks == NULL ) { - /* We have no SCBlocks at all! Better create one... */ - scblocks = sc_parse(""); - fr->scblocks = scblocks; - } - - /* We are creating the first paragraph. It uses the last SCBlock - * in the chain */ - while ( sc_block_next(scblocks) != NULL ) { - scblocks = sc_block_next(scblocks); - } - scblocks = sc_block_append(scblocks, NULL, NULL, strdup(""), NULL); - - add_run(para, scblocks, fr->fontdesc, fr->col, NULL); - wrap_paragraph(para, pc, fr->w - fr->pad_l - fr->pad_r, 0, 0); -} - - -static void rewrap_paragraph_range(struct frame *fr, int a, int b, - struct edit_pos sel_start, - struct edit_pos sel_end, - int sel_active) -{ - int i; - int sel_s, sel_e; - Paragraph *para; - - if ( a > b ) { - int t = a; - a = b; b = t; - } - - if ( fr == NULL ) return; - if ( fr->paras == NULL ) return; - - sort_positions(&sel_start, &sel_end); - - //printf("frame %p\n", fr); - //printf("start: "); - //show_edit_pos(sel_start); - //printf(" end: "); - //show_edit_pos(sel_end); - - para = fr->paras[sel_start.para]; - sel_s = pos_trail_to_offset(para, sel_start.pos, sel_start.trail); - para = fr->paras[sel_end.para]; - sel_e = pos_trail_to_offset(para, sel_end.pos, sel_end.trail); - - for ( i=a; i<=b; i++ ) { - size_t srt, end; - if ( sel_active ) { - if ( i == sel_start.para ) { - srt = sel_s; - } else { - srt = 0; - } - if ( i == sel_end.para ) { - end = sel_e; - } else { - end = G_MAXUINT; - } - if ( i > sel_start.para && i < sel_end.para ) { - end = G_MAXUINT; - } - } else { - srt = 0; - end = 0; - } - wrap_paragraph(fr->paras[i], NULL, - fr->w - fr->pad_l - fr->pad_r, srt, end); - } -} - - -static void unset_selection(SCEditor *e) -{ - int a, b; - - if ( !e->sel_active ) return; - - a = e->sel_start.para; - b = e->sel_end.para; - if ( a > b ) { - a = e->sel_end.para; - b = e->sel_start.para; - } - e->sel_active = 0; - rewrap_paragraph_range(e->cursor_frame, a, b, e->sel_start, e->sel_end, 0); -} - - -static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, - SCEditor *e) -{ - enum corner c; - gdouble x, y; - struct frame *clicked; - int shift; - - x = event->x - e->border_offs_x; - y = event->y - e->border_offs_y + e->scroll_pos; - x /= e->view_scale; - y /= e->view_scale; - shift = event->state & GDK_SHIFT_MASK; - - if ( within_frame(e->selection, x, y) ) { - clicked = e->selection; - } else { - clicked = find_frame_at_position(e->top, x, y); - } - - /* Clicked within the currently selected frame - * -> resize, move or select text */ - if ( (e->selection != NULL) && (clicked == e->selection) ) { - - struct frame *fr; - - fr = e->selection; - - /* Within the resizing region? */ - c = which_corner(x, y, fr); - if ( (c != CORNER_NONE) && fr->resizable && shift ) { - - e->drag_reason = DRAG_REASON_RESIZE; - e->drag_corner = c; - - e->start_corner_x = x; - e->start_corner_y = y; - e->diagonal_length = pow(fr->w, 2.0); - e->diagonal_length += pow(fr->h, 2.0); - e->diagonal_length = sqrt(e->diagonal_length); - - calculate_box_size(fr, e, x, y); - - e->drag_status = DRAG_STATUS_COULD_DRAG; - e->drag_reason = DRAG_REASON_RESIZE; - - } else { - - /* Position cursor and prepare for possible drag */ - e->cursor_frame = clicked; - check_paragraph(e->cursor_frame, e->pc, sc_block_child(fr->scblocks)); - find_cursor(clicked, x-fr->x, y-fr->y, &e->cpos); - ensure_run(e->cursor_frame, e->cpos); - - e->start_corner_x = x; - e->start_corner_y = y; - - if ( event->type == GDK_2BUTTON_PRESS ) { - check_callback_click(e->cursor_frame, e->cpos.para); - } - - if ( fr->resizable && shift ) { - e->drag_status = DRAG_STATUS_COULD_DRAG; - e->drag_reason = DRAG_REASON_MOVE; - } else if ( !e->para_highlight ) { - e->drag_status = DRAG_STATUS_COULD_DRAG; - e->drag_reason = DRAG_REASON_TEXTSEL; - unset_selection(e); - find_cursor(clicked, x-fr->x, y-fr->y, &e->sel_start); - } - - } - - } else if ( (clicked == NULL) - || ( !e->top_editable && (clicked == e->top) ) ) - { - /* Clicked no object. Deselect old object. - * If shift held, set up for creating a new one. */ - e->selection = NULL; - unset_selection(e); - - if ( shift ) { - e->start_corner_x = x; - e->start_corner_y = y; - e->drag_status = DRAG_STATUS_COULD_DRAG; - e->drag_reason = DRAG_REASON_CREATE; - } else { - e->drag_status = DRAG_STATUS_NONE; - e->drag_reason = DRAG_REASON_NONE; - } - - } else { - - /* Clicked an existing frame, no immediate dragging */ - e->drag_status = DRAG_STATUS_COULD_DRAG; - e->drag_reason = DRAG_REASON_TEXTSEL; - unset_selection(e); - find_cursor(clicked, x-clicked->x, y-clicked->y, - &e->sel_start); - find_cursor(clicked, x-clicked->x, y-clicked->y, - &e->sel_end); - e->selection = clicked; - e->cursor_frame = clicked; - if ( clicked == e->top ) { - check_paragraph(e->cursor_frame, e->pc, clicked->scblocks); - } else { - check_paragraph(e->cursor_frame, e->pc, - sc_block_child(clicked->scblocks)); - } - find_cursor(clicked, x-clicked->x, y-clicked->y, &e->cpos); - ensure_run(e->cursor_frame, e->cpos); - - } - - gtk_widget_grab_focus(GTK_WIDGET(da)); - sc_editor_redraw(e); - return FALSE; -} - - -static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, - SCEditor *e) -{ - struct frame *fr = e->selection; - gdouble x, y; - - x = event->x - e->border_offs_x; - y = event->y - e->border_offs_y + e->scroll_pos; - x /= e->view_scale; - y /= e->view_scale; - - if ( e->drag_status == DRAG_STATUS_COULD_DRAG ) { - - /* We just got a motion signal, and the status was "could drag", - * therefore the drag has started. */ - e->drag_status = DRAG_STATUS_DRAGGING; - - } - - switch ( e->drag_reason ) { - - case DRAG_REASON_NONE : - break; - - case DRAG_REASON_CREATE : - e->drag_corner_x = x; - e->drag_corner_y = y; - sc_editor_redraw(e); - break; - - case DRAG_REASON_IMPORT : - /* Do nothing, handled by dnd_motion() */ - break; - - case DRAG_REASON_RESIZE : - calculate_box_size(fr, e, x, y); - sc_editor_redraw(e); - break; - - case DRAG_REASON_MOVE : - e->box_x = (fr->x - e->start_corner_x) + x; - e->box_y = (fr->y - e->start_corner_y) + y; - e->box_width = fr->w; - e->box_height = fr->h; - sc_editor_redraw(e); - break; - - case DRAG_REASON_TEXTSEL : - unset_selection(e); - find_cursor(fr, x-fr->x, y-fr->y, &e->sel_end); - rewrap_paragraph_range(fr, e->sel_start.para, e->sel_end.para, - e->sel_start, e->sel_end, 1); - find_cursor(fr, x-fr->x, y-fr->y, &e->cpos); - e->sel_active = !positions_equal(e->sel_start, e->sel_end); - sc_editor_redraw(e); - break; - - } - - gdk_event_request_motions(event); - return FALSE; -} - - -static struct frame *create_frame(SCEditor *e, double x, double y, - double w, double h) -{ - struct frame *parent; - struct frame *fr; - SCBlock *scblocks; - - parent = e->top; - - if ( w < 0.0 ) { - x += w; - w = -w; - } - - if ( h < 0.0 ) { - y += h; - h = -h; - } - - /* Add to frame structure */ - fr = add_subframe(parent); - - /* Add to SC */ - scblocks = sc_block_append_end(sc_block_child(e->scblocks), "f", NULL, NULL); - fr->scblocks = scblocks; - sc_block_append_inside(scblocks, NULL, NULL, strdup("")); - - fr->x = x; - fr->y = y; - fr->w = w; - fr->h = h; - fr->is_image = 0; - fr->empty = 1; - fr->resizable = 1; - - update_geom(fr); - - full_rerender(e); - return find_frame_with_scblocks(e->top, scblocks); -} - - -static void do_resize(SCEditor *e, double x, double y, double w, double h) -{ - struct frame *fr; - - assert(e->selection != NULL); - - if ( w < 0.0 ) { - w = -w; - x -= w; - } - - if ( h < 0.0 ) { - h = -h; - y -= h; - } - - fr = e->selection; - fr->x = x; - fr->y = y; - fr->w = w; - fr->h = h; - update_geom(fr); - - full_rerender(e); - sc_editor_redraw(e); -} - - -static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event, - SCEditor *e) -{ - gdouble x, y; - struct frame *fr; - - x = event->x - e->border_offs_x; - y = event->y - e->border_offs_y; - x /= e->view_scale; - y /= e->view_scale; - - /* Not dragging? Then I don't care. */ - if ( e->drag_status != DRAG_STATUS_DRAGGING ) return FALSE; - - e->drag_corner_x = x; - e->drag_corner_y = y; - e->drag_status = DRAG_STATUS_NONE; - - switch ( e->drag_reason ) - { - - case DRAG_REASON_NONE : - printf("Release on pointless drag.\n"); - break; - - case DRAG_REASON_CREATE : - fr = create_frame(e, e->start_corner_x, e->start_corner_y, - e->drag_corner_x - e->start_corner_x, - e->drag_corner_y - e->start_corner_y); - if ( fr != NULL ) { - check_paragraph(fr, e->pc, sc_block_child(fr->scblocks)); - e->selection = fr; - e->cursor_frame = fr; - e->cpos.para = 0; - e->cpos.pos = 0; - e->cpos.trail = 0; - } else { - fprintf(stderr, _("Failed to create frame!\n")); - } - break; - - case DRAG_REASON_IMPORT : - /* Do nothing, handled in dnd_drop() or dnd_leave() */ - break; - - case DRAG_REASON_RESIZE : - do_resize(e, e->box_x, e->box_y, e->box_width, e->box_height); - break; - - case DRAG_REASON_MOVE : - do_resize(e, e->box_x, e->box_y, e->box_width, e->box_height); - break; - - case DRAG_REASON_TEXTSEL : - /* Do nothing (text is already selected) */ - break; - - } - - e->drag_reason = DRAG_REASON_NONE; - - gtk_widget_grab_focus(GTK_WIDGET(da)); - sc_editor_redraw(e); - return FALSE; -} - - -static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event, - SCEditor *e) -{ - gboolean r; - int claim = 0; - - /* Throw the event to the IM context and let it sort things out */ - r = gtk_im_context_filter_keypress(GTK_IM_CONTEXT(e->im_context), - event); - if ( r ) return FALSE; /* IM ate it */ - - switch ( event->keyval ) { - - case GDK_KEY_Escape : - if ( !e->para_highlight ) { - sc_editor_remove_cursor(e); - sc_editor_redraw(e); - claim = 1; - } - break; - - case GDK_KEY_Left : - if ( e->selection != NULL ) { - cursor_moveh(e->cursor_frame, &e->cpos, -1); - sc_editor_redraw(e); - } - claim = 1; - break; - - case GDK_KEY_Right : - if ( e->selection != NULL ) { - cursor_moveh(e->cursor_frame, &e->cpos, +1); - sc_editor_redraw(e); - } - claim = 1; - break; - - case GDK_KEY_Up : - if ( e->selection != NULL ) { - cursor_moveh(e->cursor_frame, &e->cpos, -1); - sc_editor_redraw(e); - } - claim = 1; - break; - - case GDK_KEY_Down : - if ( e->selection != NULL ) { - cursor_moveh(e->cursor_frame, &e->cpos, +1); - sc_editor_redraw(e); - } - claim = 1; - break; - - - case GDK_KEY_Return : - im_commit_sig(NULL, "\n", e); - claim = 1; - break; - - case GDK_KEY_BackSpace : - if ( e->selection != NULL ) { - do_backspace(e->selection, e); - claim = 1; - } - break; - - case GDK_KEY_F5 : - full_rerender(e); - break; - - case GDK_KEY_F6 : - show_edit_pos(e->cpos); - break; - - case GDK_KEY_F7 : - if ( e->cursor_frame != NULL ) { - if ( event->state & GDK_CONTROL_MASK ) { - debug_paragraphs(e); - } else if ( event->state & GDK_SHIFT_MASK ) { - printf("Cursor frame block = %p\n", e->cursor_frame->scblocks); - printf("Editor top block = %p\n", e->scblocks); - show_sc_block(e->cursor_frame->scblocks, ""); - } else { - open_debugger(e->cursor_frame); - } - } else { - if ( event->state & GDK_SHIFT_MASK ) { - printf("Debugging the top frame:\n"); - printf("Editor top block = %p\n", e->scblocks); - show_sc_block(e->top->scblocks, ""); - } - } - break; - - case GDK_KEY_C : - case GDK_KEY_c : - if ( event->state == GDK_CONTROL_MASK ) { - copy_selection(e); - } - break; - - case GDK_KEY_V : - case GDK_KEY_v : - if ( event->state == GDK_CONTROL_MASK ) { - sc_editor_paste(e); - } - break; - - - } - - if ( claim ) return TRUE; - return FALSE; -} - - -static gboolean dnd_motion(GtkWidget *widget, GdkDragContext *drag_context, - gint x, gint y, guint time, SCEditor *e) -{ - GdkAtom target; - - /* If we haven't already requested the data, do so now */ - if ( !e->drag_preview_pending && !e->have_drag_data ) { - - target = gtk_drag_dest_find_target(widget, drag_context, NULL); - - if ( target != GDK_NONE ) { - gtk_drag_get_data(widget, drag_context, target, time); - e->drag_preview_pending = 1; - } else { - e->import_acceptable = 0; - gdk_drag_status(drag_context, 0, time); - } - - } - - if ( e->have_drag_data && e->import_acceptable ) { - - gdk_drag_status(drag_context, GDK_ACTION_LINK, time); - e->start_corner_x = x - e->import_width/2.0; - e->start_corner_y = y - e->import_height/2.0; - e->drag_corner_x = x + e->import_width/2.0; - e->drag_corner_y = y + e->import_height/2.0; - - sc_editor_redraw(e); - - } - - return TRUE; -} - - -static gboolean dnd_drop(GtkWidget *widget, GdkDragContext *drag_context, - gint x, gint y, guint time, SCEditor *e) -{ - GdkAtom target; - - target = gtk_drag_dest_find_target(widget, drag_context, NULL); - - if ( target == GDK_NONE ) { - gtk_drag_finish(drag_context, FALSE, FALSE, time); - } else { - gtk_drag_get_data(widget, drag_context, target, time); - } - - return TRUE; -} - - -/* Scale the image down if it's a silly size */ -static void check_import_size(SCEditor *e) -{ - if ( e->import_width > e->w ) { - - int new_import_width; - - new_import_width = e->w/2; - e->import_height = (new_import_width * e->import_height) / - e->import_width; - e->import_width = new_import_width; - - } - - if ( e->import_height > e->h ) { - - int new_import_height; - - new_import_height = e->w/2; - e->import_width = (new_import_height*e->import_width) / - e->import_height; - e->import_height = new_import_height; - - } -} - - -static void dnd_receive(GtkWidget *widget, GdkDragContext *drag_context, - gint x, gint y, GtkSelectionData *seldata, - guint info, guint time, SCEditor *e) -{ - if ( e->drag_preview_pending ) { - - gchar *filename = NULL; - GdkPixbufFormat *f; - gchar **uris; - int w, h; - - e->have_drag_data = 1; - e->drag_preview_pending = 0; - uris = gtk_selection_data_get_uris(seldata); - if ( uris != NULL ) { - filename = g_filename_from_uri(uris[0], NULL, NULL); - } - g_strfreev(uris); - - if ( filename == NULL ) { - - /* This doesn't even look like a sensible URI. - * Bail out. */ - gdk_drag_status(drag_context, 0, time); - if ( e->drag_highlight ) { - gtk_drag_unhighlight(widget); - e->drag_highlight = 0; - } - e->import_acceptable = 0; - return; - - } - chomp(filename); - - f = gdk_pixbuf_get_file_info(filename, &w, &h); - g_free(filename); - - e->import_width = w; - e->import_height = h; - - if ( f == NULL ) { - - gdk_drag_status(drag_context, 0, time); - if ( e->drag_highlight ) { - gtk_drag_unhighlight(widget); - e->drag_highlight = 0; - } - e->drag_status = DRAG_STATUS_NONE; - e->drag_reason = DRAG_REASON_NONE; - e->import_acceptable = 0; - - } else { - - /* Looks like a sensible image */ - gdk_drag_status(drag_context, GDK_ACTION_PRIVATE, time); - e->import_acceptable = 1; - - if ( !e->drag_highlight ) { - gtk_drag_highlight(widget); - e->drag_highlight = 1; - } - - check_import_size(e); - e->drag_reason = DRAG_REASON_IMPORT; - e->drag_status = DRAG_STATUS_DRAGGING; - - } - - } else { - - gchar **uris; - char *filename = NULL; - - uris = gtk_selection_data_get_uris(seldata); - if ( uris != NULL ) { - filename = g_filename_from_uri(uris[0], NULL, NULL); - } - g_strfreev(uris); - - if ( filename != NULL ) { - - struct frame *fr; - char *opts; - size_t len; - int w, h; - - gtk_drag_finish(drag_context, TRUE, FALSE, time); - chomp(filename); - - w = e->drag_corner_x - e->start_corner_x; - h = e->drag_corner_y - e->start_corner_y; - - len = strlen(filename)+64; - opts = malloc(len); - if ( opts == NULL ) { - free(filename); - fprintf(stderr, "Failed to allocate SC\n"); - return; - } - snprintf(opts, len, "1fx1f+0+0,filename=\"%s\"", - filename); - - fr = create_frame(e, e->start_corner_x, - e->start_corner_y, w, h); - fr->is_image = 1; - fr->empty = 0; - sc_block_set_name(sc_block_child(fr->scblocks), strdup("image")); - sc_block_set_options(sc_block_child(fr->scblocks), opts); - full_rerender(e); - sc_editor_remove_cursor(e); - sc_editor_redraw(e); - free(filename); - - } else { - - gtk_drag_finish(drag_context, FALSE, FALSE, time); - - } - - } -} - - -static void dnd_leave(GtkWidget *widget, GdkDragContext *drag_context, - guint time, SCEditor *sceditor) -{ - if ( sceditor->drag_highlight ) { - gtk_drag_unhighlight(widget); - } - sceditor->have_drag_data = 0; - sceditor->drag_highlight = 0; - sceditor->drag_status = DRAG_STATUS_NONE; - sceditor->drag_reason = DRAG_REASON_NONE; -} - - -static gint realise_sig(GtkWidget *da, SCEditor *e) -{ - GdkWindow *win; - - /* Keyboard and input method stuff */ - e->im_context = gtk_im_multicontext_new(); - win = gtk_widget_get_window(GTK_WIDGET(e)); - gtk_im_context_set_client_window(GTK_IM_CONTEXT(e->im_context), win); - gdk_window_set_accept_focus(win, TRUE); - g_signal_connect(G_OBJECT(e->im_context), "commit", G_CALLBACK(im_commit_sig), e); - g_signal_connect(G_OBJECT(e), "key-press-event", G_CALLBACK(key_press_sig), e); - - /* FIXME: Can do this "properly" by setting up a separate font map */ - e->pc = gtk_widget_get_pango_context(GTK_WIDGET(e)); - - return FALSE; -} - - -void sc_editor_set_scblock(SCEditor *e, SCBlock *scblocks) -{ - e->scblocks = scblocks; - full_rerender(e); -} - - -static void update_size_request(SCEditor *e) -{ - gtk_widget_set_size_request(GTK_WIDGET(e), 0, e->h + 2.0*e->min_border); -} - - -void sc_editor_set_logical_size(SCEditor *e, double w, double h) -{ - e->log_w = w; - e->log_h = h; - if ( gtk_widget_get_mapped(GTK_WIDGET(e)) ) { - full_rerender(e); - sc_editor_redraw(e); - } -} - - -void sc_editor_set_slidenum(SCEditor *e, int slidenum) -{ - e->slidenum = slidenum; -} - - -void sc_editor_set_min_border(SCEditor *e, double min_border) -{ - e->min_border = min_border; - update_size_request(e); -} - - -void sc_editor_set_top_frame_editable(SCEditor *e, int top_frame_editable) -{ - e->top_editable = top_frame_editable; -} - - -void sc_editor_set_stylesheet(SCEditor *e, Stylesheet *stylesheet) -{ - e->stylesheet = stylesheet; -} - - -void sc_editor_set_callbacks(SCEditor *e, SCCallbackList *cbl) -{ - if ( e->cbl != NULL ) sc_callback_list_free(e->cbl); - e->cbl = cbl; -} - - -void sc_editor_set_para_highlight(SCEditor *e, int para_highlight) -{ - e->para_highlight = para_highlight; - sc_editor_redraw(e); -} - -int sc_editor_get_cursor_para(SCEditor *e) -{ - if ( e->cursor_frame == NULL ) return 0; - return e->cpos.para; -} - - -void *sc_editor_get_cursor_bvp(SCEditor *e) -{ - Paragraph *para; - if ( e->cursor_frame == NULL ) return 0; - para = e->cursor_frame->paras[e->cpos.para]; - return get_para_bvp(para); -} - - -void sc_editor_set_cursor_para(SCEditor *e, signed int pos) -{ - double h; - int i; - - if ( e->cursor_frame == NULL ) { - e->cursor_frame = e->top; - e->selection = e->top; - } - - if ( pos < 0 ) { - e->cpos.para = e->cursor_frame->n_paras - 1; - } else if ( pos >= e->cursor_frame->n_paras ) { - e->cpos.para = e->cursor_frame->n_paras - 1; - } else { - e->cpos.para = pos; - } - e->cpos.pos = 0; - e->cpos.trail = 0; - - h = 0; - for ( i=0; i<e->cpos.para; i++ ) { - h += paragraph_height(e->cursor_frame->paras[i]); - } - h += (paragraph_height(e->cursor_frame->paras[e->cpos.para]))/2; - e->scroll_pos = h - (e->visible_height/2); - set_vertical_params(e); - - sc_editor_redraw(e); -} - - -int sc_editor_get_num_paras(SCEditor *e) -{ - if ( e->cursor_frame == NULL ) return 1; - return e->cursor_frame->n_paras; -} - - -void sc_editor_set_scale(SCEditor *e, int scale) -{ - e->scale = scale; - if ( !scale ) { - e->view_scale = 1.0; - } -} - - -void sc_editor_set_imagestore(SCEditor *e, ImageStore *is) -{ - if ( e->is != NULL ) { - fprintf(stderr, "WARNING: Changing imagestore\n"); - } - e->is = is; -} - - -SCEditor *sc_editor_new(SCBlock *scblocks, Stylesheet *stylesheet, - PangoLanguage *lang, const char *storename) -{ - SCEditor *sceditor; - GtkTargetEntry targets[1]; - GError *err; - - sceditor = g_object_new(SC_TYPE_EDITOR, NULL); - - sceditor->scblocks = scblocks; - sceditor->w = 100; - sceditor->h = 100; - sceditor->log_w = 100; - sceditor->log_h = 100; - sceditor->border_offs_x = 0; - sceditor->border_offs_y = 0; - sceditor->is = NULL; - sceditor->slidenum = 0; - sceditor->min_border = 0.0; - sceditor->top_editable = 0; - sceditor->cbl = NULL; - sceditor->scroll_pos = 0; - sceditor->flow = 0; - sceditor->scale = 0; - sceditor->view_scale = 1.0; - sceditor->lang = lang; - - sceditor->para_highlight = 0; - sc_editor_remove_cursor(sceditor); - - sceditor->stylesheet = stylesheet; - - err = NULL; - sceditor->bg_pixbuf = gdk_pixbuf_new_from_resource("/uk/me/bitwiz/Colloquium/sky.png", - &err); - if ( sceditor->bg_pixbuf == NULL ) { - fprintf(stderr, _("Failed to load background: %s\n"), - err->message); - } - - gtk_widget_set_size_request(GTK_WIDGET(sceditor), - sceditor->w, sceditor->h); - - g_signal_connect(G_OBJECT(sceditor), "destroy", - G_CALLBACK(destroy_sig), sceditor); - g_signal_connect(G_OBJECT(sceditor), "realize", - G_CALLBACK(realise_sig), sceditor); - g_signal_connect(G_OBJECT(sceditor), "button-press-event", - G_CALLBACK(button_press_sig), sceditor); - g_signal_connect(G_OBJECT(sceditor), "button-release-event", - G_CALLBACK(button_release_sig), sceditor); - g_signal_connect(G_OBJECT(sceditor), "motion-notify-event", - G_CALLBACK(motion_sig), sceditor); - g_signal_connect(G_OBJECT(sceditor), "configure-event", - G_CALLBACK(resize_sig), sceditor); - - /* Drag and drop */ - targets[0].target = "text/uri-list"; - targets[0].flags = 0; - targets[0].info = 1; - gtk_drag_dest_set(GTK_WIDGET(sceditor), 0, targets, 1, - GDK_ACTION_PRIVATE); - g_signal_connect(sceditor, "drag-data-received", - G_CALLBACK(dnd_receive), sceditor); - g_signal_connect(sceditor, "drag-motion", - G_CALLBACK(dnd_motion), sceditor); - g_signal_connect(sceditor, "drag-drop", - G_CALLBACK(dnd_drop), sceditor); - g_signal_connect(sceditor, "drag-leave", - G_CALLBACK(dnd_leave), sceditor); - - gtk_widget_set_can_focus(GTK_WIDGET(sceditor), TRUE); - gtk_widget_add_events(GTK_WIDGET(sceditor), - GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON1_MOTION_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK - | GDK_SCROLL_MASK); - - g_signal_connect(G_OBJECT(sceditor), "draw", - G_CALLBACK(draw_sig), sceditor); - - gtk_widget_grab_focus(GTK_WIDGET(sceditor)); - - gtk_widget_show(GTK_WIDGET(sceditor)); - - return sceditor; -} diff --git a/src-old/sc_editor.h b/src-old/sc_editor.h deleted file mode 100644 index d3c111b..0000000 --- a/src-old/sc_editor.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * sc_editor.h - * - * Copyright © 2014-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef SC_EDITOR_H -#define SC_EDITOR_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gtk/gtk.h> -#include <glib-object.h> - -#include "frame.h" -#include "sc_interp.h" -#include "stylesheet.h" - -struct presentation; - - -#define SC_TYPE_EDITOR (sc_editor_get_type()) - -#define SC_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ - SC_TYPE_EDITOR, SCEditor)) - -#define SC_IS_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ - SC_TYPE_EDITOR)) - -#define SC_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), \ - SC_TYPE_EDITOR, SCEditorClass)) - -#define SC_IS_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), \ - SC_TYPE_EDITOR)) - -#define SC_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ - SC_TYPE_EDITOR, SCEditorClass)) - -enum drag_reason -{ - DRAG_REASON_NONE, - DRAG_REASON_CREATE, - DRAG_REASON_IMPORT, - DRAG_REASON_RESIZE, - DRAG_REASON_MOVE, - DRAG_REASON_TEXTSEL -}; - - -enum corner -{ - CORNER_NONE, - CORNER_TL, - CORNER_TR, - CORNER_BL, - CORNER_BR -}; - - -enum drag_status -{ - DRAG_STATUS_NONE, - DRAG_STATUS_COULD_DRAG, - DRAG_STATUS_DRAGGING, -}; - - -struct _sceditor -{ - GtkDrawingArea parent_instance; - PangoLanguage *lang; - - /*< private >*/ - GtkIMContext *im_context; - int w; /* Surface size in pixels */ - int h; - double log_w; /* Size of surface in "SC units" */ - double log_h; - SCBlock *scblocks; - Stylesheet *stylesheet; - ImageStore *is; - SCCallbackList *cbl; - struct frame *top; - int para_highlight; - - /* Redraw/scroll stuff */ - GtkScrollablePolicy hpol; - GtkScrollablePolicy vpol; - GtkAdjustment *hadj; - GtkAdjustment *vadj; - double scroll_pos; - double h_scroll_pos; - int visible_height; - int visible_width; - int flow; - int scale; /* Whether the SCEditor should scale to fit */ - double view_scale; /* The scale factor, if scale=1 */ - - /* Pointers to the frame currently being edited */ - struct frame *selection; - int top_editable; - - PangoContext *pc; - - /* Location of the cursor */ - struct frame *cursor_frame; - struct edit_pos cpos; - - /* Border surrounding actual slide within drawingarea */ - double border_offs_x; - double border_offs_y; - double min_border; - double bgcol[3]; - GdkPixbuf *bg_pixbuf; - - /* Rubber band boxes and related stuff */ - double start_corner_x; - double start_corner_y; - double drag_corner_x; - double drag_corner_y; - double diagonal_length; - double box_x; - double box_y; - double box_width; - double box_height; - enum drag_reason drag_reason; - enum drag_status drag_status; - enum corner drag_corner; - int sel_active; - struct edit_pos sel_start; /* Where the user dragged from */ - struct edit_pos sel_end; - - /* Stuff to do with drag and drop import of "content" */ - int drag_preview_pending; - int have_drag_data; - int drag_highlight; - double import_width; - double import_height; - int import_acceptable; - - /* Stuff that doesn't really belong here */ - int slidenum; -}; - -struct _sceditorclass -{ - GtkDrawingAreaClass parent_class; -}; - -typedef struct _sceditor SCEditor; -typedef struct _sceditorclass SCEditorClass; - -extern void sc_editor_set_scblock(SCEditor *e, SCBlock *scblocks); -extern void sc_editor_set_stylesheet(SCEditor *e, Stylesheet *stylesheet); -extern SCEditor *sc_editor_new(SCBlock *scblocks, Stylesheet *stylesheet, - PangoLanguage *lang, const char *storename); -extern void sc_editor_set_logical_size(SCEditor *e, double w, double h); -extern void sc_editor_set_flow(SCEditor *e, int flow); -extern void sc_editor_set_scale(SCEditor *e, int scale); -extern void sc_editor_redraw(SCEditor *e); -extern void sc_editor_set_background(SCEditor *e, double r, double g, double b); -extern void sc_editor_set_slidenum(SCEditor *e, int slidenum); -extern void sc_editor_set_min_border(SCEditor *e, double min_border); -extern void sc_editor_set_top_frame_editable(SCEditor *e, - int top_frame_editable); -extern void sc_editor_set_callbacks(SCEditor *e, SCCallbackList *cbl); -extern void sc_editor_paste(SCEditor *e); -extern void sc_editor_add_storycode(SCEditor *e, const char *sc); -extern void sc_editor_copy_selected_frame(SCEditor *e); -extern void sc_editor_delete_selected_frame(SCEditor *e); -extern void sc_editor_ensure_cursor(SCEditor *e); -extern SCBlock *split_paragraph_at_cursor(SCEditor *e); - -extern void sc_editor_set_imagestore(SCEditor *e, ImageStore *is); -extern void sc_editor_set_para_highlight(SCEditor *e, int para_highlight); -extern int sc_editor_get_cursor_para(SCEditor *e); -extern void *sc_editor_get_cursor_bvp(SCEditor *e); -extern void sc_editor_set_cursor_para(SCEditor *e, signed int pos); -extern int sc_editor_get_num_paras(SCEditor *e); - -#endif /* SC_EDITOR_H */ diff --git a/src-old/sc_interp.c b/src-old/sc_interp.c deleted file mode 100644 index 07f09a5..0000000 --- a/src-old/sc_interp.c +++ /dev/null @@ -1,1148 +0,0 @@ -/* - * sc_interp.c - * - * Copyright © 2014-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <pango/pangocairo.h> -#include <gdk/gdk.h> - -#include "imagestore.h" -#include "sc_parse.h" -#include "sc_interp.h" -#include "presentation.h" -#include "utils.h" - - -struct sc_state -{ - PangoFontDescription *fontdesc; - PangoFont *font; - PangoAlignment alignment; - double col[4]; - int ascent; - int height; - float paraspace[4]; - char *constants[NUM_SC_CONSTANTS]; - - struct frame *fr; /* The current frame */ -}; - -struct _scinterp -{ - PangoContext *pc; - PangoLanguage *lang; - ImageStore *is; - - struct slide_constants *s_constants; - struct presentation_constants *p_constants; - - struct sc_state *state; - int j; /* Index of the current state */ - int max_state; - - SCCallbackList *cbl; -}; - -struct _sccallbacklist -{ - int n_callbacks; - int max_callbacks; - char **names; - SCCallbackBoxFunc *box_funcs; - SCCallbackDrawFunc *draw_funcs; - SCCallbackClickFunc *click_funcs; - void **vps; -}; - - -static int sc_interp_add_blocks(SCInterpreter *scin, SCBlock *bl, Stylesheet *ss) -{ - while ( bl != NULL ) { - if ( sc_interp_add_block(scin, bl, ss) ) return 1; - bl = sc_block_next(bl); - } - - return 0; -} - - -SCCallbackList *sc_callback_list_new() -{ - SCCallbackList *cbl; - - cbl = malloc(sizeof(struct _sccallbacklist)); - if ( cbl == NULL ) return NULL; - - cbl->names = calloc(8, sizeof(char *)); - if ( cbl->names == NULL ) { - free(cbl); - return NULL; - } - - cbl->box_funcs = calloc(8, sizeof(cbl->box_funcs[0])); - if ( cbl->box_funcs == NULL ) { - free(cbl->names); - free(cbl); - return NULL; - } - - cbl->draw_funcs = calloc(8, sizeof(cbl->draw_funcs[0])); - if ( cbl->draw_funcs == NULL ) { - free(cbl->box_funcs); - free(cbl->names); - free(cbl); - return NULL; - } - - cbl->click_funcs = calloc(8, sizeof(cbl->click_funcs[0])); - if ( cbl->click_funcs == NULL ) { - free(cbl->draw_funcs); - free(cbl->box_funcs); - free(cbl->names); - free(cbl); - return NULL; - } - - cbl->vps = calloc(8, sizeof(cbl->vps[0])); - if ( cbl->vps == NULL ) { - free(cbl->click_funcs); - free(cbl->draw_funcs); - free(cbl->box_funcs); - free(cbl->names); - free(cbl); - return NULL; - } - - cbl->max_callbacks = 8; - cbl->n_callbacks = 0; - - return cbl; -} - - -void sc_callback_list_free(SCCallbackList *cbl) -{ - int i; - - if ( cbl == NULL ) return; - - for ( i=0; i<cbl->n_callbacks; i++ ) { - free(cbl->names[i]); - } - - free(cbl->names); - free(cbl->box_funcs); - free(cbl->draw_funcs); - free(cbl->vps); - free(cbl); - -} - - -void sc_callback_list_add_callback(SCCallbackList *cbl, const char *name, - SCCallbackBoxFunc box_func, - SCCallbackDrawFunc draw_func, - SCCallbackClickFunc click_func, - void *vp) -{ - if ( cbl->n_callbacks == cbl->max_callbacks ) { - - SCCallbackBoxFunc *box_funcs_new; - SCCallbackDrawFunc *draw_funcs_new; - SCCallbackClickFunc *click_funcs_new; - char **names_new; - void **vps_new; - int mcn = cbl->max_callbacks + 8; - - names_new = realloc(cbl->names, mcn*sizeof(char *)); - box_funcs_new = realloc(cbl->box_funcs, - mcn*sizeof(SCCallbackBoxFunc)); - draw_funcs_new = realloc(cbl->draw_funcs, - mcn*sizeof(SCCallbackDrawFunc)); - click_funcs_new = realloc(cbl->click_funcs, - mcn*sizeof(SCCallbackClickFunc)); - vps_new = realloc(cbl->vps, mcn*sizeof(void *)); - - if ( (names_new == NULL) || (box_funcs_new == NULL) - || (vps_new == NULL) || (draw_funcs_new == NULL) - || (click_funcs_new == NULL) ) { - fprintf(stderr, "Failed to grow callback list\n"); - return; - } - - cbl->names = names_new; - cbl->box_funcs = box_funcs_new; - cbl->draw_funcs = draw_funcs_new; - cbl->click_funcs = click_funcs_new; - cbl->vps = vps_new; - cbl->max_callbacks = mcn; - - } - - cbl->names[cbl->n_callbacks] = strdup(name); - cbl->box_funcs[cbl->n_callbacks] = box_func; - cbl->draw_funcs[cbl->n_callbacks] = draw_func; - cbl->click_funcs[cbl->n_callbacks] = click_func; - cbl->vps[cbl->n_callbacks] = vp; - cbl->n_callbacks++; -} - - -void sc_interp_set_callbacks(SCInterpreter *scin, SCCallbackList *cbl) -{ - if ( scin->cbl != NULL ) { - fprintf(stderr, "WARNING: Interpreter already has a callback " - "list.\n"); - } - scin->cbl = cbl; -} - - -static int check_callback(SCInterpreter *scin, SCBlock *bl) -{ - int i; - const char *name = sc_block_name(bl); - SCCallbackList *cbl = scin->cbl; - - /* No callback list -> easy */ - if ( cbl == NULL ) return 0; - - /* No name -> definitely not a callback */ - if ( name == NULL ) return 0; - - for ( i=0; i<cbl->n_callbacks; i++ ) { - - double w, h; - int r; - void *bvp; - - if ( strcmp(cbl->names[i], name) != 0 ) continue; - r = cbl->box_funcs[i](scin, bl, &w, &h, &bvp, cbl->vps[i]); - if ( r ) { - struct sc_state *st = &scin->state[scin->j]; - Paragraph *pnew; - pnew = add_callback_para(sc_interp_get_frame(scin), - bl, w, h, - cbl->draw_funcs[i], - cbl->click_funcs[i], - bvp, cbl->vps[i]); - if ( pnew != NULL ) { - set_para_spacing(pnew, st->paraspace); - } - - } - return 1; - - } - - return 0; -} - - -PangoFontDescription *sc_interp_get_fontdesc(SCInterpreter *scin) -{ - struct sc_state *st = &scin->state[scin->j]; - return st->fontdesc; -} - - -double *sc_interp_get_fgcol(SCInterpreter *scin) -{ - struct sc_state *st = &scin->state[scin->j]; - return st->col; -} - - -static void set_frame_default_style(struct frame *fr, SCInterpreter *scin) -{ - if ( fr == NULL ) return; - - if ( fr->fontdesc != NULL ) { - pango_font_description_free(fr->fontdesc); - } - fr->fontdesc = pango_font_description_copy(sc_interp_get_fontdesc(scin)); - fr->col[0] = sc_interp_get_fgcol(scin)[0]; - fr->col[1] = sc_interp_get_fgcol(scin)[1]; - fr->col[2] = sc_interp_get_fgcol(scin)[2]; - fr->col[3] = sc_interp_get_fgcol(scin)[3]; -} - - -static void update_font(SCInterpreter *scin) -{ - PangoFontMetrics *metrics; - struct sc_state *st = &scin->state[scin->j]; - - if ( scin->pc == NULL ) return; - - st->font = pango_font_map_load_font(pango_context_get_font_map(scin->pc), - scin->pc, st->fontdesc); - if ( st->font == NULL ) { - char *f = pango_font_description_to_string(st->fontdesc); - fprintf(stderr, "Couldn't load font '%s' (font map %p, pc %p)\n", - f, pango_context_get_font_map(scin->pc), scin->pc); - g_free(f); - return; - } - - /* FIXME: Language for box */ - metrics = pango_font_get_metrics(st->font, NULL); - st->ascent = pango_font_metrics_get_ascent(metrics); - st->height = st->ascent + pango_font_metrics_get_descent(metrics); - pango_font_metrics_unref(metrics); - set_frame_default_style(sc_interp_get_frame(scin), scin); -} - - -static void set_font(SCInterpreter *scin, const char *font_name) -{ - struct sc_state *st = &scin->state[scin->j]; - - st->fontdesc = pango_font_description_from_string(font_name); - if ( st->fontdesc == NULL ) { - fprintf(stderr, "Couldn't describe font.\n"); - return; - } - - update_font(scin); -} - - -static void copy_top_fontdesc(SCInterpreter *scin) -{ - struct sc_state *st = &scin->state[scin->j]; - - /* If this is the first stack frame, don't even check */ - if ( scin->j == 0 ) return; - - /* If the fontdesc at the top of the stack is the same as the one - * below, make a copy because we're about to do something to it (which - * should not affect the next level up). */ - if ( st->fontdesc == scin->state[scin->j-1].fontdesc ) { - st->fontdesc = pango_font_description_copy(st->fontdesc); - } -} - - -static void set_fontsize(SCInterpreter *scin, const char *size_str) -{ - struct sc_state *st = &scin->state[scin->j]; - int size; - char *end; - - if ( size_str[0] == '\0' ) return; - - size = strtoul(size_str, &end, 10); - if ( end[0] != '\0' ) { - fprintf(stderr, _("Invalid font size '%s'\n"), size_str); - return; - } - - copy_top_fontdesc(scin); - pango_font_description_set_size(st->fontdesc, size*PANGO_SCALE); - update_font(scin); -} - - -static void set_bold(SCInterpreter *scin) -{ - struct sc_state *st = &scin->state[scin->j]; - copy_top_fontdesc(scin); - pango_font_description_set_weight(st->fontdesc, PANGO_WEIGHT_BOLD); - update_font(scin); -} - - -static void set_oblique(SCInterpreter *scin) -{ - struct sc_state *st = &scin->state[scin->j]; - copy_top_fontdesc(scin); - pango_font_description_set_style(st->fontdesc, PANGO_STYLE_OBLIQUE); - update_font(scin); -} - - -static void set_italic(SCInterpreter *scin) -{ - struct sc_state *st = &scin->state[scin->j]; - copy_top_fontdesc(scin); - pango_font_description_set_style(st->fontdesc, PANGO_STYLE_ITALIC); - update_font(scin); -} - - -static void set_alignment(SCInterpreter *scin, PangoAlignment align) -{ - struct sc_state *st = &scin->state[scin->j]; - st->alignment = align; -} - - -/* This sets the colour for the font at the top of the stack */ -static void set_colour(SCInterpreter *scin, const char *colour) -{ - GdkRGBA col; - struct sc_state *st = &scin->state[scin->j]; - - if ( colour == NULL ) { - printf(_("Invalid colour\n")); - st->col[0] = 0.0; - st->col[1] = 0.0; - st->col[2] = 0.0; - st->col[3] = 1.0; - return; - } - - gdk_rgba_parse(&col, colour); - - st->col[0] = col.red; - st->col[1] = col.green; - st->col[2] = col.blue; - st->col[3] = col.alpha; - set_frame_default_style(sc_interp_get_frame(scin), scin); -} - - -static void set_bgcol(SCInterpreter *scin, const char *colour) -{ - GdkRGBA col; - struct frame *fr = sc_interp_get_frame(scin); - - if ( fr == NULL ) return; - - if ( colour == NULL ) { - printf(_("Invalid colour\n")); - return; - } - - gdk_rgba_parse(&col, colour); - - fr->bgcol[0] = col.red; - fr->bgcol[1] = col.green; - fr->bgcol[2] = col.blue; - fr->bgcol[3] = col.alpha; - fr->grad = GRAD_NONE; -} - - -static void set_bggrad(SCInterpreter *scin, const char *options, - GradientType grad) -{ - struct frame *fr = sc_interp_get_frame(scin); - GdkRGBA col1, col2; - - if ( fr == NULL ) return; - - if ( options == NULL ) { - printf(_("Invalid colour\n")); - return; - } - - if ( parse_colour_duo(options, &col1, &col2) == 0 ) { - - fr->bgcol[0] = col1.red; - fr->bgcol[1] = col1.green; - fr->bgcol[2] = col1.blue; - fr->bgcol[3] = col1.alpha; - - fr->bgcol2[0] = col2.red; - fr->bgcol2[1] = col2.green; - fr->bgcol2[2] = col2.blue; - fr->bgcol2[3] = col2.alpha; - - fr->grad = grad; - - } -} - - -static char *get_constant(SCInterpreter *scin, unsigned int constant) -{ - struct sc_state *st = &scin->state[scin->j]; - if ( constant >= NUM_SC_CONSTANTS ) return NULL; - return st->constants[constant]; -} - - -void sc_interp_set_constant(SCInterpreter *scin, unsigned int constant, - const char *val) -{ - struct sc_state *st = &scin->state[scin->j]; - if ( constant >= NUM_SC_CONSTANTS ) return; - if ( val == NULL ) return; - st->constants[constant] = strdup(val); -} - - -void sc_interp_save(SCInterpreter *scin) -{ - if ( scin->j+1 == scin->max_state ) { - - struct sc_state *stack_new; - - stack_new = realloc(scin->state, sizeof(struct sc_state) - * (scin->max_state+8)); - if ( stack_new == NULL ) { - fprintf(stderr, "Failed to add to stack.\n"); - return; - } - - scin->state = stack_new; - scin->max_state += 8; - - } - - /* When n_fonts=0, we leave the first font uninitialised. This allows - * the stack to be "bootstrapped", but requires the first caller to do - * set_font and set_colour straight away. */ - scin->state[scin->j+1] = scin->state[scin->j]; - - scin->j++; -} - - -void sc_interp_restore(SCInterpreter *scin) -{ - struct sc_state *st = &scin->state[scin->j]; - - if ( scin->j > 0 ) { - - int i; - - if ( st->fontdesc != scin->state[scin->j-1].fontdesc ) - { - pango_font_description_free(st->fontdesc); - } /* else the font is the same as the previous one, and we - * don't need to free it just yet */ - - for ( i=0; i<NUM_SC_CONSTANTS; i++ ) { - if ( st->constants[i] != scin->state[scin->j-1].constants[i] ) { - free(st->constants[i]); - } /* same logic as above */ - } - } - - scin->j--; -} - - -struct frame *sc_interp_get_frame(SCInterpreter *scin) -{ - struct sc_state *st = &scin->state[scin->j]; - return st->fr; -} - - -static void set_frame(SCInterpreter *scin, struct frame *fr) -{ - struct sc_state *st = &scin->state[scin->j]; - st->fr = fr; -} - - -SCInterpreter *sc_interp_new(PangoContext *pc, PangoLanguage *lang, - ImageStore *is, struct frame *top) -{ - SCInterpreter *scin; - struct sc_state *st; - int i; - - scin = malloc(sizeof(SCInterpreter)); - if ( scin == NULL ) return NULL; - - scin->state = malloc(8*sizeof(struct sc_state)); - if ( scin->state == NULL ) { - free(scin); - return NULL; - } - scin->j = 0; - scin->max_state = 8; - - scin->pc = pc; - scin->is = is; - scin->s_constants = NULL; - scin->p_constants = NULL; - scin->cbl = NULL; - scin->lang = lang; - - /* Initial state */ - st = &scin->state[0]; - st->fr = NULL; - st->paraspace[0] = 0.0; - st->paraspace[1] = 0.0; - st->paraspace[2] = 0.0; - st->paraspace[3] = 0.0; - st->fontdesc = NULL; - st->col[0] = 0.0; - st->col[1] = 0.0; - st->col[2] = 0.0; - st->col[3] = 1.0; - st->alignment = PANGO_ALIGN_LEFT; - for ( i=0; i<NUM_SC_CONSTANTS; i++ ) { - st->constants[i] = NULL; - } - - /* The "ultimate" default font */ - if ( scin->pc != NULL ) { - set_frame(scin, top); - set_font(scin, "Cantarell Regular 14"); - set_colour(scin, "#000000"); - } - - return scin; -} - - -void sc_interp_destroy(SCInterpreter *scin) -{ - /* Empty the stack */ - while ( scin->j > 0 ) { - sc_interp_restore(scin); - } - - if ( scin->state[0].fontdesc != NULL ) { - pango_font_description_free(scin->state[0].fontdesc); - } - - free(scin->state); - free(scin); -} - - -static void set_padding(struct frame *fr, const char *opts) -{ - float p[4]; - - if ( parse_tuple(opts, p) ) return; - - if ( fr == NULL ) return; - - fr->pad_l = p[0]; - fr->pad_r = p[1]; - fr->pad_t = p[2]; - fr->pad_b = p[3]; -} - - -static void set_paraspace(SCInterpreter *scin, const char *opts) -{ - float p[4]; - struct sc_state *st = &scin->state[scin->j]; - - if ( parse_tuple(opts, p) ) return; - - st->paraspace[0] = p[0]; - st->paraspace[1] = p[1]; - st->paraspace[2] = p[2]; - st->paraspace[3] = p[3]; - - set_para_spacing(last_para(sc_interp_get_frame(scin)), p); -} - - -void update_geom(struct frame *fr) -{ - char geom[256]; - snprintf(geom, 255, "%.1fux%.1fu+%.1f+%.1f", - fr->w, fr->h, fr->x, fr->y); - - /* FIXME: What if there are other options? */ - sc_block_set_options(fr->scblocks, strdup(geom)); -} - - -static int calculate_dims(const char *opt, struct frame *parent, - double *wp, double *hp, double *xp, double *yp) -{ - LengthUnits h_units, w_units; - - if ( parse_dims(opt, wp, hp, &w_units, &h_units, xp, yp) ) { - return 1; - } - - if ( w_units == UNITS_FRAC ) { - if ( parent != NULL ) { - double pw = parent->w; - pw -= parent->pad_l; - pw -= parent->pad_r; - *wp = pw * *wp; - } else { - *wp = -1.0; - } - - } - if ( h_units == UNITS_FRAC ) { - if ( parent != NULL ) { - double ph = parent->h; - ph -= parent->pad_t; - ph -= parent->pad_b; - *hp = ph * *hp; - } else { - *hp = -1.0; - } - } - - return 0; -} - - -static int parse_frame_option(const char *opt, struct frame *fr, - struct frame *parent) -{ - if ( (index(opt, 'x') != NULL) && (index(opt, '+') != NULL) - && (index(opt, '+') != rindex(opt, '+')) ) { - return calculate_dims(opt, parent, &fr->w, &fr->h, &fr->x, &fr->y); - } - - fprintf(stderr, _("Unrecognised frame option '%s'\n"), opt); - - return 1; -} - - -static int parse_frame_options(struct frame *fr, struct frame *parent, - const char *opth) -{ - int i; - size_t len; - size_t start; - char *opt; - - if ( opth == NULL ) return 1; - - opt = strdup(opth); - - len = strlen(opt); - start = 0; - - for ( i=0; i<len; i++ ) { - - /* FIXME: comma might be escaped or quoted */ - if ( opt[i] == ',' ) { - opt[i] = '\0'; - if ( parse_frame_option(opt+start, fr, parent) ) { - return 1; - } - start = i+1; - } - - } - - if ( start != len ) { - if ( parse_frame_option(opt+start, fr, parent) ) return 1; - } - - free(opt); - - return 0; -} - - -static int parse_image_option(const char *opt, struct frame *parent, - double *wp, double *hp, char **filenamep) -{ - if ( (index(opt, 'x') != NULL) && (index(opt, '+') != NULL) - && (index(opt, '+') != rindex(opt, '+')) ) { - double dum; - return calculate_dims(opt, NULL, wp, hp, &dum, &dum); - } - - if ( strncmp(opt, "filename=\"", 10) == 0 ) { - char *fn; - fn = strdup(opt+10); - if ( fn[strlen(fn)-1] != '\"' ) { - fprintf(stderr, "Unterminated filename?\n"); - free(fn); - return 1; - } - fn[strlen(fn)-1] = '\0'; - *filenamep = fn; - return 0; - } - - fprintf(stderr, _("Unrecognised image option '%s'\n"), opt); - - return 1; -} - - -static int parse_image_options(const char *opth, struct frame *parent, - double *wp, double *hp, char **filenamep) -{ - int i; - size_t len; - size_t start; - char *opt; - - if ( opth == NULL ) return 1; - - opt = strdup(opth); - - len = strlen(opt); - start = 0; - - for ( i=0; i<len; i++ ) { - - /* FIXME: comma might be escaped or quoted */ - if ( opt[i] == ',' ) { - opt[i] = '\0'; - if ( parse_image_option(opt+start, parent, - wp, hp, filenamep) ) return 1; - start = i+1; - } - - } - - if ( start != len ) { - if ( parse_image_option(opt+start, parent, - wp, hp, filenamep) ) return 1; - } - - free(opt); - - return 0; -} - - -static void maybe_recurse_before(SCInterpreter *scin, SCBlock *child) -{ - if ( child == NULL ) return; - - sc_interp_save(scin); -} - - -static void maybe_recurse_after(SCInterpreter *scin, SCBlock *child, - Stylesheet *ss) -{ - if ( child == NULL ) return; - - sc_interp_add_blocks(scin, child, ss); - sc_interp_restore(scin); -} - - -static void add_newpara(SCBlock *bl, SCInterpreter *scin) -{ - Paragraph *last_para; - Paragraph *para; - struct sc_state *st = &scin->state[scin->j]; - struct frame *fr = sc_interp_get_frame(scin); - - if ( fr->paras == NULL ) return; - last_para = fr->paras[fr->n_paras-1]; - - set_newline_at_end(last_para, bl); - - /* The block after the \newpara will always be the first one of the - * next paragraph, by definition, even if it's \f or another \newpara */ - para = create_paragraph(fr, sc_block_next(bl)); - set_para_alignment(para, st->alignment); - set_para_spacing(para, st->paraspace); -} - - -/* Add the SCBlock to the text in 'frame', at the end */ -static int add_text(struct frame *fr, PangoContext *pc, SCBlock *bl, - PangoLanguage *lang, int editable, SCInterpreter *scin, - const char *real_text) -{ - const char *text = sc_block_contents(bl); - PangoFontDescription *fontdesc; - double *col; - struct sc_state *st = &scin->state[scin->j]; - Paragraph *para; - - /* Empty block? */ - if ( text == NULL && real_text == NULL ) return 1; - - fontdesc = sc_interp_get_fontdesc(scin); - col = sc_interp_get_fgcol(scin); - - para = last_para(fr); - if ( (para == NULL) || (para_type(para) != PARA_TYPE_TEXT) ) { - /* Last paragraph is not text. - * or: no paragraphs yet. - * Either way: Create the first one */ - para = create_paragraph(fr, bl); - } - - set_para_alignment(para, st->alignment); - add_run(para, bl, fontdesc, col, real_text); - set_para_spacing(para, st->paraspace); - - return 0; -} - - -static void apply_style(SCInterpreter *scin, Stylesheet *ss, const char *path) -{ - char *result; - - if ( ss == NULL ) return; - - /* Font */ - result = stylesheet_lookup(ss, path, "font"); - if ( result != NULL ) set_font(scin, result); - - /* Foreground colour */ - result = stylesheet_lookup(ss, path, "fgcol"); - if ( result != NULL ) set_colour(scin, result); - - /* Background (vertical gradient) */ - result = stylesheet_lookup(ss, path, "bggradv"); - if ( result != NULL ) set_bggrad(scin, result, GRAD_VERT); - - /* Background (horizontal gradient) */ - result = stylesheet_lookup(ss, path, "bggradh"); - if ( result != NULL ) set_bggrad(scin, result, GRAD_HORIZ); - - /* Background (solid colour) */ - result = stylesheet_lookup(ss, path, "bgcol"); - if ( result != NULL ) set_bgcol(scin, result); - - /* Padding */ - result = stylesheet_lookup(ss, path, "pad"); - if ( result != NULL ) set_padding(sc_interp_get_frame(scin), result); - - /* Paragraph spacing */ - result = stylesheet_lookup(ss, path, "paraspace"); - if ( result != NULL ) set_paraspace(scin, result); - - /* Alignment */ - result = stylesheet_lookup(ss, path, "alignment"); - if ( result != NULL ) { - if ( strcmp(result, "center") == 0 ) { - set_alignment(scin, PANGO_ALIGN_CENTER); - } - if ( strcmp(result, "left") == 0 ) { - set_alignment(scin, PANGO_ALIGN_LEFT); - } - if ( strcmp(result, "right") == 0 ) { - set_alignment(scin, PANGO_ALIGN_RIGHT); - } - } -} - - -static void output_frame(SCInterpreter *scin, SCBlock *bl, Stylesheet *ss, - const char *stylename) -{ - struct frame *fr; - SCBlock *child = sc_block_child(bl); - const char *options = sc_block_options(bl); - char *result; - - fr = add_subframe(sc_interp_get_frame(scin)); - if ( fr == NULL ) { - fprintf(stderr, _("Failed to add frame.\n")); - return; - } - - fr->scblocks = bl; - fr->resizable = 1; - - /* Lowest priority: current state of interpreter */ - set_frame_default_style(fr, scin); - - /* Next priority: geometry from stylesheet */ - result = stylesheet_lookup(ss, stylename, "geometry"); - if ( result != NULL ) { - parse_frame_options(fr, sc_interp_get_frame(scin), result); - } - - /* Highest priority: parameters to \f (or \slidetitle etc) */ - parse_frame_options(fr, sc_interp_get_frame(scin), options); - - maybe_recurse_before(scin, child); - set_frame(scin, fr); - apply_style(scin, ss, stylename); - maybe_recurse_after(scin, child, ss); -} - - -static int check_outputs(SCBlock *bl, SCInterpreter *scin, Stylesheet *ss) -{ - const char *name = sc_block_name(bl); - const char *options = sc_block_options(bl); - - if ( name == NULL ) { - add_text(sc_interp_get_frame(scin), - scin->pc, bl, scin->lang, 1, scin, NULL); - - } else if ( strcmp(name, "image")==0 ) { - double w, h; - char *filename; - if ( parse_image_options(options, sc_interp_get_frame(scin), - &w, &h, &filename) == 0 ) - { - add_image_para(sc_interp_get_frame(scin), bl, - filename, scin->is, w, h, 1); - free(filename); - } else { - fprintf(stderr, _("Invalid image options '%s'\n"), - options); - } - - } else if ( strcmp(name, "f")==0 ) { - output_frame(scin, bl, ss, "$.slide.frame"); - - } else if ( strcmp(name, "slidetitle")==0 ) { - output_frame(scin, bl, ss, "$.slide.slidetitle"); - - } else if ( strcmp(name, "prestitle")==0 ) { - output_frame(scin, bl, ss, "$.slide.prestitle"); - - } else if ( strcmp(name, "author")==0 ) { - output_frame(scin, bl, ss, "$.slide.author"); - - } else if ( strcmp(name, "footer")==0 ) { - output_frame(scin, bl, ss, "$.slide.footer"); - - } else if ( strcmp(name, "newpara")==0 ) { - add_newpara(bl, scin); - - } else if ( strcmp(name, "slidenumber")==0 ) { - char *con = get_constant(scin, SCCONST_SLIDENUMBER); - if ( con != NULL ) { - add_text(sc_interp_get_frame(scin), scin->pc, bl, - scin->lang, 1, scin, con); - } - - } else { - return 0; - } - - return 1; /* handled */ -} - - -int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl, Stylesheet *ss) -{ - const char *name = sc_block_name(bl); - const char *options = sc_block_options(bl); - SCBlock *child = sc_block_child(bl); - - //printf("Running this --------->\n"); - //show_sc_blocks(bl); - //printf("<------------\n"); - - if ( check_callback(scin, bl) ) { - /* Handled in check_callback, don't do anything else */ - - } else if ((sc_interp_get_frame(scin) != NULL) - && check_outputs(bl, scin, ss) ) { - /* Block handled as output thing */ - - } else if ( name == NULL ) { - /* Dummy to ensure name != NULL below */ - - } else if ( strcmp(name, "presentation") == 0 ) { - maybe_recurse_before(scin, child); - apply_style(scin, ss, "$.narrative"); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "slide") == 0 ) { - maybe_recurse_before(scin, child); - apply_style(scin, ss, "$.slide"); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "font") == 0 ) { - maybe_recurse_before(scin, child); - set_font(scin, options); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "fontsize") == 0 ) { - maybe_recurse_before(scin, child); - set_fontsize(scin, options); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "bold") == 0 ) { - maybe_recurse_before(scin, child); - set_bold(scin); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "oblique") == 0 ) { - maybe_recurse_before(scin, child); - set_oblique(scin); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "italic") == 0 ) { - maybe_recurse_before(scin, child); - set_italic(scin); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "lalign") == 0 ) { - maybe_recurse_before(scin, child); - set_alignment(scin, PANGO_ALIGN_LEFT); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "ralign") == 0 ) { - maybe_recurse_before(scin, child); - set_alignment(scin, PANGO_ALIGN_RIGHT); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "center") == 0 ) { - maybe_recurse_before(scin, child); - set_alignment(scin, PANGO_ALIGN_CENTER); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "fgcol") == 0 ) { - maybe_recurse_before(scin, child); - set_colour(scin, options); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "pad") == 0 ) { - maybe_recurse_before(scin, child); - set_padding(sc_interp_get_frame(scin), options); - maybe_recurse_after(scin, child, ss); - - } else if ( strcmp(name, "bgcol") == 0 ) { - set_bgcol(scin, options); - - } else if ( strcmp(name, "bggradh") == 0 ) { - set_bggrad(scin, options, GRAD_HORIZ); - - } else if ( strcmp(name, "bggradv") == 0 ) { - set_bggrad(scin, options, GRAD_VERT); - - } else if ( strcmp(name, "paraspace") == 0 ) { - maybe_recurse_before(scin, child); - set_paraspace(scin, options); - maybe_recurse_after(scin, child, ss); - - } else { - - fprintf(stderr, "Don't know what to do with this:\n"); - show_sc_block(bl, ""); - - } - - return 0; -} - diff --git a/src-old/sc_interp.h b/src-old/sc_interp.h deleted file mode 100644 index 764b532..0000000 --- a/src-old/sc_interp.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * sc_interp.h - * - * Copyright © 2014-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef SC_INTERP_H -#define SC_INTERP_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <pango/pangocairo.h> - -struct frame; - -#define SCCONST_SLIDENUMBER (0) -#define NUM_SC_CONSTANTS (1) - -struct presentation; -typedef struct _scinterp SCInterpreter; -typedef struct _sccallbacklist SCCallbackList; -typedef int (*SCCallbackBoxFunc)(SCInterpreter *scin, SCBlock *bl, - double *w, double *h, void **, void *); -typedef cairo_surface_t *(*SCCallbackDrawFunc)(int w, int h, void *, void *); -typedef int (*SCCallbackClickFunc)(double x, double y, void *, void *); - -#include "frame.h" -#include "imagestore.h" -#include "stylesheet.h" - -extern SCInterpreter *sc_interp_new(PangoContext *pc, PangoLanguage *lang, - ImageStore *is, struct frame *top); -extern void sc_interp_destroy(SCInterpreter *scin); - -extern void sc_interp_save(SCInterpreter *scin); -extern void sc_interp_restore(SCInterpreter *scin); - -extern int sc_interp_add_block(SCInterpreter *scin, SCBlock *bl, Stylesheet *ss); - -extern void sc_interp_set_constant(SCInterpreter *scin, unsigned int constant, - const char *val); - -/* Callback lists */ -extern SCCallbackList *sc_callback_list_new(); -extern void sc_callback_list_free(SCCallbackList *cbl); -extern void sc_callback_list_add_callback(SCCallbackList *cbl, const char *name, - SCCallbackBoxFunc box_func, - SCCallbackDrawFunc draw_func, - SCCallbackClickFunc click_func, - void *vp); -extern void sc_interp_set_callbacks(SCInterpreter *scin, SCCallbackList *cbl); - -/* Get the current state of the interpreter */ -extern struct frame *sc_interp_get_frame(SCInterpreter *scin); -extern PangoFont *sc_interp_get_font(SCInterpreter *scin); -extern PangoFontDescription *sc_interp_get_fontdesc(SCInterpreter *scin); -extern double *sc_interp_get_fgcol(SCInterpreter *scin); - -extern void update_geom(struct frame *fr); - - -#endif /* SC_INTERP_H */ diff --git a/src-old/sc_parse.c b/src-old/sc_parse.c deleted file mode 100644 index 78f5799..0000000 --- a/src-old/sc_parse.c +++ /dev/null @@ -1,856 +0,0 @@ -/* - * sc_parse.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <ctype.h> -#include <glib.h> -#include <gio/gio.h> - -#include "sc_parse.h" -#include "utils.h" - -struct _scblock -{ - char *name; - char *options; - char *contents; - - SCBlock *next; - SCBlock *child; -}; - - -SCBlock *sc_block_new() -{ - SCBlock *bl; - - bl = calloc(1, sizeof(SCBlock)); - if ( bl == NULL ) return NULL; - - return bl; -} - - -SCBlock *sc_block_next(const SCBlock *bl) -{ - assert(bl != NULL); - return bl->next; -} - - -SCBlock *sc_block_child(const SCBlock *bl) -{ - return bl->child; -} - - -const char *sc_block_name(const SCBlock *bl) -{ - return bl->name; -} - - -const char *sc_block_options(const SCBlock *bl) -{ - return bl->options; -} - - -const char *sc_block_contents(const SCBlock *bl) -{ - return bl->contents; -} - - -static SCBlock *sc_find_previous(SCBlock *top, SCBlock *find) -{ - if ( top->next == find ) return top; - - if ( top->child != NULL ) { - SCBlock *t = sc_find_previous(top->child, find); - if ( t != NULL ) return t; - } - if ( top->next != NULL ) { - SCBlock *t = sc_find_previous(top->next, find); - if ( t != NULL ) return t; - } - return NULL; -} - - -/* Add a new block before "bl" */ -SCBlock *sc_block_prepend(SCBlock *bl, SCBlock *top) -{ - SCBlock *bln; - SCBlock *prev; - - prev = sc_find_previous(top, bl); - if ( prev == NULL ) { - fprintf(stderr, "Couldn't find previous\n"); - return NULL; - } - - bln = sc_block_new(); - if ( bln == NULL ) return NULL; - - prev->next = bln; - bln->next = bl; - return bln; -} - - -/* Append "bln" after "bl" */ -void sc_block_append_p(SCBlock *bl, SCBlock *bln) -{ - if ( bl != NULL ) { - bln->next = bl->next; - bl->next = bln; - } -} - - -/* Insert a new block after "bl". "name", "options" and "contents" - * will not be copied. Returns the block just created, or NULL on error. - * If *blfp points to NULL, it will updated to point at the new block. */ -SCBlock *sc_block_append(SCBlock *bl, char *name, char *opt, char *contents, - SCBlock **blfp) -{ - SCBlock *bln = sc_block_new(); - - if ( bln == NULL ) return NULL; - - bln->name = name; - bln->options = opt; - bln->contents = contents; - bln->child = NULL; - bln->next = NULL; - - sc_block_append_p(bl, bln); - - if ( (blfp != NULL) && (*blfp == NULL) ) { - *blfp = bln; - } - - return bln; -} - - -/* Insert a new block at the end of the chain starting 'bl'. - * "name", "options" and "contents" will not be copied. Returns the block just - * created, or NULL on error. */ -SCBlock *sc_block_append_end(SCBlock *bl, char *name, char *opt, char *contents) -{ - SCBlock *bln = sc_block_new(); - - if ( bln == NULL ) return NULL; - - while ( bl->next != NULL ) { - bln->next = bl->next; - bl = bl->next; - }; - - return sc_block_append(bl, name, opt, contents, NULL); -} - - -void sc_block_append_block(SCBlock *bl, SCBlock *bln) -{ - - if ( bl == NULL ) return; - - while ( bl->next != NULL ) bl = bl->next; - - bl->next = bln; - bln->next = NULL; -} - - -/* Append a new block to the chain inside "parent". - * "name", "options" and "contents" will not be copied. Returns the block just - * created, or NULL on error. */ -SCBlock *sc_block_append_inside(SCBlock *parent, - char *name, char *opt, char *contents) -{ - SCBlock *bln; - SCBlock *bl; - SCBlock **ptr; - - bl = parent->child; - if ( bl != NULL ) { - while ( bl->next != NULL ) bl = bl->next; - ptr = &bl->next; - } else { - ptr = &parent->child; - } - - bln = sc_block_new(); - if ( bln == NULL ) return NULL; - - bln->name = name; - bln->options = opt; - bln->contents = contents; - bln->child = NULL; - bln->next = NULL; - - *ptr = bln; - - return bln; -} - - -/* Insert a new block to the chain, just after "afterme". - * "name", "options" and "contents" will not be copied. Returns the block just - * created, or NULL on error. */ -SCBlock *sc_block_insert_after(SCBlock *afterme, - char *name, char *opt, char *contents) -{ - SCBlock *bl; - - bl = sc_block_new(); - if ( bl == NULL ) return NULL; - - bl->name = name; - bl->options = opt; - bl->contents = contents; - bl->child = NULL; - bl->next = afterme->next; - afterme->next = bl; - - return bl; -} - - -static SCBlock *sc_find_parent(SCBlock *top, SCBlock *find) -{ - if ( top->child == find ) return top; - if ( top->next == find ) return top; - - if ( top->child != NULL ) { - SCBlock *t = sc_find_parent(top->child, find); - if ( t != NULL ) return t; - } - if ( top->next != NULL ) { - SCBlock *t = sc_find_parent(top->next, find); - if ( t != NULL ) return t; - } - return NULL; -} - - -/* Unlink "deleteme", which is somewhere under "top" */ -static int sc_block_unlink(SCBlock **top, SCBlock *deleteme) -{ - SCBlock *parent = sc_find_parent(*top, deleteme); - if ( parent == NULL ) { - /* Maybe it's the first block? */ - if ( *top == deleteme ) { - fprintf(stderr, "Unlinking at top\n"); - *top = (*top)->next; - return 0; - } else { - fprintf(stderr, "Couldn't find block parent!\n"); - return 1; - } - } - - if ( parent->next == deleteme ) { - parent->next = deleteme->next; - } - - if ( parent->child == deleteme ) { - parent->child = deleteme->next; - } - return 0; -} - - -/* Delete "deleteme", which is somewhere under "top" */ -int sc_block_delete(SCBlock **top, SCBlock *deleteme) -{ - int r; - r = sc_block_unlink(top, deleteme); - if ( !r ) { - sc_block_free(deleteme); - } - return r; -} - - -/* Frees "bl" and all its children (but not the blocks following it) */ -void sc_block_free(SCBlock *bl) -{ - if ( bl == NULL ) return; - - if ( bl->child != NULL ) { - SCBlock *ch = bl->child; - while ( ch != NULL ) { - SCBlock *next = ch->next; - sc_block_free(ch); - ch = next; - } - } - - free(bl); -} - - -/* Serialise one block (including children) */ -char *serialise_sc_block(const SCBlock *bl) -{ - char *a; - SCBlock *ch; - size_t len = 3; - - if ( bl == NULL ) return strdup(""); - - if ( bl->name != NULL ) len += 1+strlen(bl->name); - if ( bl->options != NULL ) len += 2+strlen(bl->options); - if ( bl->contents != NULL ) len += 2+strlen(bl->contents); - a = malloc(len); - if ( a == NULL ) return NULL; - a[0] = '\0'; - - if ( bl->name == NULL ) { - strcat(a, bl->contents); - } else if ( strcmp(bl->name, "newpara") == 0 ) { - strcat(a, "\n"); - - } else { - - strcat(a, "\\"); - strcat(a, bl->name); - if ( bl->options != NULL ) { - strcat(a, "["); - strcat(a, bl->options); - strcat(a, "]"); - } - if ( (bl->contents != NULL) || (bl->child != NULL) ) { - strcat(a, "{"); - } - if ( bl->contents != NULL ) { - strcat(a, bl->contents); - } - - /* Special case to prevent "\somethingSome text" */ - if ( (bl->name != NULL) && (bl->options == NULL) - && (bl->contents == NULL) && (bl->next != NULL) - && (bl->next->name == NULL) && (bl->child == NULL) ) - { - strcat(a, "{}"); - } - - } - - /* Add ALL child blocks of this one */ - ch = bl->child; - while ( ch != NULL ) { - - char *anew; - char *c = serialise_sc_block(ch); - if ( c == NULL ) { - free(a); - return NULL; - } - - len += strlen(c); - - anew = realloc(a, len); - if ( anew == NULL ) { - return NULL; - } else { - a = anew; - } - - strcat(a, c); - free(c); - - ch = ch->next; - - } - - if ( (bl->name != NULL) && - ((bl->contents != NULL) || (bl->child != NULL)) ) { - strcat(a, "}"); - } - - return a; -} - - -int save_sc_block(GOutputStream *fh, const SCBlock *bl) -{ - while ( bl != NULL ) { - GError *error = NULL; - char *a = serialise_sc_block(bl); - gssize r; - if ( a == NULL ) { - fprintf(stderr, "Failed to serialise block\n"); - return 1; - } - r = g_output_stream_write(fh, a, strlen(a), NULL, &error); - if ( r == -1 ) { - fprintf(stderr, "Write failed: %s\n", error->message); - return 1; - } - free(a); - bl = bl->next; - } - return 0; -} - - -static void recursive_show_sc_blocks(const char *prefix, const SCBlock *bl) -{ - while ( bl != NULL ) { - show_sc_block(bl, prefix); - bl = bl->next; - } -} - - -void show_sc_block(const SCBlock *bl, const char *prefix) -{ - printf("%s (%p) ", prefix, bl); - if ( bl == NULL ) return; - if ( bl->name != NULL ) printf("\\%s ", bl->name); - if ( bl->options != NULL ) printf("[%s] ", bl->options); - if ( bl->contents != NULL ) printf("{%s} ", bl->contents); - printf("\n"); - - if ( bl->child != NULL ) { - char new_prefix[strlen(prefix)+3]; - strcpy(new_prefix, " "); - strcat(new_prefix, prefix); - recursive_show_sc_blocks(new_prefix, bl->child); - } -} - - -void show_sc_blocks(const SCBlock *bl) -{ - recursive_show_sc_blocks("", bl); -} - - -static int get_subexpr(const char *sc, char *bk, char **pcontents, int *err) -{ - size_t ml; - int i; - int bct = 1; - int found = 0; - char *contents; - - *err = 0; - - ml = strlen(sc); - contents = malloc(ml+1); - if ( contents == NULL ) { - *err = -1; - return 0; - } - *pcontents = contents; - - for ( i=0; i<ml; i++ ) { - if ( sc[i] == bk[0] ) { - bct++; - } else if ( sc[i] == bk[1] ) { - bct--; - } - if ( bct == 0 ) { - found = 1; - break; - } - contents[i] = sc[i]; - } - - if ( (!found) || (bct != 0) ) { - *err = 1; - return 0; - } - - contents[i] = '\0'; - return i+1; -} - - -static size_t read_block(const char *sc, char **pname, char **options, - char **contents, int *err) -{ - size_t l, i, j; - char *name; - int done; - - *err = 0; - - l = strlen(sc); - i = 0; j = 0; - name = malloc(l+1); - if ( name == NULL ) { - *err = 1; - return 0; - } - - done = 0; - do { - - char c = sc[i]; - - if ( isalnum(c) ) { - name[j++] = c; - i++; - } else { - /* Found the end of the name */ - done = 1; - } - - } while ( !done && (i<l) ); - - name[j] = '\0'; - *pname = name; - - if ( sc[i] == '[' ) { - - i += get_subexpr(sc+i+1, "[]", options, err) + 1; - if ( *err ) { - printf("Couldn't find end of options '%s'\n", sc+i); - return 0; - } - - } else { - *options = NULL; - } - - if ( sc[i] == '{' ) { - - i += get_subexpr(sc+i+1, "{}", contents, err) + 1; - if ( *err ) { - printf("Couldn't find end of content '%s'\n", sc+i); - return 0; - } - - } else { - *contents = NULL; - } - - return i+1; -} - - -static void separate_newlines(SCBlock *bl) -{ - while ( bl != NULL ) { - - const char *contents = sc_block_contents(bl); - - if ( contents != NULL ) { - char *npos = strchr(contents, '\n'); - if ( npos != NULL ) { - SCBlock *nb = NULL; - if ( npos == contents ) { - bl->name = strdup("newpara"); - bl->contents = NULL; - nb = bl; - } else { - sc_block_append(bl, strdup("newpara"), - NULL, NULL, &nb); - } - - /* Add any text after the \n */ - if ( strlen(npos+1) > 0 ) { - sc_block_append(nb, NULL, NULL, - strdup(npos+1), &nb); - } - npos[0] = '\0'; - } - } - - if ( sc_block_child(bl) != NULL ) { - separate_newlines(sc_block_child(bl)); - } - - bl = sc_block_next(bl); - - } -} - - -SCBlock *sc_parse(const char *sc) -{ - SCBlock *bl; - SCBlock *blf = NULL; - char *tbuf; - size_t len, i, j; - - if ( sc == NULL ) return NULL; - - if ( strlen(sc) == 0 ) { - SCBlock *bl = sc_block_new(); - sc_block_set_contents(bl, g_strdup("")); - return bl; - } - - bl = NULL; - - len = strlen(sc); - tbuf = malloc(len+1); - if ( tbuf == NULL ) { - sc_block_free(bl); - return NULL; - } - - i = 0; j = 0; - do { - - if ( sc[i] == '\\' ) { - - int err; - char *name = NULL; - char *opt = NULL; - char *contents = NULL; - - /* Is this an escaped backslash? */ - if ( sc[i+1] == '\\' ) { - tbuf[j++] = '\\'; - i += 2; /* Skip both backslashes */ - continue; - } - - /* No, it's a real block. Dispatch the previous block */ - if ( j != 0 ) { - tbuf[j] = '\0'; - bl = sc_block_append(bl, NULL, NULL, - strdup(tbuf), &blf); - if ( bl == NULL ) { - fprintf(stderr, "Block add failed.\n"); - sc_block_free(blf); - free(tbuf); - return NULL; - } - j = 0; - } - - i += read_block(sc+i+1, &name, &opt, &contents, &err); - if ( err ) { - printf(_("Parse error\n")); - sc_block_free(blf); - free(tbuf); - return NULL; - } - - bl = sc_block_append(bl, name, opt, contents, &blf); - if ( bl == NULL ) { - fprintf(stderr, "Block add failed.\n"); - sc_block_free(blf); - free(tbuf); - return NULL; - } - bl->child = sc_parse(contents); - free(bl->contents); - bl->contents = NULL; - - } else { - - tbuf[j++] = sc[i++]; - } - - } while ( i<len ); - - /* Add final block, if it exists */ - if ( j > 0 ) { - - /* Leftover buffer is empty? */ - if ( (j==1) && (tbuf[0]=='\0') ) return bl; - - tbuf[j] = '\0'; - bl = sc_block_append(bl, NULL, NULL, tbuf, &blf); - if ( bl == NULL ) { - fprintf(stderr, "Block add failed.\n"); - sc_block_free(blf); - free(tbuf); - return NULL; - } - j = 0; - } - - separate_newlines(blf); - - return blf; -} - - -void sc_block_set_name(SCBlock *bl, char *nam) -{ - if ( bl == NULL ) { - fprintf(stderr, "sc_block_set_name: NULL block\n"); - return; - } - free(bl->name); - bl->name = nam; -} - - -void sc_block_set_options(SCBlock *bl, char *opt) -{ - free(bl->options); - bl->options = opt; -} - - -void sc_block_set_contents(SCBlock *bl, char *con) -{ - g_free(bl->contents); - bl->contents = con; -} - - -void sc_insert_text(SCBlock *b1, size_t o1, const char *t) -{ - size_t len; - char *cnew; - char *tmp; - char *p1; - - if ( b1->contents == NULL ) { - b1->contents = strdup(t); - return; - } - len = strlen(b1->contents)+1+strlen(t); - - cnew = realloc(b1->contents, len); - if ( cnew == NULL ) return; - - tmp = malloc(len); - if ( tmp == NULL ) { - free(cnew); - return; - } - - p1 = cnew + o1; - strcpy(tmp, p1); - strcpy(p1, t); - strcpy(p1+strlen(t), tmp); - free(tmp); - b1->contents = cnew; -} - - -void sc_insert_block(SCBlock *b1, int o1, SCBlock *ins) -{ - SCBlock *second; - char *p1 = g_utf8_offset_to_pointer(b1->contents, o1); - - /* Create a new block containing the second half of b1 */ - second = sc_block_new(); - sc_block_set_contents(second, g_strdup(p1)); - - /* Chop off b1 at the insertion point */ - sc_block_set_contents(b1, g_utf8_substring(b1->contents, 0, o1)); - - /* Link the new block into the chain */ - SCBlock *old_next = b1->next; - b1->next = ins; - ins->next = second; - second->next = old_next; -} - - -/* Delete text from SCBlock contents. o2=-1 means "to the end". - * Returns the number of bytes deleted. */ -size_t scblock_delete_text(SCBlock *b, ssize_t o1, ssize_t o2) -{ - size_t len; - - if ( b->contents == NULL ) { - fprintf(stderr, "Deleting text from block \\%s\n", b->name); - return 0; - } - - if ( (o2 != -1) && (o1 > o2) ) { - ssize_t t = o2; - o2 = o1; - o1 = t; - } - - len = strlen(b->contents); - if ( o2 < 0 ) o2 = len; - if ( (o1 >= o2) || (o1 > len) || (o2 > len) ) { - fprintf(stderr, "Invalid delete: %i %i %i\n", - (int)o1, (int)o2, (int)len); - return 0; - } - memmove(b->contents+o1, b->contents+o2, len-o2+1); - - return o2-o1; -} - - -static char *s_strdup(const char *a) -{ - if ( a == NULL ) return NULL; - return strdup(a); -} - - -SCBlock *sc_block_split(SCBlock *bl, size_t pos) -{ - SCBlock *n = sc_block_new(); - - if ( bl->child != NULL ) { - fprintf(stderr, "Splitting a block with a child!\n"); - return NULL; - } - - /* Second block */ - n->name = s_strdup(bl->name); - n->options = s_strdup(bl->options); - if ( bl->contents != NULL ) { - n->contents = strdup(bl->contents+pos); - /* Truncate the first block */ - bl->contents[pos] = '\0'; - } else { - n->contents = NULL; - } - - n->next = bl->next; - bl->next = n; - - return n; -} - - -/* Return a new block which is the parent for "bl" */ -SCBlock *sc_block_new_parent(SCBlock *bl, const char *name) -{ - SCBlock *n = sc_block_new(); - if ( n == NULL ) return NULL; - n->name = s_strdup(name); - n->child = bl; - return n; -} diff --git a/src-old/sc_parse.h b/src-old/sc_parse.h deleted file mode 100644 index 17ce2dd..0000000 --- a/src-old/sc_parse.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * sc_parse.h - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef SC_PARSE_H -#define SC_PARSE_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <gio/gio.h> - -typedef struct _scblock SCBlock; - -extern SCBlock *sc_parse(const char *sc); - -extern SCBlock *sc_block_new(void); -extern void sc_block_free(SCBlock *bl); - -extern SCBlock *sc_block_next(const SCBlock *bl); -extern SCBlock *sc_block_child(const SCBlock *bl); -extern const char *sc_block_name(const SCBlock *bl); -extern const char *sc_block_options(const SCBlock *bl); -extern const char *sc_block_contents(const SCBlock *bl); - -extern SCBlock *sc_block_append(SCBlock *bl, - char *name, char *opt, char *contents, - SCBlock **blfp); - -extern SCBlock *sc_block_new_parent(SCBlock *bl, const char *name); - -extern SCBlock *sc_block_prepend(SCBlock *bl, SCBlock *top); - -extern void sc_block_append_p(SCBlock *bl, SCBlock *bln); - -extern void sc_block_append_block(SCBlock *bl, SCBlock *bln); - -extern SCBlock *sc_block_append_end(SCBlock *bl, - char *name, char *opt, char *contents); - -extern SCBlock *sc_block_append_inside(SCBlock *parent, - char *name, char *opt, char *contents); - -extern SCBlock *sc_block_insert_after(SCBlock *afterme, - char *name, char *opt, char *contents); - -extern int sc_block_delete(SCBlock **top, SCBlock *deleteme); - - -extern void sc_block_set_name(SCBlock *bl, char *nam); -extern void sc_block_set_options(SCBlock *bl, char *opt); -extern void sc_block_set_contents(SCBlock *bl, char *con); -extern void sc_insert_text(SCBlock *b1, size_t o1, const char *t); -extern void sc_insert_block(SCBlock *b1, int o1, SCBlock *ins); -extern SCBlock *sc_block_split(SCBlock *bl, size_t pos); - -extern void show_sc_blocks(const SCBlock *bl); -extern void show_sc_block(const SCBlock *bl, const char *prefix); - -extern char *serialise_sc_block(const SCBlock *bl); -extern int save_sc_block(GOutputStream *fh, const SCBlock *bl); - -extern size_t scblock_delete_text(SCBlock *b, ssize_t o1, ssize_t o2); - -#endif /* SC_PARSE_H */ diff --git a/src-old/slide_window.c b/src-old/slide_window.c deleted file mode 100644 index ed37a50..0000000 --- a/src-old/slide_window.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * slide_window.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <gtk/gtk.h> -#include <assert.h> -#include <gdk/gdkkeysyms.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <math.h> - -#include "colloquium.h" -#include "presentation.h" -#include "slide_window.h" -#include "render.h" -#include "frame.h" -#include "slideshow.h" -#include "pr_clock.h" -#include "sc_parse.h" -#include "sc_interp.h" -#include "sc_editor.h" -#include "utils.h" - - -struct _slidewindow -{ - struct presentation *p; - GtkWidget *window; - GtkToolItem *bfirst; - GtkToolItem *bprev; - GtkToolItem *bnext; - GtkToolItem *blast; - - /* The slide being displayed. Note that the SCEditor is using the - * child of this block, but we need to keep a record of it for changing - * the slide. */ - SCBlock *scblocks; - - SCEditor *sceditor; -}; - - -static void insert_slidetitle_sig(GSimpleAction *action, GVariant *parameter, - gpointer vp) -{ - SlideWindow *sw = vp; - sc_editor_add_storycode(sw->sceditor, "\\slidetitle{Slide title}"); -} - - -static void paste_sig(GSimpleAction *action, GVariant *parameter, - gpointer vp) -{ - SlideWindow *sw = vp; - sc_editor_paste(sw->sceditor); -} - - -static void copy_frame_sig(GSimpleAction *action, GVariant *parameter, - gpointer vp) -{ - SlideWindow *sw = vp; - sc_editor_copy_selected_frame(sw->sceditor); -} - - -static void delete_frame_sig(GSimpleAction *action, GVariant *parameter, - gpointer vp) -{ - SlideWindow *sw = vp; - sc_editor_delete_selected_frame(sw->sceditor); -} - - -void slide_window_update(SlideWindow *sw) -{ - sc_editor_set_scblock(sw->sceditor, sw->scblocks); -} - - -/* Change the editor's slide to "np" */ -static void change_edit_slide(SlideWindow *sw, SCBlock *np) -{ - sc_editor_set_slidenum(sw->sceditor, slide_number(sw->p, np)); - sc_editor_set_scblock(sw->sceditor, np); - sw->scblocks = np; -} - - -static void change_slide_first(SlideWindow *sw) -{ - change_edit_slide(sw, first_slide(sw->p)); -} - - -static void change_slide_backwards(SlideWindow *sw) -{ - SCBlock *tt; - tt = prev_slide(sw->p, sw->scblocks); - if ( tt == NULL ) return; - change_edit_slide(sw, tt); -} - - -static void change_slide_forwards(SlideWindow *sw) -{ - SCBlock *tt; - tt = next_slide(sw->p, sw->scblocks); - if ( tt == NULL ) return; - change_edit_slide(sw, tt); -} - - -static void change_slide_last(SlideWindow *sw) -{ - change_edit_slide(sw, last_slide(sw->p)); -} - - -static void first_slide_sig(GSimpleAction *action, GVariant *parameter, - gpointer vp) -{ - SlideWindow *sw = vp; - change_slide_first(sw); -} - - -static void prev_slide_sig(GSimpleAction *action, GVariant *parameter, - gpointer vp) -{ - SlideWindow *sw = vp; - change_slide_backwards(sw); -} - - -static void next_slide_sig(GSimpleAction *action, GVariant *parameter, - gpointer vp) -{ - SlideWindow *sw = vp; - change_slide_forwards(sw); -} - - -static void last_slide_sig(GSimpleAction *action, GVariant *parameter, - gpointer vp) -{ - SlideWindow *sw = vp; - change_slide_last(sw); -} - - -static gboolean sw_close_sig(GtkWidget *w, SlideWindow *sw) -{ - narrative_window_sw_closed(sw->p->narrative_window, sw); - return FALSE; -} - - -static gboolean sw_key_press_sig(GtkWidget *da, GdkEventKey *event, - SlideWindow *sw) -{ - switch ( event->keyval ) { - - case GDK_KEY_Page_Up : - change_slide_backwards(sw); - break; - - case GDK_KEY_Page_Down : - change_slide_forwards(sw); - break; - - } - - return FALSE; -} - - -static void about_sig(GSimpleAction *action, GVariant *parameter, gpointer vp) -{ - SlideWindow *sw = vp; - open_about_dialog(sw->window); -} - - -GActionEntry sw_entries[] = { - - { "about", about_sig, NULL, NULL, NULL }, - { "paste", paste_sig, NULL, NULL, NULL }, - { "copyframe", copy_frame_sig, NULL, NULL, NULL }, - { "deleteframe", delete_frame_sig, NULL, NULL, NULL }, - { "first", first_slide_sig, NULL, NULL, NULL }, - { "prev", prev_slide_sig, NULL, NULL, NULL }, - { "next", next_slide_sig, NULL, NULL, NULL }, - { "last", last_slide_sig, NULL, NULL, NULL }, - { "slidetitle", insert_slidetitle_sig, NULL, NULL, NULL }, -}; - - -SlideWindow *slide_window_open(struct presentation *p, SCBlock *scblocks, - GApplication *papp) -{ - GtkWidget *window; - SlideWindow *sw; - Colloquium *app = COLLOQUIUM(papp); - - sw = calloc(1, sizeof(SlideWindow)); - if ( sw == NULL ) return NULL; - - window = gtk_application_window_new(GTK_APPLICATION(app)); - gtk_window_set_role(GTK_WINDOW(window), "slide"); - sw->window = window; - sw->p = p; - - g_action_map_add_action_entries(G_ACTION_MAP(window), sw_entries, - G_N_ELEMENTS(sw_entries), sw); - - g_signal_connect(G_OBJECT(window), "destroy", - G_CALLBACK(sw_close_sig), sw); - - sw->scblocks = scblocks; - sw->sceditor = sc_editor_new(scblocks, p->stylesheet, p->lang, - colloquium_get_imagestore(app)); - sc_editor_set_slidenum(sw->sceditor, slide_number(sw->p, scblocks)); - sc_editor_set_scale(sw->sceditor, 1); - sc_editor_set_imagestore(sw->sceditor, p->is); - -// scroll = gtk_scrolled_window_new(NULL, NULL); -// gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), -// GTK_POLICY_AUTOMATIC, -// GTK_POLICY_AUTOMATIC); -// gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(sw->sceditor)); -// gtk_window_set_focus(GTK_WINDOW(window), GTK_WIDGET(sw->sceditor)); - g_signal_connect(G_OBJECT(sw->sceditor), "key-press-event", - G_CALLBACK(sw_key_press_sig), sw); - - sc_editor_set_logical_size(sw->sceditor, - p->slide_width, p->slide_height); - - gtk_window_set_default_size(GTK_WINDOW(window), - p->slide_width, p->slide_height); - - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(sw->sceditor)); - - /* Default size */ -// gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(scroll), -// 1024); -// gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll), -// 768); - gtk_window_set_resizable(GTK_WINDOW(sw->window), TRUE); - - gtk_widget_show_all(window); -// gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(scroll), -// 100); -// gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll), -// 100); - - return sw; -} diff --git a/src-old/slide_window.h b/src-old/slide_window.h deleted file mode 100644 index 681ec39..0000000 --- a/src-old/slide_window.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * slide_window.h - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef SLIDEWINDOW_H -#define SLIDEWINDOW_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -typedef struct _slidewindow SlideWindow; - -extern SlideWindow *slide_window_open(struct presentation *p, SCBlock *scblocks, - GApplication *app); - -extern void slide_window_update(SlideWindow *sw); - -#endif /* SLIDEWINDOW_H */ diff --git a/src-old/stylesheet.c b/src-old/stylesheet.c deleted file mode 100644 index a6e2531..0000000 --- a/src-old/stylesheet.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * stylesheet.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <json-glib/json-glib.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <gio/gio.h> -#include <gdk/gdk.h> - -#include "stylesheet.h" -#include "utils.h" - - -struct _stylesheet { - JsonNode *root; -}; - - -static int find_comma(const char *a) -{ - int i = 0; - int in_brackets = 0; - size_t len = strlen(a); - - do { - if ( (a[i] == ',') && !in_brackets ) return i; - if ( a[i] == '(' ) in_brackets++; - if ( a[i] == ')' ) in_brackets--; - i++; - } while ( i < len ); - return 0; -} - - -int parse_colour_duo(const char *a, GdkRGBA *col1, GdkRGBA *col2) -{ - char *acopy; - int cpos; - - acopy = strdup(a); - if ( acopy == NULL ) return 1; - - cpos = find_comma(acopy); - if ( cpos == 0 ) { - fprintf(stderr, _("Invalid background gradient '%s'\n"), a); - return 1; - } - - acopy[cpos] = '\0'; - - if ( gdk_rgba_parse(col1, acopy) != TRUE ) { - fprintf(stderr, _("Failed to parse colour: %s\n"), acopy); - } - if ( gdk_rgba_parse(col2, &acopy[cpos+1]) != TRUE ) { - fprintf(stderr, _("Failed to parse colour: %s\n"), &acopy[cpos+1]); - } - - free(acopy); - return 0; -} - - -Stylesheet *stylesheet_load(GFile *file) -{ - JsonParser *parser; - gboolean r; - GError *err = NULL; - Stylesheet *ss; - char *everything; - gsize len; - - printf("Trying stylesheet '%s'\n", g_file_get_uri(file)); - - ss = calloc(1, sizeof(Stylesheet)); - if ( ss == NULL ) return NULL; - - parser = json_parser_new(); - - if ( !g_file_load_contents(file, NULL, &everything, &len, NULL, NULL) ) { - fprintf(stderr, _("Failed to load stylesheet '%s'\n"), - g_file_get_uri(file)); - free(ss); - return NULL; - } - - r = json_parser_load_from_data(parser, everything, len, &err); - if ( r == FALSE ) { - fprintf(stderr, _("Failed to load stylesheet: %s\n"), - err->message); - free(ss); - return NULL; - } - - ss->root = json_parser_steal_root(parser); - g_object_unref(parser); - - return ss; -} - - -static JsonObject *find_stylesheet_object(Stylesheet *ss, const char *path, - JsonNode **freeme) -{ - JsonNode *node; - JsonObject *obj; - JsonArray *array; - GError *err = NULL; - - node = json_path_query(path, ss->root, &err); - array = json_node_get_array(node); - - if ( json_array_get_length(array) == 0 ) { - json_node_unref(node); - return NULL; - } - - if ( json_array_get_length(array) > 1 ) { - json_node_unref(node); - fprintf(stderr, "More than one result in SS lookup (%s)!\n", path); - return NULL; - } - - obj = json_array_get_object_element(array, 0); - if ( obj == NULL ) { - printf("%s not a JSON object\n", path); - json_node_unref(node); - return NULL; - } - - *freeme = node; - return obj; -} - - -char *stylesheet_lookup(Stylesheet *ss, const char *path, const char *key) -{ - JsonObject *obj; - char *ret = NULL; - JsonNode *node = NULL; - - if ( ss == NULL ) { - fprintf(stderr, "No stylesheet!\n"); - return NULL; - } - - obj = find_stylesheet_object(ss, path, &node); - if ( obj == NULL ) return NULL; - - if ( json_object_has_member(obj, key) ) { - - const gchar *v; - v = json_object_get_string_member(obj, key); - if ( v != NULL ) { - ret = strdup(v); - } else { - fprintf(stderr, "Error retrieving %s.%s\n", path, key); - } - - } /* else not found, too bad */ - - if ( node != NULL ) json_node_unref(node); - return ret; -} - - -int stylesheet_set(Stylesheet *ss, const char *path, const char *key, - const char *new_val) -{ - JsonObject *obj; - JsonNode *node = NULL; - int r = 1; - - if ( ss == NULL ) { - fprintf(stderr, "No stylesheet!\n"); - return 1; - } - - obj = find_stylesheet_object(ss, path, &node); - if ( obj != NULL ) { - json_object_set_string_member(obj, key, new_val); - r = 0; - } /* else most likely the object (e.g. "$.slide", "$.slide.frame", - * "$.narrative" etc doesn't exist */ - - if ( node != NULL ) json_node_unref(node); - return r; -} - - -int stylesheet_delete(Stylesheet *ss, const char *path, const char *key) -{ - JsonObject *obj; - JsonNode *node = NULL; - int r = 1; - - if ( ss == NULL ) { - fprintf(stderr, "No stylesheet!\n"); - return 1; - } - - obj = find_stylesheet_object(ss, path, &node); - if ( obj != NULL ) { - json_object_remove_member(obj, key); - r = 0; - } /* else most likely the object (e.g. "$.slide", "$.slide.frame", - * "$.narrative" etc doesn't exist */ - - if ( node != NULL ) json_node_unref(node); - return r; -} - - -void stylesheet_free(Stylesheet *ss) -{ - json_node_unref(ss->root); - free(ss); -} - - -int stylesheet_save(Stylesheet *ss, GFile *file) -{ - JsonGenerator *gen; - GError *error = NULL; - GFileOutputStream *fh; - - fh = g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error); - if ( fh == NULL ) { - fprintf(stderr, _("Open failed: %s\n"), error->message); - return 1; - } - - gen = json_generator_new(); - json_generator_set_root(gen, ss->root); - json_generator_set_pretty(gen, TRUE); - json_generator_set_indent(gen, 1); - json_generator_set_indent_char(gen, '\t'); - if ( !json_generator_to_stream(gen, G_OUTPUT_STREAM(fh), NULL, &error) ) { - fprintf(stderr, _("Open failed: %s\n"), error->message); - return 1; - } - g_object_unref(fh); - return 0; -} - - -char *stylesheet_data(Stylesheet *ss) -{ - return json_to_string(ss->root, FALSE); -} - - -void stylesheet_set_data(Stylesheet *ss, const char *data) -{ - JsonNode *new_root; - GError *err = NULL; - new_root = json_from_string(data, &err); - if ( new_root == NULL ) { - fprintf(stderr, "Internal parse error: %s\n", err->message); - return; - } - json_node_unref(ss->root); - ss->root = new_root; -} diff --git a/src-old/stylesheet.h b/src-old/stylesheet.h deleted file mode 100644 index 16d0a0a..0000000 --- a/src-old/stylesheet.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * stylesheet.h - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef STYLESHEET_H -#define STYLESHEET_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gio/gio.h> -#include <gdk/gdk.h> - -typedef struct _stylesheet Stylesheet; - -extern Stylesheet *stylesheet_load(GFile *file); - -extern int stylesheet_save(Stylesheet *ss, GFile *file); - -extern char *stylesheet_data(Stylesheet *ss); - -extern void stylesheet_set_data(Stylesheet *ss, const char *data); - -extern int parse_colour_duo(const char *a, GdkRGBA *col1, GdkRGBA *col2); - -extern char *stylesheet_lookup(Stylesheet *ss, const char *path, const char *key); - -extern int stylesheet_set(Stylesheet *ss, const char *path, const char *key, - const char *new_val); - -extern int stylesheet_delete(Stylesheet *ss, const char *path, const char *key); - -extern void stylesheet_free(Stylesheet *ss); - -#endif /* STYLESHEET_H */ diff --git a/src-old/stylesheet_editor.c b/src-old/stylesheet_editor.c deleted file mode 100644 index 292bbf1..0000000 --- a/src-old/stylesheet_editor.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - * stylesheet_editor.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <gtk/gtk.h> - -#include "stylesheet_editor.h" -#include "presentation.h" -#include "sc_interp.h" -#include "stylesheet.h" -#include "utils.h" - - -G_DEFINE_TYPE_WITH_CODE(StylesheetEditor, stylesheet_editor, - GTK_TYPE_DIALOG, NULL) - - -struct _sspriv -{ - struct presentation *p; - const gchar *furniture; - char *ssdata; -}; - - -static void set_font_from_ss(Stylesheet *ss, const char *path, GtkWidget *w) -{ - char *result = stylesheet_lookup(ss, path, "font"); - if ( result != NULL ) { - gtk_font_button_set_font_name(GTK_FONT_BUTTON(w), result); - } -} - - -static void set_col_from_ss(Stylesheet *ss, const char *path, GtkWidget *w) -{ - char *result = stylesheet_lookup(ss, path, "fgcol"); - if ( result != NULL ) { - GdkRGBA rgba; - if ( gdk_rgba_parse(&rgba, result) == TRUE ) { - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(w), &rgba); - } - } -} - - -static void set_vals_from_ss(Stylesheet *ss, const char *path, const char *key, - GtkWidget *wl, GtkWidget *wr, - GtkWidget *wt, GtkWidget *wb) -{ - char *result = stylesheet_lookup(ss, path, key); - if ( result != NULL ) { - float v[4]; - if ( parse_tuple(result, v) == 0 ) { - gtk_spin_button_set_value(GTK_SPIN_BUTTON(wl), v[0]); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(wr), v[1]); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(wt), v[2]); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(wb), v[3]); - } else { - fprintf(stderr, _("Failed to parse quad: %s\n"), result); - } - } else { - printf("Not found %s.%s\n", path, key); - } -} - - -static void set_geom_from_ss(Stylesheet *ss, const char *path, const char *key, - GtkWidget *ww, GtkWidget *wh, - GtkWidget *wx, GtkWidget *wy, - GtkWidget *wwu, GtkWidget *whu) -{ - char *result = stylesheet_lookup(ss, path, key); - if ( result != NULL ) { - double x, y, w, h; - LengthUnits wu, hu; - if ( parse_dims(result, &w, &h, &wu, &hu, &x, &y) == 0 ) { - if ( wu == UNITS_FRAC ) { - w *= 100; - gtk_combo_box_set_active_id(GTK_COMBO_BOX(wwu), "percent"); - } else { - gtk_combo_box_set_active_id(GTK_COMBO_BOX(wwu), "units"); - } - if ( hu == UNITS_FRAC ) { - h *= 100; - gtk_combo_box_set_active_id(GTK_COMBO_BOX(whu), "percent"); - } else { - gtk_combo_box_set_active_id(GTK_COMBO_BOX(whu), "units"); - } - gtk_spin_button_set_value(GTK_SPIN_BUTTON(ww), w); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(wh), h); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(wx), x); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(wy), y); - } else { - fprintf(stderr, _("Failed to parse dims: %s\n"), result); - } - } else { - printf("Not found %s.%s\n", path, key); - } -} - -static void set_size_from_ss(Stylesheet *ss, const char *path, - GtkWidget *ww, GtkWidget *wh) -{ - char *result = stylesheet_lookup(ss, path, "size"); - if ( result != NULL ) { - float v[2]; - if ( parse_double(result, v) == 0 ) { - gtk_spin_button_set_value(GTK_SPIN_BUTTON(ww), v[0]); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(wh), v[1]); - } else { - fprintf(stderr, _("Failed to parse double: %s\n"), result); - } - } else { - printf("Not found %s.size\n", path); - } -} - - -static int alignment_ok(const char *a) -{ - if ( a == NULL ) return 0; - if ( strcmp(a, "left") == 0 ) return 1; - if ( strcmp(a, "center") == 0 ) return 1; - if ( strcmp(a, "right") == 0 ) return 1; - return 0; -} - - -static void set_alignment_from_ss(Stylesheet *ss, const char *path, - GtkWidget *d) -{ - char *result = stylesheet_lookup(ss, path, "alignment"); - if ( alignment_ok(result) ) { - gtk_combo_box_set_active_id(GTK_COMBO_BOX(d), result); - } -} - - -static void set_bg_from_ss(Stylesheet *ss, const char *path, GtkWidget *wcol, - GtkWidget *wcol2, GtkWidget *wgrad) -{ - char *result; - int found = 0; - - result = stylesheet_lookup(ss, path, "bgcol"); - if ( result != NULL ) { - GdkRGBA rgba; - found = 1; - if ( gdk_rgba_parse(&rgba, result) == TRUE ) { - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol), &rgba); - gtk_combo_box_set_active_id(GTK_COMBO_BOX(wgrad), "flat"); - gtk_widget_set_sensitive(wcol, TRUE); - gtk_widget_set_sensitive(wcol2, FALSE); - } else { - fprintf(stderr, _("Failed to parse colour: %s\n"), result); - } - } - - result = stylesheet_lookup(ss, path, "bggradv"); - if ( result != NULL ) { - GdkRGBA rgba1, rgba2; - found = 1; - if ( parse_colour_duo(result, &rgba1, &rgba2) == 0 ) { - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol), &rgba1); - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol2), &rgba2); - gtk_combo_box_set_active_id(GTK_COMBO_BOX(wgrad), "vert"); - gtk_widget_set_sensitive(wcol, TRUE); - gtk_widget_set_sensitive(wcol2, TRUE); - } - } - - result = stylesheet_lookup(ss, path, "bggradh"); - if ( result != NULL ) { - GdkRGBA rgba1, rgba2; - found = 1; - if ( parse_colour_duo(result, &rgba1, &rgba2) == 0 ) { - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol), &rgba1); - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol2), &rgba2); - gtk_combo_box_set_active_id(GTK_COMBO_BOX(wgrad), "horiz"); - gtk_widget_set_sensitive(wcol, TRUE); - gtk_widget_set_sensitive(wcol2, TRUE); - } - } - - if ( !found ) { - GdkRGBA rgba; - rgba.red = 1.0; - rgba.green = 1.0; - rgba.blue = 1.0; - rgba.alpha = 0.0; - gtk_combo_box_set_active_id(GTK_COMBO_BOX(wgrad), "flat"); - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(wcol), &rgba); - gtk_widget_set_sensitive(wcol, TRUE); - gtk_widget_set_sensitive(wcol2, FALSE); - } -} - - -static void set_furniture(StylesheetEditor *se, const char *furniture) -{ - set_geom_from_ss(se->priv->p->stylesheet, furniture, "geometry", - se->furniture_w, - se->furniture_h, - se->furniture_x, - se->furniture_y, - se->furniture_w_units, - se->furniture_h_units); - - set_vals_from_ss(se->priv->p->stylesheet, furniture, "pad", - se->furniture_padding_l, - se->furniture_padding_r, - se->furniture_padding_t, - se->furniture_padding_b); - - set_vals_from_ss(se->priv->p->stylesheet, furniture, "paraspace", - se->furniture_paraspace_l, - se->furniture_paraspace_r, - se->furniture_paraspace_t, - se->furniture_paraspace_b); - - set_font_from_ss(se->priv->p->stylesheet, furniture, se->furniture_font); - set_col_from_ss(se->priv->p->stylesheet, furniture, se->furniture_fgcol); - set_alignment_from_ss(se->priv->p->stylesheet, furniture, - se->furniture_alignment); - set_bg_from_ss(se->priv->p->stylesheet, furniture, se->furniture_bgcol, - se->furniture_bgcol2, se->furniture_bggrad); -} - - -static void set_values_from_presentation(StylesheetEditor *se) -{ - Stylesheet *ss = se->priv->p->stylesheet; - - /* Narrative */ - set_font_from_ss(ss, "$.narrative", se->narrative_style_font); - set_col_from_ss(ss, "$.narrative", se->narrative_style_fgcol); - set_alignment_from_ss(ss, "$.narrative", se->narrative_style_alignment); - set_bg_from_ss(ss, "$.narrative", se->narrative_style_bgcol, - se->narrative_style_bgcol2, - se->narrative_style_bggrad); - set_vals_from_ss(ss, "$.narrative", "pad", se->narrative_style_padding_l, - se->narrative_style_padding_r, - se->narrative_style_padding_t, - se->narrative_style_padding_b); - set_vals_from_ss(ss, "$.narrative", "paraspace", se->narrative_style_paraspace_l, - se->narrative_style_paraspace_r, - se->narrative_style_paraspace_t, - se->narrative_style_paraspace_b); - - /* Slides */ - set_size_from_ss(ss, "$.slide", se->slide_size_w, se->slide_size_h); - set_bg_from_ss(ss, "$.slide", se->slide_style_bgcol, - se->slide_style_bgcol2, - se->slide_style_bggrad); - - - /* Frames */ - set_font_from_ss(ss, "$.slide.frame", se->frame_style_font); - set_col_from_ss(ss, "$.slide.frame", se->frame_style_fgcol); - set_alignment_from_ss(ss, "$.slide.frame", se->frame_style_alignment); - set_bg_from_ss(ss, "$.slide.frame", se->frame_style_bgcol, - se->frame_style_bgcol2, - se->frame_style_bggrad); - set_vals_from_ss(ss, "$.slide.frame", "pad", se->frame_style_padding_l, - se->frame_style_padding_r, - se->frame_style_padding_t, - se->frame_style_padding_b); - set_vals_from_ss(ss, "$.slide.frame", "paraspace", se->frame_style_paraspace_l, - se->frame_style_paraspace_r, - se->frame_style_paraspace_t, - se->frame_style_paraspace_b); - - set_furniture(se, se->priv->furniture); -} - - -static GradientType id_to_gradtype(const gchar *id) -{ - assert(id != NULL); - if ( strcmp(id, "flat") == 0 ) return GRAD_NONE; - if ( strcmp(id, "horiz") == 0 ) return GRAD_HORIZ; - if ( strcmp(id, "vert") == 0 ) return GRAD_VERT; - return GRAD_NONE; -} - - -static void update_bg(struct presentation *p, const char *style_name, - GtkWidget *bggradw, GtkWidget *col1w, GtkWidget*col2w) -{ - GradientType g; - const gchar *id; - GdkRGBA rgba; - gchar *col1; - gchar *col2; - gchar *gradient; - - id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(bggradw)); - g = id_to_gradtype(id); - - gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(col1w), &rgba); - if ( rgba.alpha < 0.000001 ) rgba.alpha = 0.0; - col1 = gdk_rgba_to_string(&rgba); - - gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(col2w), &rgba); - col2 = gdk_rgba_to_string(&rgba); - - gradient = g_strconcat(col1, ",", col2, NULL); - - switch ( g ) { - - case GRAD_NONE : - stylesheet_set(p->stylesheet, style_name, "bgcol", - col1); - stylesheet_delete(p->stylesheet, style_name, "bggradv"); - stylesheet_delete(p->stylesheet, style_name, "bggradh"); - break; - - case GRAD_HORIZ : - stylesheet_set(p->stylesheet, style_name, "bggradh", - gradient); - stylesheet_delete(p->stylesheet, style_name, "bggradv"); - stylesheet_delete(p->stylesheet, style_name, "bgcol"); - break; - - case GRAD_VERT : - stylesheet_set(p->stylesheet, style_name, "bggradv", - gradient); - stylesheet_delete(p->stylesheet, style_name, "bggradh"); - stylesheet_delete(p->stylesheet, style_name, "bgcol"); - break; - - } - - g_free(gradient); - g_free(col1); - g_free(col2); -} - - -static void update_spacing(struct presentation *p, const char *style_name, - const char *key, GtkWidget *wl, GtkWidget *wr, - GtkWidget *wt, GtkWidget *wb) -{ - int v[4]; - char tmp[256]; - - v[0] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wl)); - v[1] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wr)); - v[2] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wt)); - v[3] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wb)); - - if ( snprintf(tmp, 256, "%i,%i,%i,%i", v[0], v[1], v[2], v[3]) >= 256 ) { - fprintf(stderr, "Spacing too long\n"); - } else { - stylesheet_set(p->stylesheet, style_name, key, tmp); - } -} - - -static char units_id_to_char(const char *id) -{ - if ( strcmp(id, "units") == 0 ) return 'u'; - if ( strcmp(id, "percent") == 0 ) return 'f'; - return 'u'; -} - - -static void update_ss_dims(struct presentation *p, const char *style_name, - const char *key, GtkWidget *ww, GtkWidget *wh, - GtkWidget *wx, GtkWidget *wy, - GtkWidget *wwu, GtkWidget *whu) -{ - float w, h, x, y; - char w_units, h_units; - const gchar *uid; - char tmp[256]; - - w = gtk_spin_button_get_value(GTK_SPIN_BUTTON(ww)); - h = gtk_spin_button_get_value(GTK_SPIN_BUTTON(wh)); - x = gtk_spin_button_get_value(GTK_SPIN_BUTTON(wx)); - y = gtk_spin_button_get_value(GTK_SPIN_BUTTON(wy)); - uid = gtk_combo_box_get_active_id(GTK_COMBO_BOX(wwu)); - w_units = units_id_to_char(uid); - uid = gtk_combo_box_get_active_id(GTK_COMBO_BOX(whu)); - h_units = units_id_to_char(uid); - - if ( w_units == 'f' ) w /= 100.0; - if ( h_units == 'f' ) h /= 100.0; - - if ( snprintf(tmp, 256, "%.2f%cx%.2f%c+%.0f+%0.f", - w, w_units, h, h_units, x, y) >= 256 ) - { - fprintf(stderr, "Spacing too long\n"); - } else { - stylesheet_set(p->stylesheet, style_name, key, tmp); - } -} - - -static void revert_sig(GtkButton *button, StylesheetEditor *se) -{ - stylesheet_set_data(se->priv->p->stylesheet, - se->priv->ssdata); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void set_font(GtkFontButton *widget, StylesheetEditor *se, - const char *style_name) -{ - const gchar *font; - font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget)); - - stylesheet_set(se->priv->p->stylesheet, style_name, "font", font); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void set_col(GtkColorButton *widget, StylesheetEditor *se, - const char *style_name, const char *col_name) -{ - GdkRGBA rgba; - gchar *col; - gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget), &rgba); - col = gdk_rgba_to_string(&rgba); - stylesheet_set(se->priv->p->stylesheet, style_name, "fgcol", col); - g_free(col); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void narrative_font_sig(GtkFontButton *widget, StylesheetEditor *se) -{ - set_font(widget, se, "$.narrative"); -} - - -static void narrative_fgcol_sig(GtkColorButton *widget, StylesheetEditor *se) -{ - set_col(widget, se, "$.narrative", "fgcol"); -} - - -static void narrative_bg_sig(GtkColorButton *widget, StylesheetEditor *se) -{ - update_bg(se->priv->p, "$.narrative", - se->narrative_style_bggrad, - se->narrative_style_bgcol, - se->narrative_style_bgcol2); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void narrative_alignment_sig(GtkComboBoxText *widget, StylesheetEditor *se) -{ - const gchar *id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(widget)); - stylesheet_set(se->priv->p->stylesheet, "$.narrative", "alignment", id); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void slide_size_sig(GtkSpinButton *widget, StylesheetEditor *se) -{ - int w, h; - char tmp[256]; - - w = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(se->slide_size_w)); - h = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(se->slide_size_h)); - - if ( snprintf(tmp, 256, "%ix%i", w, h) >= 256 ) { - fprintf(stderr, _("Slide size too long\n")); - } else { - stylesheet_set(se->priv->p->stylesheet, "$.slide", "size", tmp); - se->priv->p->slide_width = w; - se->priv->p->slide_height = h; - } - - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void slide_bg_sig(GtkColorButton *widget, StylesheetEditor *se) -{ - update_bg(se->priv->p, "$.slide", - se->slide_style_bggrad, - se->slide_style_bgcol, - se->slide_style_bgcol2); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void frame_font_sig(GtkFontButton *widget, StylesheetEditor *se) -{ - set_font(widget, se, "$.slide.frame"); -} - - -static void frame_fgcol_sig(GtkColorButton *widget, StylesheetEditor *se) -{ - set_col(widget, se, "$.slide.frame", "fgcol"); -} - - -static void frame_bg_sig(GtkColorButton *widget, StylesheetEditor *se) -{ - update_bg(se->priv->p, "$.slide.frame", - se->frame_style_bggrad, - se->frame_style_bgcol, - se->frame_style_bgcol2); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void frame_padding_sig(GtkSpinButton *widget, StylesheetEditor *se) -{ - update_spacing(se->priv->p, "$.slide.frame", "pad", - se->frame_style_padding_l, - se->frame_style_padding_r, - se->frame_style_padding_t, - se->frame_style_padding_b); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void frame_paraspace_sig(GtkSpinButton *widget, StylesheetEditor *se) -{ - update_spacing(se->priv->p, "$.slide.frame", "paraspace", - se->frame_style_paraspace_l, - se->frame_style_paraspace_r, - se->frame_style_paraspace_t, - se->frame_style_paraspace_b); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void frame_alignment_sig(GtkComboBoxText *widget, StylesheetEditor *se) -{ - const gchar *id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(widget)); - stylesheet_set(se->priv->p->stylesheet, "$.slide.frame", "alignment", id); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void narrative_padding_sig(GtkSpinButton *widget, StylesheetEditor *se) -{ - update_spacing(se->priv->p, "$.narrative", "pad", - se->narrative_style_padding_l, - se->narrative_style_padding_r, - se->narrative_style_padding_t, - se->narrative_style_padding_b); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void narrative_paraspace_sig(GtkSpinButton *widget, StylesheetEditor *se) -{ - update_spacing(se->priv->p, "$.narrative", "paraspace", - se->narrative_style_paraspace_l, - se->narrative_style_paraspace_r, - se->narrative_style_paraspace_t, - se->narrative_style_paraspace_b); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void furniture_selector_change_sig(GtkComboBoxText *widget, StylesheetEditor *se) -{ - se->priv->furniture = gtk_combo_box_get_active_id(GTK_COMBO_BOX(widget)); - set_furniture(se, se->priv->furniture); -} - - -static void furniture_font_sig(GtkFontButton *widget, StylesheetEditor *se) -{ - set_font(widget, se, se->priv->furniture); -} - - -static void furniture_fgcol_sig(GtkColorButton *widget, StylesheetEditor *se) -{ - set_col(widget, se,se->priv->furniture, "fgcol"); -} - - -static void furniture_bg_sig(GtkColorButton *widget, StylesheetEditor *se) -{ - update_bg(se->priv->p, se->priv->furniture, se->furniture_bggrad, - se->furniture_bgcol, se->furniture_bgcol2); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void furniture_paraspace_sig(GtkSpinButton *widget, StylesheetEditor *se) -{ - update_spacing(se->priv->p, se->priv->furniture, "pad", - se->furniture_padding_l, - se->furniture_padding_r, - se->furniture_padding_t, - se->furniture_padding_b); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void furniture_padding_sig(GtkSpinButton *widget, StylesheetEditor *se) -{ - update_spacing(se->priv->p, se->priv->furniture, "pad", - se->furniture_padding_l, - se->furniture_padding_r, - se->furniture_padding_t, - se->furniture_padding_b); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void furniture_alignment_sig(GtkComboBoxText *widget, StylesheetEditor *se) -{ - const gchar *id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(widget)); - stylesheet_set(se->priv->p->stylesheet, se->priv->furniture, - "alignment", id); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void furniture_dims_sig(GtkSpinButton *widget, StylesheetEditor *se) -{ - update_ss_dims(se->priv->p, se->priv->furniture, "geometry", - se->furniture_w, se->furniture_h, - se->furniture_x, se->furniture_y, - se->furniture_w_units, se->furniture_h_units); - set_values_from_presentation(se); - g_signal_emit_by_name(se, "changed"); -} - - -static void stylesheet_editor_finalize(GObject *obj) -{ - StylesheetEditor *se = COLLOQUIUM_STYLESHEET_EDITOR(obj); - free(se->priv->ssdata); - G_OBJECT_CLASS(stylesheet_editor_parent_class)->finalize(obj); -} - - -static void stylesheet_editor_init(StylesheetEditor *se) -{ - se->priv = G_TYPE_INSTANCE_GET_PRIVATE(se, COLLOQUIUM_TYPE_STYLESHEET_EDITOR, - StylesheetEditorPrivate); - gtk_widget_init_template(GTK_WIDGET(se)); -} - - -#define SE_BIND_CHILD(a, b) \ - gtk_widget_class_bind_template_child(widget_class, StylesheetEditor, a); \ - gtk_widget_class_bind_template_callback(widget_class, b); - -void stylesheet_editor_class_init(StylesheetEditorClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gtk_widget_class_set_template_from_resource(widget_class, - "/uk/me/bitwiz/Colloquium/stylesheeteditor.ui"); - - g_type_class_add_private(gobject_class, sizeof(StylesheetEditorPrivate)); - gobject_class->finalize = stylesheet_editor_finalize; - - /* Narrative style */ - SE_BIND_CHILD(narrative_style_font, narrative_font_sig); - SE_BIND_CHILD(narrative_style_fgcol, narrative_fgcol_sig); - SE_BIND_CHILD(narrative_style_bgcol, narrative_bg_sig); - SE_BIND_CHILD(narrative_style_bgcol2, narrative_bg_sig); - SE_BIND_CHILD(narrative_style_bggrad, narrative_bg_sig); - SE_BIND_CHILD(narrative_style_paraspace_l, narrative_paraspace_sig); - SE_BIND_CHILD(narrative_style_paraspace_r, narrative_paraspace_sig); - SE_BIND_CHILD(narrative_style_paraspace_t, narrative_paraspace_sig); - SE_BIND_CHILD(narrative_style_paraspace_b, narrative_paraspace_sig); - SE_BIND_CHILD(narrative_style_padding_l, narrative_padding_sig); - SE_BIND_CHILD(narrative_style_padding_r, narrative_padding_sig); - SE_BIND_CHILD(narrative_style_padding_t, narrative_padding_sig); - SE_BIND_CHILD(narrative_style_padding_b, narrative_padding_sig); - SE_BIND_CHILD(narrative_style_alignment, narrative_alignment_sig); - - /* Slide style */ - SE_BIND_CHILD(slide_size_w, slide_size_sig); - SE_BIND_CHILD(slide_size_h, slide_size_sig); - SE_BIND_CHILD(slide_style_bgcol, slide_bg_sig); - SE_BIND_CHILD(slide_style_bgcol2, slide_bg_sig); - SE_BIND_CHILD(slide_style_bggrad, slide_bg_sig); - - /* Slide->frame style */ - SE_BIND_CHILD(frame_style_font, frame_font_sig); - SE_BIND_CHILD(frame_style_fgcol, frame_fgcol_sig); - SE_BIND_CHILD(frame_style_bgcol, frame_bg_sig); - SE_BIND_CHILD(frame_style_bgcol2, frame_bg_sig); - SE_BIND_CHILD(frame_style_bggrad, frame_bg_sig); - SE_BIND_CHILD(frame_style_paraspace_l, frame_paraspace_sig); - SE_BIND_CHILD(frame_style_paraspace_r, frame_paraspace_sig); - SE_BIND_CHILD(frame_style_paraspace_t, frame_paraspace_sig); - SE_BIND_CHILD(frame_style_paraspace_b, frame_paraspace_sig); - SE_BIND_CHILD(frame_style_padding_l, frame_padding_sig); - SE_BIND_CHILD(frame_style_padding_r, frame_padding_sig); - SE_BIND_CHILD(frame_style_padding_t, frame_padding_sig); - SE_BIND_CHILD(frame_style_padding_b, frame_padding_sig); - SE_BIND_CHILD(frame_style_alignment, frame_alignment_sig); - - /* Furniture */ - SE_BIND_CHILD(furniture_selector, furniture_selector_change_sig); - SE_BIND_CHILD(furniture_paraspace_l, furniture_paraspace_sig); - SE_BIND_CHILD(furniture_paraspace_r, furniture_paraspace_sig); - SE_BIND_CHILD(furniture_paraspace_t, furniture_paraspace_sig); - SE_BIND_CHILD(furniture_paraspace_b, furniture_paraspace_sig); - SE_BIND_CHILD(furniture_padding_l, furniture_padding_sig); - SE_BIND_CHILD(furniture_padding_r, furniture_padding_sig); - SE_BIND_CHILD(furniture_padding_t, furniture_padding_sig); - SE_BIND_CHILD(furniture_padding_b, furniture_padding_sig); - SE_BIND_CHILD(furniture_font, furniture_font_sig); - SE_BIND_CHILD(furniture_fgcol, furniture_fgcol_sig); - SE_BIND_CHILD(furniture_bgcol, furniture_bg_sig); - SE_BIND_CHILD(furniture_bgcol2, furniture_bg_sig); - SE_BIND_CHILD(furniture_bggrad, furniture_bg_sig); - SE_BIND_CHILD(furniture_alignment, furniture_alignment_sig); - SE_BIND_CHILD(furniture_w, furniture_dims_sig); - SE_BIND_CHILD(furniture_h, furniture_dims_sig); - SE_BIND_CHILD(furniture_x, furniture_dims_sig); - SE_BIND_CHILD(furniture_y, furniture_dims_sig); - SE_BIND_CHILD(furniture_w_units, furniture_dims_sig); - SE_BIND_CHILD(furniture_h_units, furniture_dims_sig); - - gtk_widget_class_bind_template_callback(widget_class, revert_sig); - - g_signal_new("changed", COLLOQUIUM_TYPE_STYLESHEET_EDITOR, - G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); -} - - -StylesheetEditor *stylesheet_editor_new(struct presentation *p) -{ - StylesheetEditor *se; - - se = g_object_new(COLLOQUIUM_TYPE_STYLESHEET_EDITOR, NULL); - if ( se == NULL ) return NULL; - - se->priv->p = p; - se->priv->furniture = gtk_combo_box_get_active_id(GTK_COMBO_BOX(se->furniture_selector)); - set_values_from_presentation(se); - - se->priv->ssdata = stylesheet_data(p->stylesheet); - - return se; -} - diff --git a/src-old/stylesheet_editor.h b/src-old/stylesheet_editor.h deleted file mode 100644 index a7c77b6..0000000 --- a/src-old/stylesheet_editor.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * stylesheet_editor.h - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef STYLESHEET_EDITOR_H -#define STYLESHEET_EDITOR_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gtk/gtk.h> - -#include "presentation.h" -#include "frame.h" - -#define COLLOQUIUM_TYPE_STYLESHEET_EDITOR (stylesheet_editor_get_type()) - -#define COLLOQUIUM_STYLESHEET_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ - COLLOQUIUM_TYPE_STYLESHEET_EDITOR, \ - StylesheetEditor)) - -#define COLLOQUIUM_IS_STYLESHEET_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ - COLLOQUIUM_TYPE_STYLESHEET_EDITOR)) - -#define COLLOQUIUM_STYLESHEET_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), \ - COLLOQUIUM_TYPE_STYLESHEET_EDITOR, \ - StylesheetEditorClass)) - -#define COLLOQUIUM_IS_STYLESHEET_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), \ - COLLOQUIUM_TYPE_STYLESHEET_EDITOR)) - -#define COLLOQUIUM_STYLESHEET_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ - COLLOQUIUM_TYPE_STYLESHEET_EDITOR, \ - StylesheetEditorClass)) - - -typedef struct _sspriv StylesheetEditorPrivate; - -struct _stylesheeteditor -{ - GtkDialog parent_instance; - GtkWidget *narrative_style_font; - GtkWidget *narrative_style_fgcol; - GtkWidget *narrative_style_bgcol; - GtkWidget *narrative_style_bgcol2; - GtkWidget *narrative_style_bggrad; - GtkWidget *narrative_style_paraspace_l; - GtkWidget *narrative_style_paraspace_r; - GtkWidget *narrative_style_paraspace_t; - GtkWidget *narrative_style_paraspace_b; - GtkWidget *narrative_style_padding_l; - GtkWidget *narrative_style_padding_r; - GtkWidget *narrative_style_padding_t; - GtkWidget *narrative_style_padding_b; - GtkWidget *narrative_style_alignment; - GtkWidget *slide_size_w; - GtkWidget *slide_size_h; - GtkWidget *slide_style_bgcol; - GtkWidget *slide_style_bgcol2; - GtkWidget *slide_style_bggrad; - GtkWidget *frame_style_font; - GtkWidget *frame_style_fgcol; - GtkWidget *frame_style_bgcol; - GtkWidget *frame_style_bgcol2; - GtkWidget *frame_style_bggrad; - GtkWidget *frame_style_paraspace_l; - GtkWidget *frame_style_paraspace_r; - GtkWidget *frame_style_paraspace_t; - GtkWidget *frame_style_paraspace_b; - GtkWidget *frame_style_padding_l; - GtkWidget *frame_style_padding_r; - GtkWidget *frame_style_padding_t; - GtkWidget *frame_style_padding_b; - GtkWidget *frame_style_alignment; - GtkWidget *furniture_selector; - GtkWidget *furniture_paraspace_l; - GtkWidget *furniture_paraspace_r; - GtkWidget *furniture_paraspace_t; - GtkWidget *furniture_paraspace_b; - GtkWidget *furniture_padding_l; - GtkWidget *furniture_padding_r; - GtkWidget *furniture_padding_t; - GtkWidget *furniture_padding_b; - GtkWidget *furniture_font; - GtkWidget *furniture_fgcol; - GtkWidget *furniture_bgcol; - GtkWidget *furniture_bgcol2; - GtkWidget *furniture_bggrad; - GtkWidget *furniture_alignment; - GtkWidget *furniture_w; - GtkWidget *furniture_h; - GtkWidget *furniture_x; - GtkWidget *furniture_y; - GtkWidget *furniture_w_units; - GtkWidget *furniture_h_units; - StylesheetEditorPrivate *priv; -}; - -struct _stylesheeteditorclass -{ - GtkDialogClass parent_class; -}; - -typedef struct _stylesheeteditor StylesheetEditor; -typedef struct _stylesheeteditorclass StylesheetEditorClass; - -extern StylesheetEditor *stylesheet_editor_new(struct presentation *p); - -#endif /* STYLESHEET_EDITOR_H */ diff --git a/src-old/utils.c b/src-old/utils.c deleted file mode 100644 index b41f344..0000000 --- a/src-old/utils.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * utils.c - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#include "utils.h" - -void chomp(char *s) -{ - size_t i; - - if ( !s ) return; - - for ( i=0; i<strlen(s); i++ ) { - if ( (s[i] == '\n') || (s[i] == '\r') ) { - s[i] = '\0'; - return; - } - } -} - - -int safe_strcmp(const char *a, const char *b) -{ - if ( a == NULL ) return 1; - if ( b == NULL ) return 1; - return strcmp(a, b); -} - - -int parse_double(const char *a, float v[2]) -{ - int nn; - - nn = sscanf(a, "%fx%f", &v[0], &v[1]); - if ( nn != 2 ) { - fprintf(stderr, _("Invalid size '%s'\n"), a); - return 1; - } - - return 0; -} - - -int parse_tuple(const char *a, float v[4]) -{ - int nn; - - nn = sscanf(a, "%f,%f,%f,%f", &v[0], &v[1], &v[2], &v[3]); - if ( nn != 4 ) { - fprintf(stderr, _("Invalid tuple '%s'\n"), a); - return 1; - } - - return 0; -} - - -static LengthUnits get_units(const char *t) -{ - size_t len = strlen(t); - - if ( t[len-1] == 'f' ) return UNITS_FRAC; - if ( t[len-1] == 'u' ) return UNITS_SLIDE; - - fprintf(stderr, _("Invalid units in '%s'\n"), t); - return UNITS_SLIDE; -} - - -int parse_dims(const char *opt, double *wp, double *hp, - LengthUnits *wup, LengthUnits *hup, - double *xp, double *yp) -{ - char *w; - char *h; - char *x; - char *y; - char *check; - - w = strdup(opt); - h = index(w, 'x'); - h[0] = '\0'; h++; - - x = index(h, '+'); - if ( x == NULL ) goto invalid; - x[0] = '\0'; x++; - - y = index(x, '+'); - if ( x == NULL ) goto invalid; - y[0] = '\0'; y++; - - *wp = strtod(w, &check); - if ( check == w ) goto invalid; - *wup = get_units(w); - - *hp = strtod(h, &check); - if ( check == h ) goto invalid; - *hup = get_units(h); - - *xp= strtod(x, &check); - if ( check == x ) goto invalid; - *yp = strtod(y, &check); - if ( check == y ) goto invalid; - - return 0; - -invalid: - fprintf(stderr, _("Invalid dimensions '%s'\n"), opt); - return 1; -} diff --git a/src-old/utils.h b/src-old/utils.h deleted file mode 100644 index af3c7b8..0000000 --- a/src-old/utils.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * utils.h - * - * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk> - * - * This file is part of Colloquium. - * - * Colloquium 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 3 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, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef UTILS_H -#define UTILS_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -typedef enum -{ - UNITS_SLIDE, - UNITS_FRAC -} LengthUnits; - -extern void chomp(char *s); -extern int safe_strcmp(const char *a, const char *b); -extern int parse_double(const char *a, float v[2]); -extern int parse_tuple(const char *a, float v[4]); -extern int parse_dims(const char *opt, double *wp, double *hp, - LengthUnits *wup, LengthUnits *hup, - double *xp, double *yp); - -#include <libintl.h> -#define _(x) gettext(x) - -#endif /* UTILS_H */ |