home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ucb_logoppc / source / amiterm.c next >
Encoding:
C/C++ Source or Header  |  1998-02-20  |  23.3 KB  |  883 lines

  1. /*
  2.    amiterm.c           Amiga screen module
  3.  
  4.    Copyright (C) 1997 Tony Belding, <tlbelding@htcomp.net>
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20. #include "logo.h"
  21. #include "globals.h"
  22.  
  23. #if defined(__PPC__) && defined(AMIGA)
  24.  
  25. #define __USE_SYSBASE
  26. #include <proto/exec.h>
  27. #include <proto/dos.h>
  28. #include <proto/graphics.h>
  29. #include <proto/intuition.h>
  30. #include <proto/asl.h>
  31. #include <powerup/ppclib/interface.h>
  32. #include <powerup/gcclib/powerup_protos.h>
  33.  
  34. #define AllocVec(n, f) PPCAllocVec(n, f)
  35. #define FreeVec(b)     PPCFreeVec(b)
  36.  
  37. #endif
  38.  
  39. #include "amiterm.h"
  40.  
  41. /*
  42.    version = standard AmigaDOS string for "version" command
  43.  
  44.    The revision and amiga_revision values are intended mainly
  45.    for internal checking of file formats.  See load_prefs() and
  46.    save_prefs() for an example.
  47. */
  48. char *version = "$VER: Berkeley_Amiga_Logo 4.01 (23.6.97)";
  49. int revision = 401;
  50. int amiga_revision = 8;
  51.  
  52. extern NODE* make_static_strnode();
  53.  
  54. BPTR console=NULL;   /* pointer of AmigaDOS console device */
  55.  
  56. /*
  57.    This will create an auto-window that will open on the Workbench only if
  58.    text is sent to it.  The standard C I/O, stdout, is directed to it, so
  59.    you can send debugging or error info with printf().  Text directed to
  60.    the Logo text console should go to ndprintf() or ami_print() instead.
  61. */
  62. __near char __stdiowin[]="CON:40/380/600/100/Logo Debugging";
  63. __near char __stdiov37[]="/AUTO";
  64.  
  65.  
  66. #define INTUI_V36_NAMES_ONLY
  67.  
  68. #include <exec/types.h>
  69. #include <intuition/intuition.h>
  70. #include <intuition/intuitionbase.h>
  71. #include <intuition/screens.h>
  72. #include <graphics/displayinfo.h>
  73.  
  74. #include <clib/exec_protos.h>
  75. #include <clib/dos_protos.h>
  76. #include <clib/intuition_protos.h>
  77. #include <clib/layers_protos.h>
  78.  
  79.  
  80. struct IntuitionBase *IntuitionBase;
  81.  
  82. struct Screen *scrn=NULL; /* Points to the Intuition screen */
  83. struct Window *win;       /* Points to the graphics window */
  84. int current_vis;          /* Is the pen writing */
  85.  
  86.  
  87. char *prefsname = "logo.cfg";    /* name of Amiga preferences file */
  88. char screenname[20];  /* name of Amiga public screen */
  89.  
  90. BAL_Prefs prefs;
  91.  
  92. /* remember which was the last screen layout that was set */
  93. enum Layout { NOSCREEN, TEXTSCREEN, FULLSCREEN, SPLITSCREEN } layout;
  94.  
  95. void handle_window_events(struct Window *);
  96. void amiga_init(int argc, char *argv[]);
  97. void amiga_deinit(void);
  98. void amiga_noscreen(void);
  99. void amiga_layout(enum Layout);
  100. void announce_closescreen(struct Screen *);
  101.  
  102. BOOL save_prefs()
  103. {
  104.     BPTR outfile=Open(prefsname,MODE_NEWFILE);
  105.     BOOL success = FALSE;;
  106.  
  107.     if (outfile) {
  108.         Write(outfile,&amiga_revision,(long)sizeof(revision));
  109.         Write(outfile,&prefs,(long)sizeof(prefs));
  110.         Close(outfile);
  111.         success = TRUE;
  112.     } else
  113.         ami_print("I couldn't open the file to save your preferences!\n");
  114.     return success;
  115. }
  116.  
  117.  
  118. BOOL load_prefs()
  119. {
  120.    BPTR infile=Open(prefsname,MODE_OLDFILE);
  121.    BAL_Prefs new_prefs;
  122.    int revcheck;
  123.    BOOL success = FALSE;
  124.  
  125.    if (infile==NULL)
  126.       ami_print("I couldn't open the file to load your preferences!\n");
  127.    else {
  128.       Read(infile,&revcheck,(long)sizeof(revcheck));
  129.       if (revcheck>=8 && revcheck<=amiga_revision)
  130.          success = Read(infile,&new_prefs,sizeof(prefs))==sizeof(prefs);
  131.       if (success==FALSE)
  132.          ami_print("The preferences file seems to be corrupted.\n");
  133.       Close(infile);
  134.    }
  135.    if (success)  /* here we are going to copy the new_prefs into prefs */
  136.       prefs = new_prefs;
  137.    else
  138.       default_prefs();
  139.    return success;
  140. }
  141.  
  142.  
  143. void default_prefs()
  144. {
  145.    /* try for values that will work on any system, even NTSC ECS */
  146.    prefs.DisplayID = HIRES_KEY;
  147.    prefs.DisplayWidth = 640;
  148.    prefs.DisplayHeight = 200;
  149.    prefs.DisplayDepth = 4;
  150.    prefs.OverscanType = OSCAN_STANDARD;
  151.    prefs.font[0]='\0';
  152.    strcpy(prefs.editor,
  153.       "ed %s window \"CON:20/20/600/200/Logo Editor/CLOSE/SCREEN %s\"");
  154. }
  155.  
  156.  
  157. void amiga_open_graphics_screen()
  158. {
  159.    short my_pens[] = { ~0 };   /* for the new 3D rendering look */
  160.  
  161.    /*
  162.       Each public screen I open is given a unique name based on the Amiga
  163.       process address.  It's the same method I use for generating the
  164.       temporary filename in ledit().  So, multiple instances of Berkeley
  165.       Amiga Logo can be running at a given time without conflict.
  166.    */
  167.    sprintf(screenname,"BAL%ld",FindTask(NULL));
  168.    (void)load_prefs();
  169.  
  170.    /* Open the screen. */
  171.    scrn = OpenScreenTags(NULL,
  172.       SA_Type,       CUSTOMSCREEN,
  173.       SA_DetailPen,  BLACK,
  174.       SA_BlockPen,   WHITE,
  175.       SA_Title,      "Berkeley Amiga Logo",
  176.       SA_PubName,    screenname,
  177.       SA_DisplayID,  prefs.DisplayID,
  178.       SA_Width,      prefs.DisplayWidth,
  179.       SA_Height,     prefs.DisplayHeight,
  180.       SA_AutoScroll, TRUE,
  181.       SA_Depth,      prefs.DisplayDepth,
  182.       SA_Pens,       my_pens,
  183.       TAG_END );
  184.  
  185.    if (scrn==NULL) {
  186.       printf("I can't open the screen for Logo!\n");
  187.       prepare_to_exit();
  188.       exit(1);
  189.    }
  190.  
  191.    PubScreenStatus(scrn,0);   /* take it public */
  192.  
  193.    {
  194.       /*
  195.          I want  to determine the ModeID of the screen, then search the
  196.          display database and calculate the correct aspect ratio from
  197.          that.  I am also calculating magnification here.  This means
  198.          turtle graphics will look about the same, no matter what screen
  199.          mode we are using.  It does assume the user has set his overscan
  200.          prefs correctly.
  201.  
  202.          It also means Logo programs should not change the scrunch value,
  203.          such as for drawing ellipses or other distorted shapes, then set
  204.          the scrunch back to [1.0 1.0].  They should store the scrunch
  205.          value before messing with it, and then restore to its original
  206.          value when they are through.
  207.       */
  208.       LONG modeid;
  209.  
  210.       modeid = GetVPModeID(&(scrn->ViewPort));
  211.       x_scale = 1;   y_scale = 1;
  212.       if (modeid!=INVALID_ID) {
  213.          struct DimensionInfo di;
  214.  
  215.          /*
  216.             The values are taken from "text overscan" mode.  If the user
  217.             has set his overscan prefs correctly, this should most closely
  218.             conform to the actual shape of his screen.  I found it comes
  219.             to about [2.75 2.75] on an 800x600 display.  That gives a visual
  220.             field a little over 200 turtle steps tall, as recommended in
  221.             the docs.
  222.          */
  223.          (void)GetDisplayInfoData(NULL,(UBYTE *)&di,(ULONG)sizeof(di),DTAG_DIMS,modeid);
  224.          x_scale = (di.TxtOScan.MaxX+1)/(800.0/2.75);
  225.          y_scale = (di.TxtOScan.MaxY+1)/(600.0/2.75);
  226.       }
  227.    }
  228.  
  229.    {
  230.       /*
  231.          We've got to set the base palette of the screen.
  232.       */
  233.       int ctr, maxcolor=18, screen_maxcolor=(1<<scrn->RastPort.BitMap->Depth)-1;
  234.       const int data[]={
  235.  
  236.          /*** following are fixed colors ***/
  237.          168,  168,  168,  /* 0 WB gray   */
  238.          0,    0,    0,    /* 1 black     */
  239.          255,  255,  255,  /* 2 white     */
  240.          100,  136,  184,  /* 3 WB blue   */
  241.          0,    0,    255,  /* 4 blue      */
  242.          0,    255,  0,    /* 5 green     */
  243.          0,    255,  255,  /* 6 cyan      */
  244.          255,  0,    0,    /* 7 red       */
  245.          255,  0,    200,  /* 8 magenta   */
  246.          255,  255,  0,    /* 9 yellow    */
  247.  
  248.          /*** following are variable Logo presets ***/
  249.          144,  76,   0,    /* 10 brown    */
  250.          208,  172,  100,  /* 11 tan      */
  251.          0,    100,  0,    /* 12 forest   */
  252.          0,    176,  152,  /* 13 aqua     */
  253.          232,  172,  152,  /* 14 salmon   */
  254.          184,  0,    255,  /* 15 purple   */
  255.  
  256.          /*** these last two will be cut off on 16-color screens ***/
  257.          255,  108,  0,    /* 16 orange   */
  258.          -1,   -1,   -1,   /* Don't touch!  This is for mouse pointer. */
  259.          120,  120,  120   /* 18 gray     */
  260.       };
  261.  
  262.       if (maxcolor>screen_maxcolor)
  263.          maxcolor = screen_maxcolor;
  264.  
  265.       for (ctr=0; ctr<=maxcolor; ctr++) {
  266.          ULONG r, g, b;
  267.  
  268.          if (data[ctr*3]<0)   /* some colors shouldn't be touched */
  269.             continue;
  270.          /*
  271.             Note that Amiga OS 3.0+ wants a 32-bit value for each color
  272.             gun, so I have to scale them up as per autodocs.
  273.          */
  274.          r = data[ctr*3]<<24 | 0xffffff;
  275.          g = data[ctr*3+1]<<24 | 0xffffff;
  276.          b = data[ctr*3+2]<<24 | 0xffffff;
  277.          SetRGB32(&(scrn->ViewPort),(ULONG)ctr,r,g,b);
  278.       }
  279.    }
  280.  
  281. }
  282.  
  283. void amiga_open_graphics_window()
  284. {
  285.    if (win==NULL) {
  286.       /*
  287.          It is a full-screen (except for titlebar), borderless,
  288.          backdrop window.  Thus, it looks like graphics are being
  289.          drawn directly on the public screen bitmap.  However,
  290.          using a backdrop window is cleaner and more flexible.
  291.          It could be easy to adapt this to run on Workbench: most
  292.          of the needed code is already in place.
  293.       */
  294.       win = OpenWindowTags(NULL,
  295.          WA_Top,             scrn->BarHeight,
  296.          WA_Width,           scrn->Width,
  297.          WA_Height,          scrn->Height-scrn->BarHeight,
  298.          WA_Backdrop,        TRUE,
  299.          WA_Borderless,      TRUE,
  300.          WA_IDCMP,           NULL,
  301.          WA_CustomScreen,    scrn,
  302.          TAG_DONE );
  303.  
  304.       if (win==NULL) {
  305.          /* window failed to open */
  306.          prepare_to_exit();
  307.          exit(1);
  308.       } else {
  309.          /* window successfully opened here */
  310.          /* ClipWindow( win); */
  311.          SetAPen(win->RPort,WHITE);
  312.          SetBPen(win->RPort,BLACK);
  313.  
  314.          /* handle_window_events(win); */
  315.       }
  316.    }
  317. }
  318.  
  319. /***** ABOUT COLOR MAPPING
  320.  
  321. The functions MapColor() and RevMapColor() do conversion between Amiga and
  322. Logo color index numbers.  I have reserved certain colors that Amiga wants
  323. for rendering the gadgets, text console, and pointer, so Logo can't touch
  324. them.  We will need a whole new mapping and allocation system whenever
  325. support for 16-bit or 24-bit color is added.
  326.  
  327. *****/
  328.  
  329.  
  330. ULONG MapColor(FIXNUM logo_color)
  331. {
  332.    /* convert a logo color to an Amiga palette entry */
  333.    int screen_maxcolor=(1<<scrn->RastPort. BitMap->Depth)-1;
  334.    const int table[]={BLACK,BLUE,GREEN,CYAN,RED,MAGENTA,YELLOW,WHITE};
  335.    ULONG newcolor=WHITE;
  336.  
  337.    if (logo_color>=0 && logo_color<=7)
  338.       newcolor = table[logo_color];
  339.    if (logo_color>7) {
  340.       newcolor = logo_color+2;
  341.       if (newcolor>=17) /* color 17 is reserved for mouse pointer */
  342.          newcolor++;
  343.    }
  344.    if (newcolor>screen_maxcolor)
  345.       newcolor = screen_maxcolor;
  346.    return newcolor;
  347. }
  348.  
  349. FIXNUM RevMapColor(ULONG ami_color)
  350. {
  351.    /* convert an Amiga palette entry to a Logo color number */
  352.  
  353.    int screen_maxcolor=(1<<scrn->RastPort.BitMap->Depth)-1;
  354.    const int table[]={-1,0,7,-1,1,2,3,4,5,6};
  355.    int lc=-1;
  356.  
  357.    /* the -1 indicates a color Logo shouldn't use */
  358.  
  359.    if (ami_color>screen_maxcolor)
  360.       ami_color = screen_maxcolor;
  361.  
  362.    if (ami_color>=0 && ami_color<=9)
  363.       lc=table[ami_color];
  364.  
  365.    if (lc>=0)
  366.       return (FIXNUM)lc;
  367.    else if (ami_color>=18)
  368.       ami_color--;   /* skip over register 17 */
  369.    return (FIXNUM)ami_color-2;
  370. }
  371.  
  372.  
  373. void set_palette(slot,r,g,b)
  374. int slot;
  375. unsigned int r,g,b;
  376. {
  377.    ULONG index = MapColor(slot);
  378.    ULONG ar, ag, ab;
  379.  
  380.    /* note scaling from 16-bit to 32-bit values */
  381.    ar = r<<16 | 0xffff;
  382.    ag = g<<16 | 0xffff;
  383.    ab = b<<16 | 0xffff;
  384.    SetRGB32(&(scrn->ViewPort),index,ar,ag,ab);
  385. }
  386.  
  387. void get_palette(slot,r,g,b)
  388. int slot;
  389. unsigned int *r, *g, *b;
  390. {
  391.    ULONG index = MapColor(slot);
  392.    ULONG table[3];
  393.  
  394.    GetRGB32(scrn->ViewPort.ColorMap,index,1L,table);
  395.    /* convert from Amiga 32-bit to Logo 16-bit values */
  396.    *r = table[0]>>16;
  397.    *g = table[1]>>16;
  398.    *b = table[2]>>16;
  399. }
  400.  
  401. NODE *lam_version()
  402. {
  403.    /*
  404.       This simply converts the AmigaDOS version string into a list and
  405.       outputs it.
  406.    */
  407.    return parser(make_static_strnode(version));
  408. }
  409.  
  410.  
  411. NODE *lam_prefs()
  412. {
  413.    struct ScreenModeRequester *aslsm;
  414.    BOOL result;
  415.    ULONG tags[40], i=0L;
  416.  
  417.    /*
  418.       This primitive brings up the requester(s) for setting the Amiga
  419.       preferences -- currently limited to screen display mode, but there
  420.       will be more options in the future.
  421.    */
  422.  
  423.    aslsm = AllocAslRequestTags(ASL_ScreenModeRequest,TAG_DONE);
  424.    if (aslsm==NULL) {
  425.       ami_print("I can't open the screen mode requester.\n");
  426.       return (UNBOUND);
  427.    }
  428.  
  429.    if (scrn) {
  430.       tags[i++]=ASLSM_Screen;    tags[i++]=(ULONG)scrn;
  431.    }
  432.    tags[i++]=ASLSM_PrivateIDCMP;    tags[i++]=TRUE;
  433.    tags[i++]=ASLSM_TitleText;       tags[i++]=(ULONG)"Logo Screen Mode:";
  434.    tags[i++]=ASLSM_InitialDisplayID;      tags[i++]=prefs.DisplayID;
  435.    tags[i++]=ASLSM_InitialDisplayWidth;   tags[i++]=prefs.DisplayWidth;
  436.    tags[i++]=ASLSM_InitialDisplayHeight;  tags[i++]=prefs.DisplayHeight;
  437.    tags[i++]=ASLSM_InitialDisplayDepth;   tags[i++]=prefs.DisplayDepth;
  438.    tags[i++]=ASLSM_InitialOverscanType;   tags[i++]=prefs.OverscanType;
  439.    tags[i++]=ASLSM_DoWidth;   tags[i++]=TRUE;
  440.    tags[i++]=ASLSM_DoHeight;  tags[i++]=TRUE;
  441.    tags[i++]=ASLSM_DoDepth;   tags[i++]=TRUE;
  442.    tags[i++]=ASLSM_DoOverscanType;   tags[i++]=TRUE;
  443.    tags[i++]=ASLSM_MinWidth;   tags[i++]=640L;
  444.    tags[i++]=ASLSM_MinHeight;  tags[i++]=200L;
  445.    tags[i++]=ASLSM_MinDepth;  tags[i++]=4L;
  446.    tags[i++]=ASLSM_MaxDepth;  tags[i++]=8L;
  447.  
  448.    tags[i++]=TAG_DONE;
  449.    result = AslRequest(aslsm,(struct TagItem *)tags);
  450.  
  451.    if (result==FALSE)
  452.       ami_print("New screen mode not accepted.\n");
  453.    else {
  454.       /* read the new values from the requester structure */
  455.       prefs.DisplayID      = aslsm->sm_DisplayID;
  456.       prefs.DisplayWidth   = aslsm->sm_DisplayWidth;
  457.       prefs.DisplayHeight  = aslsm->sm_DisplayHeight;
  458.       prefs.DisplayDepth   = aslsm->sm_DisplayDepth;
  459.       prefs.OverscanType   = aslsm->sm_OverscanType;
  460.       if (save_prefs()) {
  461.          enum Layout relay;
  462.  
  463.          relay = layout;
  464.          amiga_noscreen();
  465.          amiga_layout(relay);
  466.          cs_helper(FALSE);
  467.       }
  468.    }
  469.    FreeAslRequest(aslsm);
  470.    return (UNBOUND);
  471. }
  472.  
  473.  
  474. static struct Region* ClipWindow( struct Window* w)
  475. {
  476.    struct Region* new_region;
  477.    struct Rectangle rect;
  478.  
  479.    /*
  480.       This function is used only if you are going to open a graphics
  481.       window that has a border, to keep from rendering over Intuition's
  482.       stuff.  Since we are currently using a borderless window, the
  483.       function isn't serving any useful purpose.  I'm keeping it in the
  484.       code just in case we need it later.  Same for UnClipWindow().
  485.    */
  486.    rect.MinX = w->BorderLeft;
  487.    rect.MinY = w->BorderTop;
  488.    rect.MaxX = w->Width - w->BorderRight - 1;
  489.    rect.MaxY = w->Height - w->BorderBottom - 1;
  490.  
  491.    if ( new_region = NewRegion()) {
  492.       if ( !OrRectRegion(new_region, &rect)) {
  493.          DisposeRegion(new_region);
  494.          return 0;
  495.       }
  496.    }
  497.    return InstallClipRegion(w->WLayer, new_region);
  498. }
  499.  
  500. static void UnClipWindow( struct Window* w)
  501. {
  502.    struct Region* old_region;
  503.  
  504.    old_region = InstallClipRegion( w->WLayer, 0);
  505.    if (old_region)
  506.         DisposeRegion(old_region);
  507. }
  508.  
  509.  
  510. void announce_closescreen(scrn)
  511. struct Screen *scrn;
  512. {
  513.    /*
  514.       I need to use a public screen so I can open the CON: window and Ed
  515.       (for ledit() on it.  This poses a problem, though.  What if someone
  516.       else opened a visitor window on the screen?  Then the screenclose
  517.       might fail.  So, we have to bug the user about it and try again
  518.       until we can close it successfully.
  519.  
  520.       Unfortunately, Intuition won't let me put up an EasyRequest()
  521.       without a window to tie it to.  So, I have to open a tiny dummy
  522.       window, then EasyRequest(), then close the window.  It's a
  523.       nuisance, but it works.
  524.    */
  525.    struct EasyStruct psx={
  526.       sizeof(struct EasyStruct),
  527.       0,
  528.       "Closing Screen",
  529.       "I need to close this screen, but there\n\
  530. are visitor windows open on it.  Please\n\
  531. close the windows, then TRY AGAIN.",
  532.       "Try Again"
  533.    };
  534.    struct Window *win;
  535.  
  536.    win = OpenWindowTags(NULL,    /* dummy window for EasyRequest() */
  537.       WA_Width, 1,
  538.       WA_Top, 1,
  539.       WA_CustomScreen, scrn,
  540.       WA_Backdrop, TRUE,
  541.       WA_Borderless, TRUE
  542.    );
  543.  
  544.    if (win) {
  545.       (void)EasyRequest(win,&psx,NULL,NULL);
  546.       CloseWindow(win);
  547.    }
  548. }
  549.  
  550.  
  551. void amiga_noscreen() {
  552.    if (console) {
  553.       Close(console);
  554.       console = NULL;
  555.    }
  556.    if (win) {
  557.       /*  UnClipWindow( win); */
  558.       CloseWindow(win);
  559.       win = NULL;
  560.    }
  561.    while (scrn) {
  562.       if (CloseScreen(scrn))
  563.          scrn = NULL;
  564.       else
  565.          announce_closescreen(scrn);
  566.    }
  567.    layout = NOSCREEN;
  568. }
  569.  
  570. void amiga_splitscreen()
  571. {
  572.    /*
  573.       I want to close the existing console so I can
  574.       reconfigure it as needed.
  575.    */
  576.    if (console) {
  577.       Close(console);
  578.       console = NULL;
  579.    }
  580.  
  581.    /* make sure screen and window are open */
  582.    if (scrn==NULL)
  583.       amiga_open_graphics_screen();
  584.  
  585.    if (win==NULL)
  586.       amiga_open_graphics_window();
  587.  
  588.    {   /* open the text console window */
  589.       char foo[256];
  590.  
  591.       sprintf(foo,
  592. "CON:0/%d/%d/%d/Berkeley Amiga Logo/ALT0/%d/%d/%d/SIMPLE/NOCLOSE/SCREEN %s",
  593.             scrn->Height*3/4, scrn->Width, scrn->Height/4,
  594.             scrn->BarHeight+1, scrn->Width, scrn->Height-scrn->BarHeight-1,
  595.             screenname);
  596.  
  597.       console = Open(foo,MODE_NEWFILE);
  598.       SetMode(console,1);  /* turn buffering off */
  599.    }
  600.    layout = SPLITSCREEN;
  601. }
  602.  
  603. void amiga_fullscreen()
  604. {
  605.    if (console) {
  606.       Close(console);
  607.       console = NULL;
  608.    }
  609.  
  610.    if (scrn==NULL)
  611.       amiga_open_graphics_screen();
  612.  
  613.    if (win==NULL)
  614.       amiga_open_graphics_window();
  615.  
  616.    {   /* open the text console window */
  617.       char foo[256];
  618.  
  619.       sprintf(foo,
  620. "CON:0/%d/%d/%d/Berkeley Amiga Logo/ALT0/%d/%d/%d/AUTO/SIMPLE/NOCLOSE/SCREEN %s",
  621.             scrn->Height*3/4, scrn->Width, scrn->Height/4,
  622.             scrn->BarHeight+1, scrn->Width, scrn->Height-scrn->BarHeight-1,
  623.             screenname);
  624.  
  625.       console = Open(foo,MODE_NEWFILE);
  626.       SetMode(console,1);  /* turn buffering off */
  627.    }
  628.    layout = FULLSCREEN;
  629. }
  630.  
  631.  
  632. void amiga_textscreen()
  633. {
  634.    if (console) {
  635.       Close(console);
  636.       console = NULL;
  637.    }
  638.  
  639.    if (scrn==NULL)
  640.       amiga_open_graphics_screen();
  641.  
  642.    if (win==NULL)
  643.       amiga_open_graphics_window();
  644.  
  645.    {   /* open the text console window */
  646.       char foo[256];
  647.  
  648.       sprintf(foo,
  649. "CON:0/%d/%d/%d/Berkeley Amiga Logo/ALT0/%d/%d/%d/SIMPLE/NOCLOSE/SCREEN %s",
  650.             scrn->BarHeight+1, scrn->Width, scrn->Height-scrn->BarHeight-1,
  651.             scrn->Height*3/4, scrn->Width, scrn->Height/4,
  652.             screenname);
  653.  
  654.       console = Open(foo,MODE_NEWFILE);
  655.       SetMode(console,1);  /* turn buffering off */
  656.    }
  657.    layout = TEXTSCREEN;
  658. }
  659.  
  660.  
  661. void amiga_layout(al)
  662. enum Layout al;
  663. {
  664.    switch (al) {
  665.       case SPLITSCREEN:
  666.          amiga_splitscreen();
  667.          break;
  668.       case FULLSCREEN:
  669.          amiga_fullscreen();
  670.          break;
  671.       case TEXTSCREEN:
  672.          amiga_textscreen();
  673.          break;
  674.       case NOSCREEN:
  675.          amiga_noscreen();
  676.    }
  677. }
  678.  
  679. int check_amiga_stop()
  680. {
  681.    ULONG signal = CheckSignal(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D);
  682.  
  683.    if (signal&SIGBREAKF_CTRL_C) {
  684.       logo_stop();
  685.       return 1;
  686.    }
  687.    if (signal&SIGBREAKF_CTRL_D) {
  688.       logo_pause();
  689.       return 2;
  690.    }
  691.    return 0;
  692. }
  693.  
  694. void amiga_wait(time)
  695. unsigned int time;
  696. {
  697.    ULONG chunk, ticks=time*50/60;   /* convert to 50ths of a second */
  698.  
  699.    while (ticks) {
  700.       chunk = ticks;
  701.       if (chunk>25)
  702.          chunk = 25;
  703.       Delay(chunk);
  704.       ticks -= chunk;
  705.       if (check_amiga_stop()==1)
  706.          break;
  707.    }
  708. }
  709.  
  710. void amiga_init(int argc, char *argv[])
  711. {
  712.    /* Logo requires Intuition version 39 or greater (Amiga OS 3.0+) */
  713.    IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",39);
  714.    if (IntuitionBase!=NULL) {
  715.       layout = NOSCREEN;
  716.       amiga_textscreen();
  717.       cs_helper(FALSE);
  718.    }
  719. }
  720.  
  721. void amiga_deinit(void)
  722. {
  723.    if (console) {
  724.       Close(console);
  725.       console = NULL;
  726.    }
  727.    if (win) {
  728.       /* UnClipWindow( win); */
  729.       CloseWindow(win);
  730.       win = NULL;
  731.    }
  732.    while (scrn) {
  733.       if (CloseScreen(scrn))
  734.          scrn = NULL;
  735.       else
  736.          announce_closescreen(scrn);
  737.    }
  738.    layout = NOSCREEN;
  739.    CloseLibrary((struct Library *)IntuitionBase);
  740. }
  741.  
  742. /* Normally this routine would contain an event loop like the one given
  743. ** in the chapter "Intuition Input and Output Methods".  Here we just
  744. ** wait for any messages we requested to appear at the Window's port.
  745. */
  746. VOID handle_window_events(struct Window *win)
  747. {
  748.     WaitPort(win->UserPort);
  749. }
  750.  
  751. /* Text IO functions */
  752. #define CSI 0x9B
  753. extern char so_arr[];
  754. extern char se_arr[];
  755.  
  756. /* Initialization */
  757. void ami_term_init(void)
  758. {
  759.     /* code for green text on black background */
  760.     so_arr[0] = (char)CSI;
  761.     strcpy( &(so_arr[1]), "0;35;41m");
  762.  
  763.     /* return console to normal */
  764.     se_arr[0] = (char)CSI;
  765.     strcpy( &(se_arr[1]), "0;39;39m");
  766. }
  767.  
  768.  
  769. void get_con_position()
  770. {
  771.    int index, len;
  772.    char inbuf[41];
  773.  
  774.    if (console) {
  775.       Flush(console);
  776.       SetMode(console,1);  /* turn buffering off */
  777.       Write(console,"\x9b\x36\x6e",3L);   /* requesting status */
  778.       len = (int)Read(console,inbuf,40L);
  779.       inbuf[len]='\0';  /* just making sure it's terminated */
  780.       for (index=0; index<40; index++)
  781.          if (inbuf[index]=='\x9b') {
  782.             sscanf(inbuf+index,"\x9b%d;%dR",&y_coord,&x_coord);
  783.             break;
  784.          }
  785.    }
  786. }
  787.  
  788.  
  789. /* Clear the window */
  790. void ami_clear_text(void)
  791. {
  792.     char control[20];
  793.  
  794.     control[0] = 0x0C;
  795.     control[1] = 0;
  796.     if (console) {
  797.         FPuts(console,control);
  798.         Flush(console);
  799.     } else
  800.         puts(control);
  801. }
  802.  
  803. /* Position in window */
  804. void ami_gotoxy( int x, int y)
  805. {
  806.    char bf[40];
  807.    sprintf(bf,"%c%d;%dH", CSI, y, x);
  808.    if (console) {
  809.       FPuts(console,bf);
  810.       Flush(console);
  811.    } else
  812.       printf(bf);
  813. }
  814.  
  815. void ami_print(foo)
  816. char *foo;
  817. {
  818.     /*
  819.         Print to AmigaDOS console if it's available, otherwise stdout.
  820.     */
  821.     if (console)
  822.         FPuts(console,foo);
  823.     else
  824.         printf(foo);
  825. }
  826.  
  827.  
  828. /************************************************************/
  829.  
  830. /* NOTE NOTE NOTE:  graphics.c really really believes that the top left
  831.  * corner of the screen has hardware coords (0,0).
  832.  */
  833.  
  834. /************************************************************/
  835. /* These are the machine-specific graphics definitions.  All versions must
  836.    provide a set of functions analogous to these. */
  837. void erase_screen( void)
  838. {
  839.     SetRast( win->RPort, win->RPort->BgPen);
  840. }
  841.  
  842. void save_pen(p)
  843. pen_info *p;
  844. {
  845.     p->x =       win->RPort->cp_x;
  846.     p->y =       win->RPort->cp_y;
  847.     p->vis =     pen_vis;
  848.     p->fcolor =  GetAPen(win->RPort);
  849.     p->bcolor =  GetBPen(win->RPort);
  850.     p->pattern = win->RPort->LinePtrn;
  851.     p->mode =    GetDrMd(win->RPort);
  852. }
  853.  
  854. void restore_pen(p)
  855. pen_info *p;
  856. {
  857.    SetABPenDrMd(win->RPort,p->fcolor,p->bcolor,p->mode);
  858.    Move(win->RPort,p->x,p->y);
  859.    set_pen_vis(p->vis);
  860.    SetDrPt(win->RPort, p->pattern);
  861. }
  862.  
  863. NODE *Get_node_pen_pattern()
  864. {
  865.     return(cons(make_intnode(-1)), NIL);
  866. }
  867.  
  868. NODE *Get_node_pen_mode()
  869. {
  870.    if ( 0/* in_erase_mode */)
  871.       return(make_static_strnode("erase"));
  872.    if ( 0 /* current_write_mode == FG_MODE_XOR */ )
  873.       return(make_static_strnode("reverse"));
  874.    return(make_static_strnode("paint"));
  875. }
  876.  
  877. void logofill()
  878. {
  879.     ; /* fg_fill(ztc_x, MaxY-ztc_y, turtle_color, turtle_color); */
  880. }
  881.  
  882. /* end of listing */
  883.