1 /* Hello, Emacs, this is -*-C-*-
2 * $Id: hp26.trm,v 1.18 2006/07/21 02:35:46 sfeam Exp $
5 /* GNUPLOT - HP26.trm */
8 * Copyright 1990 - 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 * This file is included by ../term.c.
40 * This terminal driver supports:
44 * luecken@udel.edu (Bruce Lueckenhoff)
45 * hplvlch!ch (Chuck Heller)
47 * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
52 * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
58 register_term(hp2623a)
62 TERM_PUBLIC void HP26_vector __PROTO((unsigned int x, unsigned int y));
63 TERM_PUBLIC void HP26_move __PROTO((unsigned int x, unsigned int y));
64 TERM_PUBLIC void HP26_init __PROTO((void));
65 TERM_PUBLIC void HP26_graphics __PROTO((void));
66 TERM_PUBLIC void HP26_text __PROTO((void));
67 TERM_PUBLIC void HP26_reset __PROTO((void));
68 TERM_PUBLIC int HP26_text_angle __PROTO((int ang));
69 TERM_PUBLIC void HP26_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
70 TERM_PUBLIC void HP26_linetype __PROTO((int linetype));
71 TERM_PUBLIC void HP26_line_and_point __PROTO((unsigned int x, unsigned int y, int number));
76 /* Use a size 1 character, or a 7 x 10 grid. */
81 #endif /* TERM_PROTO */
83 #ifndef TERM_PROTO_ONLY
85 /* include the stream compaction routines */
87 #define HP26_XLAST (HP26_XMAX - 1)
88 #define HP26_YLAST (HP26_XMAX - 1)
90 static void HP26_do_point __PROTO((unsigned int x, unsigned int y, int number));
91 static int compact_slope __PROTO((int xp[], int yp[], int isa_move[], int *sz, double delta));
92 static struct _HP26_Buffer_Node *BN_create __PROTO((int index, int size, int linetype));
93 static void BN_delete __PROTO((struct _HP26_Buffer_Node * the_node));
94 static int HP26_flush __PROTO((struct _HP26_Buffer_Node * the_buff));
95 static void HP26_handle_overflow __PROTO((void));
99 typedef struct _HP26_Buffer_Node {
109 /* constructor method */
110 static HP26_Buffer_Node *
111 BN_create(int index, int size, int linetype)
113 HP26_Buffer_Node *the_node;
114 the_node = (HP26_Buffer_Node *) malloc(sizeof(HP26_Buffer_Node));
115 the_node->index = index;
116 the_node->linetype = linetype;
117 the_node->size = size;
119 the_node->x = (int *) calloc(the_node->size, sizeof(int));
120 the_node->y = (int *) calloc(the_node->size, sizeof(int));
121 the_node->isa_move = (TBOOLEAN *) calloc(the_node->size, sizeof(TBOOLEAN));
122 if (the_node->x == NULL
123 || the_node->y == NULL
124 || the_node->isa_move == NULL)
130 /* destructor method */
132 BN_delete(HP26_Buffer_Node *the_node)
136 free(the_node->isa_move);
140 /* 2 for border and axes + 9 for plots + 1 for dots */
141 #define HP26_gnu_map_size 12
142 static HP26_Buffer_Node *HP26_gnu_map[HP26_gnu_map_size];
143 static HP26_Buffer_Node *HP26_buff;
144 static int HP26_pen_x;
145 static int HP26_pen_y;
146 static int HP26_angle;
147 static int HP26_cursor_x;
148 static int HP26_cursor_y;
149 static TBOOLEAN HP26_in_text;
150 static int HP26_linetype_current;
151 static int HP26_reduction_int;
152 static int HP26_reduction_slope;
153 static int HP26_overflows;
154 static int HP26_nop_move;
155 static int HP26_nop_vect;
156 static int HP26_nop_line;
173 #define swap(a, b) a ^= b; b ^= a; a ^= b;
175 static char HP26_bin_short_table[32] =
177 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>',
178 '?', ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-',
181 /* encodes an integer (assumed to be in range) into
182 binary short incremental format (j)*/
183 #define short_encode(n) (HP26_bin_short_table[n+16])
185 /* tells whether a given delta_x,delta_y pair can be expressed in
186 binary short incremental format */
187 #define qualified(dx,dy) ((dx>-17)&&(dy>-17)&&(dx<16)&&(dy<16))
190 static char HP26_bin_table[32] =
192 ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-',
193 '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<',
196 /* returns the high byte of integer n in binary absolute format (i) */
197 #define bin_encode_hi(n) (HP26_bin_table[n>>5])
198 /* returns the low byte of integer n in binary absolute format (i) */
199 #define bin_encode_lo(n) (HP26_bin_table[n & 31])
203 /* the guts of the program
204 -- first checks if any work need be done and, failing that, returns
206 -- tries to compress the vector stream
207 -- goes through the buffer, using binary short incremental (2 bytes/point)
208 as much as possible, even if must output two pairs to express one vector
209 (it's no more expensive, and will hopefully damp any excessive switching
210 back and forth between the two formats)
211 if can't use binary short incremental, use binary
212 absolute(4 bytes/point)
213 -- finally, resets the HP26_next pointer to zero */
215 HP26_flush(HP26_Buffer_Node *the_buff)
217 int i, delta_x, delta_y, half_dx, half_dy;
218 int *buff_x, *buff_y;
222 if (the_buff->next == 0)
224 /* init pointers for easy access */
225 buff_x = the_buff->x;
226 buff_y = the_buff->y;
227 isa_move = the_buff->isa_move;
229 fputs("\033*dT", gpoutfile);
230 HP26_in_text = FALSE;
232 if (HP26_linetype_current != the_buff->linetype
233 && (the_buff->next > 1 || !isa_move[0])) {
234 fprintf(gpoutfile, "\033*m%dB", the_buff->linetype);
235 HP26_linetype_current = the_buff->linetype;
237 /* try to compress the stream */
238 if (the_buff->next > 30 && the_buff->linetype != POINT) {
239 HP26_reduction_slope += compact_slope(buff_x, buff_y, (int *)isa_move, &(the_buff->next), 0.1);
241 /* start escape sequence */
242 fputs("\033*p", gpoutfile);
243 /* initialize the state: binary short incremental or binary absolute */
244 delta_x = buff_x[0] - HP26_pen_x;
245 delta_y = buff_y[0] - HP26_pen_y;
246 if (qualified(delta_x, delta_y)) {
247 fputc('j', gpoutfile);
250 fputc('i', gpoutfile);
253 /* now work through the list */
254 for (i = 0; i < the_buff->next; i++) {
256 delta_x = buff_x[i] - buff_x[i - 1];
257 delta_y = buff_y[i] - buff_y[i - 1];
259 if ((delta_x == 0) && (delta_y == 0)) {
260 if (i > 0 && !isa_move[i - 1] && !isa_move[i]) {
261 /* allow null vectors only when drawing dots */
264 } else if (isa_move[i]) {
270 && i + 1 < the_buff->next
272 && isa_move[i + 1]) {
273 /* consecutive moves are condensed into one */
276 } else if (!qualified(delta_x, delta_y)
278 && i + 2 < the_buff->next
282 && qualified(buff_x[i + 1] - buff_x[i - 1], buff_y[i + 1] - buff_y[i - 1])) {
283 swap(buff_x[i], buff_x[i + 1]);
284 swap(buff_y[i], buff_y[i + 1]);
285 /* set up new delta_x & delta_y */
286 delta_x = buff_x[i] - buff_x[i - 1];
287 delta_y = buff_y[i] - buff_y[i - 1];
289 if (qualified(delta_x, delta_y)) {
291 fputc('j', gpoutfile);
295 fputc('a', gpoutfile);
296 fputc(short_encode(delta_x), gpoutfile);
297 fputc(short_encode(delta_y), gpoutfile);
299 half_dx = (delta_x + (delta_x > 0 ? 1 : -1)) / 2;
300 half_dy = (delta_y + (delta_y > 0 ? 1 : -1)) / 2;
301 if (bin_short && qualified(half_dx, half_dy)) {
303 fputc('a', gpoutfile);
304 fputc(short_encode(half_dx), gpoutfile);
305 fputc(short_encode(half_dy), gpoutfile);
307 fputc('a', gpoutfile);
308 fputc(short_encode(delta_x - half_dx), gpoutfile);
309 fputc(short_encode(delta_y - half_dy), gpoutfile);
313 fputc('i', gpoutfile);
316 fputc('a', gpoutfile);
317 fputc(bin_encode_hi(buff_x[i]), gpoutfile);
318 fputc(bin_encode_lo(buff_x[i]), gpoutfile);
319 fputc(bin_encode_hi(buff_y[i]), gpoutfile);
320 fputc(bin_encode_lo(buff_y[i]), gpoutfile);
324 /* the term doesn't seem to mind leaving this out */
325 /* finish the escape sequence */
326 fputc('Z', gpoutfile);
327 /* set these for next time */
328 HP26_pen_x = buff_x[the_buff->next - 1];
329 HP26_pen_y = buff_y[the_buff->next - 1];
335 HP26_handle_overflow()
337 HP26_Buffer_Node *bigger, *old;
339 x = (HP26_buff->x)[HP26_buff->next - 1];
340 y = (HP26_buff->y)[HP26_buff->next - 1];
341 HP26_flush(HP26_buff);
342 bigger = BN_create(HP26_buff->index, HP26_buff->size * 2,
343 HP26_buff->linetype);
344 if (bigger != NULL) {
346 HP26_gnu_map[bigger->index] = bigger;
347 /* special case since DOTS entry is shared 3 ways */
348 if (bigger->index == 0) {
349 HP26_gnu_map[1] = bigger;
350 HP26_gnu_map[3] = bigger;
355 (HP26_buff->x)[0] = x;
356 (HP26_buff->y)[0] = y;
357 (HP26_buff->isa_move)[0] = TRUE;
362 /* checks for NOP, overcapacity condition, and then adds vector to the list */
364 HP26_vector(unsigned int x, unsigned int y)
366 if (HP26_buff->next > 2
367 && x == (HP26_buff->x)[HP26_buff->next - 1]
368 && y == (HP26_buff->y)[HP26_buff->next - 1]
369 && !(HP26_buff->isa_move)[HP26_buff->next - 1]) {
373 if (HP26_buff->next == HP26_buff->size)
374 HP26_handle_overflow();
375 /* otherwise add to the list */
376 (HP26_buff->x)[HP26_buff->next] = x;
377 (HP26_buff->y)[HP26_buff->next] = y;
378 (HP26_buff->isa_move)[HP26_buff->next] = FALSE;
382 /* checks for NOP, checks for overcapacity, puts self on list */
384 HP26_move(unsigned int x, unsigned int y)
386 if (HP26_buff->next > 0) {
387 if (((HP26_buff->x)[HP26_buff->next - 1] == x)
388 && ((HP26_buff->y)[HP26_buff->next - 1] == y)) {
389 /* null moves are NOP's */
392 } else if ((HP26_buff->isa_move)[HP26_buff->next - 1]) {
393 /* consecutive moves are NOP's */
394 (HP26_buff->x)[HP26_buff->next - 1] = x;
395 (HP26_buff->y)[HP26_buff->next - 1] = y;
400 if (HP26_buff->next == HP26_buff->size)
401 HP26_handle_overflow();
402 (HP26_buff->x)[HP26_buff->next] = x;
403 (HP26_buff->y)[HP26_buff->next] = y;
404 (HP26_buff->isa_move)[HP26_buff->next] = TRUE;
412 HP26_gnu_map[-2 + 2] = BN_create(0, 2048, DOTS); /* border */
413 HP26_gnu_map[-1 + 2] = HP26_gnu_map[-2 + 2]; /* axes */
414 HP26_gnu_map[0 + 2] = BN_create(2, 3072, SOLID); /* plot 0 */
415 HP26_gnu_map[1 + 2] = HP26_gnu_map[-2 + 2]; /* plot 1 */
416 HP26_gnu_map[2 + 2] = BN_create(4, 1024, LINE5); /* plot 2 */
417 HP26_gnu_map[3 + 2] = BN_create(5, 256, LINE6); /* plot 3 */
418 HP26_gnu_map[4 + 2] = BN_create(6, 256, LINE8); /* plot 4 */
419 HP26_gnu_map[5 + 2] = BN_create(7, 128, LINE9); /* plot 5 */
420 HP26_gnu_map[6 + 2] = BN_create(8, 128, LINE10); /* plot 6 */
421 HP26_gnu_map[7 + 2] = BN_create(9, 64, LINE6); /* plot 7 */
422 HP26_gnu_map[8 + 2] = BN_create(10, 64, LINE4); /* plot 8 */
423 HP26_gnu_map[9 + 2] = BN_create(11, 512, POINT); /* point plot */
424 HP26_buff = HP26_gnu_map[10]; /* set to an unlikely linetype */
425 HP26_linetype_current = 0; /* set to force a linetype change */
426 HP26_angle = 1; /* left to right, default */
427 fputs("\033*mp1m2a2Q", gpoutfile);
430 2. select text size 1
431 3. make SET the default drawing op
432 4. left justify text */
440 fputs("\033*daflsC", gpoutfile);
442 1. clear graphics display
443 2. shut off the alphanumeric display
444 3. graphics cursor off
445 4. into graphics text mode
446 5. enable graphics display */
447 /* set the pen & cursor positions to force an initial absolute move */
448 HP26_pen_x = HP26_pen_y = -200;
449 HP26_cursor_x = HP26_cursor_y = 800;
451 /* initialize statistics */
452 HP26_reduction_int = 0;
453 HP26_reduction_slope = 0;
466 /* always flush the current line first */
467 for (i = 0; i < HP26_gnu_map_size; i++)
468 if ((HP26_gnu_map[i])->linetype == HP26_linetype_current)
469 HP26_flush(HP26_gnu_map[i]);
470 /* now flush the rest of the lines */
471 for (i = 0; i < HP26_gnu_map_size; i++) {
472 HP26_flush(HP26_gnu_map[i]);
473 curr = HP26_gnu_map[i]->linetype;
474 for (j = 0; j < HP26_gnu_map_size; j++)
475 if ((HP26_gnu_map[j])->linetype == curr)
476 HP26_flush(HP26_gnu_map[j]);
478 fputs("\033*deT", gpoutfile);
480 1. turn on the alphanumeric display
481 2. back to text mode */
483 /* informational: tells how many points compressed, how
484 many NOP's of each type, and how many times a buffer
485 overflowed during this plot */
487 if(HP26_reduction_int
488 + HP26_reduction_slope
492 + HP26_nop_line > 0){
493 if (HP26_reduction_int>0)
494 printf("%d int-compress",HP26_reduction_int);
495 if (HP26_reduction_slope>0)
496 printf("%d slope-compress",HP26_reduction_slope);
498 printf(" %d nop_move",HP26_nop_move);
500 printf(" %d nop_vect",HP26_nop_vect);
502 printf(" %d nop_line",HP26_nop_line);
503 if (HP26_overflows>0)
504 printf(" %d buffer overflows",HP26_overflows);
514 for (i = 2; i < HP26_gnu_map_size; i++)
515 BN_delete(HP26_gnu_map[i]);
519 HP26_text_angle(int ang)
521 HP26_angle = (ang ? 2 : 1);
522 fprintf(gpoutfile, "\033*m%dN", HP26_angle);
528 HP26_put_text(unsigned int x, unsigned int y, const char *str)
530 char abs_str[10], rel_str[10];
535 fputs("\033*d", gpoutfile);
537 fputc('s', gpoutfile);
540 sprintf(rel_str, "%d,%dP", x - HP26_cursor_x, y - HP26_cursor_y);
541 sprintf(abs_str, "%d,%dO", x, y);
542 if (strlen(rel_str) < strlen(abs_str))
543 fputs(rel_str, gpoutfile);
545 fputs(abs_str, gpoutfile);
546 fputs(str, gpoutfile);
547 HP26_pen_x = HP26_cursor_x = x;
548 HP26_pen_y = HP26_cursor_y = y;
551 tmp = &(HP26_all_buffers[HP26_linetype_current]);
552 tmp->x[tmp->next] = x;
553 tmp->y[tmp->next] = y;
554 tmp->isa_move[tmp->next] = TRUE;
557 fprintf(gpoutfile,"\033*l%s\r",str);
563 /* checks for NOP, sets HP26_buff to point to the right buffer */
565 HP26_linetype(int linetype)
572 if (HP26_gnu_map[linetype] == HP26_buff) {
574 return; /* gnuplot just sent us another NOP */
576 HP26_buff = HP26_gnu_map[linetype];
581 /* switches to a solid linetype and calls do_point, then switches back */
583 HP26_line_and_point(unsigned int x, unsigned int y, int number)
585 int line_save, not_solid;
587 /* shut up warnings with dummy initializer -SB */
589 not_solid = (HP26_buff->linetype != SOLID);
591 line_save = HP26_buff->linetype;
592 HP26_linetype(0); /*switch to a solid line */
594 HP26_do_point(x, y, number);
596 HP26_linetype(line_save);
600 /* provides 9 point types so they stay in sync with the linetypes
601 puts simpler point types first on the assumption they are more
604 HP26_do_point(unsigned int x, unsigned int y, int number)
607 HP26_Buffer_Node *tmp;
609 vtic = HP26_VTIC / 2;
610 htic = HP26_HTIC / 2;
612 /* do a dot -- special case */
614 HP26_buff = HP26_gnu_map[11]; /* point plot */
618 switch (number % 9) {
621 HP26_move(x - htic, y - vtic);
622 HP26_vector(x, y + vtic);
623 HP26_vector(x + htic, y - vtic);
624 HP26_vector(x - htic, y - vtic);
628 HP26_move(x - htic, y + vtic);
629 HP26_vector(x, y - vtic);
630 HP26_vector(x + htic, y + vtic);
631 HP26_vector(x - htic, y + vtic);
634 /* do left triangle */
635 HP26_move(x - htic, y);
636 HP26_vector(x + htic, y + vtic);
637 HP26_vector(x + htic, y - vtic);
638 HP26_vector(x - htic, y);
641 /* do right triangle */
642 HP26_move(x + htic, y);
643 HP26_vector(x - htic, y + vtic);
644 HP26_vector(x - htic, y - vtic);
645 HP26_vector(x + htic, y);
649 HP26_move(x - htic, y - vtic);
650 HP26_vector(x - htic, y + vtic);
651 HP26_vector(x + htic, y + vtic);
652 HP26_vector(x + htic, y - vtic);
653 HP26_vector(x - htic, y - vtic);
657 HP26_move(x, y + vtic);
658 HP26_vector(x, y - vtic);
659 HP26_move(x - htic, y);
660 HP26_vector(x + htic, y);
664 HP26_move(x + htic, y + vtic);
665 HP26_vector(x - htic, y - vtic);
666 HP26_move(x - htic, y + vtic);
667 HP26_vector(x + htic, y - vtic);
671 HP26_move(x, y - vtic);
672 HP26_vector(x - htic, y);
673 HP26_vector(x, y + vtic);
674 HP26_vector(x + htic, y);
675 HP26_vector(x, y - vtic);
680 #endif /* TERM_BODY */
684 TERM_TABLE_START(hp2623a_driver)
685 "hp2623A", "HP2623A and maybe others",
686 HP26_XMAX, HP26_YMAX, HP26_VCHAR, HP26_HCHAR,
687 HP26_VTIC, HP26_HTIC, options_null, HP26_init, HP26_reset,
688 HP26_text, null_scale, HP26_graphics, HP26_move, HP26_vector,
689 HP26_linetype, HP26_put_text, HP26_text_angle,
690 null_justify_text, HP26_line_and_point, do_arrow, set_font_null
691 TERM_TABLE_END(hp2623a_driver)
694 #define LAST_TERM hp2623a_driver
696 #endif /* TERM_TABLE */
697 #endif /* TERM_PROTO_ONLY */
702 "?commands set terminal hp2623a",
703 "?set terminal hp2623a",
708 " The `hp2623a` terminal driver supports the Hewlett Packard HP2623A. It has",