1 /* Hello, Emacs, this is -*-C-*-
2 * $Id: amiga.trm,v 1.20 2006/07/21 02:35:45 sfeam Exp $
6 /* GNUPLOT - amiga.trm */
9 * Copyright 1991, 1992, 1993, 1998, 2004
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.
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,
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
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.
34 * This software is provided "as is" without express or implied warranty
35 * to the extent permitted by applicable law.
39 * This file is included by ../term.c.
41 * This terminal driver supports:
47 * Pat R. Empleo Slightly modified for Aztec C v5.2a (beta); sort of
48 * 08/27/91 supports overscan; for large WB 2.0 virtual screens,
49 * we limit the plot size so we don't have to scroll
52 * Carsten Steger Modified to support Kickstart 2.0.
53 * 09/11/91 Opens a text overscan screen when used with WB 2.0.
54 * Discerns between NTSC and PAL Amigas when used with
57 * Pat R. Empleo Defined some 2.0 stuff in order to get Aztec C to
58 * 09/20/91 work with Carsten's new code (see above). When
59 * KS/WB 2.0 support gets implemented in Aztec C, this
60 * kludge will get deleted!
61 * (Aztec C release 5.2 beta)
63 * Carsten Steger Converted to new terminal layout.
66 * Lars Hecking Add code from George Coulouris <glc5@cornell.edu> to
67 * 06/20/97 implement window option, requires AmigaOS 3.0+.
68 * General cleanup, better readability.
70 * Lars Hecking Replace static arrays for AMIGA_FontName and temporary
71 * 06/21/97 arrays with AllocMem()'d memory.
73 * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
85 #define AMIGA_XMAX 640
86 #define AMIGA_YMAX 512
88 #define AMIGA_VCHAR 12
93 TERM_PUBLIC void AMIGA_reset __PROTO((void));
94 TERM_PUBLIC void AMIGA_init __PROTO((void));
95 TERM_PUBLIC void AMIGA_options __PROTO((void));
96 TERM_PUBLIC void AMIGA_text __PROTO((void));
97 TERM_PUBLIC void AMIGA_graphics __PROTO((void));
98 TERM_PUBLIC void AMIGA_move __PROTO((unsigned int x, unsigned int y));
99 TERM_PUBLIC void AMIGA_vector __PROTO((unsigned int x, unsigned int y));
100 TERM_PUBLIC void AMIGA_linetype __PROTO((int linetype));
101 TERM_PUBLIC void AMIGA_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
102 TERM_PUBLIC int AMIGA_justify_text __PROTO((enum JUSTIFY mode));
103 TERM_PUBLIC int AMIGA_set_font __PROTO((const char *font));
104 TERM_PUBLIC void AMIGA_suspend __PROTO((void));
105 TERM_PUBLIC void AMIGA_resume __PROTO((void));
107 #define GOT_AMIGA_PROTO
109 #endif /* TERM_PROTO */
112 #ifndef TERM_PROTO_ONLY
116 #include <intuition/intuitionbase.h>
117 #include <intuition/screens.h>
118 #include <graphics/text.h>
119 #include <graphics/gfxbase.h>
121 /* You will have to use the Kickstart 2.0 header files for this to compile */
122 #include <exec/types.h>
124 #include <intuition/intuitionbase.h>
125 #include <graphics/gfxbase.h>
126 #include <proto/intuition.h>
127 #include <proto/graphics.h>
128 #include <proto/exec.h>
129 #include <proto/diskfont.h>
130 #endif /* !AMIGA_AC_5 */
133 void AMIGA_exit(void);
134 # define ATEXIT(x) (atexit(x) != 0)
136 /* # define ATEXIT(x) (onexit(x) == 0) */
137 # define RAWCON(x) rawcon(x)
139 # define RAWCON(x) /* nought */
143 #endif /* HAVE_ATEXIT */
146 # define RETURN_FAIL 20
149 #define LIB_VERSION(LibBase) ((LibBase)->LibNode.lib_Version)
151 #define AMIGA_ERROR(string,rc) {fprintf (stderr,"%s\n",string);\
152 AMIGA_reset (); exit (rc);}
155 extern TBOOLEAN interactive;
157 /* The origin is in the upper left hand corner, so we have to translate */
158 /* and flip the coordinates: */
159 #define AMIGA_VTF(y) (AMIGA_ymax-1-(y))
163 struct IntuitionBase *IntuitionBase;
164 struct GfxBase *GfxBase;
165 struct Library *DiskfontBase;
168 /* Name of font, size in pts */
169 static char *AMIGA_FontName = NULL;
170 static int AMIGA_FontNameLen = 0;
171 static int AMIGA_FontSize = 8;
172 static char AMIGA_default_font[MAX_ID_LEN+1] = {'\0'};
173 #define AMIGA_DEFAULTFONT "topaz"
176 static struct TextAttr AMIGA_Font =
178 "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT
180 static struct TextFont *AMIGA_TextFont;
184 static struct NewScreen AMIGA_NewScreen =
186 0, 0, AMIGA_XMAX, AMIGA_YMAX, 4, 15, 0, HIRES | LACE,
187 CUSTOMSCREEN | SCREENBEHIND | SCREENQUIET, NULL, NULL, NULL, NULL
189 static struct Screen *AMIGA_Screen;
190 static struct TagItem AMIGA_ScrTagList[] =
192 { SA_Overscan, OSCAN_TEXT },
198 /* FALSE: plot to screen; TRUE: plot to window */
199 static TBOOLEAN AMIGA_window_mode = FALSE;
201 #define AMIGA_WIN_XMAX 512
202 #define AMIGA_WIN_YMAX 320
204 static struct Window *AMIGA_Window;
205 static struct TagItem AMIGA_WinTagList[] =
207 { WA_InnerWidth, AMIGA_WIN_XMAX },
208 { WA_InnerHeight, AMIGA_WIN_YMAX },
209 { WA_Title, (ULONG) "gnuplot" },
210 { WA_DragBar, TRUE },
211 { WA_DepthGadget, TRUE },
212 { WA_WBenchWindow, TRUE },
213 { WA_SmartRefresh, TRUE },
214 { WA_GimmeZeroZero, TRUE },
215 { WA_AutoAdjust, TRUE },
220 * This is the palette. Values are stored as 0xrrggbb, where rr, gg, and, bb
221 * are big-endian 8-bit intensities for red, green, and blue, respectively.
223 static unsigned int palette[] =
225 0xffffff, /* white */
226 0x000000, /* black */
228 0x00ff00, /* green */
231 0xff00ff, /* magenta */
232 0xffff00, /* yellow */
233 0x7f007f, /* purple */
234 0xff7f00, /* orange */
237 #define PALETTE_SIZE (sizeof (palette) / sizeof (unsigned int))
239 /* This is the color look-up table, indexed in the same order as
240 * the above palette. The values stored in this table are pen numbers;
241 * e.g clut[2] is the pen which represents the color "red".
243 static unsigned int clut[PALETTE_SIZE];
247 static UWORD AMIGA_Colors[] =
249 0x000, 0xfff, 0xbbb, 0x0f0, 0xf00, 0x00f, 0x3ca, 0xf0f,
250 0x94d, 0x0ff, 0x82f, 0xff0, 0x0af, 0xc5e, 0xfa2, 0xf44
255 static int AMIGA_slinetype;
256 static enum JUSTIFY AMIGA_justify = LEFT;
257 static unsigned int AMIGA_ymax, AMIGA_xmax;
258 static WORD AMIGA_cwd, AMIGA_cht, AMIGA_bsl, AMIGA_vadj;
259 /* Common RastPort */
260 static struct RastPort *AMIGA_RastPort;
263 enum AMIGA_id { AMI_SCREEN, AMI_WINDOW, AMI_OTHER };
265 static struct gen_table AMIGA_opts[] =
267 {"scr$een", AMI_SCREEN },
268 {"win$dow", AMI_WINDOW },
274 * Scan terminal options
280 while (!END_OF_COMMAND) {
281 switch(lookup_table(&AMIGA_opts[0],c_token)) {
283 AMIGA_window_mode = FALSE;
287 AMIGA_window_mode = TRUE;
293 if (isstring(c_token)) {
294 if (AMIGA_FontName != NULL) {
295 FreeMem(AMIGA_FontName,AMIGA_FontNameLen);
296 AMIGA_FontName = NULL;
297 AMIGA_FontNameLen = 0;
300 AMIGA_FontNameLen = token_len(c_token);
302 AMIGA_FontName = AllocMem(AMIGA_FontNameLen,0);
303 if (AMIGA_FontName == NULL)
304 AMIGA_ERROR("No memory for font name", RETURN_FAIL);
305 quote_str(AMIGA_FontName, c_token, AMIGA_FontNameLen);
310 AMIGA_FontSize = (int) real(const_express(&a));
317 if (AMIGA_FontName == NULL && AMIGA_FontSize != 0) {
318 AMIGA_FontNameLen = strlen(AMIGA_DEFAULTFONT) + 1;
319 AMIGA_FontName = AllocMem(AMIGA_FontNameLen,0);
320 if (AMIGA_FontName == NULL)
321 AMIGA_ERROR("No memory for font name", RETURN_FAIL);
322 strcpy(AMIGA_FontName, AMIGA_DEFAULTFONT);
324 if (AMIGA_FontName != NULL && AMIGA_FontSize == 0)
327 if (AMIGA_FontName != NULL && AMIGA_FontSize != 0) {
328 sprintf(AMIGA_default_font, "%s,%d", AMIGA_FontName, AMIGA_FontSize);
329 sprintf(term_options, "%s \"%s\" %d", \
330 (AMIGA_window_mode != TRUE ? "screen" : "window"), \
331 AMIGA_FontName, AMIGA_FontSize);
333 sprintf(term_options, "%s", (AMIGA_window_mode != TRUE ? "screen" : "window"));
338 * Close open font, screen and libraries.
343 if (AMIGA_window_mode == TRUE) {
347 while (i < PALETTE_SIZE) {
349 ReleasePen(AMIGA_Window->WScreen->ViewPort.ColorMap, clut[i]);
354 /* Close the window */
355 if (AMIGA_Window != NULL)
356 CloseWindow(AMIGA_Window);
359 AMIGA_window_mode = FALSE;
361 if (AMIGA_TextFont != NULL)
362 CloseFont(AMIGA_TextFont);
364 if (DiskfontBase != NULL)
365 CloseLibrary(DiskfontBase);
367 if (AMIGA_Screen != NULL)
368 CloseScreen(AMIGA_Screen);
370 if (IntuitionBase != NULL)
371 CloseLibrary((struct Library *) IntuitionBase);
374 CloseLibrary((struct Library *) GfxBase);
376 if (AMIGA_FontName != NULL)
377 FreeMem(AMIGA_FontName,AMIGA_FontNameLen);
379 AMIGA_FontName = NULL;
380 AMIGA_FontNameLen = 0;
381 AMIGA_TextFont = NULL;
384 IntuitionBase = NULL;
387 AMIGA_RastPort = NULL;
398 /* Install exit trap in case of abnormal termination (see below). */
399 if (ATEXIT(AMIGA_exit))
400 AMIGA_ERROR("Couldn't set exit trap", RETURN_FAIL);
402 /* Open needed libraries */
403 GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0);
405 AMIGA_ERROR("No Graphics-Library", RETURN_FAIL);
407 IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0);
408 if (IntuitionBase == NULL)
409 AMIGA_ERROR("No Intuition-Library", RETURN_FAIL);
411 if (AMIGA_window_mode == TRUE) {
414 /* Initialize the clut */
415 while (i < PALETTE_SIZE)
418 if (LIB_VERSION(IntuitionBase) <= 34) {
419 /* We compute the vertical resolution for those poor NTSC-souls :-) */
420 if (GfxBase->DisplayFlags & PAL)
426 AMIGA_NewScreen.Width = AMIGA_xmax;
427 AMIGA_NewScreen.Height = AMIGA_ymax;
429 AMIGA_Screen = OpenScreen(&AMIGA_NewScreen);
431 if (AMIGA_Screen == NULL)
432 AMIGA_ERROR("No Screen", RETURN_FAIL);
434 AMIGA_RastPort = &AMIGA_Screen->RastPort;
436 } else { /* Intuition version > 34 */
437 /* Kickstart 2.0 support */
438 AMIGA_NewScreen.Width = STDSCREENWIDTH;
439 AMIGA_NewScreen.Height = STDSCREENHEIGHT;
441 if (AMIGA_window_mode != TRUE) {
443 AMIGA_Screen = OpenScreenTagList(&AMIGA_NewScreen, AMIGA_ScrTagList);
445 if (AMIGA_Screen == NULL)
446 AMIGA_ERROR("No Screen", RETURN_FAIL);
448 AMIGA_RastPort = &AMIGA_Screen->RastPort;
450 AMIGA_xmax = AMIGA_Screen->Width;
451 AMIGA_ymax = AMIGA_Screen->Height;
452 } else if (LIB_VERSION(GfxBase) >= 39) { /* AMIGA_window_mode == TRUE */
453 /* Open the plot window */
455 AMIGA_Window = (struct Window *)OpenWindowTagList(NULL, AMIGA_WinTagList);
457 /* Don't do this: fall back to screen */
458 if (AMIGA_Window == NULL)
459 AMIGA_ERROR("Could not open plot window", RETURN_FAIL);
461 AMIGA_RastPort = AMIGA_Window->RPort;
463 AMIGA_xmax = AMIGA_WIN_XMAX;
464 AMIGA_ymax = AMIGA_WIN_YMAX;
466 } /* Gfx version >= 39 */
467 } /* Intuition version <= 34 */
469 term->xmax = AMIGA_xmax;
470 term->ymax = AMIGA_ymax;
472 if (AMIGA_window_mode != TRUE) {
474 /* assert(AMIGA_FontName != NULL); */
475 /* should even do for ridiculously large FontSize :) */
476 name = AllocMem(AMIGA_FontNameLen + 1 + INT_STR_LEN + 1,0);
478 AMIGA_ERROR("No memory for font name", RETURN_FAIL);
479 sprintf(name, "%s,%d", AMIGA_FontName, AMIGA_FontSize);
480 AMIGA_set_font(name);
481 FreeMem(name,AMIGA_FontNameLen + INT_STR_LEN + 2);
483 LoadRGB4(&AMIGA_Screen->ViewPort, AMIGA_Colors, 16);
486 SetAPen(&AMIGA_Screen->RastPort, AMIGA_slinetype);
490 AMIGA_bsl = AMIGA_Window->RPort->TxBaseline; /* Reference line */
491 AMIGA_cht = AMIGA_Window->RPort->TxHeight; /* Height of characters */
494 for (i = 0; i < PALETTE_SIZE; i++) {
495 r = (palette[i] << 8) & 0xFF000000;
496 g = (palette[i] << 16) & 0xFF000000;
497 b = (palette[i] << 24) & 0xFF000000;
498 clut[i] = ObtainBestPenA(AMIGA_Window->WScreen->ViewPort.ColorMap, r, g, b, NULL);
503 SetDrMd(AMIGA_RastPort, JAM1);
514 if (AMIGA_window_mode != TRUE) {
515 if (interactive == TRUE) {
518 if ((fp = fopen("*", "r")) != NULL) {
524 ScreenToBack(AMIGA_Screen);
537 SetRast(AMIGA_RastPort, 0);
539 if (AMIGA_window_mode == TRUE) {
540 /* clear the window */
541 SetAPen(AMIGA_Window->RPort, clut[0]);
542 RectFill(AMIGA_Window->RPort, 0, 0, 640, 400);
543 AMIGA_slinetype = clut[1];
545 SetAPen(AMIGA_RastPort, AMIGA_slinetype);
554 AMIGA_move(unsigned int x, unsigned int y)
556 if ((x >= AMIGA_xmax) || (y >= AMIGA_ymax))
559 Move(AMIGA_RastPort, x, AMIGA_VTF(y));
567 AMIGA_vector(unsigned int x, unsigned int y)
569 if ((x >= AMIGA_xmax) || (y >= AMIGA_ymax))
572 Draw(AMIGA_RastPort, x, AMIGA_VTF(y));
580 AMIGA_linetype(int linetype)
582 if (AMIGA_window_mode != TRUE) {
589 AMIGA_slinetype = linetype + 3;
592 linetype = (linetype % 9) + 1;
597 AMIGA_slinetype = clut[linetype];
599 SetAPen(AMIGA_RastPort, AMIGA_slinetype);
607 AMIGA_put_text(unsigned int x, unsigned int y, const char *str)
610 WORD x_min, x_max, y_min, y_max;
614 tx_len = TextLength(AMIGA_RastPort, str, len);
616 switch (AMIGA_justify) {
622 x_min = x - tx_len / 2;
623 x_max = x + tx_len - tx_len / 2; /* avoid roundoff errors ! */
625 default: /* does this make sense ?? */
632 y_min = AMIGA_VTF(y) - AMIGA_vadj;
633 y_max = y_min + AMIGA_cht;
635 /* Check if character-string lies completely within the screen: */
636 /* What about clipping? */
637 if ((x_max >= AMIGA_xmax) || (y_min < 0) || (y_max >= AMIGA_ymax))
640 Move(AMIGA_RastPort, x_min, y_min + AMIGA_bsl);
641 Text(AMIGA_RastPort, str, len);
649 AMIGA_justify_text(enum JUSTIFY mode)
651 AMIGA_justify = mode;
660 AMIGA_set_font(const char *font)
662 static char test_str[] =
663 " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
664 static WORD test_len, test_pxl;
666 /* Disable for window mode */
667 if (AMIGA_window_mode != TRUE) {
669 int size, sep, namelen;
671 /* Allow caller to pass "" to indicate default font */
672 if (!font || !(*font))
673 font = AMIGA_default_font;
675 sep = strcspn(font, ",");
676 namelen = strlen(font) + strlen(".font") + 1;
677 name = AllocMem(namelen,0);
679 AMIGA_ERROR("No memory for font name", RETURN_FAIL);
682 size = AMIGA_FontSize;
683 if (font[sep] == ',')
684 sscanf(&(font[sep + 1]), "%d", &size);
686 if (name != NULL && strcmp(name, "") != 0) {
687 strcat(name, ".font");
689 /* Avoid opening "diskfont.library" if a built-in font is desired */
690 if ((strcmp("topaz.font", name) == 0) &&
691 ((size == TOPAZ_EIGHTY) || (size == TOPAZ_SIXTY))) {
692 AMIGA_Font.ta_Name = name;
693 AMIGA_Font.ta_YSize = size;
694 AMIGA_Font.ta_Style = FS_NORMAL;
695 AMIGA_Font.ta_Flags = FPF_ROMFONT;
696 AMIGA_TextFont = OpenFont(&AMIGA_Font);
698 if (AMIGA_TextFont != NULL)
699 SetFont(&AMIGA_Screen->RastPort, AMIGA_TextFont);
702 DiskfontBase = OpenLibrary("diskfont.library", 0);
704 if (DiskfontBase != NULL) {
705 AMIGA_Font.ta_Name = name;
706 AMIGA_Font.ta_YSize = size;
707 AMIGA_Font.ta_Style = FS_NORMAL;
708 AMIGA_Font.ta_Flags = FPF_ROMFONT | FPF_DISKFONT;
709 AMIGA_TextFont = OpenDiskFont(&AMIGA_Font);
711 if (AMIGA_TextFont != NULL)
712 SetFont(&AMIGA_Screen->RastPort, AMIGA_TextFont);
716 /* Width of characters: This works better for proportional fonts than */
717 /* AMIGA_Screen->RastPort.TxWidth + AMIGA_Screen->RastPort.TxSpacing */
718 test_len = strlen(test_str);
719 test_pxl = TextLength(&AMIGA_Screen->RastPort, test_str, test_len);
721 AMIGA_cwd = test_pxl / test_len;
722 AMIGA_cht = AMIGA_Screen->RastPort.TxHeight; /* Height of characters */
723 AMIGA_bsl = AMIGA_Screen->RastPort.TxBaseline; /* Reference line */
725 /* Amount by which characters have to be shifted upwards to be */
726 /* vertically justified: */
727 AMIGA_vadj = AMIGA_bsl / 2;
728 term->v_char = AMIGA_cht + 4; /* So lines won't be too close */
729 term->h_char = AMIGA_cwd;
731 FreeMem(name,namelen);
743 if (AMIGA_window_mode != TRUE) {
744 if (interactive == TRUE) {
747 if ((fp = fopen("*", "r")) != NULL) {
753 ScreenToBack(AMIGA_Screen);
765 if (AMIGA_window_mode != TRUE)
766 ScreenToFront(AMIGA_Screen);
768 WindowToFront(AMIGA_Window);
773 /* This function is mainly included if the program terminates abnormally
774 * and the screen and libraries are still open. It closes down all opened
775 * libraries and screens. This happens e.g. when loading "bivariat.demo"
776 * and the stack is smaller than 120000 bytes.
785 #endif /* HAVE_ATEXIT */
788 #endif /* TERM_BODY */
792 TERM_TABLE_START(amiga_driver)
793 "amiga", "Amiga Custom Screen/Window [screen window]",
794 AMIGA_XMAX, AMIGA_YMAX, AMIGA_VCHAR, AMIGA_HCHAR,
795 AMIGA_VTIC, AMIGA_HTIC, AMIGA_options, AMIGA_init, AMIGA_reset,
796 AMIGA_text, null_scale, AMIGA_graphics, AMIGA_move, AMIGA_vector,
797 AMIGA_linetype, AMIGA_put_text, null_text_angle,
798 AMIGA_justify_text, do_point, do_arrow, AMIGA_set_font,
800 TERM_CAN_MULTIPLOT, AMIGA_suspend, AMIGA_resume
801 TERM_TABLE_END(amiga_driver)
804 #define LAST_TERM amiga_driver
806 #endif /* TERM_TABLE */
807 #endif /* TERM_PROTO_ONLY */
813 "?commands set terminal amiga",
814 "?set terminal amiga",
819 " The `amiga` terminal, for Commodore Amiga computers, allows the user to",
820 " plot either to a screen (default), or, if Kickstart 3.0 or higher is",
821 " installed, to a window on the current public screen. The font and its size",
822 " can also be selected.",
825 " set terminal amiga {screen | window} {\"<fontname>\"} {<fontsize>}",
827 " The default font is 8-point \"topaz\".",
829 " The screen option uses a virtual screen, so it is possible that the graph",
830 " will be larger than the screen."
832 #endif /* TERM_HELP */