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