1 /* Hello, Emacs, this is -*-C-*-
2 * $Id: pm.trm,v 1.53 2006/07/21 02:35:47 sfeam Exp $
8 * Copyright 1992, 1993, 1998, 2004
10 * Permission to use, copy, and distribute this software and its
11 * documentation for any purpose with or without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and
13 * that both that copyright notice and this permission notice appear
14 * in supporting documentation.
16 * Permission to modify the software is granted, but not the right to
17 * distribute the complete modified source code. Modifications are to
18 * be distributed as patches to the released version. Permission to
19 * distribute binaries produced by compiling modified sources is granted,
21 * 1. distribute the corresponding source modifications from the
22 * released version in the form of a patch file along with the binaries,
23 * 2. add special version identification to distinguish your version
24 * in addition to the base release version number,
25 * 3. provide your name and address as the primary contact for the
26 * support of your modified version, and
27 * 4. retain our contact information in regard to use of the base
29 * Permission to distribute the released version of the source code along
30 * with corresponding source modifications in the form of a patch file is
31 * granted with same provisions 2 through 4 for binary distributions.
33 * This software is provided "as is" without express or implied warranty
34 * to the extent permitted by applicable law.
38 * pm.trm --- inboard terminal driver for Presentation Manager
39 * --- after X-11 driver, by R.W.Fearick 31/1/92.
40 * v1.1 11/8/92 -- speed things up
42 * since March 1998: additions for mouse support implemented by Petr Mikulik
43 * last change: January 2000
44 * for mouse support, pm.trm has to be compiled with USE_MOUSE, e.g.
45 * gcc ... -DUSE_MOUSE ...
46 * January 1999: terminal entries for PM3D functionality by Petr Mikulik
56 TERM_PUBLIC void PM_init __PROTO((void));
57 TERM_PUBLIC void PM_options __PROTO((void));
58 TERM_PUBLIC void PM_reset __PROTO((void));
59 TERM_PUBLIC void PM_text __PROTO((void));
60 TERM_PUBLIC void PM_graphics __PROTO((void));
61 TERM_PUBLIC void PM_linetype __PROTO((int lt));
62 TERM_PUBLIC void PM_move __PROTO((unsigned int x, unsigned int y));
63 TERM_PUBLIC void PM_vector __PROTO((unsigned int x, unsigned int y));
64 TERM_PUBLIC int PM_text_angle __PROTO((int ang));
65 TERM_PUBLIC void PM_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
66 TERM_PUBLIC int PM_justify_text __PROTO((enum JUSTIFY mode));
67 TERM_PUBLIC void PM_point __PROTO((unsigned int x, unsigned int y, int number));
68 TERM_PUBLIC void PM_suspend __PROTO((void));
69 TERM_PUBLIC void PM_resume __PROTO((void));
70 TERM_PUBLIC void PM_fillbox __PROTO((int style, unsigned int x, unsigned int y, unsigned int w, unsigned int h));
71 TERM_PUBLIC void PM_linewidth __PROTO((double linewidth));
73 TERM_PUBLIC void PM_set_ruler __PROTO((int, int));
74 TERM_PUBLIC void PM_set_cursor __PROTO((int, int, int));
75 TERM_PUBLIC void PM_put_tmptext __PROTO((int, const char str[]));
76 TERM_PUBLIC void PM_set_clipboard __PROTO((const char[]));
78 TERM_PUBLIC int PM_make_palette (t_sm_palette *);
80 TERM_PUBLIC void PM_previous_palette (void);
82 TERM_PUBLIC void PM_set_color (t_colorspec *);
83 TERM_PUBLIC void PM_filled_polygon (int, gpiPoint *);
85 TERM_PUBLIC void PM_image __PROTO((unsigned int, unsigned int, coordval *, gpiPoint *, t_imagecolor));
87 #ifndef PM_OLD_ENHANCED_TEXT
88 /* To support "set term pm enhanced" */
89 TERM_PUBLIC void PM_enhanced_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
90 TERM_PUBLIC void PM_enhanced_open __PROTO((char * fontname, double fontsize,
91 double base, TBOOLEAN widthflag, TBOOLEAN showflag,
93 TERM_PUBLIC void PM_enhanced_flush __PROTO((void));
96 /* define PM world coordinate limits */
101 /* approximations for typical font/screen sizes */
102 #define PM_VCHAR (550)
103 #define PM_HCHAR (220)
104 /* Note: VCHAR AND HCHAR sizes in gnuplot 3.5 were 415 and 242,
105 in X11 are 500 and 195, respectively.
107 #if 0 /* Sizes of gnuplot 3.6 and 3.7: */
108 # define PM_VTIC (200)
109 # define PM_HTIC (200)
110 #else /* Sizes as X11: */
111 # define PM_VTIC (125)
112 # define PM_HTIC (130)
113 /* Note: sizes for VTIC and HTIC in gnuplot 3.5 were 122 and 128, respectively.
124 #define INCL_DOSPROCESS
125 #define INCL_DOSSEMAPHORES
127 #define INCL_DOSMODULEMGR
129 #include "os2/pm_msgs.h"
133 /* path for pm program */
134 static char PM_path[256] = "";
135 /* track mode to avoid redraw after hitting break */
136 static int PM_mode = 0;
138 static int PM_termmode = 0;
139 static int PM_must_reset_opts = FALSE;
140 static int PM_must_abort = 0;
142 static char PM_opts[256] = "";
143 static int PM_optargs = 0;
144 static int PM_plot_number = 0;
145 static char PM_term_title[128] = "";
147 static int mouseGnupmdrv = 0; /* PM set to 1 if we are connected to a mouseable gnupmdrv */
149 static FILE *PM_pipe = NULL;
150 static FILE *PM_savepipe = NULL;
153 #ifndef PM_OLD_ENHANCED_TEXT
155 /* track current state of pm terminal */
156 /* this is only needed for enhanced text */
157 static char * PM_font = NULL;
158 static double PM_fontsize = 12.0;
159 static unsigned int PM_x = 0;
160 static unsigned int PM_y = 0;
161 static enum JUSTIFY PM_justification = LEFT;
162 static double PM_angle = 0.; /* unit is radian */
164 /* state variables for enhanced text processing */
165 static TBOOLEAN ENHpm_opened_string;
166 static TBOOLEAN ENHpm_show = TRUE;
167 static int ENHpm_overprint = 0;
168 static TBOOLEAN ENHpm_widthflag = TRUE;
169 static TBOOLEAN ENHpm_sizeonly = FALSE;
170 static double ENHpm_base;
174 static void PM_reset_opts(void);
175 static void PM_query(void);
176 static void PM_make_servername(char *);
177 static void PM_abortplot();
178 static void PM_query_font(void);
184 static char buffer[1024];
194 term_force_init = TRUE;
195 if (PM_savepipe != NULL && PM_termmode == 0) {
196 PM_pipe = PM_savepipe;
198 if ((PM_pipe == NULL) && (PM_termmode & 2)) {
199 /* check if term is running */
200 PM_make_servername(tempname);
201 strcpy(pipename, "\\pipe\\");
202 strcat(pipename, tempname);
203 /* sprintf( pipename, "\\pipe\\gpServ%d", PM_plot_number ) ; */
204 DosGetInfoBlocks(&tib, &pib);
205 PM_pipe = fopen(pipename, "r+b");
206 if (PM_pipe != NULL) {
207 setvbuf(PM_pipe, buffer, _IOFBF, 1024);
208 pid = pib->pib_ulpid;
209 fwrite(&pid, 1, 4, PM_pipe);
211 /* set new options */
212 /* PM_reset_opts() ; */
215 /* else we start up term here */
216 if (PM_pipe == NULL) {
217 if (PM_termmode & 2) {
218 PM_make_servername(tempname);
219 /* sprintf( tempname, "gpServ%d", PM_plot_number ) ; */
223 sprintf(tempname, "gp%X%d", getpid(), gpid);
225 strcpy(semname, "\\sem32\\");
226 strcpy(pipename, "\\pipe\\");
227 strcat(semname, tempname);
228 strcat(pipename, tempname);
229 strcat(PM_path, "\\gnupmdrv.exe");
230 rc = access(PM_path, 0);
233 rc = DosSearchPath(0x0002, /* search GNUPLOT environment */
240 rc = DosSearchPath(0x0003, /* then try current directory & path */
246 fputs("Cannot find gnupmdrv.exe !\n", stderr);
249 rc = DosCreateEventSem(semname, &hev, 1, 0);
251 fputs("Cannot create semaphore !\n", stderr);
254 spawnmode = P_SESSION | P_DEFAULT;
256 spawnmode |= P_UNRELATED;
257 pid = spawnl(spawnmode, PM_path, PM_path, tempname, PM_opts, NULL);
259 fputs("Cannot spawn gnupmdrv.exe !\n", stderr);
262 DosGetInfoBlocks(&tib, &pib);
263 DosWaitEventSem(hev, 10000);
264 DosCloseEventSem(hev);
265 PM_pipe = fopen(pipename, "r+b");
266 if (PM_pipe == NULL) {
267 fputs("Cannot open pipe to gnupmdrv.exe !\n", stderr);
269 } else if (PM_termmode == 0)
270 PM_savepipe = PM_pipe;
271 setvbuf(PM_pipe, buffer, _IOFBF, 1024);
272 pid = pib->pib_ulpid;
273 fwrite(&pid, 1, 4, PM_pipe);
276 if (PM_must_reset_opts)
280 /* PM: notify gnupmdrv that this is mouse-enhanced terminal */
281 putc( GR_MOUSECAPABLE, PM_pipe ) ;
283 /* we catch mouseable gnupmdrv's answer in PM_query by 0xABCD */
290 PM_make_servername(char *str)
292 if (PM_term_title[0]) {
294 char *p = PM_term_title + 1;
295 int match = PM_term_title[0];
296 while (*p != match) {
297 hash = (hash << 1) + hash + *p++;
299 hash %= (256 * 256 * 256 - 1);
300 sprintf(str, "gp%x", hash);
302 sprintf(str, "gpServ%d", PM_plot_number);
309 int old_termmode = PM_termmode;
311 term_options[0] = NUL;
312 PM_term_title[0] = NUL;
315 while (!END_OF_COMMAND) {
316 if (almost_equals(c_token, "pe$rsist")) {
317 strcat(PM_opts, "-p ");
318 strcat(term_options, "persist ");
321 if (!(old_termmode & 1))
323 } else if (almost_equals(c_token, "s$erver")) {
324 strcat(PM_opts, "-s ");
325 strcat(term_options, "server ");
328 if (!(old_termmode & 2))
330 if (isanumber(c_token + 1)) {
332 char *p = PM_opts + strlen(PM_opts);
334 PM_plot_number = (int) real(const_express(&t));
335 sprintf(p, "%d", PM_plot_number);
336 sprintf(term_options + strlen(term_options), "%d", PM_plot_number);
338 } else if (almost_equals(c_token, "w$idelines")) {
339 strcat(PM_opts, "-w ");
340 strcat(term_options, "widelines ");
342 } else if (almost_equals(c_token, "e$nhanced")) {
343 strcat(term_options, "enhanced ");
344 #ifdef PM_OLD_ENHANCED_TEXT
346 strcat(PM_opts, "-e ");
347 term->put_text = PM_put_text;
349 term->put_text = PM_enhanced_put_text;
351 term->flags |= TERM_ENHANCED_TEXT;
352 } else if (almost_equals(c_token, "noe$nhanced")) {
353 strcat(term_options, "noenhanced ");
354 term->put_text = PM_put_text;
355 term->flags &= ~TERM_ENHANCED_TEXT;
356 } else if (isstring(c_token)) {
357 copy_str(PM_term_title, c_token, 127);
360 else if (almost_equals(c_token, "po$rtrait")) {
361 strcat(PM_opts, "-l ");
362 strcat(term_options, "portrait ");
368 if (PM_term_title[0]) {
369 strcat(PM_opts, " ");
370 strcat(term_options, " ");
371 strcat(PM_opts, PM_term_title);
372 strcat(term_options, PM_term_title);
374 PM_must_reset_opts = TRUE;
382 putc(SET_OPTIONS, PM_pipe);
383 len = strlen(PM_opts) + 1;
384 fwrite(&len, sizeof(int), 1, PM_pipe);
385 fwrite(PM_opts, 1, len, PM_pipe);
386 for (len = sizeof(int) - len % sizeof(int); len > 0; len--) {
387 /* pad rest of int with zeros */
391 PM_must_reset_opts = FALSE;
400 putc(GR_QUERY, PM_pipe);
402 rc = DosRead(fileno(PM_pipe), &term->h_char, sizeof(int), &cbR);
403 if (term->h_char == 0xABCD) {
404 /* PM we have got greetings from mouseable gnupmdrv */
405 mouseGnupmdrv = 1; /* thus set mouseGnupmdrv on and reread h_char */
406 rc = DosRead( fileno(PM_pipe), &term->h_char, sizeof(int), &cbR ) ;
408 rc = DosRead(fileno(PM_pipe), &term->v_char, sizeof(int), &cbR);
413 /* update menu items in PM terminal */
415 PM_update_menu_items()
417 /* connected to a mouseable gnupmdrv */
418 if ((PM_pipe != NULL) && (mouseGnupmdrv)) {
419 struct t_gpPMmenu gpPMmenu;
421 PM_set_gpPMmenu(&gpPMmenu);
422 putc(SET_MENU, PM_pipe);
423 fwrite(&gpPMmenu, sizeof(gpPMmenu), 1, PM_pipe);
432 putc(GR_RESET, PM_pipe);
434 term_force_init = FALSE;
435 if (PM_termmode > 0) {
445 putc(GR_SUSPEND, PM_pipe);
453 putc(GR_RESUME, PM_pipe);
462 if (PM_mode != SET_TEXT) {
463 putc(SET_TEXT, PM_pipe);
466 keep_term_initialised = term_initialised ;
467 term_initialised = FALSE ; /* need to force init */
474 /* FIXME 20040712: 'extern' in a source file is always wrong. */
475 extern TBOOLEAN allowmotion;
485 static int last_encoding = -999;
486 putc(SET_GRAPHICS, PM_pipe);
489 PM_update_menu_items();
491 if (encoding != last_encoding) {
494 case S_ENC_ISO8859_2: cp = 912; break;
495 case S_ENC_CP437: cp = 437; break;
496 case S_ENC_CP850: cp = 850; break;
497 default: /* S_ENC_DEFAULT, S_ENC_ISO8859_1 */
500 putc(SET_SPECIAL, PM_pipe);
501 putc('c', PM_pipe); /* set codepage */
502 fwrite(&cp, sizeof(int), 1, PM_pipe);
504 last_encoding = encoding;
506 PM_mode = SET_GRAPHICS;
511 PM_move(unsigned int x, unsigned int y)
516 putc(GR_MOVE, PM_pipe);
517 fwrite(&x, sizeof(int), 1, PM_pipe);
518 fwrite(&y, sizeof(int), 1, PM_pipe);
520 #ifndef PM_OLD_ENHANCED_TEXT
521 /* save current position, only needed for enhanced text */
529 PM_vector(unsigned int x, unsigned int y)
533 putc(GR_DRAW, PM_pipe);
534 fwrite(&x, sizeof(int), 1, PM_pipe);
535 fwrite(&y, sizeof(int), 1, PM_pipe);
542 putc(SET_LINE, PM_pipe);
543 fwrite(<, sizeof(int), 1, PM_pipe);
548 PM_text_angle(int ang)
550 putc(SET_ANGLE, PM_pipe);
551 fwrite(&ang, sizeof(int), 1, PM_pipe);
552 #ifndef PM_OLD_ENHANCED_TEXT
553 /* store text angle, only needed for enhanced text */
554 PM_angle = (double)ang * M_PI / 180.;
561 PM_put_text(unsigned int x, unsigned int y, const char *str)
568 #ifdef PM_OLD_ENHANCED_TEXT
569 if (ignore_enhanced_text) {
570 putc(SET_SPECIAL, PM_pipe);
571 putc('e', PM_pipe); /* switch the enhanced mode off */
576 putc(GR_TEXT, PM_pipe);
577 fwrite(&x, sizeof(int), 1, PM_pipe);
578 fwrite(&y, sizeof(int), 1, PM_pipe);
579 len = strlen(str) + 1;
580 fwrite(&len, sizeof(int), 1, PM_pipe);
581 fwrite(str, 1, len, PM_pipe);
582 for (len = sizeof(int) - len % sizeof(int); len > 0; len--) {
583 /* pad rest of int with zeros */
587 #ifdef PM_OLD_ENHANCED_TEXT
588 if (ignore_enhanced_text) {
589 putc(SET_SPECIAL, PM_pipe);
590 putc('e', PM_pipe); /* restore the enhanced mode */
598 PM_justify_text(enum JUSTIFY mode)
600 #ifdef PM_OLD_ENHANCED_TEXT
601 if (ignore_enhanced_text) {
602 putc(SET_SPECIAL, PM_pipe);
603 putc('e', PM_pipe); /* switch the enhanced mode off */
608 putc(SET_JUSTIFY, PM_pipe);
609 fwrite(&mode, sizeof(int), 1, PM_pipe);
611 #ifndef PM_OLD_ENHANCED_TEXT
612 /* store text justification, only needed for enhanced text */
613 PM_justification = mode;
615 if (ignore_enhanced_text) {
616 putc(SET_SPECIAL, PM_pipe);
617 putc('e', PM_pipe); /* restore the enhanced mode */
626 PM_set_font(const char *font)
630 putc(SET_FONT, PM_pipe);
637 fwrite(&len, sizeof(int), 1, PM_pipe);
640 fwrite(&len, sizeof(int), 1, PM_pipe);
641 fwrite(font, 1, len, PM_pipe);
642 for (len = sizeof(int) - len % sizeof(int); len > 0; len--) {
643 /* pad rest of int with zeros */
652 #ifndef PM_OLD_ENHANCED_TEXT
655 get current font name and size from gnupmdrv and
656 save them to PM_font and PM_fontsize
658 static void PM_query_font(void)
660 unsigned int len, fontsize;
664 putc(GR_QUERY_FONT, PM_pipe);
668 rc = DosRead(fileno(PM_pipe), &len, sizeof(int), &cbR);
669 newfont = (char *)malloc( len + 1 );
670 rc = DosRead(fileno(PM_pipe), newfont, len*sizeof(char), &cbR);
673 PM_font = (char *)malloc( len + 1 );
674 sscanf( newfont, "%i.%s", &fontsize, PM_font );
675 PM_fontsize = (double)fontsize;
683 PM_point(unsigned int x, unsigned int y, int number)
685 ** tell the driver we are plotting a point so it can decide whether to
691 putc(SET_POINTMODE, PM_pipe);
692 fwrite(&mode, sizeof(int), 1, PM_pipe);
693 do_point(x, y, number);
695 putc(SET_POINTMODE, PM_pipe);
696 fwrite(&mode, sizeof(int), 1, PM_pipe);
705 (void) putc('\n', stderr);
706 bail_to_command_line();
711 PM_intc_cleanup(void)
713 if (PM_pipe == NULL || PM_mode == SET_TEXT)
722 ** pause - using message box on PM screen
733 putc(GR_PAUSE, PM_pipe);
734 len = strlen(str) + 1;
735 fwrite(&len, sizeof(int), 1, PM_pipe);
736 fwrite(str, 1, len, PM_pipe);
737 for (rc = sizeof(int) - len % sizeof(int); rc > 0; rc--) {
738 /* pad rest of int with zeros */
742 rc = DosRead(fileno(PM_pipe), &len, sizeof(int), &cbR);
748 PM_fillbox(int style, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
750 putc(SET_FILLBOX, PM_pipe);
751 fwrite(&style, sizeof(style), 1, PM_pipe);
752 fwrite(&x, sizeof(x), 1, PM_pipe);
753 fwrite(&y, sizeof(y), 1, PM_pipe);
754 fwrite(&w, sizeof(w), 1, PM_pipe);
755 fwrite(&h, sizeof(h), 1, PM_pipe);
760 PM_linewidth(double linewidth)
763 lw = linewidth * 100;
764 putc(SET_LINEWIDTH, PM_pipe);
765 fwrite(&lw, sizeof(int), 1, PM_pipe);
770 PM_make_palette(t_sm_palette * palette)
772 if (palette == NULL) {
776 /* query maximum number of colours in palette */
777 putc(GR_MAKE_PALETTE, PM_pipe);
780 rc = DosRead(fileno(PM_pipe), &PM_nColors, sizeof(int), &cbR);
784 if (sm_palette.colors > 0) {
788 /* Note: gvpm sources have also limit 256, is it limit of PM palette?
789 I suppose yes, thus let colours passed as unsigned char through the pipe.
790 Gray interval [0;1] will be mapped to interval [0;255] whose r,g,b
791 components are mapped by the array below.
793 putc(GR_MAKE_PALETTE, PM_pipe);
795 rgbTable = (ULONG *) malloc(sizeof(ULONG) * sm_palette.colors);
796 for (i = 0; i < sm_palette.colors; i++) {
799 r = (ULONG) (palette->color[i].r * 255 + 0.5);
800 g = (ULONG) (palette->color[i].g * 255 + 0.5);
801 b = (ULONG) (palette->color[i].b * 255 + 0.5);
802 rgbTable[i] = (r << 16) + (g << 8) + b; /* PM API likes this form */
804 fwrite(&sm_palette.colors, sizeof(int), 1, PM_pipe);
805 fwrite(rgbTable, sizeof(ULONG) * sm_palette.colors, 1, PM_pipe);
813 /* switch back to the palette used before calling make_palette */
815 PM_previous_palette()
817 putc(GR_RELEASE_PALETTE, PM_pipe);
823 PM_set_color(t_colorspec *colorspec)
825 switch (colorspec->type) {
827 if (sm_palette.colors == 0) {
831 rgb255maxcolors_from_gray(colorspec->value, &rgb255);
832 rgb = (rgb255.r << 16) + (rgb255.g << 8) + rgb255.b;
833 putc(GR_SET_RGBCOLOR, PM_pipe);
834 fwrite(&rgb, sizeof(int), 1, PM_pipe);
836 unsigned char colorindex;
838 /* map [0;1] to interval [0;sm_palette.colors-1] */
839 colorindex = ((colorspec->value * (sm_palette.colors - 1.)) + 0.5);
840 putc(GR_SET_COLOR, PM_pipe);
841 fwrite(&colorindex, sizeof(colorindex), 1, PM_pipe);
845 PM_linetype(colorspec->lt);
848 putc(GR_SET_RGBCOLOR, PM_pipe);
849 fwrite(&(colorspec->lt), sizeof(int), 1, PM_pipe);
850 /* fflush(PM_pipe); */ /* FIXME: why should that be necessary? */
856 TERM_PUBLIC void PM_filled_polygon ( int points, gpiPoint *corners )
859 putc(GR_FILLED_POLYGON, PM_pipe);
860 fwrite(&points, sizeof(int), 1, PM_pipe); /* tell him number of corners */
861 for (i = 0; i < points; i++) {
862 fwrite(&corners[i].x, sizeof(int), 1, PM_pipe);
863 fwrite(&corners[i].y, sizeof(int), 1, PM_pipe);
871 PM_put_tmptext(int i, const char str[])
874 putc(PUT_TMPTEXT, PM_pipe);
875 fwrite(&i, sizeof(int), 1, PM_pipe);
877 fwrite(&i, sizeof(int), 1, PM_pipe);
878 fwrite(&str[0], i, 1, PM_pipe);
885 PM_set_ruler(int x, int y)
888 putc(SET_RULER, PM_pipe);
889 fwrite(&x, sizeof(int), 1, PM_pipe);
890 fwrite(&y, sizeof(int), 1, PM_pipe);
897 PM_set_cursor(int c, int x, int y)
900 putc(SET_CURSOR, PM_pipe);
901 fwrite(&c, sizeof(int), 1, PM_pipe);
902 fwrite(&x, sizeof(int), 1, PM_pipe);
903 fwrite(&y, sizeof(int), 1, PM_pipe);
910 PM_set_clipboard(const char s[])
914 putc(SET_CLIPBOARD, PM_pipe);
915 fwrite(&i, sizeof(int), 1, PM_pipe);
916 fwrite(s, i+1, 1, PM_pipe);
921 #endif /* USE_MOUSE */
927 PM_image(unsigned int M, unsigned int N, coordval *image, gpiPoint *corner, t_imagecolor color_mode)
930 unsigned int image_size;
931 unsigned int pad_bytes;
933 /* IC_PALETTE and IC_RGB images are converted to a 24bit RGB format
934 suitable for OS/2's presentation manager:
935 - sequence of lines is reversed
936 - each line starts at a 4 byte boundary
939 /* fprintf(stderr, "PM_image: %i x %i, mode=%s\n", M, N, color_mode==IC_RGB?"IC_RGB":"IC_PALETTE" ); */
940 pad_bytes = (4 - (3 * M) % 4) % 4; /* scan lines start on ULONG boundaries */
941 image_size = (M + pad_bytes ) * N * 3;
942 rgb_image = (PBYTE) gp_alloc(image_size, "PM RGB image");
944 if (color_mode == IC_PALETTE) {
947 rgb_image += N * (3 * M + pad_bytes);
948 for (y=0; y<N; y++) {
949 rgb_image -= 3 * M + pad_bytes;
952 rgb255maxcolors_from_gray(*image++, &rgb255);
953 *(rgb_image++) = rgb255.b;
954 *(rgb_image++) = rgb255.g;
955 *(rgb_image++) = rgb255.r;
959 } else if (color_mode == IC_RGB) {
962 rgb_image += N * (3 * M + pad_bytes);
963 for (y=0; y<N; y++) {
964 rgb_image -= 3 * M + pad_bytes;
967 rgb255.r = (BYTE) (*image++ * 255 + 0.5);
968 rgb255.g = (BYTE) (*image++ * 255 + 0.5);
969 rgb255.b = (BYTE) (*image++ * 255 + 0.5);
970 *(rgb_image++) = rgb255.b;
971 *(rgb_image++) = rgb255.g;
972 *(rgb_image++) = rgb255.r;
978 if ((color_mode == IC_PALETTE) || (color_mode == IC_RGB)) {
981 /* transfer data to gnupmdrv */
982 putc(GR_RGB_IMAGE, PM_pipe);
983 fwrite(&M, sizeof(M), 1, PM_pipe);
984 fwrite(&N, sizeof(N), 1, PM_pipe);
985 for (i=0; i<4; i++) {
986 fwrite(&(corner[i].x), sizeof(int), 1, PM_pipe);
987 fwrite(&(corner[i].y), sizeof(int), 1, PM_pipe);
989 fwrite(&image_size, sizeof(image_size), 1, PM_pipe);
990 fwrite(rgb_image, image_size, 1, PM_pipe);
997 #endif /* WITH_IMAGE */
1000 #ifndef PM_OLD_ENHANCED_TEXT
1005 double fontsize, double base,
1006 TBOOLEAN widthflag, TBOOLEAN showflag,
1009 static const int pm_scale = 35; /* scaling of base offset */
1010 static unsigned int ENHpm_xsave, ENHpm_ysave;
1013 /* There are two special cases:
1014 * overprint = 3 means save current position
1015 * overprint = 4 means restore saved position
1017 if (overprint == 3) {
1021 } else if (overprint == 4) {
1027 if (!ENHpm_opened_string) {
1028 ENHpm_opened_string = TRUE;
1030 /* Start new text fragment */
1031 enhanced_cur_text = &enhanced_text[0];
1033 /* Keep track of whether we are supposed to show this string */
1034 ENHpm_show = showflag;
1036 /* 0/1/2 no overprint / 1st pass / 2nd pass */
1037 ENHpm_overprint = overprint;
1039 /* widthflag FALSE means do not update text position after printing */
1040 ENHpm_widthflag = widthflag;
1043 /* FIXME: It would be nice to have fractional font sizes
1044 for super- and subscripts. */
1045 /* FIXME: sometimes fontname has zero length */
1046 if ((fontname != NULL) && strlen(fontname) > 0) {
1047 fontstring = malloc( strlen(fontname) + 16 );
1048 sprintf( fontstring, "%s,%i", fontname, (int)fontsize );
1051 fontstring = malloc( strlen(PM_font) + 16 );
1052 sprintf( fontstring, "%s,%i", PM_font, (int)fontsize );
1054 PM_set_font( fontstring );
1058 /* Scale fractional font height to vertical units of display */
1060 Font scaling is not done properly (yet) and will lead to
1061 non-optimal results for most font and size selections.
1062 The old gnupmdrv code used FONTINFO information for super-
1065 ENHpm_base = pm_scale * base;
1073 static unsigned int ENHpm_xsave, ENHpm_ysave;
1075 if (ENHpm_opened_string) {
1078 unsigned int x, y, len;
1081 *enhanced_cur_text = '\0';
1086 /* print the string fragment, perhaps invisibly */
1087 /* NB: base expresses offset from current y pos */
1088 x = PM_x - ENHpm_base * sin(PM_angle);
1089 y = PM_y + ENHpm_base * cos(PM_angle);
1090 mode = ((ENHpm_show && !ENHpm_sizeonly) ? 0x01 : 0x00 );
1091 len = strlen(enhanced_text) + 1;
1093 /* send message to gnupmdrv */
1094 putc(GR_ENH_TEXT, PM_pipe);
1095 fwrite(&x, sizeof(int), 1, PM_pipe);
1096 fwrite(&y, sizeof(int), 1, PM_pipe);
1097 /* write 'mode indicator' (currently show switch only) */
1098 fwrite(&mode, sizeof(int), 1, PM_pipe);
1099 fwrite(&len, sizeof(int), 1, PM_pipe);
1100 fwrite(enhanced_text, 1, len, PM_pipe);
1101 for (len = sizeof(int) - len % sizeof(int); len > 0; len--) {
1102 /* pad rest of int with zeros */
1106 /* answer from gnupmdrv is length of text */
1108 rc = DosRead(fileno(PM_pipe), &width, sizeof(int), &cbR);
1109 rc = DosRead(fileno(PM_pipe), &height, sizeof(int), &cbR);
1111 /* update drawing position according to len */
1112 if (!ENHpm_widthflag) {
1116 if (ENHpm_sizeonly) {
1117 /* This is the first pass for justified printing. */
1118 /* We just adjust the starting position for second pass. */
1119 if (PM_justification == RIGHT) {
1123 else if (PM_justification == CENTRE) {
1127 /* nothing to do for LEFT justified text */
1129 else if (ENHpm_overprint == 1) {
1130 /* Save current position */
1131 ENHpm_xsave = PM_x + width;
1132 ENHpm_ysave = PM_y + height;
1133 /* First pass of overprint, leave position in center of fragment */
1137 else if (ENHpm_overprint == 2) {
1138 /* Restore current position, */
1139 /* this sets the position behind the overprinted text */
1144 /* Normal case is to update position to end of fragment */
1149 ENHpm_opened_string = FALSE;
1155 PM_enhanced_put_text(unsigned int x, unsigned int y, const char *str)
1157 char *original_string = (char *)str;
1158 unsigned int pass, num_passes;
1160 /* If no enhanced text processing is needed, we can use the plain */
1161 /* vanilla put_text() routine instead of this fancy recursive one. */
1162 if (ignore_enhanced_text || !strpbrk(str, "{}^_@&~")) {
1163 PM_put_text(x,y,str);
1167 /* Set up global variables needed by enhanced_recursion() */
1168 ENHpm_opened_string = FALSE;
1169 enhanced_fontscale = 1.0;
1170 strncpy(enhanced_escape_format,"%c",sizeof(enhanced_escape_format));
1172 /* Tell the terminal to move the drawing position */
1173 /* we store the current position to PM_x and PM_y */
1177 /* Text justification requires two passes. During the first pass we */
1178 /* don't draw anything, we just measure the space it will take. */
1179 /* Without justification one pass is enough */
1180 if (PM_justification == LEFT) {
1185 ENHpm_sizeonly = TRUE;
1188 for( pass=1; pass <= num_passes; pass++ ) {
1190 /* This will restore the default font
1191 and update PM_font and PM_fontsize */
1195 /* Set the recursion going. We say to keep going until a
1196 * closing brace, but we don't really expect to find one.
1197 * If the return value is not the nul-terminator of the
1198 * string, that can only mean that we did find an unmatched
1199 * closing brace in the string. We increment past it (else
1200 * we get stuck in an infinite loop) and try again.
1202 while (*(str = enhanced_recursion((char *)str, TRUE,
1204 0.0, TRUE, TRUE, 0))) {
1205 (term->enhanced_flush)();
1207 /* I think we can only get here if *str == '}' */
1211 break; /* end of string */
1213 /* else carry on and process the rest of the string */
1216 /* In order to do text justification we need to do a second pass that */
1217 /* uses information stored during the first pass. */
1218 /* see PM_enhanced_flush() */
1220 /* do the actual printing in the next pass */
1221 ENHpm_sizeonly = FALSE;
1222 str = original_string;
1226 /* restore default font */
1230 #endif /* PM_OLD_ENHANCED_TEXT */
1233 /* helper function */
1235 pm_raise_terminal_window()
1237 putc(SET_SPECIAL, PM_pipe);
1238 putc('^', PM_pipe); /* raise window */
1243 pm_lower_terminal_window()
1245 putc(SET_SPECIAL, PM_pipe);
1246 putc('_', PM_pipe); /* lower window */
1251 #endif /* TERM_BODY */
1254 TERM_TABLE_START(PM_driver)
1255 "pm", "OS/2 Presentation Manager",
1256 PM_XMAX, PM_YMAX, PM_VCHAR, PM_HCHAR,
1257 PM_VTIC, PM_HTIC, PM_options, PM_init, PM_reset,
1258 PM_text, null_scale, PM_graphics, PM_move, PM_vector,
1259 PM_linetype, PM_put_text, PM_text_angle,
1260 PM_justify_text, PM_point, do_arrow, PM_set_font,
1261 0 /*pointsize */ , TERM_CAN_MULTIPLOT|TERM_NO_OUTPUTFILE,
1262 PM_suspend, PM_resume,
1263 PM_fillbox, PM_linewidth
1265 , 0 /* PM_waitforinput */,
1266 PM_put_tmptext, PM_set_ruler, PM_set_cursor, PM_set_clipboard
1269 0, /* PM_previous_palette */
1275 #ifndef PM_OLD_ENHANCED_TEXT
1276 , PM_enhanced_open, PM_enhanced_flush, do_enh_writec
1278 TERM_TABLE_END(PM_driver)
1281 #define LAST_TERM PM_driver
1283 #endif /* TERM_TABLE */
1288 "?commands set terminal pm",
1294 " The `pm` terminal driver provides an OS/2 Presentation Manager window in",
1295 " which the graph is plotted. The window is opened when the first graph is",
1296 " plotted. This window has its own online help as well as facilities for",
1297 " printing, copying to the clipboard and some line type and color adjustments.",
1298 " The `multiplot` option is supported.",
1301 " set terminal pm {server {n}} {persist} {widelines} {enhanced} {\"title\"}",
1303 " If `persist` is specified, each graph appears in its own window and all",
1304 " windows remain open after `gnuplot` exits. If `server` is specified, all",
1305 " graphs appear in the same window, which remains open when `gnuplot` exits.",
1306 " This option takes an optional numerical argument which specifies an instance",
1307 " of the server process. Thus multiple server windows can be in use at the",
1310 " If `widelines` is specified, all plots will be drawn with wide lines. If",
1311 " `enhanced` is specified, sub- and superscripts and multiple fonts are",
1312 " enabled using the same syntax as the `enhanced postscript` option (see",
1313 " `set terminal postscript enhanced` for details). Font names for the basic",
1314 " PostScript fonts may be abbreviated to single letters.",
1316 " If `title` is specified, it will be used as the title of the plot window.",
1317 " It will also be used as the name of the server instance, and will override",
1318 " the optional numerical argument.",
1320 " Linewidths may be changed with `set linestyle`."
1322 #endif /* TERM_HELP */