/* Hello, Emacs, this is -*-C-*- * $Id: pm.trm,v 1.53 2006/07/21 02:35:47 sfeam Exp $ */ /* GNUPLOT - pm.trm */ /*[ * Copyright 1992, 1993, 1998, 2004 * * Permission to use, copy, and distribute this software and its * documentation for any purpose with or without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. * * Permission to modify the software is granted, but not the right to * distribute the complete modified source code. Modifications are to * be distributed as patches to the released version. Permission to * distribute binaries produced by compiling modified sources is granted, * provided you * 1. distribute the corresponding source modifications from the * released version in the form of a patch file along with the binaries, * 2. add special version identification to distinguish your version * in addition to the base release version number, * 3. provide your name and address as the primary contact for the * support of your modified version, and * 4. retain our contact information in regard to use of the base * software. * Permission to distribute the released version of the source code along * with corresponding source modifications in the form of a patch file is * granted with same provisions 2 through 4 for binary distributions. * * This software is provided "as is" without express or implied warranty * to the extent permitted by applicable law. ]*/ /* * pm.trm --- inboard terminal driver for Presentation Manager * --- after X-11 driver, by R.W.Fearick 31/1/92. * v1.1 11/8/92 -- speed things up * * since March 1998: additions for mouse support implemented by Petr Mikulik * last change: January 2000 * for mouse support, pm.trm has to be compiled with USE_MOUSE, e.g. * gcc ... -DUSE_MOUSE ... * January 1999: terminal entries for PM3D functionality by Petr Mikulik */ #include "driver.h" #ifdef TERM_REGISTER register_term(pm) #endif #ifdef TERM_PROTO TERM_PUBLIC void PM_init __PROTO((void)); TERM_PUBLIC void PM_options __PROTO((void)); TERM_PUBLIC void PM_reset __PROTO((void)); TERM_PUBLIC void PM_text __PROTO((void)); TERM_PUBLIC void PM_graphics __PROTO((void)); TERM_PUBLIC void PM_linetype __PROTO((int lt)); TERM_PUBLIC void PM_move __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC void PM_vector __PROTO((unsigned int x, unsigned int y)); TERM_PUBLIC int PM_text_angle __PROTO((int ang)); TERM_PUBLIC void PM_put_text __PROTO((unsigned int x, unsigned int y, const char *str)); TERM_PUBLIC int PM_justify_text __PROTO((enum JUSTIFY mode)); TERM_PUBLIC void PM_point __PROTO((unsigned int x, unsigned int y, int number)); TERM_PUBLIC void PM_suspend __PROTO((void)); TERM_PUBLIC void PM_resume __PROTO((void)); TERM_PUBLIC void PM_fillbox __PROTO((int style, unsigned int x, unsigned int y, unsigned int w, unsigned int h)); TERM_PUBLIC void PM_linewidth __PROTO((double linewidth)); #ifdef USE_MOUSE TERM_PUBLIC void PM_set_ruler __PROTO((int, int)); TERM_PUBLIC void PM_set_cursor __PROTO((int, int, int)); TERM_PUBLIC void PM_put_tmptext __PROTO((int, const char str[])); TERM_PUBLIC void PM_set_clipboard __PROTO((const char[])); #endif TERM_PUBLIC int PM_make_palette (t_sm_palette *); #if 0 TERM_PUBLIC void PM_previous_palette (void); #endif TERM_PUBLIC void PM_set_color (t_colorspec *); TERM_PUBLIC void PM_filled_polygon (int, gpiPoint *); #ifdef WITH_IMAGE TERM_PUBLIC void PM_image __PROTO((unsigned int, unsigned int, coordval *, gpiPoint *, t_imagecolor)); #endif #ifndef PM_OLD_ENHANCED_TEXT /* To support "set term pm enhanced" */ TERM_PUBLIC void PM_enhanced_put_text __PROTO((unsigned int x, unsigned int y, const char *str)); TERM_PUBLIC void PM_enhanced_open __PROTO((char * fontname, double fontsize, double base, TBOOLEAN widthflag, TBOOLEAN showflag, int overprint)); TERM_PUBLIC void PM_enhanced_flush __PROTO((void)); #endif /* define PM world coordinate limits */ #define PM_XMAX 19500 #define PM_YMAX 12500 /* approximations for typical font/screen sizes */ #define PM_VCHAR (550) #define PM_HCHAR (220) /* Note: VCHAR AND HCHAR sizes in gnuplot 3.5 were 415 and 242, in X11 are 500 and 195, respectively. */ #if 0 /* Sizes of gnuplot 3.6 and 3.7: */ # define PM_VTIC (200) # define PM_HTIC (200) #else /* Sizes as X11: */ # define PM_VTIC (125) # define PM_HTIC (130) /* Note: sizes for VTIC and HTIC in gnuplot 3.5 were 122 and 128, respectively. */ #endif #endif #ifdef TERM_BODY #include #include #include #define INCL_DOSPROCESS #define INCL_DOSSEMAPHORES #define INCL_DOSMISC #define INCL_DOSMODULEMGR #include #include "os2/pm_msgs.h" #define PM_nopts 1 /* path for pm program */ static char PM_path[256] = ""; /* track mode to avoid redraw after hitting break */ static int PM_mode = 0; static HEV hev; static int PM_termmode = 0; static int PM_must_reset_opts = FALSE; static int PM_must_abort = 0; static char PM_opts[256] = ""; static int PM_optargs = 0; static int PM_plot_number = 0; static char PM_term_title[128] = ""; static int mouseGnupmdrv = 0; /* PM set to 1 if we are connected to a mouseable gnupmdrv */ static FILE *PM_pipe = NULL; static FILE *PM_savepipe = NULL; #ifndef PM_OLD_ENHANCED_TEXT /* track current state of pm terminal */ /* this is only needed for enhanced text */ static char * PM_font = NULL; static double PM_fontsize = 12.0; static unsigned int PM_x = 0; static unsigned int PM_y = 0; static enum JUSTIFY PM_justification = LEFT; static double PM_angle = 0.; /* unit is radian */ /* state variables for enhanced text processing */ static TBOOLEAN ENHpm_opened_string; static TBOOLEAN ENHpm_show = TRUE; static int ENHpm_overprint = 0; static TBOOLEAN ENHpm_widthflag = TRUE; static TBOOLEAN ENHpm_sizeonly = FALSE; static double ENHpm_base; #endif static void PM_reset_opts(void); static void PM_query(void); static void PM_make_servername(char *); static void PM_abortplot(); static void PM_query_font(void); TERM_PUBLIC void PM_init() { static char buffer[1024]; int pid; int rc; int spawnmode; PPIB pib; PTIB tib; char semname[32]; char pipename[32]; char tempname[32]; term_force_init = TRUE; if (PM_savepipe != NULL && PM_termmode == 0) { PM_pipe = PM_savepipe; } if ((PM_pipe == NULL) && (PM_termmode & 2)) { /* check if term is running */ PM_make_servername(tempname); strcpy(pipename, "\\pipe\\"); strcat(pipename, tempname); /* sprintf( pipename, "\\pipe\\gpServ%d", PM_plot_number ) ; */ DosGetInfoBlocks(&tib, &pib); PM_pipe = fopen(pipename, "r+b"); if (PM_pipe != NULL) { setvbuf(PM_pipe, buffer, _IOFBF, 1024); pid = pib->pib_ulpid; fwrite(&pid, 1, 4, PM_pipe); fflush(PM_pipe); /* set new options */ /* PM_reset_opts() ; */ } } /* else we start up term here */ if (PM_pipe == NULL) { if (PM_termmode & 2) { PM_make_servername(tempname); /* sprintf( tempname, "gpServ%d", PM_plot_number ) ; */ } else { static int gpid = 0; gpid++; sprintf(tempname, "gp%X%d", getpid(), gpid); } strcpy(semname, "\\sem32\\"); strcpy(pipename, "\\pipe\\"); strcat(semname, tempname); strcat(pipename, tempname); strcat(PM_path, "\\gnupmdrv.exe"); rc = access(PM_path, 0); /* find exe file */ if (rc != 0) rc = DosSearchPath(0x0002, /* search GNUPLOT environment */ "GNUPLOT", "gnupmdrv.exe", PM_path, 256); if (rc != 0) rc = DosSearchPath(0x0003, /* then try current directory & path */ "PATH", "gnupmdrv.exe", PM_path, 256); if (rc != 0) { fputs("Cannot find gnupmdrv.exe !\n", stderr); exit(3); } rc = DosCreateEventSem(semname, &hev, 1, 0); if (rc != 0) { fputs("Cannot create semaphore !\n", stderr); exit(3); } spawnmode = P_SESSION | P_DEFAULT; if (PM_optargs != 0) spawnmode |= P_UNRELATED; pid = spawnl(spawnmode, PM_path, PM_path, tempname, PM_opts, NULL); if (pid == -1) { fputs("Cannot spawn gnupmdrv.exe !\n", stderr); exit(3); } DosGetInfoBlocks(&tib, &pib); DosWaitEventSem(hev, 10000); DosCloseEventSem(hev); PM_pipe = fopen(pipename, "r+b"); if (PM_pipe == NULL) { fputs("Cannot open pipe to gnupmdrv.exe !\n", stderr); exit(3); } else if (PM_termmode == 0) PM_savepipe = PM_pipe; setvbuf(PM_pipe, buffer, _IOFBF, 1024); pid = pib->pib_ulpid; fwrite(&pid, 1, 4, PM_pipe); fflush(PM_pipe); } else { if (PM_must_reset_opts) PM_reset_opts(); } #ifdef USE_MOUSE /* PM: notify gnupmdrv that this is mouse-enhanced terminal */ putc( GR_MOUSECAPABLE, PM_pipe ) ; fflush( PM_pipe ) ; /* we catch mouseable gnupmdrv's answer in PM_query by 0xABCD */ #endif PM_query(); } static void PM_make_servername(char *str) { if (PM_term_title[0]) { int hash = 0; char *p = PM_term_title + 1; int match = PM_term_title[0]; while (*p != match) { hash = (hash << 1) + hash + *p++; } hash %= (256 * 256 * 256 - 1); sprintf(str, "gp%x", hash); } else sprintf(str, "gpServ%d", PM_plot_number); } TERM_PUBLIC void PM_options() { int old_termmode = PM_termmode; PM_termmode = 0; term_options[0] = NUL; PM_term_title[0] = NUL; PM_opts[0] = NUL; PM_optargs = 0; while (!END_OF_COMMAND) { if (almost_equals(c_token, "pe$rsist")) { strcat(PM_opts, "-p "); strcat(term_options, "persist "); PM_termmode |= 1; PM_optargs = 1; if (!(old_termmode & 1)) PM_pipe = NULL; } else if (almost_equals(c_token, "s$erver")) { strcat(PM_opts, "-s "); strcat(term_options, "server "); PM_termmode |= 2; PM_optargs = 1; if (!(old_termmode & 2)) PM_pipe = NULL; if (isanumber(c_token + 1)) { struct value t; char *p = PM_opts + strlen(PM_opts); c_token++; PM_plot_number = (int) real(const_express(&t)); sprintf(p, "%d", PM_plot_number); sprintf(term_options + strlen(term_options), "%d", PM_plot_number); } } else if (almost_equals(c_token, "w$idelines")) { strcat(PM_opts, "-w "); strcat(term_options, "widelines "); PM_optargs = 1; } else if (almost_equals(c_token, "e$nhanced")) { strcat(term_options, "enhanced "); #ifdef PM_OLD_ENHANCED_TEXT PM_optargs = 1; strcat(PM_opts, "-e "); term->put_text = PM_put_text; #else term->put_text = PM_enhanced_put_text; #endif term->flags |= TERM_ENHANCED_TEXT; } else if (almost_equals(c_token, "noe$nhanced")) { strcat(term_options, "noenhanced "); term->put_text = PM_put_text; term->flags &= ~TERM_ENHANCED_TEXT; } else if (isstring(c_token)) { copy_str(PM_term_title, c_token, 127); } #if 0 else if (almost_equals(c_token, "po$rtrait")) { strcat(PM_opts, "-l "); strcat(term_options, "portrait "); PM_optargs = 1; } #endif c_token++; } if (PM_term_title[0]) { strcat(PM_opts, " "); strcat(term_options, " "); strcat(PM_opts, PM_term_title); strcat(term_options, PM_term_title); } PM_must_reset_opts = TRUE; } static void PM_reset_opts() { int len; putc(SET_OPTIONS, PM_pipe); len = strlen(PM_opts) + 1; fwrite(&len, sizeof(int), 1, PM_pipe); fwrite(PM_opts, 1, len, PM_pipe); for (len = sizeof(int) - len % sizeof(int); len > 0; len--) { /* pad rest of int with zeros */ putc(NUL, PM_pipe); } fflush(PM_pipe); PM_must_reset_opts = FALSE; } static void PM_query() { int rc; ULONG cbR; putc(GR_QUERY, PM_pipe); fflush(PM_pipe); rc = DosRead(fileno(PM_pipe), &term->h_char, sizeof(int), &cbR); if (term->h_char == 0xABCD) { /* PM we have got greetings from mouseable gnupmdrv */ mouseGnupmdrv = 1; /* thus set mouseGnupmdrv on and reread h_char */ rc = DosRead( fileno(PM_pipe), &term->h_char, sizeof(int), &cbR ) ; } rc = DosRead(fileno(PM_pipe), &term->v_char, sizeof(int), &cbR); } # ifdef USE_MOUSE /* update menu items in PM terminal */ void PM_update_menu_items() { /* connected to a mouseable gnupmdrv */ if ((PM_pipe != NULL) && (mouseGnupmdrv)) { struct t_gpPMmenu gpPMmenu; PM_set_gpPMmenu(&gpPMmenu); putc(SET_MENU, PM_pipe); fwrite(&gpPMmenu, sizeof(gpPMmenu), 1, PM_pipe); } } #endif TERM_PUBLIC void PM_reset() { putc(GR_RESET, PM_pipe); fflush(PM_pipe); term_force_init = FALSE; if (PM_termmode > 0) { fclose(PM_pipe); PM_pipe = NULL; } } TERM_PUBLIC void PM_suspend() { putc(GR_SUSPEND, PM_pipe); fflush(PM_pipe); } TERM_PUBLIC void PM_resume() { putc(GR_RESUME, PM_pipe); fflush(PM_pipe); } TERM_PUBLIC void PM_text() { fflush(PM_pipe); if (PM_mode != SET_TEXT) { putc(SET_TEXT, PM_pipe); fflush(PM_pipe); #if 0 keep_term_initialised = term_initialised ; term_initialised = FALSE ; /* need to force init */ #endif } PM_mode = SET_TEXT; #ifdef USE_MOUSE { /* FIXME 20040712: 'extern' in a source file is always wrong. */ extern TBOOLEAN allowmotion; allowmotion = TRUE; } #endif } TERM_PUBLIC void PM_graphics() { static int last_encoding = -999; putc(SET_GRAPHICS, PM_pipe); fflush(PM_pipe); #ifdef USE_MOUSE PM_update_menu_items(); #endif if (encoding != last_encoding) { int cp; switch (encoding) { case S_ENC_ISO8859_2: cp = 912; break; case S_ENC_CP437: cp = 437; break; case S_ENC_CP850: cp = 850; break; default: /* S_ENC_DEFAULT, S_ENC_ISO8859_1 */ cp = 0; break; }; putc(SET_SPECIAL, PM_pipe); putc('c', PM_pipe); /* set codepage */ fwrite(&cp, sizeof(int), 1, PM_pipe); fflush(PM_pipe); last_encoding = encoding; } PM_mode = SET_GRAPHICS; } TERM_PUBLIC void PM_move(unsigned int x, unsigned int y) { if (PM_must_abort) PM_abortplot(); putc(GR_MOVE, PM_pipe); fwrite(&x, sizeof(int), 1, PM_pipe); fwrite(&y, sizeof(int), 1, PM_pipe); #ifndef PM_OLD_ENHANCED_TEXT /* save current position, only needed for enhanced text */ PM_x = x; PM_y = y; #endif } TERM_PUBLIC void PM_vector(unsigned int x, unsigned int y) { if (PM_must_abort) PM_abortplot(); putc(GR_DRAW, PM_pipe); fwrite(&x, sizeof(int), 1, PM_pipe); fwrite(&y, sizeof(int), 1, PM_pipe); } TERM_PUBLIC void PM_linetype(int lt) { putc(SET_LINE, PM_pipe); fwrite(<, sizeof(int), 1, PM_pipe); } TERM_PUBLIC int PM_text_angle(int ang) { putc(SET_ANGLE, PM_pipe); fwrite(&ang, sizeof(int), 1, PM_pipe); #ifndef PM_OLD_ENHANCED_TEXT /* store text angle, only needed for enhanced text */ PM_angle = (double)ang * M_PI / 180.; #endif return TRUE; } TERM_PUBLIC void PM_put_text(unsigned int x, unsigned int y, const char *str) { int len; if (PM_must_abort) PM_abortplot(); #ifdef PM_OLD_ENHANCED_TEXT if (ignore_enhanced_text) { putc(SET_SPECIAL, PM_pipe); putc('e', PM_pipe); /* switch the enhanced mode off */ putc('0', PM_pipe); } #endif putc(GR_TEXT, PM_pipe); fwrite(&x, sizeof(int), 1, PM_pipe); fwrite(&y, sizeof(int), 1, PM_pipe); len = strlen(str) + 1; fwrite(&len, sizeof(int), 1, PM_pipe); fwrite(str, 1, len, PM_pipe); for (len = sizeof(int) - len % sizeof(int); len > 0; len--) { /* pad rest of int with zeros */ putc(NUL, PM_pipe); } #ifdef PM_OLD_ENHANCED_TEXT if (ignore_enhanced_text) { putc(SET_SPECIAL, PM_pipe); putc('e', PM_pipe); /* restore the enhanced mode */ putc('2', PM_pipe); } #endif } TERM_PUBLIC int PM_justify_text(enum JUSTIFY mode) { #ifdef PM_OLD_ENHANCED_TEXT if (ignore_enhanced_text) { putc(SET_SPECIAL, PM_pipe); putc('e', PM_pipe); /* switch the enhanced mode off */ putc('0', PM_pipe); } #endif putc(SET_JUSTIFY, PM_pipe); fwrite(&mode, sizeof(int), 1, PM_pipe); #ifndef PM_OLD_ENHANCED_TEXT /* store text justification, only needed for enhanced text */ PM_justification = mode; #else if (ignore_enhanced_text) { putc(SET_SPECIAL, PM_pipe); putc('e', PM_pipe); /* restore the enhanced mode */ putc('2', PM_pipe); } #endif return TRUE; } TERM_PUBLIC int PM_set_font(const char *font) { unsigned int len; putc(SET_FONT, PM_pipe); if (font == NULL) len = 0; else len = strlen(font); if (len==0) { fwrite(&len, sizeof(int), 1, PM_pipe); } else { len += 1; fwrite(&len, sizeof(int), 1, PM_pipe); fwrite(font, 1, len, PM_pipe); for (len = sizeof(int) - len % sizeof(int); len > 0; len--) { /* pad rest of int with zeros */ putc(NUL, PM_pipe); } } return TRUE; } #ifndef PM_OLD_ENHANCED_TEXT /* PM_query_font: get current font name and size from gnupmdrv and save them to PM_font and PM_fontsize */ static void PM_query_font(void) { unsigned int len, fontsize; char *newfont; ULONG cbR, rc; putc(GR_QUERY_FONT, PM_pipe); fflush(PM_pipe); free( PM_font ); rc = DosRead(fileno(PM_pipe), &len, sizeof(int), &cbR); newfont = (char *)malloc( len + 1 ); rc = DosRead(fileno(PM_pipe), newfont, len*sizeof(char), &cbR); newfont[len] = '\0'; PM_font = (char *)malloc( len + 1 ); sscanf( newfont, "%i.%s", &fontsize, PM_font ); PM_fontsize = (double)fontsize; free(newfont); } #endif TERM_PUBLIC void PM_point(unsigned int x, unsigned int y, int number) /* ** tell the driver we are plotting a point so it can decide whether to ** use colour or not */ { int mode; mode = 1; putc(SET_POINTMODE, PM_pipe); fwrite(&mode, sizeof(int), 1, PM_pipe); do_point(x, y, number); mode = 0; putc(SET_POINTMODE, PM_pipe); fwrite(&mode, sizeof(int), 1, PM_pipe); } void PM_abortplot(void) { PM_must_abort = 0; term_reset(); (void) putc('\n', stderr); bail_to_command_line(); } void PM_intc_cleanup(void) { if (PM_pipe == NULL || PM_mode == SET_TEXT) PM_abortplot(); PM_must_abort = 1; } int PM_pause(char *str) /* ** pause - using message box on PM screen */ { int len, rc; ULONG cbR; char buf[256]; char *bp; if (PM_pipe == NULL) return 2; bp = buf; putc(GR_PAUSE, PM_pipe); len = strlen(str) + 1; fwrite(&len, sizeof(int), 1, PM_pipe); fwrite(str, 1, len, PM_pipe); for (rc = sizeof(int) - len % sizeof(int); rc > 0; rc--) { /* pad rest of int with zeros */ putc(NUL, PM_pipe); } fflush(PM_pipe); rc = DosRead(fileno(PM_pipe), &len, sizeof(int), &cbR); return len; } TERM_PUBLIC void PM_fillbox(int style, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { putc(SET_FILLBOX, PM_pipe); fwrite(&style, sizeof(style), 1, PM_pipe); fwrite(&x, sizeof(x), 1, PM_pipe); fwrite(&y, sizeof(y), 1, PM_pipe); fwrite(&w, sizeof(w), 1, PM_pipe); fwrite(&h, sizeof(h), 1, PM_pipe); } TERM_PUBLIC void PM_linewidth(double linewidth) { int lw; lw = linewidth * 100; putc(SET_LINEWIDTH, PM_pipe); fwrite(&lw, sizeof(int), 1, PM_pipe); } TERM_PUBLIC int PM_make_palette(t_sm_palette * palette) { if (palette == NULL) { ULONG rc, cbR; int PM_nColors; /* query maximum number of colours in palette */ putc(GR_MAKE_PALETTE, PM_pipe); putc(0, PM_pipe); fflush(PM_pipe); rc = DosRead(fileno(PM_pipe), &PM_nColors, sizeof(int), &cbR); return PM_nColors; } if (sm_palette.colors > 0) { ULONG *rgbTable; unsigned int i; /* Note: gvpm sources have also limit 256, is it limit of PM palette? I suppose yes, thus let colours passed as unsigned char through the pipe. Gray interval [0;1] will be mapped to interval [0;255] whose r,g,b components are mapped by the array below. */ putc(GR_MAKE_PALETTE, PM_pipe); putc(1, PM_pipe); rgbTable = (ULONG *) malloc(sizeof(ULONG) * sm_palette.colors); for (i = 0; i < sm_palette.colors; i++) { ULONG r, g, b; r = (ULONG) (palette->color[i].r * 255 + 0.5); g = (ULONG) (palette->color[i].g * 255 + 0.5); b = (ULONG) (palette->color[i].b * 255 + 0.5); rgbTable[i] = (r << 16) + (g << 8) + b; /* PM API likes this form */ } fwrite(&sm_palette.colors, sizeof(int), 1, PM_pipe); fwrite(rgbTable, sizeof(ULONG) * sm_palette.colors, 1, PM_pipe); free(rgbTable); } return 0; } #if 0 /* switch back to the palette used before calling make_palette */ TERM_PUBLIC void PM_previous_palette() { putc(GR_RELEASE_PALETTE, PM_pipe); } #endif TERM_PUBLIC void PM_set_color(t_colorspec *colorspec) { switch (colorspec->type) { case TC_FRAC: if (sm_palette.colors == 0) { rgb255_color rgb255; unsigned int rgb; rgb255maxcolors_from_gray(colorspec->value, &rgb255); rgb = (rgb255.r << 16) + (rgb255.g << 8) + rgb255.b; putc(GR_SET_RGBCOLOR, PM_pipe); fwrite(&rgb, sizeof(int), 1, PM_pipe); } else { unsigned char colorindex; /* map [0;1] to interval [0;sm_palette.colors-1] */ colorindex = ((colorspec->value * (sm_palette.colors - 1.)) + 0.5); putc(GR_SET_COLOR, PM_pipe); fwrite(&colorindex, sizeof(colorindex), 1, PM_pipe); } break; case TC_LT: PM_linetype(colorspec->lt); break; case TC_RGB: putc(GR_SET_RGBCOLOR, PM_pipe); fwrite(&(colorspec->lt), sizeof(int), 1, PM_pipe); /* fflush(PM_pipe); */ /* FIXME: why should that be necessary? */ break; } } TERM_PUBLIC void PM_filled_polygon ( int points, gpiPoint *corners ) { int i; putc(GR_FILLED_POLYGON, PM_pipe); fwrite(&points, sizeof(int), 1, PM_pipe); /* tell him number of corners */ for (i = 0; i < points; i++) { fwrite(&corners[i].x, sizeof(int), 1, PM_pipe); fwrite(&corners[i].y, sizeof(int), 1, PM_pipe); } } #ifdef USE_MOUSE TERM_PUBLIC void PM_put_tmptext(int i, const char str[]) { if (PM_pipe) { putc(PUT_TMPTEXT, PM_pipe); fwrite(&i, sizeof(int), 1, PM_pipe); i = strlen(str) + 1; fwrite(&i, sizeof(int), 1, PM_pipe); fwrite(&str[0], i, 1, PM_pipe); fflush(PM_pipe); } } TERM_PUBLIC void PM_set_ruler(int x, int y) { if (PM_pipe) { putc(SET_RULER, PM_pipe); fwrite(&x, sizeof(int), 1, PM_pipe); fwrite(&y, sizeof(int), 1, PM_pipe); fflush(PM_pipe); } } TERM_PUBLIC void PM_set_cursor(int c, int x, int y) { if (PM_pipe) { putc(SET_CURSOR, PM_pipe); fwrite(&c, sizeof(int), 1, PM_pipe); fwrite(&x, sizeof(int), 1, PM_pipe); fwrite(&y, sizeof(int), 1, PM_pipe); fflush(PM_pipe); } } TERM_PUBLIC void PM_set_clipboard(const char s[]) { if (PM_pipe) { int i = strlen(s); putc(SET_CLIPBOARD, PM_pipe); fwrite(&i, sizeof(int), 1, PM_pipe); fwrite(s, i+1, 1, PM_pipe); fflush(PM_pipe); } } #endif /* USE_MOUSE */ #ifdef WITH_IMAGE TERM_PUBLIC void PM_image(unsigned int M, unsigned int N, coordval *image, gpiPoint *corner, t_imagecolor color_mode) { PBYTE rgb_image; unsigned int image_size; unsigned int pad_bytes; /* IC_PALETTE and IC_RGB images are converted to a 24bit RGB format suitable for OS/2's presentation manager: - sequence of lines is reversed - each line starts at a 4 byte boundary */ /* fprintf(stderr, "PM_image: %i x %i, mode=%s\n", M, N, color_mode==IC_RGB?"IC_RGB":"IC_PALETTE" ); */ pad_bytes = (4 - (3 * M) % 4) % 4; /* scan lines start on ULONG boundaries */ image_size = (M + pad_bytes ) * N * 3; rgb_image = (PBYTE) gp_alloc(image_size, "PM RGB image"); if (color_mode == IC_PALETTE) { unsigned int x, y; rgb_image += N * (3 * M + pad_bytes); for (y=0; y 0) { fontstring = malloc( strlen(fontname) + 16 ); sprintf( fontstring, "%s,%i", fontname, (int)fontsize ); } else { fontstring = malloc( strlen(PM_font) + 16 ); sprintf( fontstring, "%s,%i", PM_font, (int)fontsize ); } PM_set_font( fontstring ); free( fontstring ); PM_query_font(); /* Scale fractional font height to vertical units of display */ /* FIXME: Font scaling is not done properly (yet) and will lead to non-optimal results for most font and size selections. The old gnupmdrv code used FONTINFO information for super- and subscripts. */ ENHpm_base = pm_scale * base; } } TERM_PUBLIC void PM_enhanced_flush() { static unsigned int ENHpm_xsave, ENHpm_ysave; if (ENHpm_opened_string) { int width, height; unsigned int mode; unsigned int x, y, len; ULONG rc, cbR; *enhanced_cur_text = '\0'; if (PM_must_abort) PM_abortplot(); /* print the string fragment, perhaps invisibly */ /* NB: base expresses offset from current y pos */ x = PM_x - ENHpm_base * sin(PM_angle); y = PM_y + ENHpm_base * cos(PM_angle); mode = ((ENHpm_show && !ENHpm_sizeonly) ? 0x01 : 0x00 ); len = strlen(enhanced_text) + 1; /* send message to gnupmdrv */ putc(GR_ENH_TEXT, PM_pipe); fwrite(&x, sizeof(int), 1, PM_pipe); fwrite(&y, sizeof(int), 1, PM_pipe); /* write 'mode indicator' (currently show switch only) */ fwrite(&mode, sizeof(int), 1, PM_pipe); fwrite(&len, sizeof(int), 1, PM_pipe); fwrite(enhanced_text, 1, len, PM_pipe); for (len = sizeof(int) - len % sizeof(int); len > 0; len--) { /* pad rest of int with zeros */ putc(NUL, PM_pipe); } /* answer from gnupmdrv is length of text */ fflush(PM_pipe); rc = DosRead(fileno(PM_pipe), &width, sizeof(int), &cbR); rc = DosRead(fileno(PM_pipe), &height, sizeof(int), &cbR); /* update drawing position according to len */ if (!ENHpm_widthflag) { width = 0; height = 0; } if (ENHpm_sizeonly) { /* This is the first pass for justified printing. */ /* We just adjust the starting position for second pass. */ if (PM_justification == RIGHT) { PM_x -= width; PM_y -= height; } else if (PM_justification == CENTRE) { PM_x -= width / 2; PM_y -= height / 2; } /* nothing to do for LEFT justified text */ } else if (ENHpm_overprint == 1) { /* Save current position */ ENHpm_xsave = PM_x + width; ENHpm_ysave = PM_y + height; /* First pass of overprint, leave position in center of fragment */ PM_x += width / 2; PM_y += height / 2; } else if (ENHpm_overprint == 2) { /* Restore current position, */ /* this sets the position behind the overprinted text */ PM_x = ENHpm_xsave; PM_y = ENHpm_ysave; } else { /* Normal case is to update position to end of fragment */ PM_x += width; PM_y += height; } ENHpm_opened_string = FALSE; } } TERM_PUBLIC void PM_enhanced_put_text(unsigned int x, unsigned int y, const char *str) { char *original_string = (char *)str; unsigned int pass, num_passes; /* If no enhanced text processing is needed, we can use the plain */ /* vanilla put_text() routine instead of this fancy recursive one. */ if (ignore_enhanced_text || !strpbrk(str, "{}^_@&~")) { PM_put_text(x,y,str); return; } /* Set up global variables needed by enhanced_recursion() */ ENHpm_opened_string = FALSE; enhanced_fontscale = 1.0; strncpy(enhanced_escape_format,"%c",sizeof(enhanced_escape_format)); /* Tell the terminal to move the drawing position */ /* we store the current position to PM_x and PM_y */ PM_x = x; PM_y = y; /* Text justification requires two passes. During the first pass we */ /* don't draw anything, we just measure the space it will take. */ /* Without justification one pass is enough */ if (PM_justification == LEFT) { num_passes = 1; } else { num_passes = 2; ENHpm_sizeonly = TRUE; } for( pass=1; pass <= num_passes; pass++ ) { /* This will restore the default font and update PM_font and PM_fontsize */ PM_set_font(NULL); PM_query_font(); /* Set the recursion going. We say to keep going until a * closing brace, but we don't really expect to find one. * If the return value is not the nul-terminator of the * string, that can only mean that we did find an unmatched * closing brace in the string. We increment past it (else * we get stuck in an infinite loop) and try again. */ while (*(str = enhanced_recursion((char *)str, TRUE, NULL, PM_fontsize, 0.0, TRUE, TRUE, 0))) { (term->enhanced_flush)(); /* I think we can only get here if *str == '}' */ enh_err_check(str); if (!*++str) break; /* end of string */ /* else carry on and process the rest of the string */ } /* In order to do text justification we need to do a second pass that */ /* uses information stored during the first pass. */ /* see PM_enhanced_flush() */ if (pass == 1) { /* do the actual printing in the next pass */ ENHpm_sizeonly = FALSE; str = original_string; } } /* restore default font */ PM_set_font(NULL); } #endif /* PM_OLD_ENHANCED_TEXT */ /* helper function */ void pm_raise_terminal_window() { putc(SET_SPECIAL, PM_pipe); putc('^', PM_pipe); /* raise window */ fflush(PM_pipe); } void pm_lower_terminal_window() { putc(SET_SPECIAL, PM_pipe); putc('_', PM_pipe); /* lower window */ fflush(PM_pipe); } #endif /* TERM_BODY */ #ifdef TERM_TABLE TERM_TABLE_START(PM_driver) "pm", "OS/2 Presentation Manager", PM_XMAX, PM_YMAX, PM_VCHAR, PM_HCHAR, PM_VTIC, PM_HTIC, PM_options, PM_init, PM_reset, PM_text, null_scale, PM_graphics, PM_move, PM_vector, PM_linetype, PM_put_text, PM_text_angle, PM_justify_text, PM_point, do_arrow, PM_set_font, 0 /*pointsize */ , TERM_CAN_MULTIPLOT|TERM_NO_OUTPUTFILE, PM_suspend, PM_resume, PM_fillbox, PM_linewidth #ifdef USE_MOUSE , 0 /* PM_waitforinput */, PM_put_tmptext, PM_set_ruler, PM_set_cursor, PM_set_clipboard #endif , PM_make_palette, 0, /* PM_previous_palette */ PM_set_color, PM_filled_polygon #ifdef WITH_IMAGE , PM_image #endif #ifndef PM_OLD_ENHANCED_TEXT , PM_enhanced_open, PM_enhanced_flush, do_enh_writec #endif TERM_TABLE_END(PM_driver) #undef LAST_TERM #define LAST_TERM PM_driver #endif /* TERM_TABLE */ #ifdef TERM_HELP START_HELP(pm) "1 pm", "?commands set terminal pm", "?set terminal pm", "?set term pm", "?terminal pm", "?term pm", "?pm", " The `pm` terminal driver provides an OS/2 Presentation Manager window in", " which the graph is plotted. The window is opened when the first graph is", " plotted. This window has its own online help as well as facilities for", " printing, copying to the clipboard and some line type and color adjustments.", " The `multiplot` option is supported.", "", " Syntax:", " set terminal pm {server {n}} {persist} {widelines} {enhanced} {\"title\"}", "", " If `persist` is specified, each graph appears in its own window and all", " windows remain open after `gnuplot` exits. If `server` is specified, all", " graphs appear in the same window, which remains open when `gnuplot` exits.", " This option takes an optional numerical argument which specifies an instance", " of the server process. Thus multiple server windows can be in use at the", " same time.", "", " If `widelines` is specified, all plots will be drawn with wide lines. If", " `enhanced` is specified, sub- and superscripts and multiple fonts are", " enabled using the same syntax as the `enhanced postscript` option (see", " `set terminal postscript enhanced` for details). Font names for the basic", " PostScript fonts may be abbreviated to single letters.", "", " If `title` is specified, it will be used as the title of the plot window.", " It will also be used as the name of the server instance, and will override", " the optional numerical argument.", "", " Linewidths may be changed with `set linestyle`." END_HELP(pm) #endif /* TERM_HELP */