/* * dvipage: DVI Previewer Program for Suns * * Neil Hunt (hunt@spar.slb.com) * * This program is based, in part, upon the program dvisun, * distributed by the UnixTeX group, extensively modified by * Neil Hunt at the Schlumberger Palo Alto Research Laboratories * of Schlumberger Technologies, Inc. * * From the dvisun manual page entry: * Mark Senn wrote the early versions of [dvisun] for the * BBN BitGraph. Stephan Bechtolsheim, Bob Brown, Richard * Furuta, James Schaad and Robert Wells improved it. Norm * Hutchinson ported the program to the Sun. Further bug fixes * by Rafael Bracho at Schlumberger. * * Copyright (c) 1988 Schlumberger Technologies, Inc 1988. * Anyone can use this software in any manner they choose, * including modification and redistribution, provided they make * no charge for it, and these conditions remain unchanged. * * This program is distributed as is, with all faults (if any), and * without any warranty. No author or distributor accepts responsibility * to anyone for the consequences of using it, or for whether it serves any * particular purpose at all, or any other reason. * * $Log: dvipage.c,v $ * Revision 1.6 88/12/15 09:08:03 hunt * Added iteration to gobble inputs in panning and magnifier. * * Revision 1.5 88/11/28 18:39:21 hunt * Major rewrite for 4.0 and sparc architecture. * Split up into multiple files for easier maintenance. * Reads GF files as well as PXL files now. * * Revision 1.4 88/11/26 11:10:53 hunt * Used varargs with *_prompt() functions for correct behaviour on a sun4. * * Revision 1.3 88/08/30 13:04:13 hunt * Changed default cmap for darker looking letters. * * Revision 1.2 88/08/30 09:26:29 hunt * Fixed problem pointed out by pell@rainier.UUCP * (pell@rainier.se, enea!rainier!pell@uunet.UU.NET) * so that opened files are closed on exec, and do not clutter up * space in print spoolers which may be invoked * to print the document. * * Revision 1.1 88/08/30 09:05:19 hunt * Initial revision * * HISTORY * * 12 April 1988 - Neil Hunt * Version 2.0 released for use. * * 11 April 1988 - Neil Hunt * Applied fixes supplied by Rafael Bracho (Schlumberger Austin) * for operation on Sun-4 workstations. * * Earlier history unavailable. */ #include #include #include #include #include #include /* For MAXPATHLEN */ #include #include #include #include #include #include "dvipage.h" #include "dvi.h" #define GOBBLE_PAN #define GOBBLE_MAGNIFY /* * Forward functions. * ================= */ forward int main(); forward Notify_value page_paint(); forward Notify_value page_event(); forward int page_menu(); forward void page_magnify(); forward void page_pan(); forward bool goto_sheet(); forward bool goto_page(); forward bool init_dvi_file(); forward void close_dvi_file(); forward bool check_dvi_file(); forward bool read_postamble(); forward bool find_postamble_ptr(); forward bool process_page(); forward void set_font_num(); forward void set_char(); forward void set_rule(); forward void move_down(); forward void move_over(); forward char * a_prog_name; forward char a_next(); forward char * a_arg(); forward double a_number(); forward int a_integer(); /* * Internal data structures. * ======================== */ struct stack_entry /* stack entry */ { int h, v, w, x, y, z; /* what's on stack */ }; /* * Globals. * ======= */ int hconv, vconv; /* converts DVI units to pixels */ int num; /* numerator specified in preamble */ int den; /* denominator specified in preamble */ int mag; /* magnification specified in preamble */ struct font_entry *fontptr; /* font_entry pointer */ struct font_entry *hfontptr=NULL;/* font_entry pointer */ double page_w = PAGE_WIDTH; /* page width (inches) */ double page_h = PAGE_HEIGHT; /* page width (inches) */ int h; /* current horizontal position */ int hh; /* current horizontal position in pixels */ int v; /* current vertical position */ int vv; /* current vertical position in pixels */ bool pre_load = TRUE; /* preload the font descriptions? */ bool silent = FALSE; /* suppress messages */ bool show_page_frame = FALSE; /* show page window */ long postambleptr; /* Pointer to the postamble */ char *font_path; /* Font path name for search */ bool use_gf = USE_GF; /* Enable the use of GF fonts. */ bool use_pxl = USE_PXL; /* Enable the use of PXL fonts. */ bool use_pk = USE_PK; /* Enable the use of PK fonts. */ FILE *dvifp = NULL; /* File pointer */ struct stat stat_buf; /* For checking file changes. */ time_t mtime = 0; char label[STRSIZE]; char pathname[STRSIZE] = ""; /* Complete path */ char directory[STRSIZE] = ""; /* Directory */ char filename[STRSIZE] = ""; /* File name */ char print_spooler[STRSIZE] = PRINT_SPOOLER; /* Print commands. */ char print_page_spooler[STRSIZE] = PRINT_PAGE_SPOOLER; int last_sheet = 0; /* Sheet number of last page in file */ int file_sheet = 1; /* Position of file pointer */ int disp_sheet = 0; /* Current displayed page */ int disp_page = 0; /* Real Page number */ int sheet_page[MAX_SHEETS]; /* Page number of each sheet. */ long sheet_table[MAX_SHEETS]; /* pointers to start of each page in file */ int last_known_sheet = 0; /* Points to table at next unread sheet */ int resolution = 0; /* Assumed screen resolution for rendering */ int sampling = 0; /* Sample down sampling factor */ bool mono; /* Monochrome screen */ Frame disp_frame; /* Frame for display window. */ Canvas disp_canvas; /* Canvas for display window. */ struct mem_pixrect page_mpr; /* Page bitmap. */ struct pixrect *page_pr; struct mem_pixrect sample_mpr; /* Sampled/filtered bitmap. */ struct pixrect *sample_pr; int origin_x; /* Nominal origin of the dvi on the page */ int origin_y; /* Nominal origin of the dvi on the page */ int offset_x; /* Offsets of page in window. */ int offset_y; /* Offsets of page in window. */ int start_x; /* Starting position of page in the window */ int start_y; /* Starting position of page in the window */ int verbose; /* Flags for debugging. */ int mag_size_x = DEFAULT_MAG_SIZE_X; /* Magnifier parameters. */ int mag_size_y = DEFAULT_MAG_SIZE_Y; int mag_border = DEFAULT_MAG_BORDER; forward uchar cmap_red[]; forward uchar cmap_green[]; forward uchar cmap_blue[]; short icon_image[] = { /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 */ 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001, 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001, 0x8000,0x0000,0x00C0,0x0001,0x8000,0x0000,0x0338,0x0001, 0x8000,0x0000,0x0447,0x0001,0x8000,0x0000,0x1911,0xE001, 0x8000,0x0000,0x2888,0x9E01,0x8000,0x0000,0xC222,0x23C1, 0x8000,0x0001,0x4444,0x4479,0x8000,0x0007,0x1111,0x1117, 0x8000,0x0008,0x8888,0x8889,0x8000,0x0032,0x2222,0x2223, 0x8000,0x0044,0x4444,0x4445,0x8000,0x0191,0x1111,0x1111, 0x8000,0x0288,0x8888,0x888B,0x8000,0x0C22,0x2222,0x2225, 0x8000,0x1444,0x4444,0x4447,0x8000,0x6111,0x1111,0x1119, 0x8000,0xC888,0x8888,0x889B,0x8000,0xB222,0x2222,0x2235, 0x8000,0xCE44,0x4444,0x446B,0x8000,0x91D1,0x1111,0x11D5, 0x8000,0x88B8,0x8888,0x88AB,0x8000,0xAC2E,0x2222,0x2355, 0x8000,0xC345,0xC444,0x46AB,0x8000,0x9CD1,0x3111,0x1555, 0x8000,0xB338,0x8E88,0x8AA5,0x8000,0xE0C6,0x23E2,0x3559, 0x8000,0xC039,0x8474,0x56B1,0x8000,0xC006,0x611F,0x2D41, 0x8000,0x9001,0x9C89,0xDEA1,0x8001,0x0C00,0x6322,0xFD41, 0x8002,0x43E0,0x1CC4,0xBE81,0x8004,0x2C18,0x0331,0xFD01, 0x8008,0x3606,0x00C8,0xBB01,0x8031,0xC781,0x0032,0xF601, 0x8040,0x4CC1,0x0014,0xAC01,0x818C,0x9840,0xC021,0xD801, 0x8602,0xB208,0xB048,0xA801,0x9861,0x6788,0x4CC2,0xD001, 0xB011,0xCCD9,0xC0C4,0xA001,0xA30D,0x1817,0x60B1,0xC001, 0x9883,0x3E1C,0x590E,0xC001,0x8463,0x6270,0x4101,0x8001, 0x821F,0xC1D0,0xC100,0x0001,0x813F,0xB310,0xB200,0x0001, 0x81FC,0x5831,0x0200,0x0001,0x87F8,0x4021,0x0400,0x0001, 0x9F8C,0x3006,0xC400,0x0001,0x9E07,0x0C18,0x0800,0x0001, 0x8C00,0x83E8,0x1000,0x0001,0x8000,0x6106,0x2000,0x0001, 0x8000,0x18C0,0x4000,0x0001,0x8000,0x0430,0x8000,0x0001, 0x8000,0x0309,0x0000,0x0001,0x8000,0x0081,0x0000,0x0001, 0x8000,0x0062,0x0000,0x0001,0x8000,0x0014,0x0000,0x0001, 0x8000,0x0008,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001, 0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF }; DEFINE_ICON_FROM_IMAGE(icon, icon_image); short hand[] = { 0x0C00,0x1200,0x1200,0x1380,0x1240,0x7270,0x9248,0x924E, 0x9249,0x9249,0x9009,0x8001,0x4002,0x4002,0x2004,0x2004 }; mpr_static(hand_pr, 16, 16, 1, hand); Cursor hand_cursor; /* * Functions. * ========= */ /* * main: * Interpret args, open windows, loop forever. */ int main(argc, argv) int argc; char *argv[]; { int f; char opt; char *slash; char *extension; Pixwin *pw; bool fake_mono; char *printer; double set_origin_x; double set_origin_y; double set_start_x; double set_start_y; /* * local initialisations. */ fake_mono = FALSE; set_origin_x = 0.0; set_origin_y = 0.0; set_start_x = 0.0; set_start_y = 0.0; /* * Customise this part for your local printer environment. * ====================================================== */ #ifdef SPAR_HACKS /* * Set local printer hacks. */ printer = getenv("PRINTER"); if(printer && strncmp(printer, "lw", 2) == 0) { sprintf(print_spooler, "dvips -P%s %%s >/dev/null 2>/dev/null", printer); sprintf(print_page_spooler, "dvips -P%s -f %%d -t %%d %%s >/dev/null 2>/dev/null", printer); } else if(printer && strncmp(printer, "im", 2) == 0) { sprintf(print_spooler, "dviimp -P%s %%s >/dev/null 2>/dev/null", printer); sprintf(print_page_spooler, "dviimp -P%s -S %%d -E %%d %%s >/dev/null 2>/dev/null", printer); } else { fprintf(stderr, "PRINTER environment not recognised:\n"); fprintf(stderr, " using `%s' to print files\n", print_spooler); fprintf(stderr, " using `%s' to print pages\n", print_page_spooler); } if(verbose & DEBUG_PRINTER) { fprintf(stderr, "Using `%s' to print files\n", print_spooler); fprintf(stderr, "Using `%s' to print pages\n", print_page_spooler); } #endif SPAR_HACKS /* * Find font path environment. */ if((font_path = getenv(FONT_PATH)) == NULL) font_path = FONT_AREA; /* * Get cursor. */ hand_cursor = cursor_create( CURSOR_IMAGE, &hand_pr, CURSOR_XHOT, 5, CURSOR_YHOT, 0, CURSOR_OP, PIX_SRC ^ PIX_DST, 0); /* * Create a disp_frame. */ disp_frame = window_create(0, FRAME, WIN_X, 300, WIN_Y, 50, WIN_WIDTH, (int)(page_w * DEFAULT_COLOUR_RES / DEFAULT_COLOUR_SAMPLING) + 10, WIN_HEIGHT, (int)(page_h * DEFAULT_COLOUR_RES / DEFAULT_COLOUR_SAMPLING) + 20, FRAME_ARGC_PTR_ARGV, &argc, argv, FRAME_LABEL, DVIPAGE_LABEL, FRAME_ICON, &icon, 0); /* * Create the disp_canvas. */ disp_canvas = window_create(disp_frame, CANVAS, CANVAS_RETAINED, FALSE, CANVAS_AUTO_CLEAR, FALSE, CANVAS_FIXED_IMAGE, TRUE, WIN_CURSOR, hand_cursor, WIN_CONSUME_PICK_EVENTS, WIN_NO_EVENTS, LOC_DRAG, WIN_MOUSE_BUTTONS, LOC_WINENTER, /* Otherwise misses first event */ LOC_WINEXIT, 0, WIN_CONSUME_KBD_EVENTS, WIN_NO_EVENTS, WIN_ASCII_EVENTS, WIN_LEFT_KEYS, /* For Expose, Hide, Close etc. */ KBD_USE, /* Otherwise click to type doesn't work */ KBD_DONE, 0, CANVAS_REPAINT_PROC, page_paint, WIN_EVENT_PROC, page_event, WIN_WIDTH, WIN_EXTEND_TO_EDGE, WIN_HEIGHT, WIN_EXTEND_TO_EDGE, 0); /* * Interpret args. */ f = 0; while((opt = a_next(argc, argv)) != A_END) { switch(opt) { default: fprintf(stderr, "%s: illegal flag -%c\n", a_prog_name, opt); /* FALLTHROUGH */ case 'H': fprintf(stderr, "Usage: %s \\\n", a_prog_name); fprintf(stderr, " [-v mode] # Verbose mode (for debugging) \\\n"); fprintf(stderr, " [-m] # Force monochrome mode \\\n"); fprintf(stderr, " [-p font-file-path] # List of font directories \\\n"); fprintf(stderr, " [-P flag] # Enable or disable the use of PXL files \\\n"); fprintf(stderr, " [-K flag] # Enable or disable the use of PK files \\\n"); fprintf(stderr, " [-G flag] # Enable or disable the use of GF files \\\n"); fprintf(stderr, " [-l] # Don't preload font data \\\n"); fprintf(stderr, " [-q] # Quiet: no warning messages \\\n"); fprintf(stderr, " [-f] # Show rendering frame on page \\\n"); fprintf(stderr, " [-r res] # Use `res' dpi fonts \\\n"); fprintf(stderr, " [-s sample] # Reduce by factor of `sample' \\\n"); fprintf(stderr, " [-x x] [-y y] # Initial pos of sheet in inches \\\n"); fprintf(stderr, " [-X ox] [-Y oy] # Pos of (0, 0) on page in inches \\\n"); fprintf(stderr, " [-w width] [-h height] # Total size of page in inches \\\n"); fprintf(stderr, " [dvifile[.dvi]]\n"); exit(1); case 'v': verbose = a_integer(argc, argv); break; case 'm': fake_mono = TRUE; break; case 'p': font_path = a_arg(argc, argv); break; case 'P': use_pxl = a_integer(argc, argv); break; case 'K': use_pk = a_integer(argc, argv); break; case 'G': use_gf = a_integer(argc, argv); break; case 'l': pre_load = ! pre_load; break; case 'q': silent = ! silent; break; case 'f': show_page_frame = ! show_page_frame; break; case 'r': resolution = a_integer(argc, argv); break; case 's': sampling = a_integer(argc, argv); break; case 'x': set_start_x = a_number(argc, argv); break; case 'y': set_start_y = a_number(argc, argv); break; case 'X': set_origin_x = a_number(argc, argv); break; case 'Y': set_origin_y = a_number(argc, argv); break; case 'w': page_w = a_number(argc, argv); break; case 'h': page_h = a_number(argc, argv); break; case A_ARG: switch(f++) { case 0: /* * Get the whole pathname. */ strcpy(pathname, a_arg(argc, argv)); /* * Get the filename and directory */ strcpy(directory, pathname); if((slash = rindex(directory, '/')) != NULL) { strcpy(filename, slash+1); *++slash = '\0'; } else { directory[0] = '\0'; strcpy(filename, pathname); } /* * If the filename has no extension, or if it * has an extension and it is not '.dvi' then * cat .dvi onto the filename. */ if((extension = rindex(pathname, '.')) == NULL || strcmp(extension, ".dvi") != 0) strcat(pathname, ".dvi"); break; default: fprintf(stderr, "%s: too many dvi files\n", a_prog_name); exit(1); } break; } } pw = canvas_pixwin(disp_canvas); /* * Now that we know whether we are on a colour machine or a monochrome, * we can set the defaults for the resolution and sampling, unless * they have already been set from the args. */ if(fake_mono || (pw->pw_pixrect->pr_depth == 1)) { /* * Monochrome */ mono = TRUE; if(resolution == 0) resolution = DEFAULT_MONO_RES; if(sampling == 0) sampling = DEFAULT_MONO_SAMPLING; } else { /* * Colour */ mono = FALSE; if(resolution == 0) resolution = DEFAULT_COLOUR_RES; if(sampling == 0) sampling = DEFAULT_COLOUR_SAMPLING; /* * Compute and set a colour map */ make_cmap(); pw_setcmsname(pw, "dvipage-greys"); pw_putcolormap(pw, 0, 64, cmap_red, cmap_green, cmap_blue); } /* * Now that we know the resolution and sampling, we can set * the margin and origin properly. */ if(set_origin_x != 0.0) origin_x = (int)(set_origin_x * resolution); else origin_x = (int)(DEFAULT_ORIGIN_X * resolution); if(set_origin_y != 0.0) origin_y = (int)(set_origin_y * resolution); else origin_y = (int)(DEFAULT_ORIGIN_Y * resolution); if(set_start_x != 0.0) start_x = (int)(set_start_x * resolution); else start_x = (int)(DEFAULT_START_X * resolution); if(set_start_y != 0.0) start_y = (int)(set_start_y * resolution); else start_y = (int)(DEFAULT_START_Y * resolution); /* * Insert the window into the heap now, so that if a message is * generated by the init_dvi_file below, it is displayed after the * window, and is therefore on top of it. If we display the window * after doing the initialisation of the dvi file, it would obscure * any error messages which might have been generated. */ window_set(disp_frame, WIN_SHOW, TRUE, 0); /* * If we don't run the notifier at this time, the window will * not be painted, and the effect will be a gross area of the * screen which is not painted, through which the previous windows * are still visible. */ notify_dispatch(); /* * If there was a filename specified, then open it * and prepare the first page. */ if(f >= 1) { /* * Init the file. */ if(init_dvi_file()) { process_page(RASTERISE); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(disp_canvas, pw, 0); } } else getwd(directory); /* * Loop forever in the notifier. */ notify_start(); } /* * Window Functions. * ================ */ /* * page_paint: * Called whenever the window is to be painted. * Just maps the sampled pixrect into the screen at the appropriate * offset position. */ Notify_value page_paint(canvas, pw, area) Canvas canvas; Pixwin *pw; Rectlist *area; { if(sample_pr == NULL) { pw_rop(pw, 0, 0, (int)window_get(canvas, WIN_WIDTH), (int)window_get(canvas, WIN_HEIGHT), PIX_CLR, NULL, 0, 0); sprintf(label, "%s: No File", DVIPAGE_LABEL); window_set(disp_frame, FRAME_LABEL, label, 0); } else { pw_cover(pw, 0, 0, (int)window_get(canvas, WIN_WIDTH), (int)window_get(canvas, WIN_HEIGHT), PIX_SRC, sample_pr, -offset_x, -offset_y); sprintf(label, "%s: File \"%s\" %s %d", DVIPAGE_LABEL, filename, (last_sheet && disp_sheet >= last_sheet-1)? "Last page" : "Page", disp_page); window_set(disp_frame, FRAME_LABEL, label, 0); } } /* * page_event: * Called whenever an input event arrives at the window. * Controls panning of the page, turning to the next page, * and reloading a new file. */ Notify_value page_event(canvas, event, arg) Window canvas; Event *event; caddr_t arg; { Pixwin *pw; int e; int pp; bool page_or_sheet; static int num = 0; static bool valid_num = FALSE; bool keep_num; char *extension; char command[STRSIZE]; double x, y; if(event_is_up(event)) return; pw = canvas_pixwin(canvas); keep_num = FALSE; if(verbose & DEBUG_SHEET) fprintf(stderr, "page_event: num = %d @ %d\n", num, valid_num); /* * If there is a call for a menu, then translate that into * a command character. */ if((e = event_id(event)) == MS_RIGHT) if((e = page_menu(canvas, pw, event)) == 0) return; switch(e) { case MS_LEFT: page_magnify(canvas, pw, event); break; case MS_MIDDLE: page_pan(canvas, pw, event); break; default: if(e >= '0' && e <= '9') num = num * 10 + e - '0'; else if(e == DEL || e == Control('H')) num = num / 10; else break; keep_num = TRUE; valid_num = TRUE; break; case '\r': /* Next page */ case 'n': case ' ': case '+': if(! valid_num) num = 1; if(! goto_sheet(disp_sheet + num)) break; process_page(RASTERISE); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); break; case '\n': /* Previous page */ case 'p': case '-': if(! valid_num) num = 1; if(! goto_sheet(disp_sheet - num)) break; process_page(RASTERISE); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); break; case '_': num = 1; valid_num = TRUE; /* FALLTHROUGH */ case 'G': if(! valid_num) num = LAST_PAGE; if(! goto_sheet(num)) break; process_page(RASTERISE); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); break; case 'g': if(! valid_num) num = LAST_PAGE; if(! goto_page(num)) break; process_page(RASTERISE); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); break; case 'h': /* Home page */ offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); break; case 'l': /* Left page */ offset_x -= 200; page_paint(canvas, pw, 0); break; case 'r': /* Right page */ offset_x += 200; page_paint(canvas, pw, 0); break; case 'u': /* Up page */ offset_y -= 300; page_paint(canvas, pw, 0); break; case 'd': /* Down page */ offset_y += 300; page_paint(canvas, pw, 0); break; case 'm': /* Mark margins */ start_x = offset_x * sampling; start_y = offset_y * sampling; break; case 'M': /* Set margins */ x = ((double)start_x / resolution); y = ((double)start_y / resolution); if(! doubles_prompt(1152/2, 900/2, "left margin: (inches) ", &x, "top margin: (inches) ", &y, 0)) break; start_x = (int)(x * resolution); start_y = (int)(y * resolution); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); break; case '*': case '!': case '@': case '#': case '$': case '%': case '^': valid_num = TRUE; if(e == '*') num = (mono ? DEFAULT_MONO_SAMPLING : DEFAULT_COLOUR_SAMPLING); else if(e == '!') num = 1; else if(e == '@') num = 2; else if(e == '#') num = 3; else if(e == '$') num = 4; else if(e == '%') num = 5; else valid_num = FALSE; /* FALLTHROUGH */ case 's': if(mono) break; if(! valid_num || (num < 1 || num > 5)) sampling = DEFAULT_COLOUR_SAMPLING; else sampling = num; sample_page(); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); break; case 'S': if(mono) break; if(! integers_prompt(1152/2, 900/2, "sampling: (1, 2, 3, 4) ", &sampling, 0)) break; if(sampling < 1 || sampling > 5) sampling = DEFAULT_COLOUR_SAMPLING; sample_page(); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); break; case 'x': if(valid_num) mag_size_x = num; else mag_size_x = DEFAULT_MAG_SIZE_X; break; case 'y': if(valid_num) mag_size_y = num; else mag_size_y = DEFAULT_MAG_SIZE_Y; break; case 'X': case 'Y': if(mono) break; if(! integers_prompt(1152/2, 900/2, "magnifier size (x) : ", &mag_size_x, "magnifier size (y) : ", &mag_size_y, 0)) break; break; case '[': mag_size_x = 128; mag_size_y = 64; break; case ']': mag_size_x = 128; mag_size_y = 128; break; case '{': mag_size_x = 256; mag_size_y = 128; break; case '}': mag_size_x = 256; mag_size_y = 256; break; case '(': mag_size_x = 512; mag_size_y = 256; break; case ')': mag_size_x = 512; mag_size_y = 512; break; case 'b': if(valid_num) mag_border = num; else mag_border = DEFAULT_MAG_BORDER; break; case 'F': if(! strings_prompt(1152/2, 900/2, "Directory: ", directory, "Filename: ", filename, 0)) break; /* * Build the whole pathname. */ if(directory[0] != '\0') { strcpy(pathname, directory); if(pathname[strlen(pathname)-1] != '/') strcat(pathname, "/"); strcat(pathname, filename); } else strcpy(pathname, filename); /* * If the filename has no extension, or if it * has an extension and it is not '.dvi' then * cat .dvi onto the filename. */ if((extension = rindex(pathname, '.')) == NULL || strcmp(extension, ".dvi") != 0) strcat(pathname, ".dvi"); sprintf(label, "%s: Opening file \"%s\"", DVIPAGE_LABEL, filename); window_set(disp_frame, FRAME_LABEL, label, 0); close_dvi_file(); if(init_dvi_file()) { process_page(RASTERISE); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); } break; case 'R': /* Reopen file */ sprintf(label, "%s: Reopening file \"%s\"", DVIPAGE_LABEL, filename); window_set(disp_frame, FRAME_LABEL, label, 0); if(valid_num) { pp = num; page_or_sheet = TRUE; } else { pp = disp_sheet; page_or_sheet = FALSE; } close_dvi_file(); if(init_dvi_file()) { if(page_or_sheet) { if(! goto_page(pp)) (void)goto_sheet(1); } else { if(! goto_sheet(pp)) (void)goto_sheet(1); } process_page(RASTERISE); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); } break; case 'P': sprintf(command, print_page_spooler, disp_page, disp_page, pathname); if(verbose & DEBUG_PRINTER) fprintf(stderr, "Printer command '%s'\n", command); system(command); break; case Control('P'): sprintf(command, print_spooler, pathname); if(verbose & DEBUG_PRINTER) fprintf(stderr, "Printer command '%s'\n", command); system(command); break; case 'w': show_page_frame = ! show_page_frame; if(goto_sheet(disp_sheet)) { process_page(RASTERISE); offset_x = start_x / sampling; offset_y = start_y / sampling; page_paint(canvas, pw, 0); } break; case 'v': if(valid_num) verbose = num; else verbose = 0; break; case 'Q': exit(); } if(! keep_num) { num = 0; valid_num = FALSE; } if(verbose & DEBUG_SHEET) fprintf(stderr, "end__event: num = %d @ %d\n", num, valid_num); } /* * page_menu: * Displays a menu in response to MS_RIGHT, returns a character * code to calling function to effect action. */ int page_menu(canvas, pw, event) Canvas canvas; Pixwin *pw; Event *event; { static Menu menu = NULL; int action; if(! menu) { /* * Return values from this menu are passed to the * event procedure, and the codes here must match * codes in that function. */ menu = menu_create( MENU_ITEM, MENU_STRING, "Next Page", MENU_VALUE, 'n', 0, MENU_ITEM, MENU_STRING, "Previous Page", MENU_VALUE, 'p', 0, MENU_ITEM, MENU_STRING, "First Page", MENU_VALUE, '_', 0, MENU_ITEM, MENU_STRING, "Last Page", MENU_VALUE, 'G', 0, MENU_ITEM, MENU_STRING, "Sampling", MENU_PULLRIGHT, menu_create( MENU_ITEM, MENU_STRING, "Default Sampling", MENU_VALUE, '%', 0, MENU_ITEM, MENU_STRING, "No Sampling", MENU_VALUE, '!', 0, MENU_ITEM, MENU_STRING, "2:1 Sampling", MENU_VALUE, '@', 0, MENU_ITEM, MENU_STRING, "3:1 Sampling", MENU_VALUE, '#', 0, MENU_ITEM, MENU_STRING, "4:1 Sampling", MENU_VALUE, '$', 0, 0), 0, MENU_ITEM, MENU_STRING, "Magnifier", MENU_PULLRIGHT, menu_create( MENU_ITEM, MENU_STRING, "128 x 64", MENU_VALUE, '[', 0, MENU_ITEM, MENU_STRING, "128 x 128", MENU_VALUE, ']', 0, MENU_ITEM, MENU_STRING, "256 x 128", MENU_VALUE, '{', 0, MENU_ITEM, MENU_STRING, "256 x 256", MENU_VALUE, '}', 0, MENU_ITEM, MENU_STRING, "512 x 256", MENU_VALUE, '(', 0, MENU_ITEM, MENU_STRING, "512 x 512", MENU_VALUE, ')', 0, 0), 0, MENU_ITEM, MENU_STRING, "Reopen DVI file", MENU_VALUE, 'R', 0, MENU_ITEM, MENU_STRING, "New DVI file", MENU_VALUE, 'F', 0, /* MENU_ITEM, MENU_STRING, "Print Page", MENU_VALUE, 'P', 0, MENU_ITEM, MENU_STRING, "Print Document", MENU_VALUE, Control('P'), 0, */ MENU_ITEM, MENU_STRING, "Quit", MENU_VALUE, 'Q', 0, 0); } return (int)menu_show(menu, canvas, event, 0); } /* * page_magnify: * Pops up magnified region (only if sampling != 1). * Currently unimplemented. */ void page_magnify(canvas, pw, event) Canvas canvas; Pixwin *pw; Event *event; { Rect r; int w, h; double scale_x, scale_y; int sample_w, sample_h; int new_sample_x, new_sample_y; int delta_x, delta_y; int sample_x, sample_y; int dst_x, dst_y; int page_x, page_y; int old_cursor_op; bool first_time = TRUE; int win_x, win_y; #ifdef GOBBLE_MAGNIFY int ninputs, canvasfd; #endif GOBBLE_MAGNIFY if(sampling == 1 || sample_pr == NULL) return; if(mag_size_x < 4) mag_size_x = 4; if(mag_size_y < 4) mag_size_y = 4; if(mag_size_x > sample_pr->pr_width) mag_size_x = sample_pr->pr_width; if(mag_size_y > sample_pr->pr_height) mag_size_y = sample_pr->pr_height; if(mag_border < 0) mag_border = 0; if(mag_border > 8) mag_border = 8; /* * Get Lock rect. */ r.r_left = 0; r.r_top = 0; r.r_width = (int)window_get(canvas, WIN_WIDTH); r.r_height = (int)window_get(canvas, WIN_HEIGHT); /* * Precompute some window sizes. */ w = sample_pr->pr_width; h = sample_pr->pr_height; switch(sampling) { case 2: scale_x = 2.0; scale_y = 2.0; break; case 3: scale_x = 8.0 / 3.0; scale_y = 3.0; break; case 4: scale_x = 4.0; scale_y = 4.0; break; case 5: scale_x = 8.0/3.0; scale_y = 4.0; break; default: return; } sample_w = mag_size_x / scale_x; sample_h = mag_size_y / scale_y; if(verbose & DEBUG_MAGNIFY) fprintf(stderr, "page_magnify: scale %lf %lf; %d %d -> %d %d\n", scale_x, scale_y, sample_w, sample_h, mag_size_x, mag_size_y); /* * Remove the cursor */ old_cursor_op = (int)cursor_get(hand_cursor, CURSOR_OP); cursor_set(hand_cursor, CURSOR_OP, PIX_DST, 0); window_set(canvas, WIN_CURSOR, hand_cursor, 0); /* * Grab all input */ window_set(canvas, WIN_GRAB_ALL_INPUT, TRUE, 0); #ifdef GOBBLE_MAGNIFY canvasfd = (int)window_get(canvas, WIN_FD); #endif GOBBLE_MAGNIFY /* * Loop until up mouse. */ sample_x = MAXINT; sample_y = MAXINT; while(! event_is_up(event)) { /* * Compute the region which will be magnified. */ new_sample_x = Range(0, event_x(event)-offset_x-sample_w/2, w-sample_w); new_sample_y = Range(0, event_y(event)-offset_y-sample_h/2, h-sample_h); /* * See how this differs from last magnified region. */ delta_x = new_sample_x - sample_x; delta_y = new_sample_y - sample_y; /* * Lock */ pw_lock(pw, &r); if(! first_time) { if(verbose & DEBUG_MAGNIFY) fprintf(stderr, " covering with %d %d\n", delta_x, delta_y); /* * Paint those portions of the image which were * covered by the last magnifier, and exposed now. * We could just paint the entire patch, but this * gives unpleasant flashing when moving the window. */ if(delta_x > 0) pw_cover(pw, win_x, win_y, delta_x, mag_size_y, PIX_SRC, sample_pr, dst_x, dst_y); else if(delta_x < 0) pw_cover(pw, win_x+mag_size_x+delta_x, win_y, -delta_x, mag_size_y, PIX_SRC, sample_pr, dst_x+mag_size_x+delta_x, dst_y); if(delta_y > 0) pw_cover(pw, win_x, win_y, mag_size_x, delta_y, PIX_SRC, sample_pr, dst_x, dst_y); else if(delta_y < 0) pw_cover(pw, win_x, win_y+mag_size_y+delta_y, mag_size_x, -delta_y, PIX_SRC, sample_pr, dst_x, dst_y+mag_size_y+delta_y); } else first_time = FALSE; /* * Compute the new destination and window positions * for the new magnified region. */ sample_x = new_sample_x; sample_y = new_sample_y; dst_x = sample_x - (mag_size_x - sample_w)/2; dst_y = sample_y - (mag_size_y - sample_h)/2; win_x = dst_x + offset_x; win_y = dst_y + offset_y; page_x = sample_x * scale_x; page_y = sample_y * scale_y; if(verbose & DEBUG_MAGNIFY) fprintf(stderr, " painting at %d %d from %d %d\n", dst_x, dst_y, page_x, page_y); /* * Display the magnified region. */ pw_write(pw, win_x, win_y, mag_size_x, mag_size_y, PIX_SRC, page_pr, page_x, page_y); if(mag_border) pw_rect(pw, win_x, win_y, mag_size_x, mag_size_y, mag_border, PIX_SRC, -1); /* * Unlock */ pw_unlock(pw); /* * Read another event. */ window_read_event(canvas, event); #ifdef GOBBLE_MAGNIFY if(ioctl(canvasfd, FIONREAD, &ninputs) == 0) while(ninputs >= sizeof(Event) && window_read_event(canvas, event) == 0 && ! event_is_up(event)) ninputs -= sizeof(Event); #endif GOBBLE_MAGNIFY } /* * Ungrab all input. */ window_set(canvas, WIN_GRAB_ALL_INPUT, FALSE, 0); /* * Repaint */ pw_cover(pw, win_x, win_y, mag_size_x, mag_size_y, PIX_SRC, sample_pr, dst_x, dst_y); /* * Restore the cursor. */ cursor_set(hand_cursor, CURSOR_OP, old_cursor_op, 0); window_set(canvas, WIN_CURSOR, hand_cursor, 0); } /* * page_pan: * Pans page within screen. */ void page_pan(canvas, pw, event) Canvas canvas; Pixwin *pw; Event *event; { int x, y; int dx, dy; #ifdef GOBBLE_PAN int ninputs, canvasfd; #endif GOBBLE_PAN if(sample_pr == NULL) return; window_set(canvas, WIN_GRAB_ALL_INPUT, TRUE, 0); #ifdef GOBBLE_PAN canvasfd = (int)window_get(canvas, WIN_FD); #endif GOBBLE_PAN do { x = event_x(event); y = event_y(event); window_read_event(canvas, event); #ifdef GOBBLE_PAN if(ioctl(canvasfd, FIONREAD, &ninputs) == 0) while(ninputs >= sizeof(Event) && window_read_event(canvas, event) == 0 && ! event_is_up(event)) ninputs -= sizeof(Event); #endif GOBBLE_PAN dx = event_x(event) - x; dy = event_y(event) - y; if(dx != 0 || dy != 0) { offset_x += dx; offset_y += dy; pw_cover(pw, 0, 0, (int)window_get(canvas, WIN_WIDTH), (int)window_get(canvas, WIN_HEIGHT), PIX_SRC, sample_pr, -offset_x, -offset_y); } } while(! event_is_up(event)); window_set(canvas, WIN_GRAB_ALL_INPUT, FALSE, 0); } /* * goto_sheet: * Opens requested sheet on screen. */ bool goto_sheet(new_sheet) int new_sheet; { if(! check_dvi_file()) return FALSE; if(verbose & DEBUG_SHEET) fprintf(stderr, "goto_sheet(%d)\n", new_sheet); /* * Check against page limits. */ if(new_sheet <= 0) { message("Attempt to go to sheet %d.", new_sheet); return FALSE; } /* * Are we already at the desired page ? */ if(file_sheet == new_sheet) return TRUE; /* * Do we already know where the page is ? */ if(new_sheet < MAX_SHEETS && new_sheet <= last_known_sheet) { fseek(dvifp, sheet_table[new_sheet], 0); file_sheet = new_sheet; return TRUE; } /* * Can't find it directly in the table: * Go to the last known sheet... */ file_sheet = last_known_sheet; fseek(dvifp, sheet_table[file_sheet], 0); /* * Skip through the rest of the pages to the new page. */ while(file_sheet < new_sheet) { /* * Check for last page: * Last page is always returned. */ if(last_sheet && file_sheet >= last_sheet) { file_sheet = last_sheet - 1; fseek(dvifp, sheet_table[file_sheet], 0); return TRUE; } /* * Otherwise, skip this page and look at the next. */ process_page(SKIP); } return TRUE; } /* * goto_page: * Opens requested page on screen. */ bool goto_page(new_page) int new_page; { int sheet; if(! check_dvi_file()) return FALSE; if(verbose & DEBUG_SHEET) fprintf(stderr, "goto_page(%d)\n", new_page); /* * Search for page in the table. */ for(sheet = 1; sheet < last_known_sheet; sheet++) { if(sheet_page[sheet] == new_page) { file_sheet = sheet; fseek(dvifp, sheet_table[file_sheet], 0); return TRUE; } } /* * Can't find it directly in the table: * Go to the last known sheet... */ file_sheet = last_known_sheet; fseek(dvifp, sheet_table[file_sheet], 0); /* * Skip through the rest of the pages to the new page. */ for( ; ; ) { /* * Check for last page: */ if(last_sheet && file_sheet >= last_sheet) { if(new_page == LAST_PAGE) { file_sheet = last_sheet - 1; fseek(dvifp, sheet_table[file_sheet], 0); return TRUE; } else return FALSE; } /* * Otherwise, examine this page. */ sheet = file_sheet; process_page(SKIP); /* * If this was the page, go back, * and return it. */ if(sheet_page[sheet] == new_page) { file_sheet = sheet; fseek(dvifp, sheet_table[file_sheet], 0); return TRUE; } } } /* * DVI file functions. * ================== */ /* * init_dvi_file: * Opens the dvi file, and checks for valid codes etc. * Reads the postamble (if enabled) * Leaves the file pointer at the start of the first page. */ bool init_dvi_file() { int i; /* * Open the file; close-on-exec. */ if((dvifp = fopen(pathname, "r")) == NULL) { message("Cant open file %s", pathname); return FALSE; } fcntl(fileno(dvifp), F_SETFD, 1); /* * Read the magic number and version number */ if((i = get_unsigned(dvifp, 1)) != PRE) { message("%s: not a dvi file.", filename); fclose(dvifp); return FALSE; } if((i = get_signed(dvifp, 1)) != DVIFORMAT) { message("%s: dvi format %d not supported.", filename, i); fclose(dvifp); return FALSE; } /* * Make a note of the access time. */ if(fstat(fileno(dvifp), &stat_buf) == 0) { mtime = stat_buf.st_mtime; } else { message("%s: dvifile stat failed.", filename); mtime = 0; } if(pre_load) { /* * Load font information from postable. */ if(! read_postamble()) { fclose(dvifp); return FALSE; } /* * Return to start of first page. */ fseek(dvifp, (long)14, 0); } else { /* * Read basic data from preamble. */ num = get_unsigned(dvifp, 4); den = get_unsigned(dvifp, 4); mag = get_unsigned(dvifp, 4); hconv = vconv = do_convert(num, den, resolution); } /* * Skip i more bytes of preamble. */ i = get_unsigned(dvifp, 1); fseek(dvifp, (long)i, 1); /* * Allocate buffer for the page. */ if(! (page_pr = pr_alloc(&page_mpr, (int)(page_w * resolution), (int)(page_h * resolution), 1))) { message("Out of memory for image allocation."); fclose(dvifp); return FALSE; } if(verbose & DEBUG_IMSIZE) fprintf(stderr, "Allocated buffer (%d x %d)\n", page_pr->pr_width, page_pr->pr_height); /* * Set up the page fseek pointer table. * We are now at page 0. */ for(i = 0; i < MAX_SHEETS; i++) { sheet_table[i] = 0; sheet_page[i] = BAD_PAGE; } file_sheet = 1; last_sheet = 0; /* last page == unknown */ last_known_sheet = 1; sheet_table[last_known_sheet] = ftell(dvifp); if(verbose & DEBUG_SHEET) fprintf(stderr, "sheet_table[%d] = %d\n", last_known_sheet, ftell(dvifp)); return TRUE; } /* * close_dvi_file: * Cleans up after reading a file. */ void close_dvi_file() { if(dvifp == NULL) return; /* * Get rid of image memory. */ sample_pr = pr_free(&sample_mpr); page_pr = pr_free(&page_mpr); /* * close the dvifile. */ fclose(dvifp); dvifp = NULL; mtime = 0; /* * Hack the sheet numbers to prevent access to the file. */ last_sheet = -1; last_known_sheet = -1; /* * Close the fonts and free up memory. */ close_fonts(); } /* * check_dvi_file: * Checks that this is the same file -- has not been modified since * it was opened. */ bool check_dvi_file() { if(dvifp == NULL) { message("No dvifile open"); return FALSE; } if(fstat(fileno(dvifp), &stat_buf) != 0) { message("%s: dvifile fstat failed.", filename); return FALSE; } if(stat_buf.st_mtime != mtime) { message("%s: dvifile modified", filename); return FALSE; } return TRUE; } /* * read_postamble: * This routine is used to read in the postamble values. It * initializes the magnification and checks the stack height prior to * starting printing the document. * Returns TRUE unless document cannot be processed. */ bool read_postamble() { if(! check_dvi_file()) return FALSE; if(! find_postamble_ptr (&postambleptr)) return FALSE; if(get_unsigned(dvifp, 1) != POST) { message("%s: bad dvi file: no POST at head of postamble.", filename); return FALSE; } (void)get_unsigned(dvifp, 4); /* discard last page pointer */ num = get_unsigned(dvifp, 4); den = get_unsigned(dvifp, 4); mag = get_unsigned(dvifp, 4); hconv = vconv = do_convert(num, den, resolution); (void)get_unsigned(dvifp, 4); /* height-plus-depth of tallest page */ (void)get_unsigned(dvifp, 4); /* width of widest page */ if(get_unsigned(dvifp, 2) >= STACKSIZE) { message("%s: bad dvi file: stack is too large.", filename); return FALSE; } /* last_sheet = */ get_unsigned(dvifp, 2); if(! get_font_def()) return FALSE; return TRUE; } /* * find_postamble_ptr * Move to the end of the dvifile and find the start of the postamble. */ bool find_postamble_ptr(postambleptr) long *postambleptr; { int i; fseek(dvifp, (long) 0, 2); *postambleptr = ftell(dvifp) - 4; fseek(dvifp, *postambleptr, 0); for( ; ; ) { fseek(dvifp, --(*postambleptr), 0); if(((i = get_unsigned(dvifp, 1)) != 223) && (i != DVIFORMAT)) { message("%s: Bad dvi file: bad end of file", filename); return FALSE; } if(i == DVIFORMAT) break; } fseek(dvifp, (*postambleptr) - 4, 0); *postambleptr = get_unsigned(dvifp, 4); fseek(dvifp, *postambleptr, 0); return TRUE; } /* * process_page: * Rasterises the next page in the dvifile into page_mpr. * Leaves the file pointer at the start of the next page. * * If skip mode is true, then nothing is actually drawn, the commands * are interpreted only for the side effect of moving the filepointer * to the next page. */ bool process_page(skip_mode) register bool skip_mode; { int command; /* current command */ register int i; /* command parameter; loop index */ int k; /* temporary parameter */ int val, val2; /* temporarys to hold command information*/ int w; /* current horizontal spacing */ int x; /* current horizontal spacing */ int y; /* current vertical spacing */ int z; /* current vertical spacing */ int counter[10]; int sp; /* stack pointer */ static struct stack_entry stack[STACKSIZE]; /* stack */ if(! check_dvi_file()) return FALSE; if(verbose & DEBUG_SHEET) fprintf(stderr, "sheet %d starts at %d\n", file_sheet, ftell(dvifp)); while((command = get_unsigned(dvifp, 1)) != EOP) { switch(command) { case SET1: case SET2: case SET3: case SET4: val = get_unsigned(dvifp, command-SET1+1); if(! skip_mode) set_char(val, command); break; case SET_RULE: val = get_unsigned(dvifp, 4); val2 = get_unsigned(dvifp, 4); if(! skip_mode) set_rule(val, val2, 1); break; case PUT1: case PUT2: case PUT3: case PUT4: val = get_unsigned(dvifp,command-PUT1+1); if(! skip_mode) set_char(val, command); break; case PUT_RULE: val = get_unsigned(dvifp, 4); val2 = get_unsigned(dvifp, 4); if(! skip_mode) set_rule(val, val2, 0); break; case NOP: break; case BOP: /* * These are the 10 counters. * Discard previous page pointer. */ for(i=0; i<10; i++) counter[i] = get_unsigned(dvifp, 4); (void)get_unsigned(dvifp, 4); /* * The first counter is the page number. */ disp_page = counter[0]; if(file_sheet < MAX_SHEETS) sheet_page[file_sheet] = disp_page; /* * Show what is happening. */ sprintf(label, "%s: File \"%s\" Page %d %s", DVIPAGE_LABEL, filename, disp_page, (skip_mode) ? "Skipping" : "Processing"); window_set(disp_frame, FRAME_LABEL, label, 0); if(! skip_mode) { /* * Clear the page */ pr_rop(page_pr, 0, 0, page_pr->pr_width, page_pr->pr_height, PIX_CLR, NULL, 0, 0); /* * Mark the edges of the page */ pr_rect(page_pr, 0, 0, (int)(page_w * resolution), (int)(page_h * resolution), 3, PIX_SET, 1); /* * Mark the nominal page window. */ if(show_page_frame) { pr_rect(page_pr, 0+origin_x, 0+origin_y, (int)(page_w*resolution) - 2*origin_x, (int)(page_h*resolution) - 2*origin_y, 1, PIX_SET, 1); } } h = v = w = x = y = z = 0; sp = 0; fontptr = NULL; break; case PUSH: if (sp >= STACKSIZE) { message("%s: Bad dvi file: stack overflow", filename); return FALSE; } stack[sp].h = h; stack[sp].v = v; stack[sp].w = w; stack[sp].x = x; stack[sp].y = y; stack[sp].z = z; sp++; break; case POP: --sp; if (sp < 0) { message("%s: Bad dvi file: stack underflow", filename); return FALSE; } h = stack[sp].h; v = stack[sp].v; w = stack[sp].w; x = stack[sp].x; y = stack[sp].y; z = stack[sp].z; break; case RIGHT1: case RIGHT2: case RIGHT3: case RIGHT4: val = get_signed(dvifp,command-RIGHT1+1); if(! skip_mode) move_over(val); break; case W0: if(! skip_mode) move_over(w); break; case W1: case W2: case W3: case W4: w = get_signed(dvifp,command-W1+1); if(! skip_mode) move_over(w); break; case X0: if(! skip_mode) move_over(x); break; case X1: case X2: case X3: case X4: x = get_signed(dvifp,command-X1+1); if(! skip_mode) move_over(x); break; case DOWN1: case DOWN2: case DOWN3: case DOWN4: val = get_signed(dvifp,command-DOWN1+1); if(! skip_mode) move_down(val); break; case Y0: if(! skip_mode) move_down(y); break; case Y1: case Y2: case Y3: case Y4: y = get_signed(dvifp,command-Y1+1); if(! skip_mode) move_down(y); break; case Z0: if(! skip_mode) move_down(z); break; case Z1: case Z2: case Z3: case Z4: z = get_signed(dvifp,command-Z1+1); if(! skip_mode) move_down(z); break; case FNT1: case FNT2: case FNT3: case FNT4: if(! skip_mode) set_font_num( get_unsigned(dvifp,command-FNT1+1)); break; case XXX1: case XXX2: case XXX3: case XXX4: k = get_unsigned(dvifp,command-XXX1+1); while(k--) get_unsigned(dvifp, 1); break; case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4: if(pre_load) skip_font_def( get_unsigned(dvifp, command-FNT_DEF1+1)); else if(! read_font_def( get_unsigned(dvifp, command-FNT_DEF1+1))) return FALSE; break; case PRE: message( "%s: Bad dvi file: preamble found within main section.", filename); return FALSE; case POST: fseek(dvifp, (long) -1, 1); last_sheet = file_sheet; /* * We have done nothing, so there is no need to * resample the page or increment the page counter. */ return FALSE; case POST_POST: message( "%s: Bad dvi file: postpostamble found within main section.", filename); return FALSE; default: if(command >= FONT_00 && command <= FONT_63) { if(! skip_mode) set_font_num(command - FONT_00); } else if(command >= SETC_000 && command <= SETC_127) { if(! skip_mode) set_char(command - SETC_000, command); } else { message( "%s: Bad dvi file: undefined command (%d) found.", filename, command); return FALSE; } } } /* * End of page. */ if(! skip_mode) { /* * Sample the page. */ sample_page(); disp_sheet = file_sheet; } /* * The file is now at the start of the next page. */ file_sheet++; if(file_sheet > last_known_sheet) { if(file_sheet < MAX_SHEETS) { last_known_sheet = file_sheet; sheet_table[file_sheet] = ftell(dvifp); } if(verbose & DEBUG_SHEET) fprintf(stderr, "sheet %d starts at %d\n", file_sheet, ftell(dvifp)); } return TRUE; } /* * Draw and Move Functions. * ======================== */ /* * set_font_num: * This routine is used to specify the font to be used in printing future * chars. */ void set_font_num(k) int k; { for(fontptr = hfontptr; fontptr != NULL; fontptr = fontptr->next) { if(fontptr->k == k) { fontptr->use_count++; return; } } fprintf(stderr, "I have lost a font; this cant happen\n"); exit(1); } /* * set_char: */ void set_char(c, command) int c, command; { register struct char_entry *ptr; ptr = &(fontptr->ch[c]); hh = Pix_round(h, hconv); vv = Pix_round(v, vconv); if(! ptr->where.isloaded) if(! load_char(fontptr, ptr)) return; if(ptr->where.address.pixrectptr) pr_rop(page_pr, hh - ptr->xOffset + origin_x, vv - ptr->yOffset + origin_y, ptr->width, ptr->height, PIX_SRC | PIX_DST, ptr->where.address.pixrectptr, 0, 0); if(command <= SET4) h += ptr->tfmw; return; } /* * set_rule: * This routine will draw a rule on the screen */ void set_rule(a, b, Set) int a, b; bool Set; { int ehh, evv; hh = Pix_round(h, hconv); vv = Pix_round(v - a, vconv); ehh = Pix_round(h + b, hconv); evv = Pix_round(v, vconv); if(hh == ehh) ehh++; if(vv == evv) vv--; if((a > 0) && (b > 0)) pr_rop(page_pr, hh+origin_x, vv+origin_y, ehh-hh, evv-vv, PIX_SET, NULL, 0, 0); if(Set) { h += b; /* v += a; */ } } /* * move_down: */ void move_down(a) int a; { v += a; } /* * move_over: */ void move_over(b) int b; { h += b; }