/* @(#)graphics.c 1.10 89/12/11 * * Independent graphics routines associated with the popi program. * * Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs. * This version is based on the code in his Prentice Hall book, * "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7, * which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. * * Permission is given to distribute these extensions, as long as these * introductory messages are not removed, and no monies are exchanged. * * No responsibility is taken for any errors or inaccuracies inherent * either to the comments or the code of this program, but if reported * (see README file) then an attempt will be made to fix them. */ #include "popi.h" #include "graphics.h" #define RES 8 char nextline[MAXLINE] ; /* Next input line to be parsed. */ unsigned char *mptr ; /* Pointer to scanline data. */ int errpos = -1 ; /* Character position error occured at. */ int iscolor ; /* Set if this is a color screen. */ int ix = 0 ; /* Initial X position of the icon. */ int iy = 0 ; /* Initial Y position of the icon. */ int nfont_width ; /* Width of normal font characters. */ int ops[MAXOPS] ; /* Rasterop functions. */ int posspec = 0 ; /* Set if -g option is present (for X11) */ int started = 0 ; /* Set if we've drawn the percent dialog box. */ int tptr = 0 ; /* Input buffer pointer. */ int wx = 0 ; /* Initial X position of the open window. */ int wy = 0 ; /* Initial Y position of the open window. */ int thresh[RES][RES] = { /* Array containing threshold values. */ { 0, 128, 32, 160, 8, 136, 40, 168, }, { 192, 64, 224, 96, 200, 72, 232, 104, }, { 48, 176, 16, 144, 56, 184, 24, 152, }, { 240, 112, 208, 80, 248, 120, 216, 88, }, { 12, 140, 44, 172, 4, 132, 36, 164, }, { 204, 76, 236, 108, 196, 68, 228, 100, }, { 60, 188, 28, 156, 52, 180, 20, 148, }, { 252, 124, 220, 92, 244, 116, 212, 84, }, } ; extern int errno ; extern char *sys_errlist[] ; /* There are ten exportable routines used by the popi program. * * These are: * * disp_init(argc, argv) - called from main at the start. * disp_finish() - called from main prior to exit. * disp_imgstart() - called prior to drawing an image. * disp_imgend() - called after drawing an image. * disp_putline(line, y) - to draw an image scanline. * disp_getchar() - to get the next character typed. * disp_ungetc(c) - put back the last character typed. * disp_prompt() - display popi prompt and clear input buffer. * disp_error(errtype, pos) - display error message. * disp_percentdone(n) - display percentage value of conversion. */ void disp_init(argc, argv) /* Called from main at the start. */ int argc ; char *argv[] ; { if (init_ws_type()) /* Determine window system type. */ { FPRINTF(stderr, "Error initialising window system.\n") ; exit(1) ; } init_fonts() ; /* Open required fonts. */ make_items(argc, argv) ; /* Create icon, frame, canvas etc.. */ paint_canvas() ; /* Draw dialog boxes. */ start_tool() ; } void disp_finish() /* Called from main prior to exit. */ { cleanup() ; } void disp_imgstart() /* Called prior to drawing an image. */ { } void disp_imgend() /* Called after drawing an image. */ { } void disp_putline(line, y) /* Draw an image scanline. */ unsigned char *line ; int y ; { draw_scanline(line, y) ; } disp_getchar() /* Get next user typed character. */ { char c ; int finished = 0 ; if (tptr >= strlen(nextline)) { while (!finished) { get_next_char(&c) ; /* Get next character typed. */ if (c == '\0') continue ; if (errpos != -1) { drawarea(BOXX+100+errpos*nfont_width, BOXY+BOXH-9, nfont_width, 4, GCLR) ; drawarea(BOXX+91, BOXY+51, BOXW-102, BOXH-22, GCLR) ; errpos = -1 ; } if (c == BACKSPACE || c == DEL) nextline[strlen(nextline)-1] = '\0' ; else if (c == RETURN || c == LINEFEED) { set_cursor(BUSY_CUR) ; /* We will now get busy! */ c = '\n' ; STRNCAT(nextline, &c, 1) ; finished = 1 ; } else if (c >= 32) STRNCAT(nextline, &c, 1) ; drawarea(BOXX+91, BOXY+11, BOXW-102, BOXH-22, GCLR) ; put_text(BOXX, BOXY, BOXW, BOXH, nextline, 1) ; } tptr = 0 ; } return(nextline[tptr++]) ; } /*ARGSUSED*/ void disp_ungetc(c) /* Put back the last character typed. */ char c ; { tptr-- ; } disp_prompt() /* Display popi prompt and clear input line. */ { set_cursor(NORMAL_CUR) ; if (errpos == -1) drawarea(BOXX+91, BOXY+11, BOXW-102, BOXH-22, GCLR) ; STRCPY(nextline, "") ; tptr = 0 ; return 0 ; } void disp_error(errtype, pos) /* Display error message. */ int errtype ; int pos ; { errpos = pos ; if (errtype & ERR_PARSE) drawarea(BOXX+100+errpos*nfont_width, BOXY+BOXH-9, nfont_width, 4, GSET) ; put_text(BOXX, BOXY+40, BOXW, BOXH, ErrBuf, 0) ; /* We assume errno hasn't been reset by the preceding output */ if (errtype & ERR_SYS) { sleep(2) ; SPRINTF(ErrBuf, "\t(%s)\n", sys_errlist[errno]) ; drawarea(BOXX+91, BOXY+51, BOXW-102, BOXH-22, GCLR) ; put_text(BOXX, BOXY+40, BOXW, BOXH, ErrBuf, 0) ; } } /* These are other independent graphics routines used by popi. */ draw_frame(x, y, width, height) int x, y, width, height ; { drawarea(x, y, width, height, GSET) ; drawarea(x+1, y+1, width-2, height-2, GCLR) ; drawarea(x+3, y+3, width-6, height-6, GSET) ; drawarea(x+5, y+5, width-10, height-10, GCLR) ; } /* Display a text box of given width and height with top left corner at * the given x,y location, displaying a title and the given text value. */ draw_textbox(x, y, w, h, title, str, showcur) int x, y, w, h, showcur ; char *title, *str ; { draw_frame(x, y, w, h) ; drawtext(x+10, y+h-15, BFONT, title) ; draw_rect(x+90, y+10, x+w-10, y+h-10) ; put_text(x, y, w, h, str, showcur) ; } draw_rect(x1, y1, x2, y2) int x1, y1, x2, y2 ; { drawline(x1, y1, x2, y1) ; drawline(x1, y1, x1, y2) ; drawline(x2, y1, x2, y2) ; drawline(x1, y2, x2, y2) ; } halftone(line, y) /* Halftone 8bit scanline image. */ unsigned char *line ; int y ; { int x ; for (x = 0; x < Xsize; x++) if (line[x] < thresh[y % RES][x % RES]) mptr[x / 8] |= (1 << (7 - (x % 8))) ; /* Set pixel black. */ else mptr[x / 8] &= ~(1 << (7 - (x % 8))) ; /* Set pixel white. */ } /* Paint the contents of the popi canvas. This consists of first clearing * the whole canvas, then drawing a line to distinguish between the image * drawing area and the command feedback area. Two text boxes are then * drawn, one for user input and the other to shown any error messages. */ paint_canvas() { drawarea(0, 0, TWIDTH, THEIGHT, GCLR) ; drawline(0, 99, TWIDTH, 99) ; draw_textbox(BOXX, BOXY, BOXW, BOXH, "Command:", nextline, 1) ; draw_textbox(BOXX, BOXY+40, BOXW, BOXH, "Error:", "", 0) ; } /* With the screen based window systems, display the character string * str at the given x,y location. The width of the dialog box is given, * so that if the text exceeds the displayable area, it is scrolled to * the left. A soft cursor in the form of a vertical line is shown if * so requested. */ put_text(x, y, w, h, str, showcur) int x, y, w, h ; char *str ; { char dummy[MAXLINE] ; int limit, nochars ; limit = ((w - 100) / nfont_width) - 1 ; nochars = (strlen(str) <= limit) ? strlen(str) : limit ; STRNCPY(dummy, &str[strlen(str) - nochars], nochars) ; dummy[nochars] = '\0' ; drawtext(x+100, y+h-17, NFONT, dummy) ; if (showcur) drawline(x+100+strlen(dummy)*nfont_width, y+15, x+100+strlen(dummy)*nfont_width, y+h-15) ; } /* Show the percentage of the image converted as a graphical slider using * the error dialog box. If the percentage is zero, then we are just starting, * so the box is relabeled (to % done:). If the percentage is 100, then we * are just finishing, and the box is relabel back (to Error:), and cleared. * Otherwise we show an intermediate percentage value. */ void disp_percentdone(percent) int percent ; { if (!percent) { if (!started) draw_textbox(BOXX, BOXY+40, BOXW, BOXH, "% done:", "", 0) ; started = 1 ; } else if (percent == 100) { if (started) draw_textbox(BOXX, BOXY+40, BOXW, BOXH, "Error:", "", 0) ; started = 0 ; } else drawarea(BOXX+91, BOXY+51, (int) ((double) (BOXW-102) / 100 * percent), BOXH-20, GSET) ; }