/usr/bin/gnuplot symlinks packageing problems were fixed gor gnuplot-x11
[gnuplot] / term / next.trm
1 /* Hello, Emacs, this is -*- objc -*-
2  * $Id: next.trm,v 1.27 2006/07/21 02:35:47 sfeam Exp $
3  *
4  */
5
6 /* GNUPLOT - next.trm */
7
8 /*[
9  * Copyright 1991 - 1993, 1998, 2004
10  *
11  * Permission to use, copy, and distribute this software and its
12  * documentation for any purpose with or without fee is hereby granted,
13  * provided that the above copyright notice appear in all copies and
14  * that both that copyright notice and this permission notice appear
15  * in supporting documentation.
16  *
17  * Permission to modify the software is granted, but not the right to
18  * distribute the complete modified source code.  Modifications are to
19  * be distributed as patches to the released version.  Permission to
20  * distribute binaries produced by compiling modified sources is granted,
21  * provided you
22  *   1. distribute the corresponding source modifications from the
23  *    released version in the form of a patch file along with the binaries,
24  *   2. add special version identification to distinguish your version
25  *    in addition to the base release version number,
26  *   3. provide your name and address as the primary contact for the
27  *    support of your modified version, and
28  *   4. retain our contact information in regard to use of the base
29  *    software.
30  * Permission to distribute the released version of the source code along
31  * with corresponding source modifications in the form of a patch file is
32  * granted with same provisions 2 through 4 for binary distributions.
33  *
34  * This software is provided "as is" without express or implied warranty
35  * to the extent permitted by applicable law.
36 ]*/
37
38 /*
39  * This file is included by ../term.c via ../term.h.
40  *
41  * This terminal driver supports:
42  *     next
43  *
44  * AUTHORS
45  *  Robert Lutwak from Russell Lang's post.trm
46  *  'old' option invokes Nick Strobel's original, single viewport terminal
47  *
48  * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
49  *
50  * This terminal attempts to connect, via the NeXTstep Distributed
51  * Objects system, to the "gnuplotServer."  If there is no such
52  * service registered with the OS, the terminal attempts to fire
53  * up GnuTerm.app.  If the user has not set the environment variable
54  * GNUTERMPATH, the terminal uses the users ApplicationPaths Workspace
55  * dwrite to search for GnuTerm.app (Note:  this is usually something
56  * like ~/Apps, ~/LocalApps, ~/NextApps, etc.).
57  * In order to use this filter, you MUST have GnuTerm.app installed
58  * on your system.
59  *
60  * Once connected to the server, this filter is basically Russell Lang's
61  * Postscript filter, except that the resultant postscript code
62  * is sent, via the D.O. system, to GnuTerm.app, which manages
63  * the windows which produce the postscript output on the screen.
64  *
65  *
66  * Defaults are
67  * 'set term next new dashed auto "Helvetica" 14'
68  *
69  * To change font to Times-Roman and font size to 20pts use
70  * 'set term next "Times-Roman" 20'.
71  *
72  * to choose window by title
73  * 'set term next title "Window title"
74  *
75  * Monitor Options:
76  * monochrome, color
77  *
78  * To invoke Nick Strobel's old terminal
79  * 'set term next old'
80  */
81
82 #include "driver.h"
83
84 #ifdef TERM_REGISTER
85 register_term(next)
86 #endif
87
88 #ifdef TERM_PROTO
89
90 /* whether or not to compile support for the old (self-contained)
91    NeXT terminal */
92 /* #define NEXT_OLDTERMINAL     1 */
93
94 #import <appkit/appkit.h>
95 #import <remote/NXProxy.h>      /* setProtocolForProxy */
96 #import <remote/NXConnection.h> /* setProtocolForProxy */
97 #import <machkit/NXNetNameServer.h>
98 #import <machkit/senderIsInvalid.h>
99 #import <stdarg.h>
100
101
102 #ifdef NEXT_OLDTERMINAL
103 static void window_create __PROTO((void));
104 @interface EpsViewer:Application
105 {
106     id theNewWin;
107 }
108
109 -windowCreate:(NXCoord)
110 width Height:(NXCoord) height;
111 -(NXRect *) nextRectForWidth:(NXCoord)
112 width Height:(NXCoord) height;
113 @end
114 #endif /* NEXT_OLDTERMINAL */
115
116
117 TERM_PUBLIC void NEXT_options __PROTO((void));
118 TERM_PUBLIC void NEXT_common_init __PROTO((int uses_fonts, unsigned int xoff, unsigned int yoff, unsigned int xsize, unsigned int ysize, char **dict));
119 TERM_PUBLIC void NEXT_init __PROTO((void));
120 TERM_PUBLIC void NEXT_graphics __PROTO((void));
121 TERM_PUBLIC void NEXT_text __PROTO((void));
122 TERM_PUBLIC void NEXT_reset __PROTO((void));
123 TERM_PUBLIC void NEXT_linetype __PROTO((int linetype));
124 TERM_PUBLIC void NEXT_move __PROTO((unsigned int x, unsigned int y));
125 TERM_PUBLIC void NEXT_vector __PROTO((unsigned int x, unsigned int y));
126 TERM_PUBLIC void NEXT_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
127 TERM_PUBLIC int NEXT_text_angle __PROTO((int ang));
128 TERM_PUBLIC int NEXT_justify_text __PROTO((enum JUSTIFY mode));
129 TERM_PUBLIC void NEXT_point __PROTO((unsigned int x, unsigned int y, int number));
130 TERM_PUBLIC int NEXT_set_font __PROTO((const char *font));
131 TERM_PUBLIC char *NEXT_RememberFont __PROTO((char *fname));
132 TERM_PUBLIC void NEXT_set_pointsize __PROTO((double size));
133
134
135 #define NEXT_POINT_TYPES 8      /* div */
136 #define NEXT_XOFF       1       /* page offset in pts */
137 #define NEXT_YOFF       1
138 #define NEXT_XMAX 6400
139 #define NEXT_YMAX 4800
140 #define NEXT_XLAST (NEXT_XMAX - 1)
141 #define NEXT_YLAST (NEXT_YMAX - 1)
142 #define NEXT_VTIC (NEXT_YMAX/80)
143 #define NEXT_HTIC (NEXT_YMAX/80)
144 #define NEXT_SC (10)            /* scale is 1pt = 10 units */
145 #define NEXT_LW (0.5*NEXT_SC)   /* linewidth = 0.5 pts */
146 #define NEXT_VCHAR (14*NEXT_SC) /* default is 14 point characters */
147 #define NEXT_HCHAR (14*NEXT_SC*6/10)
148
149 #define GOT_NEXT_PROTO
150 #endif
151
152
153 #ifndef TERM_PROTO_ONLY
154
155 #ifdef TERM_BODY
156
157 @interface GnuTermDriver:Object < NXSenderIsInvalid >
158 {
159     id server;
160 }
161
162 -senderIsInvalid:(id) sender;
163 -plot:(char *) PSstr;
164 -init;
165 @end
166
167
168 #define DEFAULTNEXTSIZE 10000
169
170 static id gnuTermAccess;        /* local object manages the D.O. connection */
171
172 static char *NEXTBuffer, *NEXTBufAt, *NEXTBufEnd;
173 static int NEXTsize;
174 static char NEXTTmpBuf[1000];
175 static void NEXTPrintf(char *,...);
176 static TBOOLEAN NEXT_oldterminal = FALSE;
177 /*static TBOOLEAN NEXT_colordetect();*/
178
179 static char NEXT_title[MAX_LINE_LEN + 1];       /* name of font */
180
181 static char NEXT_font[MAX_LINE_LEN + 1] = "Helvetica";  /* name of font */
182 static int NEXT_fontsize = 14;  /* size of font in pts */
183 static int NEXT_default_font[MAX_ID_LEN+1] = {'\0'};
184 static TBOOLEAN NEXT_color = FALSE;
185 static TBOOLEAN NEXT_solid = FALSE;     /*  use dashed lines */
186 static int NEXT_path_count = 0; /* count of lines in path */
187 static int NEXT_ang = 0;        /* text angle */
188 static enum JUSTIFY NEXT_justify = LEFT;        /* text is flush left */
189
190 static TBOOLEAN NEXT_duplex_state = FALSE;
191 static TBOOLEAN NEXT_duplex_option = FALSE;
192
193 static char GPFAR *GPFAR NEXT_header[] =
194 {
195     "/M {moveto} bind def\n",
196     "/L {lineto} bind def\n",
197     "/R {rmoveto} bind def\n",
198     "/V {rlineto} bind def\n",
199     "/vpt2 vpt 2 mul def\n",
200     "/hpt2 hpt 2 mul def\n",
201 /* flush left show */
202     "/Lshow { currentpoint stroke M\n",
203     "  0 vshift R show } def\n",
204 /* flush right show */
205     "/Rshow { currentpoint stroke M\n",
206     "  dup stringwidth pop neg vshift R show } def\n",
207 /* centred show */
208     "/Cshow { currentpoint stroke M\n",
209     "  dup stringwidth pop -2 div vshift R show } def\n",
210 /* Dash or Color Line */
211     "/DL { Color {setrgbcolor Solid {pop []} if 0 setdash }\n",
212     " {pop pop pop Solid {pop []} if 0 setdash} ifelse } def\n",
213 /* Border Lines */
214     "/BL { stroke gnulinewidth 2 mul setlinewidth } def\n",
215 /* Axes Lines */
216     "/AL { stroke gnulinewidth 2 div setlinewidth } def\n",
217 /* Plot Lines */
218     "/PL { stroke gnulinewidth setlinewidth } def\n",
219 /* Line Types */
220     "/LTb { BL [] 0 0 0 DL } def\n",    /* border */
221     "/LTa { AL [1 dl 2 dl] 0 setdash 0 0 0 setrgbcolor } def\n",        /* axes */
222     "/LT0 { PL [] 0 1 0 DL } def\n",
223     "/LT1 { PL [4 dl 2 dl] 0 0 1 DL } def\n",
224     "/LT2 { PL [2 dl 3 dl] 1 0 0 DL } def\n",
225     "/LT3 { PL [1 dl 1.5 dl] 1 0 1 DL } def\n",
226     "/LT4 { PL [5 dl 2 dl 1 dl 2 dl] 0 1 1 DL } def\n",
227     "/LT5 { PL [4 dl 3 dl 1 dl 3 dl] 1 1 0 DL } def\n",
228     "/LT6 { PL [2 dl 2 dl 2 dl 4 dl] 0 0 0 DL } def\n",
229     "/LT7 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 1 0.3 0 DL } def\n",
230     "/LT8 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 0.5 0.5 0.5 DL } def\n",
231 /* Point (Round) */ /* Matt Heffron make it round */
232     "/Pnt { stroke [] 0 setdash\n",
233     "   gsave 1 setlinecap M 0 0 V stroke grestore } def\n",
234
235 /* Diamond */
236     "/Dia { stroke [] 0 setdash 2 copy vpt add M\n",
237     "  hpt neg vpt neg V hpt vpt neg V\n",
238     "  hpt vpt V hpt neg vpt V closepath stroke\n",
239     "  Pnt } def\n",
240
241 /* Plus */
242     "/Pls { stroke [] 0 setdash vpt sub M 0 vpt2 V\n",
243     "  currentpoint stroke M\n",
244     "  hpt neg vpt neg R hpt2 0 V stroke\n",
245     "  } def\n",
246
247 /* Box */
248     "/Box { stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M\n",
249     "  0 vpt2 neg V hpt2 0 V 0 vpt2 V\n",
250     "  hpt2 neg 0 V closepath stroke\n",
251     "  Pnt } def\n",
252
253 /* Cross (X) */
254     "/Crs { stroke [] 0 setdash exch hpt sub exch vpt add M\n",
255     "  hpt2 vpt2 neg V currentpoint stroke M\n",
256     "  hpt2 neg 0 R hpt2 vpt2 V stroke } def\n",
257
258 /* Triangle Up*/
259     "/TriU { stroke [] 0 setdash 2 copy vpt 1.12 mul add M\n",
260     "  hpt neg vpt -1.62 mul V\n",
261     "  hpt 2 mul 0 V\n",
262     "  hpt neg vpt 1.62 mul V closepath stroke\n",
263     "  Pnt  } def\n",
264
265 /* Star */
266     "/Star { 2 copy Pls Crs } def\n",
267
268 /* div added filed box */
269 /* Filled Box */
270     "/BoxF { stroke [] 0 setdash exch hpt sub exch vpt add M\n",
271     "  0 vpt2 neg V  hpt2 0 V  0 vpt2 V\n",
272     "  hpt2 neg 0 V  closepath fill } def\n",
273
274 /* div added filled triangle */
275 /* Triangle Up, Filled */
276     "/TriUF { stroke [] 0 setdash vpt 1.12 mul add M\n",
277     "  hpt neg vpt -1.62 mul V\n",
278     "  hpt 2 mul 0 V\n",
279     "  hpt neg vpt 1.62 mul V closepath fill } def\n",
280
281 /* Matt Heffron: added a few more types */
282 /* Triangle Down */
283     "/TriD { stroke [] 0 setdash 2 copy vpt 1.12 mul sub M\n",
284     "  hpt neg vpt 1.62 mul V\n",
285     "  hpt 2 mul 0 V\n",
286     "  hpt neg vpt -1.62 mul V closepath stroke\n",
287     "  Pnt  } def\n",
288
289 /* Triangle Down, Filled*/
290     "/TriDF { stroke [] 0 setdash vpt 1.12 mul sub M\n",
291     "  hpt neg vpt 1.62 mul V\n",
292     "  hpt 2 mul 0 V\n",
293     "  hpt neg vpt -1.62 mul V closepath fill} def\n",
294
295 /* Diamond, Filled */
296     "/DiaF { stroke [] 0 setdash vpt add M\n",
297     "  hpt neg vpt neg V hpt vpt neg V\n",
298     "  hpt vpt V hpt neg vpt V closepath fill } def\n",
299
300 /* Pentagon */
301     "/Pent { stroke [] 0 setdash 2 copy gsave\n",
302     "  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat\n",
303     "  closepath stroke grestore Pnt } def\n",
304
305 /* Pentagon, Filled */
306     "/PentF { stroke [] 0 setdash gsave\n",
307     "  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat\n",
308     "  closepath fill grestore } def\n",
309
310 /* Circle */
311     "/Circle { stroke [] 0 setdash 2 copy\n",
312     "  hpt 0 360 arc stroke Pnt } def\n",
313
314 /* Circle,Filled */
315     "/CircleF { stroke [] 0 setdash hpt 0 360 arc fill } def\n",
316 /* 16 differently filled circles */
317     "/C0 { BL [] 0 setdash 2 copy moveto vpt 90 450  arc } bind def\n",
318     "/C1 { BL [] 0 setdash 2 copy        moveto\n",
319     "       2 copy  vpt 0 90 arc closepath fill\n",
320     "               vpt 0 360 arc closepath } bind def\n",
321     "/C2 { BL [] 0 setdash 2 copy moveto\n",
322     "       2 copy  vpt 90 180 arc closepath fill\n",
323     "               vpt 0 360 arc closepath } bind def\n",
324     "/C3 { BL [] 0 setdash 2 copy moveto\n",
325     "       2 copy  vpt 0 180 arc closepath fill\n",
326     "               vpt 0 360 arc closepath } bind def\n",
327     "/C4 { BL [] 0 setdash 2 copy moveto\n",
328     "       2 copy  vpt 180 270 arc closepath fill\n",
329     "               vpt 0 360 arc closepath } bind def\n",
330     "/C5 { BL [] 0 setdash 2 copy moveto\n",
331     "       2 copy  vpt 0 90 arc\n",
332     "       2 copy moveto\n",
333     "       2 copy  vpt 180 270 arc closepath fill\n",
334     "               vpt 0 360 arc } bind def\n",
335     "/C6 { BL [] 0 setdash 2 copy moveto\n",
336     "      2 copy  vpt 90 270 arc closepath fill\n",
337     "              vpt 0 360 arc closepath } bind def\n",
338     "/C7 { BL [] 0 setdash 2 copy moveto\n",
339     "      2 copy  vpt 0 270 arc closepath fill\n",
340     "              vpt 0 360 arc closepath } bind def\n",
341     "/C8 { BL [] 0 setdash 2 copy moveto\n",
342     "      2 copy vpt 270 360 arc closepath fill\n",
343     "              vpt 0 360 arc closepath } bind def\n",
344     "/C9 { BL [] 0 setdash 2 copy moveto\n",
345     "      2 copy  vpt 270 450 arc closepath fill\n",
346     "              vpt 0 360 arc closepath } bind def\n",
347     "/C10 { BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill\n",
348     "       2 copy moveto\n",
349     "       2 copy vpt 90 180 arc closepath fill\n",
350     "               vpt 0 360 arc closepath } bind def\n",
351     "/C11 { BL [] 0 setdash 2 copy moveto\n",
352     "       2 copy  vpt 0 90 arc closepath fill\n",
353     "       2 copy moveto\n",
354     "       2 copy  vpt 180 360 arc closepath fill\n",
355     "               vpt 0 360 arc closepath } bind def\n",
356     "/C12 { BL [] 0 setdash 2 copy moveto\n",
357     "       2 copy  vpt 180 360 arc closepath fill\n",
358     "               vpt 0 360 arc closepath } bind def\n",
359     "/C13 { BL [] 0 setdash  2 copy moveto\n",
360     "       2 copy  vpt 0 90 arc closepath fill\n",
361     "       2 copy moveto\n",
362     "       2 copy  vpt 180 360 arc closepath fill\n",
363     "               vpt 0 360 arc closepath } bind def\n",
364     "/C14 { BL [] 0 setdash 2 copy moveto\n",
365     "       2 copy  vpt 90 360 arc closepath fill\n",
366     "               vpt 0 360 arc } bind def\n",
367     "/C15 { BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill\n",
368     "               vpt 0 360 arc closepath } bind def\n",
369
370 /* Auxiliary definitions for rectangles */
371
372     "/Rec   { newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n",
373     "       neg 0 rlineto closepath } bind def\n",
374     "/Square { dup Rec } bind def\n",
375     "/Bsquare { vpt sub exch vpt sub exch vpt2 Square } bind def\n",
376
377 /* 16 differently filled squares */
378
379     "/S0 { BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare } bind def\n",
380     "/S1 { BL [] 0 setdash 2 copy vpt Square fill Bsquare } bind def\n",
381     "/S2 { BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare } bind def\n",
382     "/S3 { BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare } bind def\n",
383     "/S4 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare } bind def\n",
384     "/S5 { BL [] 0 setdash 2 copy 2 copy vpt Square fill\n",
385     "       exch vpt sub exch vpt sub vpt Square fill Bsquare } bind def\n",
386     "/S6 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare } bind def\n",
387     "/S7 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill\n",
388     "       2 copy vpt Square fill\n",
389     "       Bsquare } bind def\n",
390     "/S8 { BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare } bind def\n",
391     "/S9 { BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare } bind def\n",
392     "/S10 { BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill\n",
393     "       Bsquare } bind def\n",
394     "/S11 { 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill\n",
395     "       Bsquare } bind def\n",
396     "/S12 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare } bind def\n",
397     "/S13 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill\n",
398     "       2 copy vpt Square fill Bsquare } bind def\n",
399     "/S14 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill\n",
400     "       2 copy exch vpt sub exch vpt Square fill Bsquare } bind def\n",
401     "/S15 { BL [] 0 setdash 2 copy Bsquare fill Bsquare } bind def\n",
402
403 /* 16 different diamonds (actually just rotated squares) */
404
405     "/D0 { gsave translate 45 rotate 0 0 Box stroke grestore } bind def\n",
406     "/D1 { gsave translate 45 rotate 0 0 S1 stroke grestore } bind def\n",
407     "/D2 { gsave translate 45 rotate 0 0 S2 stroke grestore } bind def\n",
408     "/D3 { gsave translate 45 rotate 0 0 S3 stroke grestore } bind def\n",
409     "/D4 { gsave translate 45 rotate 0 0 S4 stroke grestore } bind def\n",
410     "/D5 { gsave translate 45 rotate 0 0 S5 stroke grestore } bind def\n",
411     "/D6 { gsave translate 45 rotate 0 0 S6 stroke grestore } bind def\n",
412     "/D7 { gsave translate 45 rotate 0 0 S7 stroke grestore } bind def\n",
413     "/D8 { gsave translate 45 rotate 0 0 S8 stroke grestore } bind def\n",
414     "/D9 { gsave translate 45 rotate 0 0 S9 stroke grestore } bind def\n",
415     "/D10 { gsave translate 45 rotate 0 0 S10 stroke grestore } bind def\n",
416     "/D11 { gsave translate 45 rotate 0 0 S11 stroke grestore } bind def\n",
417     "/D12 { gsave translate 45 rotate 0 0 S12 stroke grestore } bind def\n",
418     "/D13 { gsave translate 45 rotate 0 0 S13 stroke grestore } bind def\n",
419     "/D14 { gsave translate 45 rotate 0 0 S14 stroke grestore } bind def\n",
420     "/D15 { gsave translate 45 rotate 0 0 S15 stroke grestore } bind def\n",
421
422     NULL
423 };
424
425 static char GPFAR *GPFAR ENHNEXT_header[] =
426 {
427 /* For MFshow and MFwidth the tos is an array with the string and font info:  */
428 /*      [<fontname (a string)> <fontsize> <vertical offset> <width significant?> <text string>]  */
429
430     "/MFshow {{dup dup 0 get findfont exch 1 get scalefont setfont\n",
431     "     [ currentpoint ] exch dup 2 get 0 exch rmoveto dup 4 get show dup\n",
432     "     3 get {2 get neg 0 exch rmoveto pop} {pop aload pop moveto}ifelse} forall} bind def\n",
433     "/MFwidth {0 exch {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont\n",
434     "      4 get stringwidth pop add}\n",
435     "    {pop} ifelse} forall} bind def\n",
436
437 /* flush left show */
438     "/MLshow { currentpoint stroke M\n",
439     "  0 exch R MFshow } bind def\n",
440
441 /* flush right show */
442     "/MRshow { currentpoint stroke M\n",
443     "  exch dup MFwidth neg 3 -1 roll R MFshow } def\n",
444
445 /* centred show */
446     "/MCshow { currentpoint stroke M\n",
447     "  exch dup MFwidth -2 div 3 -1 roll R MFshow } def\n",
448     NULL
449 };
450
451 /* added to post by Matt Heffron <heffron@falstaff.css.beckman.com> */
452 /* moved to post.trm by drd */
453
454 struct NEXT_FontName {
455     char *name;
456     struct NEXT_FontName *next;
457 } *NEXT_DocFonts = NULL;
458
459 enum NEXT_id {
460     NEXT_DEFAULT, NEXT_MONOCHROME, NEXT_COLOR,
461     NEXT_SOLID, NEXT_DASHED,
462     NEXT_SIMPLEX, NEXT_DUPLEX, NEXT_DEFAULTPLEX,
463     NEXT_OLD, NEXT_NEW, NEXT_TITLE,
464     NEXT_OTHER
465 };
466
467 static struct gen_table NEXT_opts[] =
468 {
469     { "d$efault", NEXT_DEFAULT },
470     { "mono$chrome", NEXT_MONOCHROME },
471     { "col$or", NEXT_COLOR },
472     { "col$our", NEXT_COLOR },
473     { "so$lid", NEXT_SOLID },
474     { "da$shed", NEXT_DASHED },
475     { "si$mplex", NEXT_SIMPLEX },
476     { "du$plex", NEXT_DUPLEX },
477     { "defaultp$lex", NEXT_DEFAULTPLEX },
478     { "old", NEXT_OLD },
479     { "new", NEXT_NEW },
480     { "ti$tle", NEXT_TITLE },
481     { NULL, NEXT_OTHER }
482 };
483
484 TERM_PUBLIC void
485 NEXT_options()
486 {
487     char buf[40];
488     struct value a;
489
490     while (!END_OF_COMMAND) {
491         switch(lookup_table(&NEXT_opts[0],c_token)) {
492         case NEXT_DEFAULT:
493             NEXT_oldterminal = FALSE;
494             /*NEXT_color=NEXT_colordetect(); */
495             NEXT_color = FALSE;
496             NEXT_solid = FALSE;
497             NEXT_duplex_option = FALSE;
498             strcpy(NEXT_font, "Helvetica");
499             NEXT_fontsize = 14;
500             term->v_char = (unsigned int) (NEXT_fontsize * NEXT_SC);
501             term->h_char = (unsigned int) (NEXT_fontsize * NEXT_SC * 6 / 10);
502             term->put_text = NEXT_put_text;
503             c_token++;
504             break;
505         case NEXT_MONOCHROME:
506             NEXT_color = FALSE;
507             c_token++;
508             break;
509         case NEXT_COLOR:
510             NEXT_color = TRUE;
511             c_token++;
512             break;
513         case NEXT_SOLID:
514             NEXT_solid = TRUE;
515             c_token++;
516             break;
517         case NEXT_DASHED:
518             NEXT_solid = FALSE;
519             c_token++;
520             break;
521         case NEXT_SIMPLEX:
522             NEXT_duplex_state = FALSE;
523             NEXT_duplex_option = TRUE;
524             c_token++;
525             break;
526         case NEXT_DUPLEX:
527             NEXT_duplex_state = TRUE;
528             NEXT_duplex_option = TRUE;
529             c_token++;
530             break;
531         case NEXT_DEFAULTPLEX:
532             NEXT_duplex_option = FALSE;
533             c_token++;
534             break;
535         case NEXT_OLD:
536             NEXT_oldterminal = TRUE;
537             c_token++;
538             break;
539         case NEXT_NEW:
540             NEXT_oldterminal = FALSE;
541             c_token++;
542             break;
543         case NEXT_TITLE:
544             c_token++;
545             if (!isstring(c_token)) {
546                 fprintf(stderr, "usage:  set term next title \"newtitle\"\n");
547             }
548             quote_str(NEXT_title, c_token, MAX_LINE_LEN + 1);
549             break;
550         case NEXT_OTHER:
551         default:
552             if (isstring(c_token)) {
553                 quote_str(NEXT_font, c_token, MAX_LINE_LEN + 1);
554
555                 /* We must have font size specified */
556                 NEXT_fontsize = (int) real(const_express(&a));
557                 term->v_char = (unsigned int) (NEXT_fontsize * NEXT_SC);
558                 term->h_char = (unsigned int) (NEXT_fontsize * NEXT_SC * 6 / 10);
559                 sprintf(NEXT_default_font, "%s,%d", NEXT_font, NEXT_fontsize);
560             }
561             break;
562         }
563     }
564
565     sprintf(term_options, "%s %s %s %s \"%s\" %d title \"%s\"",
566             NEXT_oldterminal ? "old" : "new",
567             NEXT_color ? "color" : "monochrome",
568             NEXT_solid ? "solid" : "dashed",
569             NEXT_duplex_option ? (NEXT_duplex_state ? "duplex" : "simplex")
570             : "defaultplex",
571             NEXT_font,
572             NEXT_fontsize,
573             NEXT_title);
574 }
575
576
577 TERM_PUBLIC char *
578 NEXT_RememberFont(char *fname)
579 {
580     struct NEXT_FontName *fnp;
581
582     for (fnp = NEXT_DocFonts; fnp && strcmp(fnp->name, fname); fnp = fnp->next);
583     if (fnp)
584         return fnp->name;       /* we must have found it in the list */
585
586     if (encoding == S_ENC_ISO8859_1) {
587         NEXTPrintf("/%s reencodeISO def\n", fname);
588     }
589     fnp = (struct NEXT_FontName *) gp_alloc(sizeof(struct NEXT_FontName), "PostScript Font record");
590     fnp->name = gp_alloc(1 + strlen(fname), "PostScript Font name");
591     strcpy(fnp->name, fname);
592     fnp->next = NEXT_DocFonts;
593     NEXT_DocFonts = fnp;
594     return fnp->name;
595 }
596
597 int NEXT_pen_x, NEXT_pen_y;
598 int NEXT_taken;
599 int NEXT_linetype_last;
600 TBOOLEAN NEXT_relative_ok;
601
602 /* store settings passed to common_init() for use in NEXT_graphics()
603  * are reserved for storing the term options
604  */
605 static int NEXT_common_uses_fonts;
606 static unsigned int NEXT_common_xoff, NEXT_common_yoff;
607
608
609 TERM_PUBLIC void
610 NEXT_common_init(
611     int uses_fonts,             /* 0 for NEXT(la)tex */
612     unsigned int xoff, unsigned int yoff, /* offset  - 50 for /post, 0 for NEXT(la)tex */
613     unsigned int width, unsigned int height, /* for bounding box */
614     char **dict)                /* extra entries for the dictionary */
615 {
616     static char GPFAR NEXTi1[] = "%%%%Creator: gnuplot\n\
617 %%%%DocumentFonts: %s\n";
618     static char GPFAR NEXTi2[] = "%%%%EndComments\n\
619 /gnudict 120 dict def\ngnudict begin\n\
620 /Color %s def\n\
621 /Solid %s def\n\
622 /gnulinewidth %.3f def\n\
623 /vshift %d def\n\
624 /dl {%d mul} def\n\
625 /hpt %.1f def\n\
626 /vpt %.1f def\n";
627     static char GPFAR *NEXT_iso_8859_1_encoding[] =
628     {
629         "/reencodeISO {\n",
630         "dup dup findfont dup length dict begin\n",
631         "{ 1 index /FID ne { def }{ pop pop } ifelse } forall\n",
632         "/Encoding ISOLatin1Encoding def\n",
633         "currentdict end definefont\n",
634         "} def\n",
635         "/ISOLatin1Encoding [\n",
636         "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
637         "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
638         "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
639         "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
640         "/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright\n",
641         "/parenleft/parenright/asterisk/plus/comma/minus/period/slash\n",
642         "/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon\n",
643         "/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N\n",
644         "/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright\n",
645         "/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m\n",
646         "/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde\n",
647         "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
648         "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
649         "/.notdef/dotlessi/grave/acute/circumflex/tilde/macron/breve\n",
650         "/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut\n",
651         "/ogonek/caron/space/exclamdown/cent/sterling/currency/yen/brokenbar\n",
652         "/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot\n",
653         "/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior\n",
654         "/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine\n",
655         "/guillemotright/onequarter/onehalf/threequarters/questiondown\n",
656         "/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla\n",
657         "/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex\n",
658         "/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis\n",
659         "/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute\n",
660         "/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis\n",
661         "/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave\n",
662         "/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex\n",
663         "/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis\n",
664         "/yacute/thorn/ydieresis\n",
665         "] def\n",
666         NULL};
667
668
669     struct termentry *t = term;
670     int i;
671
672     NEXT_common_uses_fonts = uses_fonts;
673     NEXT_common_xoff = xoff;
674     NEXT_common_yoff = yoff;
675
676
677     NEXTPrintf("%%!NEXT-Adobe-2.0\n");
678
679     NEXTPrintf(NEXTi1, uses_fonts ? "(atend)" : "");
680
681     NEXTPrintf("%%%%BoundingBox: %d %d %d %d\n", xoff, yoff,
682                (int) (xsize * width / NEXT_SC + 0.5 + xoff),
683                (int) (ysize * height / NEXT_SC + 0.5 + yoff));
684
685     NEXTPrintf(NEXTi2,
686                NEXT_color ? "true" : "false",
687                NEXT_solid ? "true" : "false",
688                NEXT_LW,         /* line width */
689                (int) (t->v_char) / (-3),        /* shift for vertical centring */
690                NEXT_SC,         /* dash length */
691                NEXT_HTIC / 2.0, /* half point width */
692                NEXT_VTIC / 2.0);        /* half point height */
693
694     if (uses_fonts && (encoding == S_ENC_ISO8859_1)) {
695         for (i = 0; NEXT_iso_8859_1_encoding[i] != NULL; i++) {
696             NEXTPrintf("%s", NEXT_iso_8859_1_encoding[i]);
697         }
698     }
699     for (i = 0; NEXT_header[i] != NULL; i++)
700         NEXTPrintf("%s", NEXT_header[i]);
701     if (NEXT_duplex_option)
702         NEXTPrintf("statusdict begin %s setduplexmode end\n",
703                    NEXT_duplex_state ? "true" : "false");
704     NEXT_RememberFont(NEXT_font);
705
706     if (dict)
707         while (*dict)
708             NEXTPrintf("%s", *(dict++));
709
710     NEXTPrintf("end\n%%%%EndProlog\n");
711 }
712
713 /* the init fn for the NeXT Terminal driver */
714 TERM_PUBLIC void
715 NEXT_init()
716 {
717
718     /* Initialize output string */
719     NEXTsize = DEFAULTNEXTSIZE;
720     if ((NEXTBuffer = malloc(NEXTsize)) == NULL) {
721         printf("Malloc error in next filter init\n");
722         exit(1);
723     }
724     NEXTBufEnd = NEXTBuffer + NEXTsize;
725     NEXTBufAt = NEXTBuffer;
726
727
728     term->xmax = NEXT_XMAX;
729     term->ymax = NEXT_YMAX;
730
731 #ifdef NEXT_OLDTERMINAL
732     if (NEXT_oldterminal)
733         window_create();
734     else
735         gnuTermAccess =[[GnuTermDriver alloc] init];
736 #else
737     gnuTermAccess =[[GnuTermDriver alloc] init];
738 #endif
739
740
741
742 }
743
744
745 TERM_PUBLIC void
746 NEXT_graphics()
747 {
748     static char GPFAR NEXTg1[] = "0 setgray\nnewpath\n";
749     struct termentry *t = term;
750
751     *NEXTBuffer = 0;
752     NEXTBufAt = NEXTBuffer;
753
754     NEXT_common_init(1, NEXT_XOFF, NEXT_YOFF, term->xmax, term->ymax,
755                      ENHNEXT_header);
756
757     NEXTPrintf("gnudict begin\ngsave\n");
758     NEXTPrintf("%d %d translate\n", NEXT_common_xoff, NEXT_common_yoff);
759     NEXTPrintf("%.3f %.3f scale\n", 1.0 / NEXT_SC, 1.0 / NEXT_SC);
760
761
762     NEXTPrintf(NEXTg1);
763     if (NEXT_common_uses_fonts)
764         NEXTPrintf("(%s) findfont %d scalefont setfont\n", NEXT_font, (t->v_char));
765     NEXT_path_count = 0;
766     NEXT_relative_ok = FALSE;
767     NEXT_pen_x = NEXT_pen_y = -4000;
768     NEXT_taken = 0;
769     NEXT_linetype_last = LT_UNDEFINED;
770
771 #ifdef NEXT_OLDTERMINAL
772     if (NEXT_oldterminal) {
773         /* Fill window with white */
774         NEXTPrintf("1 setgray\n");
775         NEXTPrintf("0 0 %d %d rectfill\n", NEXT_XMAX, NEXT_YMAX);
776         NEXTPrintf("0 setgray\n");
777     }
778 #endif
779
780
781 }
782
783
784 TERM_PUBLIC void
785 NEXT_text()
786 {
787     static DPSContext d;
788
789     NEXT_path_count = 0;
790     NEXTPrintf("stroke\ngrestore\nend\n");
791
792     /* Terminate string */
793     *NEXTBufAt = 0;
794
795     if (NEXT_oldterminal) {
796         d = DPSGetCurrentContext();
797         DPSPrintf(d, NEXTBuffer);
798         DPSFlushContext(d);
799     } else {
800         /* Here's the call that dumps the string to the server */
801       [gnuTermAccess plot:NEXTBuffer];
802
803     }
804
805 }
806
807
808 TERM_PUBLIC void
809 NEXT_reset()
810 {
811     NEXTPrintf("%%%%Trailer\n");
812     if (!NEXT_common_uses_fonts) {
813         NEXTPrintf("%%%%DocumentFonts: ");
814         while (NEXT_DocFonts) {
815             struct NEXT_FontName *fnp;
816             fnp = NEXT_DocFonts->next;
817             NEXTPrintf("%s%s", NEXT_DocFonts->name, fnp ? ", " : "\n");
818             free(NEXT_DocFonts->name);
819             free(NEXT_DocFonts);
820             NEXT_DocFonts = fnp;
821         }
822     }
823 }
824
825
826 TERM_PUBLIC void
827 NEXT_linetype(int linetype)
828 {
829     linetype = (linetype % 9) + 2;
830     if (linetype < 0)
831         linetype = 0;
832     NEXT_relative_ok = FALSE;
833     if (NEXT_linetype_last == linetype)
834         return;
835     NEXT_linetype_last = linetype;
836     NEXTPrintf("LT%c\n", "ba012345678"[linetype]);
837     NEXT_path_count = 0;
838 }
839
840
841 TERM_PUBLIC void
842 NEXT_move(unsigned int x, unsigned int y)
843 {
844     int dx, dy;
845     char abso[20], rel[20];
846     dx = x - NEXT_pen_x;
847     dy = y - NEXT_pen_y;
848     /* can't cancel all null moves--need a move after stroke'ing */
849     if (dx == 0 && dy == 0 && NEXT_relative_ok)
850         return;
851     sprintf(abso, "%d %d M\n", x, y);
852     sprintf(rel, "%d %d R\n", dx, dy);
853     if (strlen(rel) < strlen(abso) && NEXT_relative_ok) {
854         NEXTPrintf("%s", rel);
855         NEXT_taken++;
856     } else
857         NEXTPrintf("%s", abso);
858     NEXT_relative_ok = TRUE;
859     NEXT_path_count += 1;
860
861     NEXT_pen_x = x;
862     NEXT_pen_y = y;
863 }
864
865 TERM_PUBLIC void
866 NEXT_vector(unsigned int x, unsigned int y)
867 {
868     int dx, dy;
869     char abso[20], rel[20];
870     dx = x - NEXT_pen_x;
871     dy = y - NEXT_pen_y;
872     if (dx == 0 && dy == 0)
873         return;
874     sprintf(abso, "%d %d L\n", x, y);
875     sprintf(rel, "%d %d V\n", dx, dy);
876     if (strlen(rel) < strlen(abso) && NEXT_relative_ok) {
877         NEXTPrintf("%s", rel);
878         NEXT_taken++;
879     } else
880         NEXTPrintf("%s", abso);
881     NEXT_relative_ok = TRUE;
882     NEXT_path_count += 1;
883     NEXT_pen_x = x;
884     NEXT_pen_y = y;
885     if (NEXT_path_count >= 400) {
886         NEXTPrintf("currentpoint stroke M\n");
887         NEXT_path_count = 0;
888     }
889 }
890
891
892
893
894 TERM_PUBLIC int
895 NEXT_text_angle(int ang)
896 {
897     NEXT_ang = ang;
898     return TRUE;
899 }
900
901
902 TERM_PUBLIC int
903 NEXT_justify_text(enum JUSTIFY mode)
904 {
905     NEXT_justify = mode;
906     return TRUE;
907 }
908
909
910 TERM_PUBLIC int
911 NEXT_set_font(const char *font)
912 {
913     char name[32];
914     int size, sep;
915
916     if (!font || !(*font))
917         font = NEXT_default_font;
918     sep = strcspn(font, ",");
919     strncpy(name, font, sep);
920     name[sep] = NUL;
921     size = NEXT_fontsize;
922     if (font[set] == ',')
923         sscanf(&(font[sep + 1]), "%d", &size);
924     NEXTPrintf("/%s findfont %d scalefont setfont\n", name, size * NEXT_SC);
925     NEXT_RememberFont(name);
926     term->v_char = (unsigned int) (size * NEXT_SC);
927     term->h_char = (unsigned int) (size * NEXT_SC * 6 / 10);
928     return TRUE;
929 }
930
931
932 /* postscript point routines */
933
934 TERM_PUBLIC void
935 NEXT_set_pointsize(double size)
936 {
937     NEXTPrintf("/vpt %.1f def /hpt %.1f def /vpt2 vpt 2 mul def /hpt2 hpt 2 mul def\n",
938                pointsize * NEXT_VTIC * 0.5, pointsize * NEXT_HTIC * 0.5);
939 }
940
941 TERM_PUBLIC void
942 NEXT_point(unsigned int x, unsigned int y, int number)
943 {
944     static char *pointFNS[] =
945     {"Pnt", "Pls", "Crs", "Star",
946      "Box", "BoxF", "Circle", "CircleF",
947      "TriU", "TriUF", "TriD", "TriDF",
948      "Dia", "DiaF", "Pent", "PentF",
949      "C0", "C1", "C2", "C3",
950      "C4", "C5", "C6", "C7",
951      "C8", "C9", "C10", "C11",
952      "C12", "C13", "C14", "C15",
953      "S0", "S1", "S2", "S3",
954      "S4", "S5", "S6", "S7",
955      "S8", "S9", "S10", "S11",
956      "S12", "S13", "S14", "S15",
957      "D0", "D1", "D2", "D3",
958      "D4", "D5", "D6", "D7",
959      "D8", "D9", "D10", "D11",
960      "D12", "D13", "D14", "D15"
961     };
962     if (number < 0)
963         number = -1;            /* negative types are all 'dot' */
964     else
965         number %= sizeof(pointFNS) / sizeof(pointFNS[0]) - 1;
966     NEXTPrintf("%d %d %s\n", x, y, pointFNS[number + 1]);
967
968     NEXT_relative_ok = 0;
969     NEXT_path_count = 0;
970     NEXT_linetype_last = LT_UNDEFINED;  /* force next linetype change */
971 }
972
973
974
975
976 /* All lifted from the enhanced postscript driver */
977
978
979
980 static TBOOLEAN NEXT_opened_string;     /* try to cut out empty ()'s */
981
982 /* used in determining height of processed text */
983
984 static float NEXT_max_height, NEXT_min_height;
985
986
987 /* process a bit of string, and return the last character used.
988  * p is start of string
989  * brace is TRUE to keep processing to }, FALSE for do one character
990  * fontname & fontsize are obvious
991  * base is the current baseline
992  * widthflag is TRUE if the width of this should count,
993  *              FALSE for zero width boxes
994  */
995
996 static char *
997 NEXT_recurse(
998     char *p,
999     TBOOLEAN brace,
1000     char *fontname,
1001     double fontsize, double base,
1002     TBOOLEAN widthflag)
1003 {
1004
1005 /* close a postscript string if it has been opened */
1006 #define NEXT_FLUSH      \
1007 {       if (NEXT_opened_string)  \
1008         {       NEXTPrintf("%s", ")]\n");   \
1009                 NEXT_opened_string = FALSE; \
1010         }                         \
1011 }
1012
1013 #define NEXT_OPEN       \
1014 {       if (!NEXT_opened_string) \
1015         { NEXTPrintf( "[(%s) %.1f %.1f %s (",  \
1016                   fontname, fontsize, base, \
1017                   widthflag ? "true" : "false");  \
1018           NEXT_opened_string = TRUE; \
1019         }       \
1020 }
1021
1022
1023     /* Start each recursion with a clean string */
1024     NEXT_FLUSH;
1025
1026         if (base + fontsize > NEXT_max_height) {
1027         NEXT_max_height = base + fontsize;
1028     }
1029     if (base < NEXT_min_height) {
1030         NEXT_min_height = base;
1031     }
1032     for (; *p; ++p) {
1033         float shift;
1034         float f = 0;            /* used for getting new font size */
1035         char *localfontname, ch;
1036
1037         switch (*p) {
1038         case '}':
1039             if (brace)
1040                 return (p);
1041
1042             fprintf(stderr, "next driver - spurious }\n");
1043             break;
1044
1045         case '_':
1046         case '^':
1047             shift = (*p == '^') ? 0.5 : -0.3;
1048
1049             NEXT_FLUSH;
1050
1051                 p = NEXT_recurse(p + 1, FALSE, fontname, fontsize * 0.8,
1052                                  base + shift * fontsize, widthflag);
1053
1054             break;
1055
1056         case '{':
1057             /*{{{  recurse (possibly with a new font) */
1058
1059             if (*++p == '/') {  /* then parse a fontname, optional fontsize */
1060                 while (*++p == ' ');
1061                 localfontname = p;
1062                 while ((ch = *p) > ' ' && ch != '=')
1063                     ++p;
1064                 if (ch == '=') {
1065                     *p++ = '\0';
1066                     /*{{{  get optional font size */
1067                     f = (float) strtod(p, &p);
1068
1069                     if (f)
1070                         f *= NEXT_SC;   /* remember the scaling */
1071                     else
1072                         f = fontsize;
1073
1074                     /*}}} */
1075                 } else {
1076                     *p++ = '\0';
1077                     f = fontsize;
1078                 }
1079
1080                 while (*p == ' ')
1081                     ++p;
1082                 if (*localfontname)
1083                     localfontname = NEXT_RememberFont(localfontname);
1084                 else
1085                     localfontname = fontname;
1086             } else {
1087                 localfontname = fontname;
1088                 f = fontsize;
1089             }
1090             /*}}} */
1091
1092
1093             p = NEXT_recurse(p, TRUE, localfontname, f, base, widthflag);
1094
1095
1096             NEXT_FLUSH
1097
1098                 break;
1099
1100         case '@':
1101             /*{{{  phantom box - prints next 'char', then restores currentpoint */
1102
1103             NEXT_FLUSH
1104
1105                 p = NEXT_recurse(++p, FALSE, fontname, fontsize, base, FALSE);
1106
1107             break;
1108             /*}}} */
1109
1110         case '(':
1111         case ')':
1112             /* special cases */
1113             NEXT_OPEN
1114                 NEXTPrintf("\\");
1115             NEXTPrintf("%c", *p);
1116             break;
1117             /*}}} */
1118
1119         case '\\':
1120             /*{{{  is it an escape */
1121             /* special cases */
1122
1123             if (p[1] == '\\' || p[1] == '(' || p[1] == ')') {
1124                 NEXT_OPEN
1125                     NEXTPrintf("%c", '\\');
1126             } else if ((ch = p[1]) >= '0' && ch <= '7') {
1127                 /* up to 3 octal digits */
1128                 NEXT_OPEN
1129                     NEXTPrintf("%c", '\\');
1130                 NEXTPrintf("%c", ch);
1131                 ++p;
1132                 if ((ch = p[1]) >= '0' && ch <= '7') {
1133                     NEXTPrintf("%c", ch);
1134                     ++p;
1135                     if ((ch = p[1]) >= '0' && ch <= '7') {
1136                         NEXTPrintf("%c", ch);
1137                         ++p;
1138                     }
1139                 }
1140                 break;
1141             }
1142             ++p;
1143             /* just go and print it (fall into the 'default' case) */
1144
1145             /*}}} */
1146         default:
1147             NEXT_OPEN
1148
1149                 NEXTPrintf("%c", *p);
1150         }
1151
1152         /* like TeX, we only do one character in a recursion, unless it's
1153          * in braces
1154          */
1155
1156         if (!brace) {
1157             NEXT_FLUSH
1158                 return (p);     /* the ++p in the outer copy will increment us */
1159         }
1160     }
1161     NEXT_FLUSH
1162         return p;
1163 }
1164
1165
1166 TERM_PUBLIC void
1167 NEXT_put_text(unsigned int x, unsigned int y, const char *str)
1168 {
1169     /* flush any pending graphics (all the XShow routines do this...) */
1170
1171     if (!strlen(str))
1172         return;
1173
1174     if (NEXT_path_count) {
1175         NEXTPrintf(" stroke\n");
1176         NEXT_path_count = 0;
1177         NEXT_relative_ok = FALSE;
1178     }
1179     NEXT_move(x, y);
1180
1181     if (NEXT_ang != 0)
1182         NEXTPrintf("currentpoint gsave translate %d rotate 0 0 moveto\n",
1183                    NEXT_ang);
1184
1185     NEXTPrintf("[ ");
1186
1187     /* set up the globals */
1188
1189     NEXT_opened_string = FALSE;
1190     NEXT_max_height = -1000;
1191     NEXT_min_height = 1000;
1192
1193     while (*(str = NEXT_recurse(str, TRUE, NEXT_font,
1194                                 (double) term->v_char,
1195                                 0.0, TRUE)));
1196
1197     NEXT_max_height += NEXT_min_height;
1198
1199     NEXTPrintf("] %.1f ", -NEXT_max_height / 3);
1200
1201     switch (NEXT_justify) {
1202     case LEFT:
1203         NEXTPrintf("MLshow\n");
1204         break;
1205     case CENTRE:
1206         NEXTPrintf("MCshow\n");
1207         break;
1208     case RIGHT:
1209         NEXTPrintf("MRshow\n");
1210         break;
1211     }
1212
1213     if (NEXT_ang != 0)
1214         NEXTPrintf("grestore\n");
1215     NEXT_path_count = 0;
1216     NEXT_relative_ok = FALSE;
1217 }
1218
1219
1220
1221 /*
1222 static TBOOLEAN
1223 NEXT_colordetect()
1224 {
1225         NXScreen * mainscreen;
1226
1227         mainscreen = [Application mainScreen];
1228         if (mainscreen->depth == NX_TwoBitGrayDepth) return(FALSE);
1229         return(TRUE);
1230 }
1231 */
1232
1233         /* This just packs all the postscript into one (possibly huge) string
1234          * which will be passed (as a fake pointer) via D.O. to the server
1235          */
1236
1237 void
1238 NEXTPrintf(char *fmt,...)
1239 {
1240     va_list ap;
1241     char *pb;
1242     int NEXToff;
1243
1244     /* Process formatting instructions */
1245     va_start(ap, fmt);
1246     vsprintf(NEXTTmpBuf, fmt, ap);
1247     va_end(ap);
1248
1249     /* Add to buffer */
1250     for (pb = NEXTTmpBuf; (*pb != 0); ++pb, ++NEXTBufAt) {
1251         /* reallocate if necessary */
1252         if (NEXTBufAt >= NEXTBufEnd) {
1253             NEXToff = NEXTBufAt - NEXTBuffer;
1254             NEXTsize *= 2;
1255             NEXTBuffer = realloc(NEXTBuffer, NEXTsize);
1256             NEXTBufEnd = NEXTBuffer + NEXTsize;
1257             NEXTBufAt = NEXTBuffer + NEXToff;
1258         }
1259         *NEXTBufAt = *pb;
1260     }
1261
1262     return;
1263
1264 }
1265
1266 /*  This next section implements the GnuTermDriver object which manages
1267         the D.O. connection and interface to OBjC
1268 */
1269
1270
1271 @protocol GnuTermServerMethods
1272 /*- (oneway) executePScode:(in char *)PStext termTitle:(in char *)title;*/
1273 - executePScode:(in char *)
1274 PStext termTitle:(in char *) title;
1275 @end
1276
1277
1278 @implementation GnuTermDriver
1279
1280 - init
1281 {
1282     NXConnection *myConnection;
1283     char serverpath[100], *envstring;
1284     int GnuTermPathSet = 0;
1285
1286
1287     /* Ask OS for connection to server */
1288   server =[NXConnection connectToName:"gnuplotServer"];
1289
1290     /* Server is running ready to go */
1291     if (server)                 /*printf("Connected to server\n") */
1292         ;
1293
1294     /* Server isn't running, we must fire it up */
1295     else {
1296         /*printf("Launching GnuTerm\n"); */
1297         *serverpath = 0;
1298
1299         /* Check for path set in environment */
1300         if ((envstring = getenv("GNUTERMPATH")) != (char *) NULL) {
1301             sprintf(serverpath, "%s/GnuTerm.app/GnuTerm", envstring);
1302             GnuTermPathSet = 1;
1303         }
1304         /* Not in environment */
1305         else
1306             strcpy(serverpath, "GnuTerm");
1307
1308         /* Try to launch application */
1309       if ([[Application workspace] launchApplication:serverpath] == NO) {
1310             printf("Failed to launch %s.\n", serverpath);
1311             /* Offer a little advice */
1312             if (GnuTermPathSet) {
1313                 printf("You must have setenv GNUTERMPATH to something wrong\n");
1314                 printf("I recommend you exit gnuplot and fix this.\n");
1315             } else {
1316                 printf("It must be located in ~/Apps or /LocalApps\n");
1317                 printf("I recommend that you either\n");
1318                 printf("- move GnuTerm.app to one of these locations\n");
1319                 printf("- set GNUTERMPATH with host%%  setenv GNUTERMPATH /directory/containing_GnuTerm.app\n");
1320                 printf("- start GnuTerm ahead of the first plot command\n");
1321 #ifdef NEXT_OLDTERMINAL
1322                 printf("- use the old driver version (set term next old)\n");
1323 #endif
1324             }
1325         }
1326         /* I wish the gnuplot terminal interface would
1327            let me return an error here.
1328          */
1329
1330         /* Application is launching */
1331         else {
1332             /* Wait for it to register Server methods with OS */
1333             do {
1334               server =[NXConnection connectToName:"gnuplotServer"];
1335             } while (!server);  /* This could result in a hang,
1336                                    but I've never seen it fail */
1337         }
1338     }
1339
1340
1341     /* By limiting ourselves to known protocol
1342      * we speed up the messaging
1343      */
1344   [server setProtocolForProxy:@protocol(GnuTermServerMethods)];
1345
1346     myConnection =[server connectionForProxy];
1347
1348     /* If the server dies we want to know about it */
1349   [myConnection registerForInvalidationNotification:self];
1350     /* In fact, we'll worry about it */
1351     [NXPort worryAboutPortInvalidation];
1352
1353     return self;
1354 }
1355
1356
1357 -plot:(char *) PSstr;
1358 {
1359     /* If server has become invalid, re-initialize */
1360     if (!server)
1361         [self init];
1362
1363     /* This is where we send the huge postscript string to the server
1364        Note:
1365        The D.O. system doesn't actually give this pointer to the server.
1366        The pointer is dereferenced on the client side and the
1367        resulting data is sent to the server. On the server side,
1368        space for the data is automatically allocated, and a pointer to
1369        the local data is received.
1370        For details check out:
1371        /NextLibrary/Documentation/NextDev/GeneralRef/06_DistributedObjects/IntroDistObjects.rtf
1372      */
1373
1374     /*printf("Calling server..."); */
1375   [server executePScode: PSstr termTitle:NEXT_title];
1376     /*printf("returned\n"); */
1377     *NEXT_title = 0;
1378
1379     return self;
1380 }
1381
1382                                                         /* This gets called by OS if server goes down */
1383 -senderIsInvalid:(id) sender
1384 {
1385     server = 0;
1386 }
1387
1388 @end
1389
1390 #ifdef NEXT_OLDTERMINAL
1391
1392 static void
1393 window_create()
1394 {
1395     float width, height;
1396
1397     width = (xsize * (NEXT_XMAX) / NEXT_SC + 0.5 + NEXT_XOFF);
1398     height = (ysize * (NEXT_YMAX) / NEXT_SC + 0.5 + NEXT_YOFF);
1399
1400     NXApp =[EpsViewer new];
1401   [NXApp windowCreate: width Height:height];
1402 }
1403
1404 @implementation EpsViewer
1405
1406 - windowCreate:(NXCoord)
1407 width Height:(NXCoord) height
1408 {
1409
1410     /* create the new window, in a good place */
1411     theNewWin =[Window
1412   newContent: [self nextRectForWidth: width Height:height]
1413   style:        NX_TITLEDSTYLE
1414   backing:      NX_RETAINED
1415   buttonMask:   (NX_CLOSEBUTTONMASK | NX_MINIATURIZEBUTTONMASK)
1416   defer:        NO];
1417     /* we need to receive windowDidBecomeMain: and windowDidResignMain: */
1418   [theNewWin setDelegate:self];
1419     /*
1420      * create a new View, make it the contentView of our new window,
1421      * and destroy the window's old contentView
1422      */
1423   [[theNewWin setContentView:[[View alloc] init]] free];
1424     /* display the window, and bring it forth */
1425     [theNewWin display];
1426   [theNewWin makeKeyAndOrderFront:self];
1427 /*      [theNewWin orderBack:self];                     */
1428     /* show the frame */
1429     return self;
1430 }
1431
1432 /***************************************************************************/
1433 /* nextRectForWidth:Height: - return the next good content rectangle       */
1434 /*  from Carl F. Sutter's wonderful ViewGif2 'Controller' method...        */
1435 /***************************************************************************/
1436 /* nextTopLeft - return the next good top left window position             */
1437 /***************************************************************************/
1438
1439 -(NXRect *) nextRectForWidth:(NXCoord)
1440 width Height:(NXCoord) height
1441 {
1442 #define OFFSET 10.0
1443 #define MAX_STEPS 20
1444 #define INITIAL_X 356.0
1445 #define INITIAL_Y 241.0
1446     NXPoint nxpTopLeft;
1447     NXRect nxrTemp;             /* used to find window height    */
1448     NXRect nxrWinHeight;        /* bounds of enclosing window    */
1449     NXSize nxsScreen;           /* size of screen                */
1450     static NXRect nxrResult;    /* the Answer!                   */
1451     static int nCurStep = 0;
1452
1453     /* find a good top-left coord */
1454     nxpTopLeft.x = INITIAL_X + nCurStep * OFFSET;
1455     nxpTopLeft.y = INITIAL_Y + nCurStep * OFFSET;
1456     if (++nCurStep > MAX_STEPS)
1457         nCurStep = 0;
1458     /* find window height using nxrTemp */
1459     nxrTemp.size.width = width;
1460     nxrTemp.size.height = height;
1461     nxrTemp.origin.x = nxrTemp.origin.y = 0;
1462   [Window getFrameRect: &nxrWinHeight forContentRect:&nxrTemp
1463   style:NX_TITLEDSTYLE];
1464   [NXApp getScreenSize:&nxsScreen];
1465     /* find the lower-left coord */
1466     nxrResult.origin.x = nxpTopLeft.x;
1467     nxrResult.origin.y = nxsScreen.height - nxrWinHeight.size.height - nxpTopLeft.y;
1468     nxrResult.size.width = width;
1469     nxrResult.size.height = height;
1470     return (&nxrResult);
1471 }
1472
1473 @end
1474 #endif /* NEXT_OLDTERMINAL */
1475
1476
1477 #endif /* TERM_BODY */
1478
1479 #ifdef TERM_TABLE
1480
1481
1482 TERM_TABLE_START(next_driver)
1483     "next",
1484     "Interface to GnuTerm.app under NeXTstep",
1485     NEXT_XMAX, NEXT_YMAX, NEXT_VCHAR, NEXT_HCHAR,
1486     NEXT_VTIC, NEXT_HTIC, NEXT_options, NEXT_init, NEXT_reset,
1487     NEXT_text, null_scale, NEXT_graphics, NEXT_move, NEXT_vector,
1488     NEXT_linetype, NEXT_put_text, NEXT_text_angle,
1489     NEXT_justify_text, NEXT_point, do_arrow, NEXT_set_font,
1490     NEXT_set_pointsize
1491 TERM_TABLE_END(next_driver)
1492
1493 #undef LAST_TERM
1494 #define LAST_TERM next_driver
1495
1496 #endif /* TERM_TABLE */
1497 #endif /* TERM_PROTO_ONLY */
1498
1499
1500 #define TERM_HELP_NEXT
1501
1502 #ifdef TERM_HELP
1503 START_HELP(next)
1504 "1 next",
1505 "?commands set terminal next",
1506 "?set terminal next",
1507 "?set term next",
1508 "?terminal next",
1509 "?term next",
1510 "?next",
1511 "?NeXT",
1512 " Several options may be set in the next driver.",
1513 "",
1514 " Syntax:",
1515 "       set terminal next {<mode>} {<type> } {<color>} {<dashed>}",
1516 "                  {\"<fontname>\"} {<fontsize>} title {\"<newtitle>\"}",
1517 "",
1518 " where <mode> is  `default`, which sets all options to their defaults;",
1519 " <type> is either `new` or `old`, where `old` invokes the old single window;",
1520 " <color> is either `color` or `monochrome`;",
1521 " <dashed> is either `solid` or `dashed`;",
1522 " \"<fontname>\" is the name of a valid PostScript font;",
1523 " <fontsize> is the size of the font in PostScript points; and",
1524 " <title> is the title for the GnuTerm window.",
1525 " Defaults are  `new`, `monochrome`, `dashed`, \"Helvetica\", 14pt.",
1526 "",
1527 " Examples:",
1528 "       set term next default",
1529 "       set term next 22",
1530 "       set term next color \"Times-Roman\" 14",
1531 "       set term next color \"Helvetica\" 12 title \"MyPlot\"",
1532 "       set term next old",
1533 "",
1534 " Pointsizes may be changed with `set linestyle`."
1535 END_HELP(next)
1536 #endif /* TERM_HELP */
1537