📄 xo-file.c
字号:
bgpdf.filename = refstring_ref(tmpBg_pdf->filename); } else { dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open background '%s'.", tmpfn); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } g_free(tmpfn); } ui.pageno = 0; ui.cur_page = (struct Page *)journal.pages->data; 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 = ui.startup_zoom; update_file_name(g_strdup(filename)); gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); make_canvas_items(); update_page_stuff(); gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0); return TRUE;}/************ file backgrounds *************/struct Background *attempt_load_pix_bg(char *filename, gboolean attach){ struct Background *bg; GdkPixbuf *pix; pix = gdk_pixbuf_new_from_file(filename, NULL); if (pix == NULL) return NULL; bg = g_new(struct Background, 1); bg->type = BG_PIXMAP; bg->canvas_item = NULL; bg->pixbuf = pix; bg->pixbuf_scale = DEFAULT_ZOOM; if (attach) { bg->filename = new_refstring(NULL); bg->file_domain = DOMAIN_ATTACH; } else { bg->filename = new_refstring(filename); bg->file_domain = DOMAIN_ABSOLUTE; } return bg;}#define BUFSIZE 65536 // a reasonable buffer size for reads from gs pipeGList *attempt_load_gv_bg(char *filename){ struct Background *bg; GList *bg_list; GdkPixbuf *pix; GdkPixbufLoader *loader; FILE *gs_pipe, *f; unsigned char *buf; char *pipename; int buflen, remnlen, file_pageno; 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); g_free(buf); return NULL; } fclose(f); pipename = g_strdup_printf(GS_CMDLINE, (double)GS_BITMAP_DPI, filename); gs_pipe = popen(pipename, "r"); g_free(pipename); bg_list = NULL; remnlen = 0; file_pageno = 0; loader = NULL; if (gs_pipe!=NULL) while (!feof(gs_pipe)) { if (!remnlen) { // new page: get a BMP header ? buflen = fread(buf, 1, 54, gs_pipe); if (buflen < 6) buflen += fread(buf, 1, 54-buflen, gs_pipe); if (buflen < 6 || buf[0]!='B' || buf[1]!='M') break; // fatal: abort remnlen = (int)(buf[5]<<24) + (buf[4]<<16) + (buf[3]<<8) + (buf[2]); loader = gdk_pixbuf_loader_new(); } else buflen = fread(buf, 1, (remnlen < BUFSIZE)?remnlen:BUFSIZE, gs_pipe); remnlen -= buflen; if (buflen == 0) break; if (!gdk_pixbuf_loader_write(loader, buf, buflen, NULL)) break; if (remnlen == 0) { // make a new bg pix = gdk_pixbuf_loader_get_pixbuf(loader); if (pix == NULL) break; gdk_pixbuf_ref(pix); gdk_pixbuf_loader_close(loader, NULL); g_object_unref(loader); loader = NULL; bg = g_new(struct Background, 1); bg->canvas_item = NULL; bg->pixbuf = pix; bg->pixbuf_scale = (GS_BITMAP_DPI/72.0); bg->type = BG_PIXMAP; bg->filename = new_refstring(NULL); bg->file_domain = DOMAIN_ATTACH; file_pageno++; bg_list = g_list_append(bg_list, bg); } } if (loader != NULL) gdk_pixbuf_loader_close(loader, NULL); pclose(gs_pipe); g_free(buf); return bg_list;}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; Window x_root, x_win; x_root = gdk_x11_get_default_root_xwindow(); if (!XGrabButton(GDK_DISPLAY(), AnyButton, AnyModifier, x_root, False, ButtonReleaseMask, GrabModeAsync, GrabModeSync, None, None)) return NULL; XWindowEvent (GDK_DISPLAY(), x_root, ButtonReleaseMask, &x_event); XUngrabButton(GDK_DISPLAY(), AnyButton, AnyModifier, x_root); x_win = x_event.xbutton.subwindow; if (x_win == None) x_win = x_root; window = gdk_window_foreign_new_for_display(gdk_display_get_default(), x_win); gdk_window_get_geometry(window, &x, &y, &w, &h, NULL); pix = gdk_pixbuf_get_from_drawable(NULL, window, gdk_colormap_get_system(), 0, 0, 0, 0, w, h); if (pix == NULL) return NULL; bg = g_new(struct Background, 1); bg->type = BG_PIXMAP; bg->canvas_item = NULL; bg->pixbuf = pix; bg->pixbuf_scale = DEFAULT_ZOOM; bg->filename = new_refstring(NULL); bg->file_domain = DOMAIN_ATTACH; return bg;}/************** pdf annotation ***************//* free tmp directory */void end_bgpdf_shutdown(void){ if (bgpdf.tmpdir!=NULL) { if (bgpdf.tmpfile_copy!=NULL) { g_unlink(bgpdf.tmpfile_copy); g_free(bgpdf.tmpfile_copy); bgpdf.tmpfile_copy = NULL; } g_rmdir(bgpdf.tmpdir); g_free(bgpdf.tmpdir); bgpdf.tmpdir = NULL; } bgpdf.status = STATUS_NOT_INIT;}/* cancel a request */void cancel_bgpdf_request(struct BgPdfRequest *req){ GList *list_link; list_link = g_list_find(bgpdf.requests, req); if (list_link == NULL) return; if (list_link->prev == NULL && bgpdf.pid > 0) { // this is being processed: kill the child but don't remove the request yet if (bgpdf.status == STATUS_RUNNING) bgpdf.status = STATUS_ABORTED; kill(bgpdf.pid, SIGHUP);// printf("Cancelling a request - killing %d\n", bgpdf.pid); } else { // remove the request bgpdf.requests = g_list_delete_link(bgpdf.requests, list_link); g_free(req);// printf("Cancelling a request - no kill needed\n"); }}/* sigchld callback */void bgpdf_child_handler(GPid pid, gint status, gpointer data){ struct BgPdfRequest *req; struct BgPdfPage *bgpg; gchar *ppm_name; GdkPixbuf *pixbuf; 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); if (pixbuf != NULL) { // success// printf("success\n"); while (req->pageno > bgpdf.npages) { bgpg = g_new(struct BgPdfPage, 1); bgpg->pixbuf = NULL; bgpdf.pages = g_list_append(bgpdf.pages, bgpg); bgpdf.npages++; } bgpg = g_list_nth_data(bgpdf.pages, req->pageno-1); if (bgpg->pixbuf!=NULL) gdk_pixbuf_unref(bgpg->pixbuf); bgpg->pixbuf = pixbuf; bgpg->dpi = req->dpi; if (req->initial_request && bgpdf.create_pages) { bgpdf_create_page_with_bg(req->pageno, bgpg); // create page n, resize it, set its bg - all without any undo effect } else { if (!req->is_printing) bgpdf_update_bg(req->pageno, bgpg); // look for all pages with this bg, and update their bg pixmaps } } else {// printf("failed or aborted\n"); bgpdf.create_pages = FALSE; req->initial_request = FALSE; } bgpdf.pid = 0; g_spawn_close_pid(pid); if (req->initial_request) req->pageno++; // try for next page else bgpdf.requests = g_list_delete_link(bgpdf.requests, bgpdf.requests); if (bgpdf.status == STATUS_SHUTDOWN) { end_bgpdf_shutdown(); return; } bgpdf.status = STATUS_IDLE; if (bgpdf.requests != NULL) bgpdf_spawn_child();}/* spawn a child to process the head request */void bgpdf_spawn_child(void){ struct BgPdfRequest *req; GPid pid; gchar pageno_str[10], dpi_str[10]; gchar *pdf_filename = bgpdf.tmpfile_copy; gchar *ppm_root = g_strdup_printf("%s/p", bgpdf.tmpdir); gchar *argv[]= PDFTOPPM_ARGV; GtkWidget *dialog; if (bgpdf.requests == NULL) return; req = (struct BgPdfRequest *)bgpdf.requests->data; if (req->pageno > bgpdf.npages+1 || (!req->initial_request && req->pageno <= bgpdf.npages && req->dpi == ((struct BgPdfPage *)g_list_nth_data(bgpdf.pages, req->pageno-1))->dpi)) { // ignore this request - it's redundant, or in outer space bgpdf.pid = 0; bgpdf.status = STATUS_IDLE; bgpdf.requests = g_list_delete_link(bgpdf.requests, bgpdf.requests); g_free(ppm_root); if (bgpdf.requests != NULL) bgpdf_spawn_child(); return; } g_snprintf(pageno_str, 10, "%d", req->pageno); g_snprintf(dpi_str, 10, "%d", req->dpi);/* printf("Processing request for page %d at %d dpi -- in %s\n", req->pageno, req->dpi, ppm_root); */ if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &pid, NULL)) { // couldn't spawn... abort this request, try next one maybe ?// printf("Couldn't spawn\n"); bgpdf.pid = 0; bgpdf.status = STATUS_IDLE; bgpdf.requests = g_list_delete_link(bgpdf.requests, bgpdf.requests); g_free(ppm_root); if (!bgpdf.has_failed) { dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Unable to start PDF loader %s.", argv[0]); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } bgpdf.has_failed = TRUE; if (bgpdf.requests != NULL) bgpdf_spawn_child(); return; } // printf("Spawned process %d\n", pid); bgpdf.pid = pid; bgpdf.status = STATUS_RUNNING; g_child_watch_add(pid, bgpdf_child_handler, NULL); g_free(ppm_root);}/* make a request */void add_bgpdf_request(int pageno, double zoom, gboolean printing){ struct BgPdfRequest *req, *cmp_req; GList *list; if (bgpdf.status == STATUS_NOT_INIT || bgpdf.status == STATUS_SHUTDOWN) return; // don't accept requests in those modes... req = g_new(struct BgPdfRequest, 1); req->is_printing = printing; if (printing) req->dpi = PDFTOPPM_PRINTING_DPI; else req->dpi = (int)floor(72*zoom+0.5);// printf("Enqueuing request for page %d at %d dpi\n", pageno, req->dpi); if (pageno >= 1) { // cancel any request this may supersede for (list = bgpdf.requests; list != NULL; ) { cmp_req = (struct BgPdfRequest *)list->data; list = list->next; if (!cmp_req->initial_request && cmp_req->pageno == pageno && cmp_req->is_printing == printing) cancel_bgpdf_request(cmp_req); } req->pageno = pageno; req->initial_request = FALSE; } else { req->pageno = 1; req->initial_request = TRUE; } bgpdf.requests = g_list_append(bgpdf.requests, req); if (!bgpdf.pid) bgpdf_spawn_child();}/* shutdown the PDF reader */void shutdown_bgpdf(void){ GList *list; struct BgPdfPage *pdfpg; struct BgPdfRequest *req; if (bgpdf.status == STATUS_NOT_INIT || bgpdf.status == STATUS_SHUTDOWN) return; refstring_unref(bgpdf.filename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -