X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2Fxo-file.c;h=016fcd4cd63bc79c3a65ed47d18186740aab4959;hb=dcbb0ab8521a5e166f257d86884407eb98ef63f0;hp=a241df396e81d7f4819d473c2bfd507fc7d7a05b;hpb=78c2f8fa93f7adcb9157699c92b1498d878f66b2;p=xournal.git diff --git a/src/xo-file.c b/src/xo-file.c index a241df3..016fcd4 100644 --- a/src/xo-file.c +++ b/src/xo-file.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "xournal.h" #include "xo-interface.h" @@ -21,8 +23,9 @@ #include "xo-callbacks.h" #include "xo-misc.h" #include "xo-file.h" +#include "xo-paint.h" -const char *tool_names[NUM_STROKE_TOOLS] = {"pen", "eraser", "highlighter"}; +const char *tool_names[NUM_TOOLS] = {"pen", "eraser", "highlighter", "text", "", "selectrect", "vertspace", "hand"}; const char *color_names[COLOR_MAX] = {"black", "blue", "red", "green", "gray", "lightblue", "lightgreen", "magenta", "orange", "yellow", "white"}; const char *bgtype_names[3] = {"solid", "pixmap", "pdf"}; @@ -30,6 +33,8 @@ const char *bgcolor_names[COLOR_MAX] = {"", "blue", "pink", "green", "", "", "", "", "orange", "yellow", "white"}; const char *bgstyle_names[4] = {"plain", "lined", "ruled", "graph"}; const char *file_domain_names[3] = {"absolute", "attach", "clone"}; +const char *unit_names[4] = {"cm", "in", "px", "pt"}; +int PDFTOPPM_PRINTING_DPI, GS_BITMAP_DPI; // creates a new empty journal @@ -71,7 +76,7 @@ gboolean save_journal(const char *filename) struct Layer *layer; struct Item *item; int i, is_clone; - char *tmpfn; + char *tmpfn, *tmpstr; gchar *pdfbuf; gsize pdflen; gboolean success; @@ -86,8 +91,8 @@ gboolean save_journal(const char *filename) setlocale(LC_NUMERIC, "C"); gzprintf(f, "\n" - "Xournal document - see http://math.mit.edu/~auroux/software/xournal/\n" - "\n"); + "\n" + "Xournal document - see http://math.mit.edu/~auroux/software/xournal/\n"); for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next) { pg = (struct Page *)pagelist->data; gzprintf(f, "\n", pg->width, pg->height); @@ -121,8 +126,10 @@ gboolean save_journal(const char *filename) } g_free(tmpfn); } + tmpstr = g_markup_escape_text(pg->bg->filename->s, -1); gzprintf(f, "domain=\"%s\" filename=\"%s\" ", - file_domain_names[pg->bg->file_domain], pg->bg->filename->s); + file_domain_names[pg->bg->file_domain], tmpstr); + g_free(tmpstr); } } else if (pg->bg->type == BG_PDF) { @@ -153,8 +160,10 @@ gboolean save_journal(const char *filename) } g_free(tmpfn); } + tmpstr = g_markup_escape_text(pg->bg->filename->s, -1); gzprintf(f, "domain=\"%s\" filename=\"%s\" ", - file_domain_names[pg->bg->file_domain], pg->bg->filename->s); + file_domain_names[pg->bg->file_domain], tmpstr); + g_free(tmpstr); } gzprintf(f, "pageno=\"%d\" ", pg->bg->file_page_seq); } @@ -171,16 +180,34 @@ gboolean save_journal(const char *filename) gzputs(f, color_names[item->brush.color_no]); else gzprintf(f, "#%08x", item->brush.color_rgba); - gzprintf(f, "\" width=\"%.2f\">\n", item->brush.thickness); + gzprintf(f, "\" width=\"%.2f", item->brush.thickness); + if (item->brush.variable_width) + for (i=0;ipath->num_points-1;i++) + gzprintf(f, " %.2f", item->widths[i]); + gzprintf(f, "\">\n"); for (i=0;i<2*item->path->num_points;i++) gzprintf(f, "%.2f ", item->path->coords[i]); gzprintf(f, "\n\n"); } + if (item->type == ITEM_TEXT) { + tmpstr = g_markup_escape_text(item->font_name, -1); + gzprintf(f, "font_size, item->bbox.left, item->bbox.top); + g_free(tmpstr); + if (item->brush.color_no >= 0) + gzputs(f, color_names[item->brush.color_no]); + else + gzprintf(f, "#%08x", item->brush.color_rgba); + tmpstr = g_markup_escape_text(item->text, -1); + gzprintf(f, "\">%s\n", tmpstr); + g_free(tmpstr); + } } gzprintf(f, "\n"); } gzprintf(f, "\n"); } + gzprintf(f, "\n"); gzclose(f); setlocale(LC_NUMERIC, ""); @@ -232,9 +259,10 @@ void xoj_parser_start_element(GMarkupParseContext *context, const gchar **attribute_values, gpointer user_data, GError **error) { int has_attr, i; - char *ptr; + char *ptr, *tmpptr; struct Background *tmpbg; char *tmpbg_filename; + gdouble val; GtkWidget *dialog; if (!strcmp(element_name, "title") || !strcmp(element_name, "xournal")) { @@ -422,6 +450,7 @@ void xoj_parser_start_element(GMarkupParseContext *context, tmpItem->type = ITEM_STROKE; tmpItem->path = NULL; tmpItem->canvas_item = NULL; + tmpItem->widths = NULL; tmpLayer->items = g_list_append(tmpLayer->items, tmpItem); tmpLayer->nitems++; // scan for tool, color, and width attributes @@ -432,6 +461,20 @@ void xoj_parser_start_element(GMarkupParseContext *context, cleanup_numeric((gchar *)*attribute_values); tmpItem->brush.thickness = g_ascii_strtod(*attribute_values, &ptr); if (ptr == *attribute_values) *error = xoj_invalid(); + i = 0; + while (*ptr!=0) { + realloc_cur_widths(i+1); + ui.cur_widths[i] = g_ascii_strtod(ptr, &tmpptr); + if (tmpptr == ptr) break; + ptr = tmpptr; + i++; + } + tmpItem->brush.variable_width = (i>0); + if (i>0) { + tmpItem->brush.variable_width = TRUE; + tmpItem->widths = (gdouble *) g_memdup(ui.cur_widths, i*sizeof(gdouble)); + ui.cur_path.num_points = i+1; + } has_attr |= 1; } else if (!strcmp(*attribute_names, "color")) { @@ -467,11 +510,73 @@ void xoj_parser_start_element(GMarkupParseContext *context, // finish filling the brush info tmpItem->brush.thickness_no = 0; // who cares ? tmpItem->brush.tool_options = 0; // who cares ? + tmpItem->brush.ruler = FALSE; + tmpItem->brush.recognizer = FALSE; if (tmpItem->brush.tool_type == TOOL_HIGHLIGHTER) { if (tmpItem->brush.color_no >= 0) - tmpItem->brush.color_rgba &= HILITER_ALPHA_MASK; + tmpItem->brush.color_rgba &= ui.hiliter_alpha_mask; } } + else if (!strcmp(element_name, "text")) { // start of a text item + if (tmpLayer == NULL || tmpItem != NULL) { + *error = xoj_invalid(); + return; + } + tmpItem = (struct Item *)g_malloc0(sizeof(struct Item)); + tmpItem->type = ITEM_TEXT; + tmpItem->canvas_item = NULL; + tmpLayer->items = g_list_append(tmpLayer->items, tmpItem); + tmpLayer->nitems++; + // scan for font, size, x, y, and color attributes + has_attr = 0; + while (*attribute_names!=NULL) { + if (!strcmp(*attribute_names, "font")) { + if (has_attr & 1) *error = xoj_invalid(); + tmpItem->font_name = g_strdup(*attribute_values); + has_attr |= 1; + } + else if (!strcmp(*attribute_names, "size")) { + if (has_attr & 2) *error = xoj_invalid(); + cleanup_numeric((gchar *)*attribute_values); + tmpItem->font_size = g_ascii_strtod(*attribute_values, &ptr); + if (ptr == *attribute_values) *error = xoj_invalid(); + has_attr |= 2; + } + else if (!strcmp(*attribute_names, "x")) { + if (has_attr & 4) *error = xoj_invalid(); + cleanup_numeric((gchar *)*attribute_values); + tmpItem->bbox.left = g_ascii_strtod(*attribute_values, &ptr); + if (ptr == *attribute_values) *error = xoj_invalid(); + has_attr |= 4; + } + else if (!strcmp(*attribute_names, "y")) { + if (has_attr & 8) *error = xoj_invalid(); + cleanup_numeric((gchar *)*attribute_values); + tmpItem->bbox.top = g_ascii_strtod(*attribute_values, &ptr); + if (ptr == *attribute_values) *error = xoj_invalid(); + has_attr |= 8; + } + else if (!strcmp(*attribute_names, "color")) { + if (has_attr & 16) *error = xoj_invalid(); + tmpItem->brush.color_no = COLOR_OTHER; + for (i=0; ibrush.color_no = i; + tmpItem->brush.color_rgba = predef_colors_rgba[i]; + } + // there's also the case of hex (#rrggbbaa) colors + if (tmpItem->brush.color_no == COLOR_OTHER && **attribute_values == '#') { + tmpItem->brush.color_rgba = strtol(*attribute_values + 1, &ptr, 16); + if (*ptr!=0) *error = xoj_invalid(); + } + has_attr |= 16; + } + else *error = xoj_invalid(); + attribute_names++; + attribute_values++; + } + if (has_attr!=31) *error = xoj_invalid(); + } } void xoj_parser_end_element(GMarkupParseContext *context, @@ -500,6 +605,13 @@ void xoj_parser_end_element(GMarkupParseContext *context, update_item_bbox(tmpItem); tmpItem = NULL; } + if (!strcmp(element_name, "text")) { + if (tmpItem == NULL) { + *error = xoj_invalid(); + return; + } + tmpItem = NULL; + } } void xoj_parser_text(GMarkupParseContext *context, @@ -520,12 +632,23 @@ void xoj_parser_text(GMarkupParseContext *context, if (ptr == text) break; text_len -= (ptr - text); text = ptr; + if (!finite(ui.cur_path.coords[n])) { + if (n>=2) ui.cur_path.coords[n] = ui.cur_path.coords[n-2]; + else ui.cur_path.coords[n] = 0; + } n++; } - if (n<4 || n&1) { *error = xoj_invalid(); return; } + if (n<4 || n&1 || + (tmpItem->brush.variable_width && (n!=2*ui.cur_path.num_points))) + { *error = xoj_invalid(); return; } // wrong number of points tmpItem->path = gnome_canvas_points_new(n/2); g_memmove(tmpItem->path->coords, ui.cur_path.coords, n*sizeof(double)); } + if (!strcmp(element_name, "text")) { + tmpItem->text = g_malloc(text_len+1); + g_memmove(tmpItem->text, text, text_len); + tmpItem->text[text_len]=0; + } } gboolean user_wants_second_chance(char **filename) @@ -617,7 +740,7 @@ gboolean open_journal(char *filename) close_journal(); while (bgpdf.status != STATUS_NOT_INIT) gtk_main_iteration(); new_journal(); - ui.zoom = DEFAULT_ZOOM; + ui.zoom = ui.startup_zoom; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); update_page_stuff(); return init_bgpdf(filename, TRUE, DOMAIN_ABSOLUTE); @@ -662,7 +785,7 @@ gboolean open_journal(char *filename) ui.layerno = ui.cur_page->nlayers-1; ui.cur_layer = (struct Layer *)(g_list_last(ui.cur_page->layers)->data); ui.saved = TRUE; - ui.zoom = DEFAULT_ZOOM; + ui.zoom = ui.startup_zoom; update_file_name(g_strdup(filename)); gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); make_canvas_items(); @@ -709,8 +832,9 @@ GList *attempt_load_gv_bg(char *filename) char *pipename; int buflen, remnlen, file_pageno; - buf = g_malloc(BUFSIZE); // a reasonable buffer size f = fopen(filename, "r"); + if (f == NULL) return NULL; + buf = g_malloc(BUFSIZE); // a reasonable buffer size if (fread(buf, 1, 4, f) !=4 || (strncmp((char *)buf, "%!PS", 4) && strncmp((char *)buf, "%PDF", 4))) { fclose(f); @@ -769,10 +893,8 @@ struct Background *attempt_screenshot_bg(void) struct Background *bg; GdkPixbuf *pix; XEvent x_event; - GError *error = NULL; GdkWindow *window; - int x,y,w,h, status; - unsigned int tmp; + int x,y,w,h; Window x_root, x_win; x_root = gdk_x11_get_default_root_xwindow(); @@ -855,20 +977,21 @@ void bgpdf_child_handler(GPid pid, gint status, gpointer data) struct BgPdfPage *bgpg; gchar *ppm_name; GdkPixbuf *pixbuf; + int npad, ret; if (bgpdf.requests == NULL) return; req = (struct BgPdfRequest *)bgpdf.requests->data; - ppm_name = g_strdup_printf("%s/p-%06d.ppm", bgpdf.tmpdir, req->pageno); -// printf("Child %d finished, should look for %s... \n", pid, ppm_name); - - if (bgpdf.status == STATUS_ABORTED || bgpdf.status == STATUS_SHUTDOWN) - pixbuf = NULL; - else - pixbuf = gdk_pixbuf_new_from_file(ppm_name, NULL); - - unlink(ppm_name); - g_free(ppm_name); + pixbuf = NULL; + // pdftoppm used to generate p-nnnnnn.ppm (6 digits); new versions produce variable width + for (npad = 6; npad>0; npad--) { + ppm_name = g_strdup_printf("%s/p-%0*d.ppm", bgpdf.tmpdir, npad, req->pageno); + if (bgpdf.status != STATUS_ABORTED && bgpdf.status != STATUS_SHUTDOWN) + pixbuf = gdk_pixbuf_new_from_file(ppm_name, NULL); + ret = unlink(ppm_name); + g_free(ppm_name); + if (pixbuf != NULL || ret == 0) break; + } if (pixbuf != NULL) { // success // printf("success\n"); @@ -1064,14 +1187,14 @@ gboolean init_bgpdf(char *pdfname, gboolean create_pages, int file_domain) bgpdf.requests = NULL; bgpdf.create_pages = create_pages; bgpdf.has_failed = FALSE; - add_bgpdf_request(-1, DEFAULT_ZOOM, FALSE); // request all pages + add_bgpdf_request(-1, ui.startup_zoom, FALSE); // request all pages return TRUE; } // create page n, resize it, set its bg void bgpdf_create_page_with_bg(int pageno, struct BgPdfPage *bgpg) { - struct Page *pg; + struct Page *pg = NULL; struct Background *bg; if (journal.npages < pageno) { @@ -1089,7 +1212,7 @@ void bgpdf_create_page_with_bg(int pageno, struct BgPdfPage *bgpg) bg->filename = refstring_ref(bgpdf.filename); bg->file_domain = bgpdf.file_domain; bg->file_page_seq = pageno; - bg->pixbuf_scale = DEFAULT_ZOOM; + bg->pixbuf_scale = ui.startup_zoom; bg->pixbuf_dpi = bgpg->dpi; if (journal.npages < pageno) { @@ -1163,11 +1286,14 @@ void update_mru_menu(void) { int i; gboolean anyone = FALSE; + gchar *tmp; for (i=0; itype = BG_SOLID; + ui.default_page.bg->color_no = COLOR_WHITE; + ui.default_page.bg->color_rgba = predef_bgcolors_rgba[COLOR_WHITE]; + ui.default_page.bg->ruling = RULING_LINED; + ui.view_continuous = TRUE; + ui.allow_xinput = TRUE; + ui.discard_corepointer = FALSE; + ui.left_handed = FALSE; + ui.shorten_menus = FALSE; + ui.shorten_menu_items = g_strdup(DEFAULT_SHORTEN_MENUS); + ui.auto_save_prefs = FALSE; + ui.bg_apply_all_pages = FALSE; + ui.use_erasertip = FALSE; + ui.window_default_width = 720; + ui.window_default_height = 480; + ui.maximize_at_start = FALSE; + ui.fullscreen = FALSE; + ui.scrollbar_step_increment = 30; + ui.zoom_step_increment = 1; + ui.zoom_step_factor = 1.5; + ui.antialias_bg = TRUE; + ui.progressive_bg = TRUE; + ui.print_ruling = TRUE; + ui.default_unit = UNIT_CM; + ui.default_path = NULL; + ui.default_font_name = g_strdup(DEFAULT_FONT); + ui.default_font_size = DEFAULT_FONT_SIZE; + ui.pressure_sensitivity = FALSE; + ui.width_minimum_multiplier = 0.0; + ui.width_maximum_multiplier = 1.25; + + // the default UI vertical order + ui.vertical_order[0][0] = 1; + ui.vertical_order[0][1] = 2; + ui.vertical_order[0][2] = 3; + ui.vertical_order[0][3] = 0; + ui.vertical_order[0][4] = 4; + ui.vertical_order[1][0] = 2; + ui.vertical_order[1][1] = 3; + ui.vertical_order[1][2] = 0; + ui.vertical_order[1][3] = ui.vertical_order[1][4] = -1; + + ui.toolno[0] = ui.startuptool = TOOL_PEN; + for (i=1; i<=NUM_BUTTONS; i++) { + ui.toolno[i] = TOOL_ERASER; + } + for (i=0; i<=NUM_BUTTONS; i++) + ui.linked_brush[i] = BRUSH_LINKED; + ui.brushes[0][TOOL_PEN].color_no = COLOR_BLACK; + ui.brushes[0][TOOL_ERASER].color_no = COLOR_WHITE; + ui.brushes[0][TOOL_HIGHLIGHTER].color_no = COLOR_YELLOW; + for (i=0; i < NUM_STROKE_TOOLS; i++) { + ui.brushes[0][i].thickness_no = THICKNESS_MEDIUM; + ui.brushes[0][i].tool_options = 0; + ui.brushes[0][i].ruler = FALSE; + ui.brushes[0][i].recognizer = FALSE; + ui.brushes[0][i].variable_width = FALSE; + } + for (i=0; i< NUM_STROKE_TOOLS; i++) + for (j=1; j<=NUM_BUTTONS; j++) + g_memmove(&(ui.brushes[j][i]), &(ui.brushes[0][i]), sizeof(struct Brush)); + + // predef_thickness is already initialized as a global variable + GS_BITMAP_DPI = 144; + PDFTOPPM_PRINTING_DPI = 150; + + ui.hiliter_opacity = 0.5; +} + +#if GLIB_CHECK_VERSION(2,6,0) + +void update_keyval(const gchar *group_name, const gchar *key, + const gchar *comment, gchar *value) +{ + gboolean has_it = g_key_file_has_key(ui.config_data, group_name, key, NULL); + cleanup_numeric(value); + g_key_file_set_value(ui.config_data, group_name, key, value); + g_free(value); + if (!has_it) g_key_file_set_comment(ui.config_data, group_name, key, comment, NULL); +} + +#endif + +const char *vorder_usernames[VBOX_MAIN_NITEMS+1] = + {"drawarea", "menu", "main_toolbar", "pen_toolbar", "statusbar", NULL}; + +gchar *verbose_vertical_order(int *order) +{ + gchar buf[80], *p; // longer than needed + int i; + + p = buf; + for (i=0; i=VBOX_MAIN_NITEMS) continue; + if (p!=buf) *(p++) = ' '; + p = g_stpcpy(p, vorder_usernames[order[i]]); + } + return g_strdup(buf); +} + +void save_config_to_file(void) +{ + gchar *buf; + FILE *f; + +#if GLIB_CHECK_VERSION(2,6,0) + // no support for keyval files before Glib 2.6.0 + if (glib_minor_version<6) return; + + // save some data... + ui.maximize_at_start = (gdk_window_get_state(winMain->window) & GDK_WINDOW_STATE_MAXIMIZED); + if (!ui.maximize_at_start && !ui.fullscreen) + gdk_drawable_get_size(winMain->window, + &ui.window_default_width, &ui.window_default_height); + + update_keyval("general", "display_dpi", + " the display resolution, in pixels per inch", + g_strdup_printf("%.2f", DEFAULT_ZOOM*72)); + update_keyval("general", "initial_zoom", + " the initial zoom level, in percent", + g_strdup_printf("%.2f", 100*ui.zoom/DEFAULT_ZOOM)); + update_keyval("general", "window_maximize", + " maximize the window at startup (true/false)", + g_strdup(ui.maximize_at_start?"true":"false")); + update_keyval("general", "window_fullscreen", + " start in full screen mode (true/false)", + g_strdup(ui.fullscreen?"true":"false")); + update_keyval("general", "window_width", + " the window width in pixels (when not maximized)", + g_strdup_printf("%d", ui.window_default_width)); + update_keyval("general", "window_height", + " the window height in pixels", + g_strdup_printf("%d", ui.window_default_height)); + update_keyval("general", "scrollbar_speed", + " scrollbar step increment (in pixels)", + g_strdup_printf("%d", ui.scrollbar_step_increment)); + update_keyval("general", "zoom_dialog_increment", + " the step increment in the zoom dialog box", + g_strdup_printf("%d", ui.zoom_step_increment)); + update_keyval("general", "zoom_step_factor", + " the multiplicative factor for zoom in/out", + g_strdup_printf("%.3f", ui.zoom_step_factor)); + update_keyval("general", "view_continuous", + " document view (true = continuous, false = single page)", + g_strdup(ui.view_continuous?"true":"false")); + update_keyval("general", "use_xinput", + " use XInput extensions (true/false)", + g_strdup(ui.allow_xinput?"true":"false")); + update_keyval("general", "discard_corepointer", + " discard Core Pointer events in XInput mode (true/false)", + g_strdup(ui.discard_corepointer?"true":"false")); + update_keyval("general", "use_erasertip", + " always map eraser tip to eraser (true/false)", + g_strdup(ui.use_erasertip?"true":"false")); + update_keyval("general", "default_path", + " default path for open/save (leave blank for current directory)", + g_strdup((ui.default_path!=NULL)?ui.default_path:"")); + update_keyval("general", "pressure_sensitivity", + " use pressure sensitivity to control pen stroke width (true/false)", + g_strdup(ui.pressure_sensitivity?"true":"false")); + update_keyval("general", "width_minimum_multiplier", + " minimum width multiplier", + g_strdup_printf("%.2f", ui.width_minimum_multiplier)); + update_keyval("general", "width_maximum_multiplier", + " maximum width multiplier", + g_strdup_printf("%.2f", ui.width_maximum_multiplier)); + update_keyval("general", "interface_order", + " interface components from top to bottom\n valid values: drawarea menu main_toolbar pen_toolbar statusbar", + verbose_vertical_order(ui.vertical_order[0])); + update_keyval("general", "interface_fullscreen", + " interface components in fullscreen mode, from top to bottom", + verbose_vertical_order(ui.vertical_order[1])); + update_keyval("general", "interface_lefthanded", + " interface has left-handed scrollbar (true/false)", + g_strdup(ui.left_handed?"true":"false")); + update_keyval("general", "shorten_menus", + " hide some unwanted menu or toolbar items (true/false)", + g_strdup(ui.shorten_menus?"true":"false")); + update_keyval("general", "shorten_menu_items", + " interface items to hide (customize at your own risk!)\n see source file xo-interface.c for a list of item names", + g_strdup(ui.shorten_menu_items)); + update_keyval("general", "highlighter_opacity", + " highlighter opacity (0 to 1, default 0.5)\n warning: opacity level is not saved in xoj files!", + g_strdup_printf("%.2f", ui.hiliter_opacity)); + update_keyval("general", "autosave_prefs", + " auto-save preferences on exit (true/false)", + g_strdup(ui.auto_save_prefs?"true":"false")); + + update_keyval("paper", "width", + " the default page width, in points (1/72 in)", + g_strdup_printf("%.2f", ui.default_page.width)); + update_keyval("paper", "height", + " the default page height, in points (1/72 in)", + g_strdup_printf("%.2f", ui.default_page.height)); + update_keyval("paper", "color", + " the default paper color", + g_strdup(bgcolor_names[ui.default_page.bg->color_no])); + update_keyval("paper", "style", + " the default paper style (plain, lined, ruled, or graph)", + g_strdup(bgstyle_names[ui.default_page.bg->ruling])); + update_keyval("paper", "apply_all", + " apply paper style changes to all pages (true/false)", + g_strdup(ui.bg_apply_all_pages?"true":"false")); + update_keyval("paper", "default_unit", + " preferred unit (cm, in, px, pt)", + g_strdup(unit_names[ui.default_unit])); + update_keyval("paper", "print_ruling", + " include paper ruling when printing or exporting to PDF (true/false)", + g_strdup(ui.print_ruling?"true":"false")); + update_keyval("paper", "antialias_bg", + " antialiased bitmap backgrounds (true/false)", + g_strdup(ui.antialias_bg?"true":"false")); + update_keyval("paper", "progressive_bg", + " progressive scaling of bitmap backgrounds (true/false)", + g_strdup(ui.progressive_bg?"true":"false")); + update_keyval("paper", "gs_bitmap_dpi", + " bitmap resolution of PS/PDF backgrounds rendered using ghostscript (dpi)", + g_strdup_printf("%d", GS_BITMAP_DPI)); + update_keyval("paper", "pdftoppm_printing_dpi", + " bitmap resolution of PDF backgrounds when printing with libgnomeprint (dpi)", + g_strdup_printf("%d", PDFTOPPM_PRINTING_DPI)); + + update_keyval("tools", "startup_tool", + " selected tool at startup (pen, eraser, highlighter, selectrect, vertspace, hand)", + g_strdup(tool_names[ui.startuptool])); + update_keyval("tools", "pen_color", + " default pen color", + g_strdup(color_names[ui.default_brushes[TOOL_PEN].color_no])); + update_keyval("tools", "pen_thickness", + " default pen thickness (fine = 1, medium = 2, thick = 3)", + g_strdup_printf("%d", ui.default_brushes[TOOL_PEN].thickness_no)); + update_keyval("tools", "pen_ruler", + " default pen is in ruler mode (true/false)", + g_strdup(ui.default_brushes[TOOL_PEN].ruler?"true":"false")); + update_keyval("tools", "pen_recognizer", + " default pen is in shape recognizer mode (true/false)", + g_strdup(ui.default_brushes[TOOL_PEN].recognizer?"true":"false")); + update_keyval("tools", "eraser_thickness", + " default eraser thickness (fine = 1, medium = 2, thick = 3)", + g_strdup_printf("%d", ui.default_brushes[TOOL_ERASER].thickness_no)); + update_keyval("tools", "eraser_mode", + " default eraser mode (standard = 0, whiteout = 1, strokes = 2)", + g_strdup_printf("%d", ui.default_brushes[TOOL_ERASER].tool_options)); + update_keyval("tools", "highlighter_color", + " default highlighter color", + g_strdup(color_names[ui.default_brushes[TOOL_HIGHLIGHTER].color_no])); + update_keyval("tools", "highlighter_thickness", + " default highlighter thickness (fine = 1, medium = 2, thick = 3)", + g_strdup_printf("%d", ui.default_brushes[TOOL_HIGHLIGHTER].thickness_no)); + update_keyval("tools", "highlighter_ruler", + " default highlighter is in ruler mode (true/false)", + g_strdup(ui.default_brushes[TOOL_HIGHLIGHTER].ruler?"true":"false")); + update_keyval("tools", "highlighter_recognizer", + " default highlighter is in shape recognizer mode (true/false)", + g_strdup(ui.default_brushes[TOOL_HIGHLIGHTER].recognizer?"true":"false")); + update_keyval("tools", "btn2_tool", + " button 2 tool (pen, eraser, highlighter, text, selectrect, vertspace, hand)", + g_strdup(tool_names[ui.toolno[1]])); + update_keyval("tools", "btn2_linked", + " button 2 brush linked to primary brush (true/false) (overrides all other settings)", + g_strdup((ui.linked_brush[1]==BRUSH_LINKED)?"true":"false")); + update_keyval("tools", "btn2_color", + " button 2 brush color (for pen or highlighter only)", + g_strdup((ui.toolno[1] sup) return FALSE; + *val = conv; + return TRUE; +} + +gboolean parse_keyval_floatlist(const gchar *group, const gchar *key, double *val, int n, double inf, double sup) +{ + gchar *ret, *end; + double conv[5]; + int i; + + if (n>5) return FALSE; + ret = g_key_file_get_value(ui.config_data, group, key, NULL); + if (ret==NULL) return FALSE; + end = ret; + for (i=0; i sup)) { g_free(ret); return FALSE; } + end++; + } + g_free(ret); + for (i=0; i sup) return FALSE; + *val = conv; + return TRUE; +} + +gboolean parse_keyval_enum(const gchar *group, const gchar *key, int *val, const char **names, int n) +{ + gchar *ret; + int i; + + ret = g_key_file_get_value(ui.config_data, group, key, NULL); + if (ret==NULL) return FALSE; + for (i=0; iVBOX_MAIN_NITEMS) return FALSE; // too many items + for (i=0; i=VBOX_MAIN_NITEMS) { g_free(ret); return FALSE; } // parse error + // we found item #i + tmp[n++] = i; + while (*p==' ') p++; + } + + for (n=0; ncolor_no), bgcolor_names, COLOR_MAX); + ui.default_page.bg->color_rgba = predef_bgcolors_rgba[ui.default_page.bg->color_no]; + parse_keyval_enum("paper", "style", &(ui.default_page.bg->ruling), bgstyle_names, 4); + parse_keyval_boolean("paper", "apply_all", &ui.bg_apply_all_pages); + parse_keyval_enum("paper", "default_unit", &ui.default_unit, unit_names, 4); + parse_keyval_boolean("paper", "antialias_bg", &ui.antialias_bg); + parse_keyval_boolean("paper", "progressive_bg", &ui.progressive_bg); + parse_keyval_boolean("paper", "print_ruling", &ui.print_ruling); + parse_keyval_int("paper", "gs_bitmap_dpi", &GS_BITMAP_DPI, 1, 1200); + parse_keyval_int("paper", "pdftoppm_printing_dpi", &PDFTOPPM_PRINTING_DPI, 1, 1200); + + parse_keyval_enum("tools", "startup_tool", &ui.startuptool, tool_names, NUM_TOOLS); + ui.toolno[0] = ui.startuptool; + parse_keyval_enum("tools", "pen_color", &(ui.brushes[0][TOOL_PEN].color_no), color_names, COLOR_MAX); + parse_keyval_int("tools", "pen_thickness", &(ui.brushes[0][TOOL_PEN].thickness_no), 0, 4); + parse_keyval_boolean("tools", "pen_ruler", &(ui.brushes[0][TOOL_PEN].ruler)); + parse_keyval_boolean("tools", "pen_recognizer", &(ui.brushes[0][TOOL_PEN].recognizer)); + parse_keyval_int("tools", "eraser_thickness", &(ui.brushes[0][TOOL_ERASER].thickness_no), 1, 3); + parse_keyval_int("tools", "eraser_mode", &(ui.brushes[0][TOOL_ERASER].tool_options), 0, 2); + parse_keyval_enum("tools", "highlighter_color", &(ui.brushes[0][TOOL_HIGHLIGHTER].color_no), color_names, COLOR_MAX); + parse_keyval_int("tools", "highlighter_thickness", &(ui.brushes[0][TOOL_HIGHLIGHTER].thickness_no), 0, 4); + parse_keyval_boolean("tools", "highlighter_ruler", &(ui.brushes[0][TOOL_HIGHLIGHTER].ruler)); + parse_keyval_boolean("tools", "highlighter_recognizer", &(ui.brushes[0][TOOL_HIGHLIGHTER].recognizer)); + ui.brushes[0][TOOL_PEN].variable_width = ui.pressure_sensitivity; + for (i=0; i< NUM_STROKE_TOOLS; i++) + for (j=1; j<=NUM_BUTTONS; j++) + g_memmove(&(ui.brushes[j][i]), &(ui.brushes[0][i]), sizeof(struct Brush)); + + parse_keyval_enum("tools", "btn2_tool", &(ui.toolno[1]), tool_names, NUM_TOOLS); + if (parse_keyval_boolean("tools", "btn2_linked", &b)) + ui.linked_brush[1] = b?BRUSH_LINKED:BRUSH_STATIC; + parse_keyval_enum("tools", "btn3_tool", &(ui.toolno[2]), tool_names, NUM_TOOLS); + if (parse_keyval_boolean("tools", "btn3_linked", &b)) + ui.linked_brush[2] = b?BRUSH_LINKED:BRUSH_STATIC; + if (ui.linked_brush[1]!=BRUSH_LINKED) { + if (ui.toolno[1]==TOOL_PEN || ui.toolno[1]==TOOL_HIGHLIGHTER) { + parse_keyval_boolean("tools", "btn2_ruler", &(ui.brushes[1][ui.toolno[1]].ruler)); + parse_keyval_boolean("tools", "btn2_recognizer", &(ui.brushes[1][ui.toolno[1]].recognizer)); + parse_keyval_enum("tools", "btn2_color", &(ui.brushes[1][ui.toolno[1]].color_no), color_names, COLOR_MAX); + } + if (ui.toolno[1]