📄 xo-file.c
字号:
for (list = bgpdf.pages; list != NULL; list = list->next) { pdfpg = (struct BgPdfPage *)list->data; if (pdfpg->pixbuf!=NULL) gdk_pixbuf_unref(pdfpg->pixbuf); } g_list_free(bgpdf.pages); bgpdf.status = STATUS_SHUTDOWN; for (list = g_list_last(bgpdf.requests); list != NULL; ) { req = (struct BgPdfRequest *)list->data; list = list->prev; cancel_bgpdf_request(req); } if (!bgpdf.pid) end_bgpdf_shutdown(); /* The above will ultimately remove all requests and kill the child if needed. The child will set status to STATUS_NOT_INIT, clear the requests list, empty tmpdir, ... except if there's no child! */ /* note: it could look like there's a race condition here - if a child terminates and a new request is enqueued while we are destroying the queue - but actually the child handler callback is NOT a signal callback, so execution of this function is atomic */}gboolean init_bgpdf(char *pdfname, gboolean create_pages, int file_domain){ FILE *f; gchar *filebuf; gsize filelen; if (bgpdf.status != STATUS_NOT_INIT) return FALSE; bgpdf.tmpfile_copy = NULL; bgpdf.tmpdir = mkdtemp(g_strdup(TMPDIR_TEMPLATE)); if (!bgpdf.tmpdir) return FALSE; // make a local copy and check if it's a PDF if (!g_file_get_contents(pdfname, &filebuf, &filelen, NULL)) { end_bgpdf_shutdown(); return FALSE; } if (filelen < 4 || strncmp(filebuf, "%PDF", 4)) { g_free(filebuf); end_bgpdf_shutdown(); return FALSE; } bgpdf.tmpfile_copy = g_strdup_printf("%s/bg.pdf", bgpdf.tmpdir); f = fopen(bgpdf.tmpfile_copy, "w"); if (f == NULL || fwrite(filebuf, 1, filelen, f) != filelen) { g_free(filebuf); end_bgpdf_shutdown(); return FALSE; } fclose(f); g_free(filebuf); bgpdf.status = STATUS_IDLE; bgpdf.pid = 0; bgpdf.filename = new_refstring((file_domain == DOMAIN_ATTACH) ? "bg.pdf" : pdfname); bgpdf.file_domain = file_domain; bgpdf.npages = 0; bgpdf.pages = NULL; bgpdf.requests = NULL; bgpdf.create_pages = create_pages; bgpdf.has_failed = FALSE; add_bgpdf_request(-1, ui.startup_zoom, FALSE); // request all pages return TRUE;}// create page n, resize it, set its bgvoid bgpdf_create_page_with_bg(int pageno, struct BgPdfPage *bgpg){ struct Page *pg; struct Background *bg; if (journal.npages < pageno) { bg = g_new(struct Background, 1); bg->canvas_item = NULL; } else { pg = (struct Page *)g_list_nth_data(journal.pages, pageno-1); bg = pg->bg; if (bg->type != BG_SOLID) return; // don't mess with a page the user has modified significantly... } bg->type = BG_PDF; bg->pixbuf = gdk_pixbuf_ref(bgpg->pixbuf); bg->filename = refstring_ref(bgpdf.filename); bg->file_domain = bgpdf.file_domain; bg->file_page_seq = pageno; bg->pixbuf_scale = ui.startup_zoom; bg->pixbuf_dpi = bgpg->dpi; if (journal.npages < pageno) { pg = new_page_with_bg(bg, gdk_pixbuf_get_width(bg->pixbuf)*72.0/bg->pixbuf_dpi, gdk_pixbuf_get_height(bg->pixbuf)*72.0/bg->pixbuf_dpi); journal.pages = g_list_append(journal.pages, pg); journal.npages++; } else { pg->width = gdk_pixbuf_get_width(bgpg->pixbuf)*72.0/bg->pixbuf_dpi; pg->height = gdk_pixbuf_get_height(bgpg->pixbuf)*72.0/bg->pixbuf_dpi; make_page_clipbox(pg); update_canvas_bg(pg); } update_page_stuff();}// look for all journal pages with given pdf bg, and update their bg pixmapsvoid bgpdf_update_bg(int pageno, struct BgPdfPage *bgpg){ GList *list; struct Page *pg; for (list = journal.pages; list!= NULL; list = list->next) { pg = (struct Page *)list->data; if (pg->bg->type == BG_PDF && pg->bg->file_page_seq == pageno) { if (pg->bg->pixbuf!=NULL) gdk_pixbuf_unref(pg->bg->pixbuf); pg->bg->pixbuf = gdk_pixbuf_ref(bgpg->pixbuf); pg->bg->pixbuf_dpi = bgpg->dpi; update_canvas_bg(pg); } }}// initialize the recent files listvoid init_mru(void){ int i; gsize lfptr; char s[5]; GIOChannel *f; gchar *str; GIOStatus status; g_strlcpy(s, "mru0", 5); for (s[3]='0', i=0; i<MRU_SIZE; s[3]++, i++) { ui.mrumenu[i] = GET_COMPONENT(s); ui.mru[i] = NULL; } f = g_io_channel_new_file(ui.mrufile, "r", NULL); if (f) status = G_IO_STATUS_NORMAL; else status = G_IO_STATUS_ERROR; i = 0; while (status == G_IO_STATUS_NORMAL && i<MRU_SIZE) { lfptr = 0; status = g_io_channel_read_line(f, &str, NULL, &lfptr, NULL); if (status == G_IO_STATUS_NORMAL && lfptr>0) { str[lfptr] = 0; ui.mru[i] = str; i++; } } if (f) { g_io_channel_shutdown(f, FALSE, NULL); g_io_channel_unref(f); } update_mru_menu();}void update_mru_menu(void){ int i; gboolean anyone = FALSE; gchar *tmp; for (i=0; i<MRU_SIZE; i++) { if (ui.mru[i]!=NULL) { tmp = g_strdup_printf("_%d %s", i+1, g_basename(ui.mru[i])); gtk_label_set_text_with_mnemonic(GTK_LABEL(gtk_bin_get_child(GTK_BIN(ui.mrumenu[i]))), tmp); g_free(tmp); gtk_widget_show(ui.mrumenu[i]); anyone = TRUE; } else gtk_widget_hide(ui.mrumenu[i]); } gtk_widget_set_sensitive(GET_COMPONENT("fileRecentFiles"), anyone);}void new_mru_entry(char *name){ int i, j; for (i=0;i<MRU_SIZE;i++) if (ui.mru[i]!=NULL && !strcmp(ui.mru[i], name)) { g_free(ui.mru[i]); for (j=i+1; j<MRU_SIZE; j++) ui.mru[j-1] = ui.mru[j]; ui.mru[MRU_SIZE-1]=NULL; } if (ui.mru[MRU_SIZE-1]!=NULL) g_free(ui.mru[MRU_SIZE-1]); for (j=MRU_SIZE-1; j>=1; j--) ui.mru[j] = ui.mru[j-1]; ui.mru[0] = g_strdup(name); update_mru_menu();}void delete_mru_entry(int which){ int i; if (ui.mru[which]!=NULL) g_free(ui.mru[which]); for (i=which+1;i<MRU_SIZE;i++) ui.mru[i-1] = ui.mru[i]; ui.mru[MRU_SIZE-1] = NULL; update_mru_menu();}void save_mru_list(void){ FILE *f; int i; f = fopen(ui.mrufile, "w"); if (f==NULL) return; for (i=0; i<MRU_SIZE; i++) if (ui.mru[i]!=NULL) fprintf(f, "%s\n", ui.mru[i]); fclose(f);}void init_config_default(void){ int i, j; DEFAULT_ZOOM = DISPLAY_DPI_DEFAULT/72.0; ui.zoom = ui.startup_zoom = 1.0*DEFAULT_ZOOM; ui.default_page.height = 792.0; ui.default_page.width = 612.0; ui.default_page.bg->type = 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.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; // 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; ui.ruler[0] = ui.startupruler = FALSE; for (i=1; i<=NUM_BUTTONS; i++) { ui.toolno[i] = TOOL_ERASER; ui.ruler[i] = FALSE; } 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; } 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);}#endifconst 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; i++) { if (order[i]<0 || order[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", "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]));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -