📄 xo-file.c
字号:
{ *error = xoj_invalid(); return; } tmpbg = ((struct Page *)g_list_nth_data(tmpJournal.pages, i))->bg; if (tmpbg->type != tmpPage->bg->type) { *error = xoj_invalid(); return; } tmpPage->bg->filename = refstring_ref(tmpbg->filename); tmpPage->bg->pixbuf = tmpbg->pixbuf; if (tmpbg->pixbuf!=NULL) gdk_pixbuf_ref(tmpbg->pixbuf); tmpPage->bg->file_domain = tmpbg->file_domain; } else { tmpPage->bg->filename = new_refstring(*attribute_values); if (tmpPage->bg->type == BG_PIXMAP) { if (tmpPage->bg->file_domain == DOMAIN_ATTACH) { tmpbg_filename = g_strdup_printf("%s.%s", tmpFilename, *attribute_values); if (sscanf(*attribute_values, "bg_%d.png", &i) == 1) if (i > tmpJournal.last_attach_no) tmpJournal.last_attach_no = i; } else tmpbg_filename = g_strdup(*attribute_values); tmpPage->bg->pixbuf = gdk_pixbuf_new_from_file(tmpbg_filename, NULL); if (tmpPage->bg->pixbuf == NULL) { dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Could not open background '%s'. Setting background to white.", tmpbg_filename); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); tmpPage->bg->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1); gdk_pixbuf_fill(tmpPage->bg->pixbuf, 0xffffffff); // solid white } g_free(tmpbg_filename); } } has_attr |= 16; } else if (!strcmp(*attribute_names, "pageno")) { if (tmpPage->bg->type != BG_PDF || (has_attr & 32)) { *error = xoj_invalid(); return; } tmpPage->bg->file_page_seq = strtol(*attribute_values, &ptr, 10); if (ptr == *attribute_values) *error = xoj_invalid(); has_attr |= 32; } else *error = xoj_invalid(); attribute_names++; attribute_values++; } if (tmpPage->bg->type < 0) *error = xoj_invalid(); if (tmpPage->bg->type == BG_SOLID && has_attr != 7) *error = xoj_invalid(); if (tmpPage->bg->type == BG_PIXMAP && has_attr != 25) *error = xoj_invalid(); if (tmpPage->bg->type == BG_PDF && has_attr != 57) *error = xoj_invalid(); } else if (!strcmp(element_name, "layer")) { // start of a layer if (tmpPage == NULL || tmpLayer != NULL) { *error = xoj_invalid(); return; } tmpLayer = (struct Layer *)g_malloc(sizeof(struct Layer)); tmpLayer->items = NULL; tmpLayer->nitems = 0; tmpLayer->group = NULL; tmpPage->layers = g_list_append(tmpPage->layers, tmpLayer); tmpPage->nlayers++; } else if (!strcmp(element_name, "stroke")) { // start of a stroke if (tmpLayer == NULL || tmpItem != NULL) { *error = xoj_invalid(); return; } tmpItem = (struct Item *)g_malloc(sizeof(struct Item)); tmpItem->type = ITEM_STROKE; tmpItem->path = NULL; tmpItem->canvas_item = NULL; tmpLayer->items = g_list_append(tmpLayer->items, tmpItem); tmpLayer->nitems++; // scan for tool, color, and width attributes has_attr = 0; while (*attribute_names!=NULL) { if (!strcmp(*attribute_names, "width")) { if (has_attr & 1) *error = xoj_invalid(); cleanup_numeric((gchar *)*attribute_values); tmpItem->brush.thickness = g_ascii_strtod(*attribute_values, &ptr); if (ptr == *attribute_values) *error = xoj_invalid(); has_attr |= 1; } else if (!strcmp(*attribute_names, "color")) { if (has_attr & 2) *error = xoj_invalid(); tmpItem->brush.color_no = COLOR_OTHER; for (i=0; i<COLOR_MAX; i++) if (!strcmp(*attribute_values, color_names[i])) { tmpItem->brush.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 |= 2; } else if (!strcmp(*attribute_names, "tool")) { if (has_attr & 4) *error = xoj_invalid(); tmpItem->brush.tool_type = -1; for (i=0; i<NUM_STROKE_TOOLS; i++) if (!strcmp(*attribute_values, tool_names[i])) { tmpItem->brush.tool_type = i; } if (tmpItem->brush.tool_type == -1) *error = xoj_invalid(); has_attr |= 4; } else *error = xoj_invalid(); attribute_names++; attribute_values++; } if (has_attr!=7) *error = xoj_invalid(); // finish filling the brush info tmpItem->brush.thickness_no = 0; // who cares ? tmpItem->brush.tool_options = 0; // who cares ? if (tmpItem->brush.tool_type == TOOL_HIGHLIGHTER) { if (tmpItem->brush.color_no >= 0) 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; i<COLOR_MAX; i++) if (!strcmp(*attribute_values, color_names[i])) { tmpItem->brush.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, const gchar *element_name, gpointer user_data, GError **error){ if (!strcmp(element_name, "page")) { if (tmpPage == NULL || tmpLayer != NULL) { *error = xoj_invalid(); return; } if (tmpPage->nlayers == 0 || tmpPage->bg->type < 0) *error = xoj_invalid(); tmpPage = NULL; } if (!strcmp(element_name, "layer")) { if (tmpLayer == NULL || tmpItem != NULL) { *error = xoj_invalid(); return; } tmpLayer = NULL; } if (!strcmp(element_name, "stroke")) { if (tmpItem == NULL) { *error = xoj_invalid(); return; } 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, const gchar *text, gsize text_len, gpointer user_data, GError **error){ const gchar *element_name, *ptr; int n; element_name = g_markup_parse_context_get_element(context); if (element_name == NULL) return; if (!strcmp(element_name, "stroke")) { cleanup_numeric((gchar *)text); ptr = text; n = 0; while (text_len > 0) { realloc_cur_path(n/2 + 1); ui.cur_path.coords[n] = g_ascii_strtod(text, (char **)(&ptr)); if (ptr == text) break; text_len -= (ptr - text); text = ptr; n++; } if (n<4 || n&1) { *error = xoj_invalid(); return; } 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){ GtkWidget *dialog; GtkFileFilter *filt_all, *filt_pdf; GtkResponseType response; dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_YES_NO, "Could not open background '%s'.\nSelect another file?", *filename); response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if (response != GTK_RESPONSE_YES) return FALSE; dialog = gtk_file_chooser_dialog_new("Open PDF", GTK_WINDOW (winMain), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); filt_all = gtk_file_filter_new(); gtk_file_filter_set_name(filt_all, "All files"); gtk_file_filter_add_pattern(filt_all, "*"); filt_pdf = gtk_file_filter_new(); gtk_file_filter_set_name(filt_pdf, "PDF files"); gtk_file_filter_add_pattern(filt_pdf, "*.pdf"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all); if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) { gtk_widget_destroy(dialog); return FALSE; } g_free(*filename); *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); gtk_widget_destroy(dialog); return TRUE; }gboolean open_journal(char *filename){ const GMarkupParser parser = { xoj_parser_start_element, xoj_parser_end_element, xoj_parser_text, NULL, NULL}; GMarkupParseContext *context; GError *error; GtkWidget *dialog; gboolean valid; gzFile f; char buffer[1000]; int len; gchar *tmpfn; gboolean maybe_pdf; f = gzopen(filename, "r"); if (f==NULL) return FALSE; context = g_markup_parse_context_new(&parser, 0, NULL, NULL); valid = TRUE; tmpJournal.npages = 0; tmpJournal.pages = NULL; tmpJournal.last_attach_no = 0; tmpPage = NULL; tmpLayer = NULL; tmpItem = NULL; tmpFilename = filename; error = NULL; tmpBg_pdf = NULL; maybe_pdf = TRUE; while (valid && !gzeof(f)) { len = gzread(f, buffer, 1000); if (len<0) valid = FALSE; if (maybe_pdf && len>=4 && !strncmp(buffer, "%PDF", 4)) { valid = FALSE; break; } // most likely pdf else maybe_pdf = FALSE; if (len<=0) break; valid = g_markup_parse_context_parse(context, buffer, len, &error); } gzclose(f); if (valid) valid = g_markup_parse_context_end_parse(context, &error); if (tmpJournal.npages == 0) valid = FALSE; g_markup_parse_context_free(context); if (!valid) { delete_journal(&tmpJournal); if (!maybe_pdf) return FALSE; // essentially same as on_fileNewBackground from here on ui.saved = TRUE; close_journal(); while (bgpdf.status != STATUS_NOT_INIT) gtk_main_iteration(); new_journal(); ui.zoom = ui.startup_zoom; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); update_page_stuff(); return init_bgpdf(filename, TRUE, DOMAIN_ABSOLUTE); } ui.saved = TRUE; // force close_journal() to do its job close_journal(); g_memmove(&journal, &tmpJournal, sizeof(struct Journal)); // if we need to initialize a fresh pdf loader if (tmpBg_pdf!=NULL) { while (bgpdf.status != STATUS_NOT_INIT) gtk_main_iteration(); if (tmpBg_pdf->file_domain == DOMAIN_ATTACH) tmpfn = g_strdup_printf("%s.%s", filename, tmpBg_pdf->filename->s); else tmpfn = g_strdup(tmpBg_pdf->filename->s); valid = init_bgpdf(tmpfn, FALSE, tmpBg_pdf->file_domain); // in case the file name became invalid if (!valid && tmpBg_pdf->file_domain != DOMAIN_ATTACH) if (user_wants_second_chance(&tmpfn)) { valid = init_bgpdf(tmpfn, FALSE, tmpBg_pdf->file_domain); if (valid) { // change the file name... g_free(tmpBg_pdf->filename->s); tmpBg_pdf->filename->s = g_strdup(tmpfn); } } if (valid) { refstring_unref(bgpdf.filename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -