/* Hello, Emacs, this is -*- objc -*-
* $Id: next.trm,v 1.27 2006/07/21 02:35:47 sfeam Exp $
*
*/
/* GNUPLOT - next.trm */
/*[
* Copyright 1991 - 1993, 1998, 2004
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted, but not the right to
* distribute the complete modified source code. Modifications are to
* be distributed as patches to the released version. Permission to
* distribute binaries produced by compiling modified sources is granted,
* provided you
* 1. distribute the corresponding source modifications from the
* released version in the form of a patch file along with the binaries,
* 2. add special version identification to distinguish your version
* in addition to the base release version number,
* 3. provide your name and address as the primary contact for the
* support of your modified version, and
* 4. retain our contact information in regard to use of the base
* software.
* Permission to distribute the released version of the source code along
* with corresponding source modifications in the form of a patch file is
* granted with same provisions 2 through 4 for binary distributions.
*
* This software is provided "as is" without express or implied warranty
* to the extent permitted by applicable law.
]*/
/*
* This file is included by ../term.c via ../term.h.
*
* This terminal driver supports:
* next
*
* AUTHORS
* Robert Lutwak from Russell Lang's post.trm
* 'old' option invokes Nick Strobel's original, single viewport terminal
*
* send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
*
* This terminal attempts to connect, via the NeXTstep Distributed
* Objects system, to the "gnuplotServer." If there is no such
* service registered with the OS, the terminal attempts to fire
* up GnuTerm.app. If the user has not set the environment variable
* GNUTERMPATH, the terminal uses the users ApplicationPaths Workspace
* dwrite to search for GnuTerm.app (Note: this is usually something
* like ~/Apps, ~/LocalApps, ~/NextApps, etc.).
* In order to use this filter, you MUST have GnuTerm.app installed
* on your system.
*
* Once connected to the server, this filter is basically Russell Lang's
* Postscript filter, except that the resultant postscript code
* is sent, via the D.O. system, to GnuTerm.app, which manages
* the windows which produce the postscript output on the screen.
*
*
* Defaults are
* 'set term next new dashed auto "Helvetica" 14'
*
* To change font to Times-Roman and font size to 20pts use
* 'set term next "Times-Roman" 20'.
*
* to choose window by title
* 'set term next title "Window title"
*
* Monitor Options:
* monochrome, color
*
* To invoke Nick Strobel's old terminal
* 'set term next old'
*/
#include "driver.h"
#ifdef TERM_REGISTER
register_term(next)
#endif
#ifdef TERM_PROTO
/* whether or not to compile support for the old (self-contained)
NeXT terminal */
/* #define NEXT_OLDTERMINAL 1 */
#import
#import /* setProtocolForProxy */
#import /* setProtocolForProxy */
#import
#import
#import
#ifdef NEXT_OLDTERMINAL
static void window_create __PROTO((void));
@interface EpsViewer:Application
{
id theNewWin;
}
-windowCreate:(NXCoord)
width Height:(NXCoord) height;
-(NXRect *) nextRectForWidth:(NXCoord)
width Height:(NXCoord) height;
@end
#endif /* NEXT_OLDTERMINAL */
TERM_PUBLIC void NEXT_options __PROTO((void));
TERM_PUBLIC void NEXT_common_init __PROTO((int uses_fonts, unsigned int xoff, unsigned int yoff, unsigned int xsize, unsigned int ysize, char **dict));
TERM_PUBLIC void NEXT_init __PROTO((void));
TERM_PUBLIC void NEXT_graphics __PROTO((void));
TERM_PUBLIC void NEXT_text __PROTO((void));
TERM_PUBLIC void NEXT_reset __PROTO((void));
TERM_PUBLIC void NEXT_linetype __PROTO((int linetype));
TERM_PUBLIC void NEXT_move __PROTO((unsigned int x, unsigned int y));
TERM_PUBLIC void NEXT_vector __PROTO((unsigned int x, unsigned int y));
TERM_PUBLIC void NEXT_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
TERM_PUBLIC int NEXT_text_angle __PROTO((int ang));
TERM_PUBLIC int NEXT_justify_text __PROTO((enum JUSTIFY mode));
TERM_PUBLIC void NEXT_point __PROTO((unsigned int x, unsigned int y, int number));
TERM_PUBLIC int NEXT_set_font __PROTO((const char *font));
TERM_PUBLIC char *NEXT_RememberFont __PROTO((char *fname));
TERM_PUBLIC void NEXT_set_pointsize __PROTO((double size));
#define NEXT_POINT_TYPES 8 /* div */
#define NEXT_XOFF 1 /* page offset in pts */
#define NEXT_YOFF 1
#define NEXT_XMAX 6400
#define NEXT_YMAX 4800
#define NEXT_XLAST (NEXT_XMAX - 1)
#define NEXT_YLAST (NEXT_YMAX - 1)
#define NEXT_VTIC (NEXT_YMAX/80)
#define NEXT_HTIC (NEXT_YMAX/80)
#define NEXT_SC (10) /* scale is 1pt = 10 units */
#define NEXT_LW (0.5*NEXT_SC) /* linewidth = 0.5 pts */
#define NEXT_VCHAR (14*NEXT_SC) /* default is 14 point characters */
#define NEXT_HCHAR (14*NEXT_SC*6/10)
#define GOT_NEXT_PROTO
#endif
#ifndef TERM_PROTO_ONLY
#ifdef TERM_BODY
@interface GnuTermDriver:Object < NXSenderIsInvalid >
{
id server;
}
-senderIsInvalid:(id) sender;
-plot:(char *) PSstr;
-init;
@end
#define DEFAULTNEXTSIZE 10000
static id gnuTermAccess; /* local object manages the D.O. connection */
static char *NEXTBuffer, *NEXTBufAt, *NEXTBufEnd;
static int NEXTsize;
static char NEXTTmpBuf[1000];
static void NEXTPrintf(char *,...);
static TBOOLEAN NEXT_oldterminal = FALSE;
/*static TBOOLEAN NEXT_colordetect();*/
static char NEXT_title[MAX_LINE_LEN + 1]; /* name of font */
static char NEXT_font[MAX_LINE_LEN + 1] = "Helvetica"; /* name of font */
static int NEXT_fontsize = 14; /* size of font in pts */
static int NEXT_default_font[MAX_ID_LEN+1] = {'\0'};
static TBOOLEAN NEXT_color = FALSE;
static TBOOLEAN NEXT_solid = FALSE; /* use dashed lines */
static int NEXT_path_count = 0; /* count of lines in path */
static int NEXT_ang = 0; /* text angle */
static enum JUSTIFY NEXT_justify = LEFT; /* text is flush left */
static TBOOLEAN NEXT_duplex_state = FALSE;
static TBOOLEAN NEXT_duplex_option = FALSE;
static char GPFAR *GPFAR NEXT_header[] =
{
"/M {moveto} bind def\n",
"/L {lineto} bind def\n",
"/R {rmoveto} bind def\n",
"/V {rlineto} bind def\n",
"/vpt2 vpt 2 mul def\n",
"/hpt2 hpt 2 mul def\n",
/* flush left show */
"/Lshow { currentpoint stroke M\n",
" 0 vshift R show } def\n",
/* flush right show */
"/Rshow { currentpoint stroke M\n",
" dup stringwidth pop neg vshift R show } def\n",
/* centred show */
"/Cshow { currentpoint stroke M\n",
" dup stringwidth pop -2 div vshift R show } def\n",
/* Dash or Color Line */
"/DL { Color {setrgbcolor Solid {pop []} if 0 setdash }\n",
" {pop pop pop Solid {pop []} if 0 setdash} ifelse } def\n",
/* Border Lines */
"/BL { stroke gnulinewidth 2 mul setlinewidth } def\n",
/* Axes Lines */
"/AL { stroke gnulinewidth 2 div setlinewidth } def\n",
/* Plot Lines */
"/PL { stroke gnulinewidth setlinewidth } def\n",
/* Line Types */
"/LTb { BL [] 0 0 0 DL } def\n", /* border */
"/LTa { AL [1 dl 2 dl] 0 setdash 0 0 0 setrgbcolor } def\n", /* axes */
"/LT0 { PL [] 0 1 0 DL } def\n",
"/LT1 { PL [4 dl 2 dl] 0 0 1 DL } def\n",
"/LT2 { PL [2 dl 3 dl] 1 0 0 DL } def\n",
"/LT3 { PL [1 dl 1.5 dl] 1 0 1 DL } def\n",
"/LT4 { PL [5 dl 2 dl 1 dl 2 dl] 0 1 1 DL } def\n",
"/LT5 { PL [4 dl 3 dl 1 dl 3 dl] 1 1 0 DL } def\n",
"/LT6 { PL [2 dl 2 dl 2 dl 4 dl] 0 0 0 DL } def\n",
"/LT7 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 1 0.3 0 DL } def\n",
"/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",
/* Point (Round) */ /* Matt Heffron make it round */
"/Pnt { stroke [] 0 setdash\n",
" gsave 1 setlinecap M 0 0 V stroke grestore } def\n",
/* Diamond */
"/Dia { stroke [] 0 setdash 2 copy vpt add M\n",
" hpt neg vpt neg V hpt vpt neg V\n",
" hpt vpt V hpt neg vpt V closepath stroke\n",
" Pnt } def\n",
/* Plus */
"/Pls { stroke [] 0 setdash vpt sub M 0 vpt2 V\n",
" currentpoint stroke M\n",
" hpt neg vpt neg R hpt2 0 V stroke\n",
" } def\n",
/* Box */
"/Box { stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M\n",
" 0 vpt2 neg V hpt2 0 V 0 vpt2 V\n",
" hpt2 neg 0 V closepath stroke\n",
" Pnt } def\n",
/* Cross (X) */
"/Crs { stroke [] 0 setdash exch hpt sub exch vpt add M\n",
" hpt2 vpt2 neg V currentpoint stroke M\n",
" hpt2 neg 0 R hpt2 vpt2 V stroke } def\n",
/* Triangle Up*/
"/TriU { stroke [] 0 setdash 2 copy vpt 1.12 mul add M\n",
" hpt neg vpt -1.62 mul V\n",
" hpt 2 mul 0 V\n",
" hpt neg vpt 1.62 mul V closepath stroke\n",
" Pnt } def\n",
/* Star */
"/Star { 2 copy Pls Crs } def\n",
/* div added filed box */
/* Filled Box */
"/BoxF { stroke [] 0 setdash exch hpt sub exch vpt add M\n",
" 0 vpt2 neg V hpt2 0 V 0 vpt2 V\n",
" hpt2 neg 0 V closepath fill } def\n",
/* div added filled triangle */
/* Triangle Up, Filled */
"/TriUF { stroke [] 0 setdash vpt 1.12 mul add M\n",
" hpt neg vpt -1.62 mul V\n",
" hpt 2 mul 0 V\n",
" hpt neg vpt 1.62 mul V closepath fill } def\n",
/* Matt Heffron: added a few more types */
/* Triangle Down */
"/TriD { stroke [] 0 setdash 2 copy vpt 1.12 mul sub M\n",
" hpt neg vpt 1.62 mul V\n",
" hpt 2 mul 0 V\n",
" hpt neg vpt -1.62 mul V closepath stroke\n",
" Pnt } def\n",
/* Triangle Down, Filled*/
"/TriDF { stroke [] 0 setdash vpt 1.12 mul sub M\n",
" hpt neg vpt 1.62 mul V\n",
" hpt 2 mul 0 V\n",
" hpt neg vpt -1.62 mul V closepath fill} def\n",
/* Diamond, Filled */
"/DiaF { stroke [] 0 setdash vpt add M\n",
" hpt neg vpt neg V hpt vpt neg V\n",
" hpt vpt V hpt neg vpt V closepath fill } def\n",
/* Pentagon */
"/Pent { stroke [] 0 setdash 2 copy gsave\n",
" translate 0 hpt M 4 {72 rotate 0 hpt L} repeat\n",
" closepath stroke grestore Pnt } def\n",
/* Pentagon, Filled */
"/PentF { stroke [] 0 setdash gsave\n",
" translate 0 hpt M 4 {72 rotate 0 hpt L} repeat\n",
" closepath fill grestore } def\n",
/* Circle */
"/Circle { stroke [] 0 setdash 2 copy\n",
" hpt 0 360 arc stroke Pnt } def\n",
/* Circle,Filled */
"/CircleF { stroke [] 0 setdash hpt 0 360 arc fill } def\n",
/* 16 differently filled circles */
"/C0 { BL [] 0 setdash 2 copy moveto vpt 90 450 arc } bind def\n",
"/C1 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 0 90 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C2 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 90 180 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C3 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 0 180 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C4 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 180 270 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C5 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 0 90 arc\n",
" 2 copy moveto\n",
" 2 copy vpt 180 270 arc closepath fill\n",
" vpt 0 360 arc } bind def\n",
"/C6 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 90 270 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C7 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 0 270 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C8 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 270 360 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C9 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 270 450 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C10 { BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill\n",
" 2 copy moveto\n",
" 2 copy vpt 90 180 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C11 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 0 90 arc closepath fill\n",
" 2 copy moveto\n",
" 2 copy vpt 180 360 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C12 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 180 360 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C13 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 0 90 arc closepath fill\n",
" 2 copy moveto\n",
" 2 copy vpt 180 360 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
"/C14 { BL [] 0 setdash 2 copy moveto\n",
" 2 copy vpt 90 360 arc closepath fill\n",
" vpt 0 360 arc } bind def\n",
"/C15 { BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill\n",
" vpt 0 360 arc closepath } bind def\n",
/* Auxiliary definitions for rectangles */
"/Rec { newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n",
" neg 0 rlineto closepath } bind def\n",
"/Square { dup Rec } bind def\n",
"/Bsquare { vpt sub exch vpt sub exch vpt2 Square } bind def\n",
/* 16 differently filled squares */
"/S0 { BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare } bind def\n",
"/S1 { BL [] 0 setdash 2 copy vpt Square fill Bsquare } bind def\n",
"/S2 { BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare } bind def\n",
"/S3 { BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare } bind def\n",
"/S4 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare } bind def\n",
"/S5 { BL [] 0 setdash 2 copy 2 copy vpt Square fill\n",
" exch vpt sub exch vpt sub vpt Square fill Bsquare } bind def\n",
"/S6 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare } bind def\n",
"/S7 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill\n",
" 2 copy vpt Square fill\n",
" Bsquare } bind def\n",
"/S8 { BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare } bind def\n",
"/S9 { BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare } bind def\n",
"/S10 { BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill\n",
" Bsquare } bind def\n",
"/S11 { 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill\n",
" Bsquare } bind def\n",
"/S12 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare } bind def\n",
"/S13 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill\n",
" 2 copy vpt Square fill Bsquare } bind def\n",
"/S14 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill\n",
" 2 copy exch vpt sub exch vpt Square fill Bsquare } bind def\n",
"/S15 { BL [] 0 setdash 2 copy Bsquare fill Bsquare } bind def\n",
/* 16 different diamonds (actually just rotated squares) */
"/D0 { gsave translate 45 rotate 0 0 Box stroke grestore } bind def\n",
"/D1 { gsave translate 45 rotate 0 0 S1 stroke grestore } bind def\n",
"/D2 { gsave translate 45 rotate 0 0 S2 stroke grestore } bind def\n",
"/D3 { gsave translate 45 rotate 0 0 S3 stroke grestore } bind def\n",
"/D4 { gsave translate 45 rotate 0 0 S4 stroke grestore } bind def\n",
"/D5 { gsave translate 45 rotate 0 0 S5 stroke grestore } bind def\n",
"/D6 { gsave translate 45 rotate 0 0 S6 stroke grestore } bind def\n",
"/D7 { gsave translate 45 rotate 0 0 S7 stroke grestore } bind def\n",
"/D8 { gsave translate 45 rotate 0 0 S8 stroke grestore } bind def\n",
"/D9 { gsave translate 45 rotate 0 0 S9 stroke grestore } bind def\n",
"/D10 { gsave translate 45 rotate 0 0 S10 stroke grestore } bind def\n",
"/D11 { gsave translate 45 rotate 0 0 S11 stroke grestore } bind def\n",
"/D12 { gsave translate 45 rotate 0 0 S12 stroke grestore } bind def\n",
"/D13 { gsave translate 45 rotate 0 0 S13 stroke grestore } bind def\n",
"/D14 { gsave translate 45 rotate 0 0 S14 stroke grestore } bind def\n",
"/D15 { gsave translate 45 rotate 0 0 S15 stroke grestore } bind def\n",
NULL
};
static char GPFAR *GPFAR ENHNEXT_header[] =
{
/* For MFshow and MFwidth the tos is an array with the string and font info: */
/* [ ] */
"/MFshow {{dup dup 0 get findfont exch 1 get scalefont setfont\n",
" [ currentpoint ] exch dup 2 get 0 exch rmoveto dup 4 get show dup\n",
" 3 get {2 get neg 0 exch rmoveto pop} {pop aload pop moveto}ifelse} forall} bind def\n",
"/MFwidth {0 exch {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont\n",
" 4 get stringwidth pop add}\n",
" {pop} ifelse} forall} bind def\n",
/* flush left show */
"/MLshow { currentpoint stroke M\n",
" 0 exch R MFshow } bind def\n",
/* flush right show */
"/MRshow { currentpoint stroke M\n",
" exch dup MFwidth neg 3 -1 roll R MFshow } def\n",
/* centred show */
"/MCshow { currentpoint stroke M\n",
" exch dup MFwidth -2 div 3 -1 roll R MFshow } def\n",
NULL
};
/* added to post by Matt Heffron */
/* moved to post.trm by drd */
struct NEXT_FontName {
char *name;
struct NEXT_FontName *next;
} *NEXT_DocFonts = NULL;
enum NEXT_id {
NEXT_DEFAULT, NEXT_MONOCHROME, NEXT_COLOR,
NEXT_SOLID, NEXT_DASHED,
NEXT_SIMPLEX, NEXT_DUPLEX, NEXT_DEFAULTPLEX,
NEXT_OLD, NEXT_NEW, NEXT_TITLE,
NEXT_OTHER
};
static struct gen_table NEXT_opts[] =
{
{ "d$efault", NEXT_DEFAULT },
{ "mono$chrome", NEXT_MONOCHROME },
{ "col$or", NEXT_COLOR },
{ "col$our", NEXT_COLOR },
{ "so$lid", NEXT_SOLID },
{ "da$shed", NEXT_DASHED },
{ "si$mplex", NEXT_SIMPLEX },
{ "du$plex", NEXT_DUPLEX },
{ "defaultp$lex", NEXT_DEFAULTPLEX },
{ "old", NEXT_OLD },
{ "new", NEXT_NEW },
{ "ti$tle", NEXT_TITLE },
{ NULL, NEXT_OTHER }
};
TERM_PUBLIC void
NEXT_options()
{
char buf[40];
struct value a;
while (!END_OF_COMMAND) {
switch(lookup_table(&NEXT_opts[0],c_token)) {
case NEXT_DEFAULT:
NEXT_oldterminal = FALSE;
/*NEXT_color=NEXT_colordetect(); */
NEXT_color = FALSE;
NEXT_solid = FALSE;
NEXT_duplex_option = FALSE;
strcpy(NEXT_font, "Helvetica");
NEXT_fontsize = 14;
term->v_char = (unsigned int) (NEXT_fontsize * NEXT_SC);
term->h_char = (unsigned int) (NEXT_fontsize * NEXT_SC * 6 / 10);
term->put_text = NEXT_put_text;
c_token++;
break;
case NEXT_MONOCHROME:
NEXT_color = FALSE;
c_token++;
break;
case NEXT_COLOR:
NEXT_color = TRUE;
c_token++;
break;
case NEXT_SOLID:
NEXT_solid = TRUE;
c_token++;
break;
case NEXT_DASHED:
NEXT_solid = FALSE;
c_token++;
break;
case NEXT_SIMPLEX:
NEXT_duplex_state = FALSE;
NEXT_duplex_option = TRUE;
c_token++;
break;
case NEXT_DUPLEX:
NEXT_duplex_state = TRUE;
NEXT_duplex_option = TRUE;
c_token++;
break;
case NEXT_DEFAULTPLEX:
NEXT_duplex_option = FALSE;
c_token++;
break;
case NEXT_OLD:
NEXT_oldterminal = TRUE;
c_token++;
break;
case NEXT_NEW:
NEXT_oldterminal = FALSE;
c_token++;
break;
case NEXT_TITLE:
c_token++;
if (!isstring(c_token)) {
fprintf(stderr, "usage: set term next title \"newtitle\"\n");
}
quote_str(NEXT_title, c_token, MAX_LINE_LEN + 1);
break;
case NEXT_OTHER:
default:
if (isstring(c_token)) {
quote_str(NEXT_font, c_token, MAX_LINE_LEN + 1);
/* We must have font size specified */
NEXT_fontsize = (int) real(const_express(&a));
term->v_char = (unsigned int) (NEXT_fontsize * NEXT_SC);
term->h_char = (unsigned int) (NEXT_fontsize * NEXT_SC * 6 / 10);
sprintf(NEXT_default_font, "%s,%d", NEXT_font, NEXT_fontsize);
}
break;
}
}
sprintf(term_options, "%s %s %s %s \"%s\" %d title \"%s\"",
NEXT_oldterminal ? "old" : "new",
NEXT_color ? "color" : "monochrome",
NEXT_solid ? "solid" : "dashed",
NEXT_duplex_option ? (NEXT_duplex_state ? "duplex" : "simplex")
: "defaultplex",
NEXT_font,
NEXT_fontsize,
NEXT_title);
}
TERM_PUBLIC char *
NEXT_RememberFont(char *fname)
{
struct NEXT_FontName *fnp;
for (fnp = NEXT_DocFonts; fnp && strcmp(fnp->name, fname); fnp = fnp->next);
if (fnp)
return fnp->name; /* we must have found it in the list */
if (encoding == S_ENC_ISO8859_1) {
NEXTPrintf("/%s reencodeISO def\n", fname);
}
fnp = (struct NEXT_FontName *) gp_alloc(sizeof(struct NEXT_FontName), "PostScript Font record");
fnp->name = gp_alloc(1 + strlen(fname), "PostScript Font name");
strcpy(fnp->name, fname);
fnp->next = NEXT_DocFonts;
NEXT_DocFonts = fnp;
return fnp->name;
}
int NEXT_pen_x, NEXT_pen_y;
int NEXT_taken;
int NEXT_linetype_last;
TBOOLEAN NEXT_relative_ok;
/* store settings passed to common_init() for use in NEXT_graphics()
* are reserved for storing the term options
*/
static int NEXT_common_uses_fonts;
static unsigned int NEXT_common_xoff, NEXT_common_yoff;
TERM_PUBLIC void
NEXT_common_init(
int uses_fonts, /* 0 for NEXT(la)tex */
unsigned int xoff, unsigned int yoff, /* offset - 50 for /post, 0 for NEXT(la)tex */
unsigned int width, unsigned int height, /* for bounding box */
char **dict) /* extra entries for the dictionary */
{
static char GPFAR NEXTi1[] = "%%%%Creator: gnuplot\n\
%%%%DocumentFonts: %s\n";
static char GPFAR NEXTi2[] = "%%%%EndComments\n\
/gnudict 120 dict def\ngnudict begin\n\
/Color %s def\n\
/Solid %s def\n\
/gnulinewidth %.3f def\n\
/vshift %d def\n\
/dl {%d mul} def\n\
/hpt %.1f def\n\
/vpt %.1f def\n";
static char GPFAR *NEXT_iso_8859_1_encoding[] =
{
"/reencodeISO {\n",
"dup dup findfont dup length dict begin\n",
"{ 1 index /FID ne { def }{ pop pop } ifelse } forall\n",
"/Encoding ISOLatin1Encoding def\n",
"currentdict end definefont\n",
"} def\n",
"/ISOLatin1Encoding [\n",
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
"/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright\n",
"/parenleft/parenright/asterisk/plus/comma/minus/period/slash\n",
"/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon\n",
"/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N\n",
"/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright\n",
"/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m\n",
"/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde\n",
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n",
"/.notdef/dotlessi/grave/acute/circumflex/tilde/macron/breve\n",
"/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut\n",
"/ogonek/caron/space/exclamdown/cent/sterling/currency/yen/brokenbar\n",
"/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot\n",
"/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior\n",
"/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine\n",
"/guillemotright/onequarter/onehalf/threequarters/questiondown\n",
"/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla\n",
"/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex\n",
"/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis\n",
"/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute\n",
"/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis\n",
"/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave\n",
"/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex\n",
"/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis\n",
"/yacute/thorn/ydieresis\n",
"] def\n",
NULL};
struct termentry *t = term;
int i;
NEXT_common_uses_fonts = uses_fonts;
NEXT_common_xoff = xoff;
NEXT_common_yoff = yoff;
NEXTPrintf("%%!NEXT-Adobe-2.0\n");
NEXTPrintf(NEXTi1, uses_fonts ? "(atend)" : "");
NEXTPrintf("%%%%BoundingBox: %d %d %d %d\n", xoff, yoff,
(int) (xsize * width / NEXT_SC + 0.5 + xoff),
(int) (ysize * height / NEXT_SC + 0.5 + yoff));
NEXTPrintf(NEXTi2,
NEXT_color ? "true" : "false",
NEXT_solid ? "true" : "false",
NEXT_LW, /* line width */
(int) (t->v_char) / (-3), /* shift for vertical centring */
NEXT_SC, /* dash length */
NEXT_HTIC / 2.0, /* half point width */
NEXT_VTIC / 2.0); /* half point height */
if (uses_fonts && (encoding == S_ENC_ISO8859_1)) {
for (i = 0; NEXT_iso_8859_1_encoding[i] != NULL; i++) {
NEXTPrintf("%s", NEXT_iso_8859_1_encoding[i]);
}
}
for (i = 0; NEXT_header[i] != NULL; i++)
NEXTPrintf("%s", NEXT_header[i]);
if (NEXT_duplex_option)
NEXTPrintf("statusdict begin %s setduplexmode end\n",
NEXT_duplex_state ? "true" : "false");
NEXT_RememberFont(NEXT_font);
if (dict)
while (*dict)
NEXTPrintf("%s", *(dict++));
NEXTPrintf("end\n%%%%EndProlog\n");
}
/* the init fn for the NeXT Terminal driver */
TERM_PUBLIC void
NEXT_init()
{
/* Initialize output string */
NEXTsize = DEFAULTNEXTSIZE;
if ((NEXTBuffer = malloc(NEXTsize)) == NULL) {
printf("Malloc error in next filter init\n");
exit(1);
}
NEXTBufEnd = NEXTBuffer + NEXTsize;
NEXTBufAt = NEXTBuffer;
term->xmax = NEXT_XMAX;
term->ymax = NEXT_YMAX;
#ifdef NEXT_OLDTERMINAL
if (NEXT_oldterminal)
window_create();
else
gnuTermAccess =[[GnuTermDriver alloc] init];
#else
gnuTermAccess =[[GnuTermDriver alloc] init];
#endif
}
TERM_PUBLIC void
NEXT_graphics()
{
static char GPFAR NEXTg1[] = "0 setgray\nnewpath\n";
struct termentry *t = term;
*NEXTBuffer = 0;
NEXTBufAt = NEXTBuffer;
NEXT_common_init(1, NEXT_XOFF, NEXT_YOFF, term->xmax, term->ymax,
ENHNEXT_header);
NEXTPrintf("gnudict begin\ngsave\n");
NEXTPrintf("%d %d translate\n", NEXT_common_xoff, NEXT_common_yoff);
NEXTPrintf("%.3f %.3f scale\n", 1.0 / NEXT_SC, 1.0 / NEXT_SC);
NEXTPrintf(NEXTg1);
if (NEXT_common_uses_fonts)
NEXTPrintf("(%s) findfont %d scalefont setfont\n", NEXT_font, (t->v_char));
NEXT_path_count = 0;
NEXT_relative_ok = FALSE;
NEXT_pen_x = NEXT_pen_y = -4000;
NEXT_taken = 0;
NEXT_linetype_last = LT_UNDEFINED;
#ifdef NEXT_OLDTERMINAL
if (NEXT_oldterminal) {
/* Fill window with white */
NEXTPrintf("1 setgray\n");
NEXTPrintf("0 0 %d %d rectfill\n", NEXT_XMAX, NEXT_YMAX);
NEXTPrintf("0 setgray\n");
}
#endif
}
TERM_PUBLIC void
NEXT_text()
{
static DPSContext d;
NEXT_path_count = 0;
NEXTPrintf("stroke\ngrestore\nend\n");
/* Terminate string */
*NEXTBufAt = 0;
if (NEXT_oldterminal) {
d = DPSGetCurrentContext();
DPSPrintf(d, NEXTBuffer);
DPSFlushContext(d);
} else {
/* Here's the call that dumps the string to the server */
[gnuTermAccess plot:NEXTBuffer];
}
}
TERM_PUBLIC void
NEXT_reset()
{
NEXTPrintf("%%%%Trailer\n");
if (!NEXT_common_uses_fonts) {
NEXTPrintf("%%%%DocumentFonts: ");
while (NEXT_DocFonts) {
struct NEXT_FontName *fnp;
fnp = NEXT_DocFonts->next;
NEXTPrintf("%s%s", NEXT_DocFonts->name, fnp ? ", " : "\n");
free(NEXT_DocFonts->name);
free(NEXT_DocFonts);
NEXT_DocFonts = fnp;
}
}
}
TERM_PUBLIC void
NEXT_linetype(int linetype)
{
linetype = (linetype % 9) + 2;
if (linetype < 0)
linetype = 0;
NEXT_relative_ok = FALSE;
if (NEXT_linetype_last == linetype)
return;
NEXT_linetype_last = linetype;
NEXTPrintf("LT%c\n", "ba012345678"[linetype]);
NEXT_path_count = 0;
}
TERM_PUBLIC void
NEXT_move(unsigned int x, unsigned int y)
{
int dx, dy;
char abso[20], rel[20];
dx = x - NEXT_pen_x;
dy = y - NEXT_pen_y;
/* can't cancel all null moves--need a move after stroke'ing */
if (dx == 0 && dy == 0 && NEXT_relative_ok)
return;
sprintf(abso, "%d %d M\n", x, y);
sprintf(rel, "%d %d R\n", dx, dy);
if (strlen(rel) < strlen(abso) && NEXT_relative_ok) {
NEXTPrintf("%s", rel);
NEXT_taken++;
} else
NEXTPrintf("%s", abso);
NEXT_relative_ok = TRUE;
NEXT_path_count += 1;
NEXT_pen_x = x;
NEXT_pen_y = y;
}
TERM_PUBLIC void
NEXT_vector(unsigned int x, unsigned int y)
{
int dx, dy;
char abso[20], rel[20];
dx = x - NEXT_pen_x;
dy = y - NEXT_pen_y;
if (dx == 0 && dy == 0)
return;
sprintf(abso, "%d %d L\n", x, y);
sprintf(rel, "%d %d V\n", dx, dy);
if (strlen(rel) < strlen(abso) && NEXT_relative_ok) {
NEXTPrintf("%s", rel);
NEXT_taken++;
} else
NEXTPrintf("%s", abso);
NEXT_relative_ok = TRUE;
NEXT_path_count += 1;
NEXT_pen_x = x;
NEXT_pen_y = y;
if (NEXT_path_count >= 400) {
NEXTPrintf("currentpoint stroke M\n");
NEXT_path_count = 0;
}
}
TERM_PUBLIC int
NEXT_text_angle(int ang)
{
NEXT_ang = ang;
return TRUE;
}
TERM_PUBLIC int
NEXT_justify_text(enum JUSTIFY mode)
{
NEXT_justify = mode;
return TRUE;
}
TERM_PUBLIC int
NEXT_set_font(const char *font)
{
char name[32];
int size, sep;
if (!font || !(*font))
font = NEXT_default_font;
sep = strcspn(font, ",");
strncpy(name, font, sep);
name[sep] = NUL;
size = NEXT_fontsize;
if (font[set] == ',')
sscanf(&(font[sep + 1]), "%d", &size);
NEXTPrintf("/%s findfont %d scalefont setfont\n", name, size * NEXT_SC);
NEXT_RememberFont(name);
term->v_char = (unsigned int) (size * NEXT_SC);
term->h_char = (unsigned int) (size * NEXT_SC * 6 / 10);
return TRUE;
}
/* postscript point routines */
TERM_PUBLIC void
NEXT_set_pointsize(double size)
{
NEXTPrintf("/vpt %.1f def /hpt %.1f def /vpt2 vpt 2 mul def /hpt2 hpt 2 mul def\n",
pointsize * NEXT_VTIC * 0.5, pointsize * NEXT_HTIC * 0.5);
}
TERM_PUBLIC void
NEXT_point(unsigned int x, unsigned int y, int number)
{
static char *pointFNS[] =
{"Pnt", "Pls", "Crs", "Star",
"Box", "BoxF", "Circle", "CircleF",
"TriU", "TriUF", "TriD", "TriDF",
"Dia", "DiaF", "Pent", "PentF",
"C0", "C1", "C2", "C3",
"C4", "C5", "C6", "C7",
"C8", "C9", "C10", "C11",
"C12", "C13", "C14", "C15",
"S0", "S1", "S2", "S3",
"S4", "S5", "S6", "S7",
"S8", "S9", "S10", "S11",
"S12", "S13", "S14", "S15",
"D0", "D1", "D2", "D3",
"D4", "D5", "D6", "D7",
"D8", "D9", "D10", "D11",
"D12", "D13", "D14", "D15"
};
if (number < 0)
number = -1; /* negative types are all 'dot' */
else
number %= sizeof(pointFNS) / sizeof(pointFNS[0]) - 1;
NEXTPrintf("%d %d %s\n", x, y, pointFNS[number + 1]);
NEXT_relative_ok = 0;
NEXT_path_count = 0;
NEXT_linetype_last = LT_UNDEFINED; /* force next linetype change */
}
/* All lifted from the enhanced postscript driver */
static TBOOLEAN NEXT_opened_string; /* try to cut out empty ()'s */
/* used in determining height of processed text */
static float NEXT_max_height, NEXT_min_height;
/* process a bit of string, and return the last character used.
* p is start of string
* brace is TRUE to keep processing to }, FALSE for do one character
* fontname & fontsize are obvious
* base is the current baseline
* widthflag is TRUE if the width of this should count,
* FALSE for zero width boxes
*/
static char *
NEXT_recurse(
char *p,
TBOOLEAN brace,
char *fontname,
double fontsize, double base,
TBOOLEAN widthflag)
{
/* close a postscript string if it has been opened */
#define NEXT_FLUSH \
{ if (NEXT_opened_string) \
{ NEXTPrintf("%s", ")]\n"); \
NEXT_opened_string = FALSE; \
} \
}
#define NEXT_OPEN \
{ if (!NEXT_opened_string) \
{ NEXTPrintf( "[(%s) %.1f %.1f %s (", \
fontname, fontsize, base, \
widthflag ? "true" : "false"); \
NEXT_opened_string = TRUE; \
} \
}
/* Start each recursion with a clean string */
NEXT_FLUSH;
if (base + fontsize > NEXT_max_height) {
NEXT_max_height = base + fontsize;
}
if (base < NEXT_min_height) {
NEXT_min_height = base;
}
for (; *p; ++p) {
float shift;
float f = 0; /* used for getting new font size */
char *localfontname, ch;
switch (*p) {
case '}':
if (brace)
return (p);
fprintf(stderr, "next driver - spurious }\n");
break;
case '_':
case '^':
shift = (*p == '^') ? 0.5 : -0.3;
NEXT_FLUSH;
p = NEXT_recurse(p + 1, FALSE, fontname, fontsize * 0.8,
base + shift * fontsize, widthflag);
break;
case '{':
/*{{{ recurse (possibly with a new font) */
if (*++p == '/') { /* then parse a fontname, optional fontsize */
while (*++p == ' ');
localfontname = p;
while ((ch = *p) > ' ' && ch != '=')
++p;
if (ch == '=') {
*p++ = '\0';
/*{{{ get optional font size */
f = (float) strtod(p, &p);
if (f)
f *= NEXT_SC; /* remember the scaling */
else
f = fontsize;
/*}}} */
} else {
*p++ = '\0';
f = fontsize;
}
while (*p == ' ')
++p;
if (*localfontname)
localfontname = NEXT_RememberFont(localfontname);
else
localfontname = fontname;
} else {
localfontname = fontname;
f = fontsize;
}
/*}}} */
p = NEXT_recurse(p, TRUE, localfontname, f, base, widthflag);
NEXT_FLUSH
break;
case '@':
/*{{{ phantom box - prints next 'char', then restores currentpoint */
NEXT_FLUSH
p = NEXT_recurse(++p, FALSE, fontname, fontsize, base, FALSE);
break;
/*}}} */
case '(':
case ')':
/* special cases */
NEXT_OPEN
NEXTPrintf("\\");
NEXTPrintf("%c", *p);
break;
/*}}} */
case '\\':
/*{{{ is it an escape */
/* special cases */
if (p[1] == '\\' || p[1] == '(' || p[1] == ')') {
NEXT_OPEN
NEXTPrintf("%c", '\\');
} else if ((ch = p[1]) >= '0' && ch = '0' && ch = '0' && ch