home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 20 / AACD20.BIN / AACD / Programming / AmiSlate-Source / AmiSource-c / amislate.c next >
Encoding:
C/C++ Source or Header  |  1995-08-05  |  57.7 KB  |  2,082 lines

  1. #include <stdio.h>
  2. #include <stdlib.h> 
  3. #include <dos/dosextens.h>
  4.  
  5. #include <devices/timer.h>
  6. #include <intuition/intuition.h>
  7. #include <intuition/intuitionbase.h>
  8. #include <intuition/screens.h>
  9. #include <exec/ports.h>
  10. #include <exec/memory.h>
  11. #include <exec/types.h>
  12. #include <exec/io.h>
  13. #include <exec/libraries.h>
  14. #include <libraries/dos.h>            /* contains RETURN_OK, RETURN_WARN #def's */
  15. #include <clib/alib_protos.h>
  16. #include <clib/dos_protos.h>
  17. #include <clib/exec_protos.h>
  18. #include <clib/intuition_protos.h>
  19. #include <clib/graphics_protos.h>
  20. #include <clib/gadtools_protos.h>
  21. #include <clib/wb_protos.h>
  22. #include <clib/icon_protos.h>
  23. #include <clib/diskfont_protos.h>
  24. #include <clib/iffparse_protos.h>
  25.  
  26. #include <string.h>
  27. #include <graphics/gfxbase.h>
  28. #include <errno.h>
  29. #include <libraries/gadtools.h>
  30. #include <inetd.h>
  31. #include <sys/types.h>
  32. #include <workbench/workbench.h>
  33. #include <workbench/startup.h>
  34.  
  35. #include "DrawLang.h"
  36. #include "AmiSlate.h"
  37. #include "ToolBox.h"
  38. #include "drawtcp.h"
  39. #include "tools.h"
  40. #include "palette.h"
  41. #include "display.h"
  42. #include "remote.h"
  43. #include "drawrexx.h"
  44. #include "drawrexx_aux.h"
  45. #include "asl.h"
  46. #include "ilbm.h"
  47.  
  48. #define INTUI_V36_NAMES_ONLY
  49. #define INTUITION_AREA_SIZE    2000
  50. #define MIN_WIDTH_OFFSET    26    /* AmiSlate window must be at least ToolBarWidth + this */
  51. #define MIN_HEIGHT_OFFSET    10    /* AmiSlate window must be at least nTitleHeight + nGetToolBoxHeight + this */
  52. #define MAXIDCMPBATCH        3    /* How many IDCMP messages we do in a row before attending elsewhere */
  53. #define FIRSTREXXITEM        26    /* Position of first custom ARexx item in menus */
  54.  
  55. #define CHAR_ESCAPE        27    /* ASCII code for the escape key */
  56. #define RAWKEYCODE_BASEOFFSET   300    /* Raw keys start here */
  57.  
  58.  
  59. struct Library *IntuitionBase = NULL;
  60. struct Library *SocketBase    = NULL;
  61. struct Library *IconBase      = NULL;
  62. struct GfxBase *GraphicsBase  = NULL;
  63. struct Library *GadToolsBase  = NULL;
  64. struct Library *AslBase       = NULL;
  65. struct Library *TimerBase     = NULL;
  66. struct Library *IFFParseBase  = NULL;
  67.  
  68. struct Window *DrawWindow     = NULL;
  69. struct Screen *Scr           = NULL;
  70. struct RexxHost *rexxHost     = NULL;
  71.  
  72. struct PaintInfo PState;
  73. struct TextAttr topaz8 = {"topaz.font",8,NULL,FPF_ROMFONT};
  74. struct TextFont *ChatFont = NULL;
  75.  
  76. struct TmpRas TempRaster;
  77.  
  78. struct Menu     *Menu     = NULL;
  79. struct MenuItem *MenuItem = NULL;
  80.  
  81. void *vi = NULL;
  82.  
  83. PLANEPTR TempRasterBitPlane = NULL;
  84.  
  85. char szWinTitle[120];
  86. char szRexxOutputFile[200] = "";
  87.  
  88. #define REXXNAMELENGTH 15
  89. char szRexxNames[10][REXXNAMELENGTH];    /* ten names in menu, each has max 14 chars */
  90. #define REXXSCRIPTLENGTH 150
  91. char szRexxScripts[10][REXXSCRIPTLENGTH];    /* ten filepaths in menu, each has max 149 chars */
  92.  
  93. /* Gadtools menu stuff */
  94. #define P_OPEN        102
  95. #define P_SAVE        103
  96. #define P_ABOUT     104
  97. #define P_QUIT      105
  98. #define T_CONNECT     106
  99. #define T_DISCONNECT    107
  100. #define S_PLAYBACK      108
  101. #define S_RECORD        109
  102. #define S_APPEND     110
  103. #define M_LOADPALETTES  111
  104. #define M_EXPANDWINDOW  112
  105. #define M_PROTECTINTER  113
  106. #define M_SAFEFLOOD     114
  107. #define M_LOCKPALETTES  115
  108. #define M_RESYNCH    116
  109. #define M_RESETPALETTE  117
  110. #define R_EXECREXX      118
  111. #define R_ABORTREXX     119
  112. #define R_AREXX        120
  113.  
  114. /* R_AREXX goes from 120 to 129 */
  115.  
  116. const char szDefaultRexxName[] = "Unused Slot";
  117.  
  118. struct NewMenu nmMenus[] = {
  119.     NM_TITLE, "Project",      NULL,     0L,             NULL, NULL,
  120.     NM_ITEM,  "Open IFF",     "O",    0L,         NULL, (void *) P_OPEN,
  121.     NM_ITEM,  "Save IFF",     "S",    0L,         NULL, (void *) P_SAVE,
  122.     NM_ITEM,  "About",           "?",   0L,             NULL, (void *) P_ABOUT,
  123.     NM_ITEM,  NM_BARLABEL,      NULL,     0L,             NULL, NULL,
  124.     NM_ITEM,  "Quit",            "Q",      0L,             NULL, (void *) P_QUIT,
  125.     NM_TITLE, "TCP",          NULL,  0L,             NULL, NULL,
  126.     NM_ITEM,  "Connect",     "C",      0L,             NULL, (void *) T_CONNECT,
  127.     NM_ITEM,  "Disconnect",      "D",      0L,             NULL, (void *) T_DISCONNECT,
  128.     NM_TITLE, "Script",          NULL,  0L,             NULL, NULL,
  129.     NM_ITEM,  "Play Script",     "P",   0L,             NULL, (void *) S_PLAYBACK,
  130.     NM_ITEM,  "Record Script",   "B",   CHECKIT,        NULL, (void *) S_RECORD,
  131.     NM_ITEM,  "Append Scripts",  "]",   CHECKIT,        NULL, (void *) S_APPEND,
  132.     NM_TITLE, "Options",         NULL,  0L,             NULL, NULL,
  133.     NM_ITEM,  "IFF Load",     NULL,  0L,         NULL, NULL,
  134.     NM_SUB,   "Load Palette",     "T",   CHECKIT,     NULL, (void *) M_LOADPALETTES,
  135.     NM_SUB,   "Expand Window",     "W",   CHECKIT,     NULL, (void *) M_EXPANDWINDOW, 
  136.     NM_SUB,   "Protect GUI Pens","G",   CHECKIT,     NULL, (void *) M_PROTECTINTER,
  137.     NM_ITEM,  "Safe Flood Fills","F",   CHECKIT,        NULL, (void *) M_SAFEFLOOD, 
  138.     NM_ITEM,  "Lock Palettes",   "L",   CHECKIT,        NULL, (void *) M_LOCKPALETTES,
  139.     NM_ITEM,  "Resynch to Remote","R",  0L,         NULL, (void *) M_RESYNCH,
  140.     NM_ITEM,  "Reset Palette",   ".",   0L,         NULL, (void *) M_RESETPALETTE,
  141.     NM_TITLE, "Rexx",            NULL,  0L,             NULL, NULL,
  142.     NM_ITEM,  "Execute Rexx script","E",0L,             NULL, (void *) R_EXECREXX,
  143.     NM_ITEM,  "Abort Rexx scripts", "A",0L,             NULL, (void *) R_ABORTREXX,
  144.     NM_ITEM,  NM_BARLABEL,     NULL,  0L,            NULL, NULL,
  145.     NM_ITEM,  szDefaultRexxName, "1",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+0),
  146.     NM_ITEM,  szDefaultRexxName, "2",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+1),
  147.     NM_ITEM,  szDefaultRexxName, "3",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+2),
  148.     NM_ITEM,  szDefaultRexxName, "4",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+3),
  149.     NM_ITEM,  szDefaultRexxName, "5",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+4),
  150.     NM_ITEM,  szDefaultRexxName, "6",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+5),
  151.     NM_ITEM,  szDefaultRexxName, "7",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+6),
  152.     NM_ITEM,  szDefaultRexxName, "8",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+7),
  153.     NM_ITEM,  szDefaultRexxName, "9",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+8),
  154.     NM_ITEM,  szDefaultRexxName, "0",   NM_ITEMDISABLED, NULL, (void *) (R_AREXX+9),
  155.     NM_END,   NULL,          NULL,     NULL,             NULL, NULL
  156. };
  157.  
  158. char szVersionString[] = "$VER:AmiSlate v1.3";
  159. char szCompileDate[]   = __DATE__;
  160. char *sWindowTitle = szVersionString + 5;
  161. char *sScreenTitle = szVersionString + 5;
  162. char szSendString[256];
  163. char szReceiveString[256];
  164. char szUserString[256];
  165. char szTempString[256];
  166. ULONG lCacheChar = 0;
  167.  
  168. char * szProgramName = NULL;    /* used to access icon when run from cli w/o args */
  169.  
  170. int Not[2] = {TRUE, FALSE};             /* a NOT lookup array */
  171. int XPos, YPos;
  172. BOOL BMore = TRUE;
  173. BOOL BAGA = TRUE;        /* AGA chipset present? */
  174. BOOL BNetConnect = FALSE;
  175. BOOL BAcceptingTCP = FALSE;
  176. BOOL BPalettesLocked = FALSE;
  177. BOOL BProgramDone = FALSE;
  178. BOOL BStartedFromWB = FALSE;
  179. BOOL BDos20 = TRUE;
  180. BOOL BProtectInter = TRUE;    /* never overwrite colors 0-3 */
  181.  
  182. int nWinOldWidth  = -1;        /* Used for correct window erasing */ 
  183. int nWinOldHeight = -1;
  184.  
  185. ULONG timerSignal = 0L;
  186. ULONG ulIDCMPmask;
  187. ULONG lOutputQueueSize = 2047L;    /* Default size */
  188.  
  189. __chip WORD AreaBuffer[INTUITION_AREA_SIZE];
  190. struct AreaInfo AreaInfo = { 0 };
  191. struct DiskObject *AmiSlateIconDiskObject = NULL;
  192.  
  193. struct timerequest *TimerIO = NULL;    /* For ARexx timeouts */
  194. struct MsgPort     *TimerMP = NULL;
  195. struct Message     *TimerMSG= NULL;
  196.  
  197. /* network defaults */
  198. char targethost[80];
  199. char *sDefaultTitle = szVersionString+5;
  200. char *pcWhatToAbort = "whatever";
  201. char sBuf[140];
  202. char **argv;
  203.  
  204. extern LONG lQLength;    /* defined in drawtcp.c */
  205. extern BOOL BIFFLoadPending;    /* defined in ilbm.c */
  206.  
  207. /* -- GLOBAL VARIABLES TO BE (RE)SET BY USER via RUNTIME ARGUMENTS */
  208. BOOL BUseCustomScreen = TRUE, BSafeFloods = TRUE;
  209. BOOL BIgnoreResizeEvent = FALSE, BAppendScripts = FALSE;
  210. BOOL BLoadIFFPalettes = TRUE, BExpandIFFWindow = TRUE, BRexxPenDown = FALSE;
  211. int nUserReqHeight = -1, nUserReqWidth = -1, screentype = USE_CUSTOMSCREEN;
  212. int nUserReqLeft = -1, nUserReqTop = -1;
  213. int nTitleHeight = 11;    /* guess a default */
  214. int argc;
  215. char szPubScreenName[50] = "Workbench";
  216. FILE *fpIn = NULL, *fpOut = NULL;
  217.  
  218. __chip UWORD waitPointer[] =
  219.     {
  220.     0x0000, 0x0000,
  221.     0x0400, 0x07c0,
  222.     0x0000, 0x07c0,
  223.     0x0100, 0x0380,
  224.     0x0000, 0x07e0,
  225.     0x07c0, 0x1ff8,
  226.     0x1ff0, 0x3fec,
  227.     0x3ff8, 0x7fde,
  228.     0x3ff8, 0x7fbe,
  229.     0x7ffc, 0xff7f,
  230.     0x7efc, 0xffff,
  231.     0x7ffc, 0xffff,
  232.     0x3ff8, 0x7ffe,
  233.     0x3ff8, 0x7ffe,
  234.     0x1ff0, 0x3ffc,
  235.     0x07c0, 0x1ff8,
  236.     0x0000, 0x07e0,
  237.     0x0000, 0x0000};
  238.     
  239.  
  240. __chip unsigned short crossPointer[] = 
  241.     {
  242.     0x0000, 0x0000,
  243.     0x0000, 0x0100,
  244.     0x0000, 0x0100,
  245.     0x0000, 0x0100,
  246.     0x0000, 0x0100,
  247.     0x0000, 0x0100,
  248.     0x0000, 0x0000,
  249.     0x0100, 0xFC7E,
  250.     0x0000, 0x0000,
  251.     0x0000, 0x0100,
  252.     0x0000, 0x0100,
  253.     0x0000, 0x0100,
  254.     0x0000, 0x0100,
  255.     0x0000, 0x0100,
  256.     0x0000, 0x0000,
  257.     0x0000, 0x0000,
  258.     0x0000, 0x0000,
  259.     0x0000, 0x0000,
  260.     0x0000, 0x0000,
  261.     0x0000, 0x0000
  262. };
  263.  
  264.  
  265. LONG Max(LONG lA, LONG lB)
  266. {
  267.     if (lA > lB) return(lA);
  268.     return(lB);
  269. }
  270.  
  271. LONG Min(LONG lA, LONG lB)
  272. {
  273.     if (lA < lB) return(lA);
  274.     return(lB);
  275. }
  276.  
  277.  
  278. void SetStandardRexxReturns(void)
  279. {
  280.     static ULONG lMouseButton, lMouseX, lMouseY, lLastChar;
  281.     int nupX=XPos, nupY=YPos;
  282.  
  283.     UnFixCoords(&nupX, &nupY);
  284.         
  285.     lMouseButton = BRexxPenDown;
  286.     lMouseX = nupX;
  287.     lMouseY = nupY;
  288.     lLastChar = lCacheChar;
  289.     lCacheChar = 0;        /* ensure that we don't send the same char twice */
  290.     
  291.     ((struct rxd_waitevent *) *(&RexxState.array))->res.mousex  = &lMouseX;
  292.     ((struct rxd_waitevent *) *(&RexxState.array))->res.mousey  = &lMouseY;
  293.     ((struct rxd_waitevent *) *(&RexxState.array))->res.button  = &lMouseButton;
  294.     ((struct rxd_waitevent *) *(&RexxState.array))->res.lastkey = &lLastChar;
  295.     ReplyAndFreeRexxMsg(TRUE);
  296.     PState.uwRexxWaitMask = 0;
  297. }
  298.  
  299.  
  300. void ExecuteRexxScript(char *szPreparedFileName)
  301. {
  302.     char szFileName[450];
  303.     char szTemp[470];
  304.     char szRedirectOrNo[] = ">\0\0";
  305.     
  306.     if (szPreparedFileName != NULL) strncpy(szFileName,szPreparedFileName,sizeof(szFileName));
  307.     if ((szPreparedFileName != NULL)||(FileRequest("Select an ARexx macro to execute", szFileName, "Execute", "SlateRexx:", NULL, FALSE) == TRUE))
  308.     {
  309.         sprintf(szWinTitle,"Now Executing ");
  310.         strncat(szWinTitle,szFileName,sizeof(szWinTitle));
  311.         SetWindowTitle(szWinTitle);
  312.  
  313.         /* If there is no output file, don't put a redirect symbol */
  314.         if (strlen(szRexxOutputFile) == 0) *szRedirectOrNo = '\0';
  315.         
  316.         sprintf(szTemp,"run >NIL: <NIL: rx %s%s %s %s LOCAL", szRedirectOrNo, 
  317.                 UniqueName(szRexxOutputFile), szFileName, 
  318.                     rexxHost->portname);
  319.         system(szTemp);
  320.     }
  321.     return;
  322. }
  323.  
  324. void LoadUserIFF(char *szPreparedFileName)
  325. {
  326.     char szFileName[450];
  327.     
  328.     if (szPreparedFileName != NULL) strncpy(szFileName,szPreparedFileName,sizeof(szFileName));
  329.     if ((szPreparedFileName != NULL)||(FileRequest("Select an IFF ILBM to display", szFileName, "Load", NULL, NULL, FALSE) == TRUE))
  330.     {
  331.         LoadUserIFFNamed(FROM_IDCMP,szFileName);
  332.     }
  333.     return;
  334. }
  335.  
  336. /* used by both LoadUserIFF and by ARexx LOADIFF */
  337. BOOL LoadUserIFFNamed(int nFromCode, char * szFileName)
  338. {
  339.         BOOL BTemp;
  340.  
  341.         sprintf(szWinTitle,"Now Displaying ");
  342.         strncat(szWinTitle,szFileName,sizeof(szWinTitle));
  343.         SetWindowTitle(szWinTitle);
  344.  
  345.         SetPointer(DrawWindow, waitPointer, 16, 16, -6, 0);
  346.  
  347.         BTemp = LoadIFF1(nFromCode, szFileName);
  348.         
  349.              /* The operation is only done if BIFFLoadPending is FALSE, otherwise we need to resize */
  350.             if (BIFFLoadPending == FALSE)
  351.         {
  352.             if (BTemp == TRUE)
  353.                 SetWindowTitle("IFF loaded.");
  354.                 else
  355.                 SetWindowTitle("IFF load failed.");
  356.  
  357.         ClearPointer(DrawWindow);
  358.         return(BTemp);
  359.         }
  360.         else SetWindowTitle("Resizing remote screen...");        
  361.         return(TRUE);
  362. }
  363.  
  364.  
  365. void SaveUserIFF(char *szPreparedFileName)
  366. {
  367.     char szFileName[450];
  368.     
  369.  
  370.     if (szPreparedFileName != NULL) strncpy(szFileName,szPreparedFileName,sizeof(szFileName));
  371.     if ((szPreparedFileName != NULL)||(FileRequest("Choose a filename for this picture", szFileName, "Save", NULL, NULL, TRUE) == TRUE))
  372.     {
  373.         SaveUserIFFNamed(szFileName);
  374.     }
  375.  
  376.  
  377.     return;
  378. }
  379.  
  380.  
  381. BOOL SaveUserIFFNamed(char *szFileName)
  382. {
  383.     BOOL BReturn;
  384.     
  385.     SetPointer(DrawWindow, waitPointer, 16, 16, -6, 0);
  386.  
  387.     sprintf(szWinTitle,"Now Saving ");
  388.     strncat(szWinTitle,szFileName,sizeof(szWinTitle));
  389.     SetWindowTitle(szWinTitle);
  390.  
  391.     BReturn = SaveIFF(szFileName);
  392.     
  393.     if (BReturn == TRUE)
  394.         SetWindowTitle("IFF saved.");
  395.     else
  396.         SetWindowTitle("IFF save failed.");
  397.  
  398.     ClearPointer(DrawWindow);
  399.     return(BReturn);
  400. }
  401.  
  402.  
  403. void BreakRexxScripts(void)
  404. {
  405.     static LONG lAbortType = REXX_REPLY_QUIT;
  406.     
  407.     if (rexxHost == NULL) return;
  408.     
  409.     if (DrawWindow != NULL) SetPointer(DrawWindow, waitPointer, 16, 16, -6, 0);
  410.     SetWindowTitle("Closing ARexx port");
  411.     ulIDCMPmask &= ~(1L<<rexxHost->port->mp_SigBit);
  412.  
  413.     if (PState.uwRexxWaitMask != 0)
  414.     {    
  415.     ((struct rxd_waitevent *) *(&RexxState.array))->res.type  = &lAbortType;
  416.     SetStandardRexxReturns();
  417.     }
  418.         
  419.     CloseDownARexxHost(rexxHost);
  420.  
  421.     Delay(10);    /* Enough time for the next request to be sent & break, we hope */
  422.  
  423.     EnableDraw(TRUE);
  424.  
  425.     SetWindowTitle("Reopening ARexx port");
  426.     rexxHost = SetupARexxHost("AMISLATE",NULL);
  427.     if (rexxHost == NULL) 
  428.     {
  429.         MakeReq(NULL,"Warning: Couldn't reopen ARexx port!",NULL);
  430.         SetWindowTitle("ARexx port is disabled");
  431.     }
  432.     else 
  433.     {
  434.         SetWindowTitle("ARexx port cleared");
  435.         ulIDCMPmask |= (1L<<rexxHost->port->mp_SigBit); 
  436.     }
  437.     ClearPointer(DrawWindow);
  438.     SetMenuValues();
  439.     
  440.     return;
  441. }
  442.  
  443.  
  444.  
  445.  
  446. /* Updates menus */
  447. void SetMenuValues (void)
  448. {
  449.  struct Menu *currentMenu = Menu;
  450.  struct MenuItem *currentItem, *currentSub;
  451.  
  452.  if (currentMenu == NULL) return;
  453.     
  454.  if (DrawWindow != NULL) ClearMenuStrip(DrawWindow);
  455.  
  456.  currentItem = currentMenu->FirstItem;    /* Open IFF... */
  457.  if (IFFParseBase == NULL)
  458.      currentItem->Flags &= ~(ITEMENABLED);
  459.  else     currentItem->Flags |= ITEMENABLED;
  460.      
  461.  currentItem = currentItem->NextItem;    /* Save IFF... */
  462.  if (IFFParseBase == NULL)
  463.      currentItem->Flags &= ~(ITEMENABLED);
  464.  else     currentItem->Flags |= ITEMENABLED;
  465.  
  466.  currentMenu = currentMenu->NextMenu;     /* TCP Menu */
  467.  
  468.  if (SocketBase == NULL) 
  469.      currentMenu->Flags &= ~(MENUENABLED);
  470.  else 
  471.  {
  472.      currentMenu->Flags |= MENUENABLED;
  473.    currentItem = currentMenu->FirstItem;        /* #1 : Connect */
  474.  
  475.    if (BNetConnect == TRUE)
  476.    {
  477.        currentItem->Flags &= ~(ITEMENABLED);
  478.        currentItem = currentItem->NextItem;        /* #2 : Disconnect */
  479.        currentItem->Flags |= ITEMENABLED;
  480.    }
  481.    else
  482.    {
  483.        currentItem->Flags |= ITEMENABLED;
  484.        currentItem = currentItem->NextItem;        /* #2 : Disconnect */
  485.        currentItem->Flags &= ~(ITEMENABLED);
  486.    }
  487.  }
  488.  currentMenu = currentMenu->NextMenu;   /* Script Menu */
  489.  currentItem = currentMenu->FirstItem;    /* Play Script */
  490.  currentItem = currentItem->NextItem;   /* Record Script */
  491.  if (fpOut != NULL) currentItem->Flags |= CHECKED;
  492.             else currentItem->Flags &= ~(CHECKED);
  493.  currentItem = currentItem->NextItem;    /* Append Scripts */
  494.  if (BAppendScripts == TRUE) currentItem->Flags |= CHECKED;
  495.              else currentItem->Flags &= ~(CHECKED);
  496.  
  497.  currentMenu = currentMenu->NextMenu;        /* Options Menu */
  498.  currentItem = currentMenu->FirstItem;        /* IFF Load options */
  499.  currentSub  = currentItem->SubItem;        /* Load palette */
  500.  if (BLoadIFFPalettes == TRUE) currentSub->Flags |= CHECKED;
  501.                else currentSub->Flags &= ~(CHECKED);
  502.                
  503.  currentSub  = currentSub->NextItem;        /* Expand to fit */
  504.  if (BExpandIFFWindow == TRUE) currentSub->Flags |= CHECKED;
  505.                else currentSub->Flags &= ~(CHECKED);
  506.  
  507.  currentSub  = currentSub->NextItem;        /* Protect Interface pens*/
  508.  if (BProtectInter == TRUE) currentSub->Flags |= CHECKED;
  509.                 else currentSub->Flags &= ~(CHECKED);
  510.  
  511.  currentItem = currentItem->NextItem;        /* SafeFloods */
  512.  if (BNetConnect == TRUE) currentItem->Flags |= ITEMENABLED;
  513.               else currentItem->Flags &= ~(ITEMENABLED);                        
  514.  if (BSafeFloods == TRUE) currentItem->Flags |= CHECKED;
  515.              else currentItem->Flags &= ~(CHECKED);
  516.  
  517.  currentItem = currentItem->NextItem;        /* Lock Palettes */
  518.  if (BNetConnect == TRUE) currentItem->Flags |= ITEMENABLED;
  519.             else currentItem->Flags &= ~(ITEMENABLED);
  520.  if (BPalettesLocked == TRUE) currentItem->Flags |= CHECKED;
  521.               else currentItem->Flags &= ~(CHECKED);
  522.  
  523.  currentItem = currentItem->NextItem;        /* Resynch to Remote */
  524.  if (BNetConnect == TRUE) currentItem->Flags |= ITEMENABLED;
  525.               else currentItem->Flags &= ~(ITEMENABLED);                         
  526.  
  527.  
  528.  currentMenu = currentMenu->NextMenu;        /* Arexx Menu */
  529.     
  530.  if (rexxHost == NULL)    currentMenu->Flags &= ~(MENUENABLED);
  531.              else currentMenu->Flags |= MENUENABLED;
  532.  
  533. #ifdef PROBABLY_NOT_NEEDED
  534.  currentItem = currentMenu->FirstItem;    /* Execute ARexx Script */
  535.  currentItem = currentMenu->NextItem;   /* Break ARexx Scripts */
  536.  currentItem = currentMenu->NextItem;    /* First custom item */
  537. #endif
  538.  
  539.  if (DrawWindow != NULL) ResetMenuStrip(DrawWindow, Menu);                 
  540.  return;    
  541. }
  542.  
  543.  
  544. /* Custom set window title function--always shows queue size */
  545. void SetWindowTitle(char *sString)
  546. {
  547.     if (DrawWindow == NULL) return;
  548.             
  549.     if (sString != NULL)
  550.     {
  551.         /* Only do this if we're note already using szWinTitle, otherwise
  552.            we get this funky recursive effect ([Rec] [Rec] [Rec]) sometimes! */
  553.         if (sString != szWinTitle)
  554.         {
  555.             if (fpOut != NULL) sprintf(szWinTitle,"[Rec] %s", sString);
  556.                       else sprintf(szWinTitle, "%s", sString);
  557.         }        
  558.         SetWindowTitles(DrawWindow, szWinTitle, (char *) ~0);
  559.     }
  560.     else
  561.     {
  562.         Printf("SetWindowTitle: Null sString!\n");
  563.     }
  564.     return;
  565. }
  566.  
  567.  
  568. int MakeReq(char *sTitle, char *sText, char *sGadgets)
  569. {
  570.     struct EasyStruct myreq;
  571.     LONG number = 0L;
  572.     int nResult;
  573.  
  574.     if (sTitle == NULL) sTitle = "AmiSlate Message";
  575.     if (sText == NULL) sText = "Hey, something's up!";
  576.     if (sGadgets == NULL) sGadgets = "OK";
  577.  
  578.     myreq.es_TextFormat   = sText;
  579.     myreq.es_Title        = sTitle;
  580.     myreq.es_GadgetFormat = sGadgets;
  581.  
  582.     if (DrawWindow != NULL) SetPointer(DrawWindow, waitPointer, 16, 16, -6, 0);
  583.     nResult = EasyRequest(DrawWindow, &myreq, NULL, NULL, number);
  584.     if (DrawWindow != NULL) ClearPointer(DrawWindow);
  585.  
  586.     return(nResult);
  587. }
  588.  
  589.  
  590.  
  591. BOOL CreateDrawMenus(void)
  592. {   
  593.     Menu = CreateMenus(nmMenus, TAG_DONE);
  594.     if (Menu == NULL)
  595.     {
  596.         UserError("Couldn't Create Menus!");
  597.         return(FALSE);
  598.     }
  599.     
  600.     vi = GetVisualInfo(Scr, TAG_END);
  601.     if (vi == NULL)
  602.     {
  603.         UserError("Couldn't get visual info for menus!");
  604.         return(FALSE);
  605.     }
  606.     
  607.     if (LayoutMenus(Menu, vi, TAG_DONE))
  608.     {
  609.         SetMenuStrip(DrawWindow, Menu);
  610.     }
  611.     else
  612.     {
  613.         FreeVisualInfo(vi);
  614.         UserError("Couldn't LayoutMenus!");
  615.         return(FALSE);
  616.     }
  617.  
  618.     FreeVisualInfo(vi);
  619.     return(TRUE);
  620. }
  621.  
  622. int SaveScriptToDisk(void)
  623. {
  624.     char szFileName[500];
  625.     
  626.     if (fpOut != NULL)
  627.     {
  628.         fclose(fpOut);
  629.         fpOut = NULL;
  630.         SetWindowTitle("Recording complete.");
  631.         return(TRUE);
  632.     }
  633.     
  634.     if (FileRequest("Select a Script file to save to", szFileName, "Save", "SlateScripts:", NULL, TRUE) == TRUE)
  635.     {
  636.         if (BAppendScripts == FALSE) fpOut = fopen(szFileName,"wb");
  637.                     else fpOut = fopen(szFileName,"ab");    /* append mode */
  638.                     
  639.         if (fpOut == NULL) MakeReq(NULL,"Couldn't open script file for writing!",NULL);
  640.         /* Save basic state information to disk */
  641.         OutputAction(FROM_IDCMP, COMMAND, COMMAND_RGB, PState.uwFColor, PState.uwBColor, NOP_PAD, DEST_FILE);
  642.         
  643.         /* This will force a mode change back! */
  644.         OutputAction(FROM_IDCMP, MODE_CHANGE, MODE_FIRST,    NOP_PAD, NOP_PAD, NOP_PAD, DEST_FILE);
  645.         OutputAction(FROM_IDCMP, MODE_CHANGE, PState.uwMode, NOP_PAD, NOP_PAD, NOP_PAD, DEST_FILE);
  646.         SetWindowTitle("Now recording actions.");
  647.     }
  648.     return(TRUE);
  649. }
  650.  
  651.  
  652. int PlayScriptFromDisk(void)
  653. {
  654.     char szFileName[500];
  655.     UWORD uwSaveRemoteMode   = PState.uwRemoteMode;
  656.     UWORD uwSaveRemoteFColor = PState.uwRemoteFColor;
  657.     UWORD uwSaveRemoteBColor = PState.uwRemoteBColor;
  658.     if (FileRequest("Select a Script file to play", szFileName, "Play", "SlateScripts:", NULL, FALSE) == TRUE)
  659.     {
  660.         fpIn = fopen(szFileName,"rb");
  661.         if (fpIn == NULL) MakeReq(NULL,"Couldn't open script file!",NULL);
  662.         else
  663.         {
  664.             SetPointer(DrawWindow, waitPointer, 16, 16, -6, 0);
  665.       
  666.             /* playback script file */
  667.             SetWindowTitle("Playing Script file.");
  668.             while ((RemoteHandler(fpIn, TRUE) == TRUE)&&(CheckForUserAbort() == FALSE))
  669.             {
  670.                 /* re-assign this in case it was changed somehow */
  671.                 pcWhatToAbort = "Script Playback";
  672.             } 
  673.             
  674.             fclose(fpIn);
  675.             fpIn = NULL;
  676.             SetWindowTitle("Script file finished.");
  677.             
  678.             /* Restore remote state */
  679.             PState.uwRemoteMode   = uwSaveRemoteMode;
  680.             PState.uwRemoteFColor = uwSaveRemoteFColor;
  681.             PState.uwRemoteBColor = uwSaveRemoteBColor;
  682.             
  683.             /* Restore remote state on remote machine */
  684.             OutputAction(FROM_IDCMP, MODE_CHANGE, PState.uwMode, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER);
  685.             OutputAction(FROM_IDCMP, COMMAND, COMMAND_RGB, PState.uwFColor, PState.uwBColor, NOP_PAD, DEST_PEER);
  686.  
  687.             ClearPointer(DrawWindow);
  688.         }
  689.     }
  690.     return(TRUE);
  691. }
  692.  
  693. int ShowAbout(void)
  694. {
  695.     char szTempBuf[250];
  696.     sprintf(szTempBuf,"%s\nby Jeremy Friesner\njfriesne@ucsd.edu\n(Compiled %s)",szVersionString+5,szCompileDate);
  697.     MakeReq("About AmiSlate",szTempBuf,"Very Nice");
  698.     return;
  699. }
  700.     
  701. void Swap(int *i1, int *i2)
  702. {
  703.     int temp;
  704.     
  705.     temp = *i1;
  706.     *i1 = *i2;
  707.     *i2 = temp;
  708.     return;
  709. }
  710.  
  711.  
  712.  
  713. void SwapPointers(void *(*p1), void *(*p2))
  714. {
  715.     void *temp;
  716.     
  717.     temp = *p1;
  718.     *p1 = *p2;
  719.     *p2 = temp;
  720.     return;
  721. }
  722.  
  723.  
  724. void debug(int nID)
  725. {
  726.     Printf("Debug point: %i\n",nID);
  727.     Delay(100);
  728.     return;
  729. }
  730.  
  731.  
  732.  
  733.  
  734. void ClearWindow(void)
  735. {
  736.     int nToolBoxLeft = nGetToolBoxLeft();  
  737.        int nWindowBottom;
  738.  
  739.     nWindowBottom = DrawWindow->Height - DrawWindow->BorderBottom - 1;
  740.  
  741.       /* Erase Window */
  742.     SetAPen(DrawWindow->RPort,0);
  743.     Rectangle(DrawWindow->BorderLeft,DrawWindow->BorderTop
  744.                         ,nToolBoxLeft - 2, nWindowBottom-25, TRUE);    
  745.  
  746.     /* Clear chat lines */
  747.     EraseChatLines(DrawWindow->Width, DrawWindow->Height);
  748.     DrawChatLines();
  749.     
  750.     return;
  751. }
  752.  
  753. /* Given an entry in our palette, returns a word with right justified
  754.    R, G, B values for that entry */
  755. UWORD RGBComponents(UWORD uwPaletteEntry)
  756. {
  757.     ULONG ulThisColor;
  758.     
  759.     ulThisColor = GetRGB4(Scr->ViewPort.ColorMap, uwPaletteEntry);
  760.     
  761.     /* Flag if we don't want the background color used */
  762.     if (uwPaletteEntry != PState.uwBColor)
  763.         ulThisColor |= 0x00008000;
  764.         
  765.     return((UWORD) ulThisColor);
  766. }    
  767.                 
  768.  
  769.  
  770. /* This function takes red, green, blue values and gives the closest
  771.    palette color */
  772. /* returns -1 if no pen can be matched due to DeniedPen restrictions */
  773. /* If BJustAlloced is non-NULL, it will be set to TRUE if a new pen was
  774.    allocated during this call, otherwise FALSE */
  775. int MatchPalette(UBYTE ubRed, UBYTE ubGreen, UBYTE ubBlue, BOOL BDontUseBackGround, BOOL * DeniedPenMap, BOOL * BJustAlloced)
  776. {
  777.     int i,nBest=-1,nFallBackBest=-1;    /* default to error */
  778.     ULONG ulMinDist=15000,ulThisDist,ulFallBackMinDist=15000;
  779.     UWORD uwThisColor;
  780.     UBYTE ubThisRed, ubThisGreen, ubThisBlue;
  781.     BOOL BUseFallBack = TRUE;
  782.     
  783.     /* default */
  784.     if (BJustAlloced != NULL) *BJustAlloced = FALSE;
  785.     
  786.     for (i=0;i<(1<<Scr->RastPort.BitMap->Depth);i++)
  787.     {
  788.         uwThisColor = RGBComponents(i);
  789.         
  790.         /* Extract R, G, B from return value */
  791.         ubThisBlue  = (uwThisColor      & 0x000F); /* Right 4 bits */
  792.         ubThisGreen = ((uwThisColor>>4) & 0x000F); /* 2nd 4 bits from right */
  793.         ubThisRed   = ((uwThisColor>>8) & 0x000F); /* 3rd 4 bits from right */
  794.             
  795.         /* No need to sqrt since we only want order, not actual distance */
  796.         ulThisDist  = (ubRed   - ubThisRed  ) * (ubRed   - ubThisRed  ) +
  797.                       (ubGreen - ubThisGreen) * (ubGreen - ubThisGreen) +
  798.                   (ubBlue  - ubThisBlue ) * (ubBlue  - ubThisBlue );
  799.  
  800.         /* If we don't want to use the Background color, and this is it,
  801.            make it very unattractive! */
  802.         if ((BDontUseBackGround == TRUE)&&(i == PState.uwBColor)) ulThisDist = 4096;
  803.         
  804.         /* If we find an exact match, return right away */
  805.         if (ulThisDist == 0) 
  806.         {
  807.             if (BJustAlloced != NULL) *BJustAlloced = TRUE;
  808.             if ((DeniedPenMap != NULL)&&(DeniedPenMap[i] == FALSE)) DeniedPenMap[i] = TRUE;    /* Flag this pos as used */    
  809.             return(i);
  810.         }
  811.         
  812.         /* get this one--absolute best, saved or no saved. */
  813.         /* However, if DeniedPenMap[i] == 2, then don't get */
  814.         /* it no matter what. */
  815.         if ((ulThisDist < ulFallBackMinDist)&&((DeniedPenMap == NULL)||(DeniedPenMap[i] < 2)))
  816.         {
  817.             /* keep track of the absolute best, regardless of "saved" spots */
  818.             ulFallBackMinDist = ulThisDist;
  819.             nFallBackBest     = i;
  820.         }
  821.         
  822.         /* if this spot isn't saved, grab it as best of the non-saved spots */
  823.         if (((DeniedPenMap == NULL)||(DeniedPenMap[i]==FALSE)) &&
  824.             (ulThisDist < ulMinDist))
  825.         {
  826.             ulMinDist = ulThisDist;
  827.             nBest     = i;
  828.             BUseFallBack = FALSE;    /* Cause we got a free spot */
  829.         }
  830.     }
  831.     
  832.     /* No pen map?  No problem! */
  833.     if (DeniedPenMap == NULL) return(nBest);
  834.     
  835.     if (BUseFallBack == TRUE) return(nFallBackBest);    /* oops, had to double up */
  836.     else 
  837.     {
  838.         if (DeniedPenMap[nBest] == FALSE) DeniedPenMap[nBest] = TRUE;
  839.         if (BJustAlloced != NULL) *BJustAlloced = TRUE;
  840.         return(nBest);        /* a free spot is allocated */
  841.     }
  842. }
  843.  
  844.  
  845. /* Toggles Locked palettes, getting the remote palette as necessary */
  846. void ToggleLockPalettes(void)
  847. {
  848.     BPalettesLocked = Not[BPalettesLocked];    
  849.     if (BPalettesLocked == TRUE) 
  850.         OutputAction(FROM_IDCMP, COMMAND, COMMAND_SENDPALETTE, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER|DEST_FILE);    
  851.     
  852.     SetMenuValues();
  853. }
  854.  
  855.  
  856. BOOL HandleIDCMP(struct IntuiMessage * defaultMessage) 
  857. {
  858.     int nToolBoxLeft = nGetToolBoxLeft(); 
  859.     struct IntuiMessage *message = NULL;
  860.     ULONG class, code, qual, ulItemCode;
  861.     int nTestX, nTestY, nProc = 0;
  862.     struct MenuItem *mItem;
  863.     const static LONG lKeyType  = REXX_REPLY_KEYPRESS;
  864.     const static LONG lMoveType = REXX_REPLY_MOUSEMOVE;
  865.  
  866.     static LONG lCode;
  867.  
  868.     /* Get the first message from the queue, or use the one we already have */
  869.     if (defaultMessage == NULL) message = (struct IntuiMessage *) GetMsg(DrawWindow->UserPort);
  870.                    else message = defaultMessage;
  871.  
  872.     /* Examine pending messages */    
  873.     while (message != NULL)
  874.     {
  875.         nProc++;
  876.         class = message->Class;        /* extract needed info from message */
  877.         code  = message->Code;
  878.         qual  = message->Qualifier;
  879.  
  880.         XPos = message->MouseX;        /* set mouse tracking positions */
  881.         YPos = message->MouseY;
  882.  
  883.         /* tell Intuition we got the message */
  884.         ReplyMsg((struct Message *)message);
  885.  
  886.         /* see what events occured, take correct action */
  887.         switch(class)
  888.         {        
  889.             case IDCMP_CLOSEWINDOW: 
  890.                 BProgramDone = TRUE;  
  891.                 break;
  892.  
  893.             case IDCMP_MOUSEBUTTONS:
  894.               switch(code)
  895.                     {
  896.                       case SELECTUP:      BRexxPenDown = FALSE;
  897.                                 if ((PState.BPenDown == TRUE)||(PState.BDrawEnabled == FALSE))
  898.                                 {
  899.                                   MouseUpAction(PState.uwMode);   
  900.                                   crossPointer[14] = 0x0100;
  901.                                 }
  902.                                 break;
  903.  
  904.                       case SELECTDOWN:  BRexxPenDown = TRUE;
  905.                                 if (XPos < nToolBoxLeft)
  906.                                 {
  907.                                      crossPointer[14] = 0x0000;
  908.                                   MouseDownAction(PState.uwMode);
  909.                                 }
  910.                                 else HandleToolBox(-1);
  911.                                 break;
  912.  
  913.                       case MENUDOWN:      if (PState.BPenDown == TRUE)
  914.                                 {
  915.                                   BreakAction(PState.uwMode);
  916.                                   PState.BPenDown = FALSE;
  917.                                  }
  918.                                 break;
  919.  
  920.                       default:        /* Printf("IDCMP_MOUSEBUTTONS:  bad Code\n");  */
  921.                                 break;
  922.                     }                
  923.                  break;
  924.  
  925.                   case IDCMP_NEWSIZE:
  926.             if (BIgnoreResizeEvent == TRUE) BIgnoreResizeEvent = FALSE;
  927.                 else
  928.                       ReSizeWindow(DrawWindow->Width, DrawWindow->Height, TRUE);
  929.                   break;
  930.           
  931.             case IDCMP_MOUSEMOVE:
  932.                 /* Make sure we have the right pointer */
  933.                 nTestX = XPos;
  934.                 nTestY = YPos;
  935.                 if (FixPos(&nTestX, &nTestY) == TRUE)
  936.                 {
  937.                     SetPointer(DrawWindow, crossPointer, 16, 16, -8, -6);
  938.                     /* Trap RMB events--this instruction needs to be done atomically! */
  939.                     /* DrawWindow->Flags |= WFLG_RMBTRAP;  */
  940.                 }
  941.                 else
  942.                 {
  943.                     ClearPointer(DrawWindow);
  944.                     /* Don't trap RMB events */
  945.                     /* DrawWindow->Flags &= ~(WFLG_RMBTRAP);  */
  946.                 }
  947.                 if (PState.uwRexxWaitMask & REXX_REPLY_MOUSEMOVE)
  948.                 {
  949.                     ((struct rxd_waitevent *) *(&RexxState.array))->res.type  = &lMoveType;
  950.                     SetStandardRexxReturns();
  951.                 }
  952.  
  953.                 if (PState.BPenDown == TRUE) MouseMoveAction(PState.uwMode);
  954.             break;
  955.  
  956.             case IDCMP_RAWKEY:
  957.                 if ((code >= 96)&&(code <= 103)) break;    /* repress shift key events, etc.! */
  958.                 lCacheChar = code + RAWKEYCODE_BASEOFFSET;
  959.                 if (PState.uwRexxWaitMask & REXX_REPLY_KEYPRESS)
  960.                 {
  961.                     lCode = code + RAWKEYCODE_BASEOFFSET;
  962.                     ((struct rxd_waitevent *) *(&RexxState.array))->res.type  = &lKeyType;
  963.                     ((struct rxd_waitevent *) *(&RexxState.array))->res.code1 = &lCode;
  964.                     SetStandardRexxReturns();
  965.                 }
  966.                 break;                
  967.             
  968.             case IDCMP_VANILLAKEY: 
  969.                 if ((qual & IEQUALIFIER_NUMERICPAD)&&
  970.                     (code >= '1') && (code <= '9')) 
  971.                         AdjustColor((char) code, 
  972.                             1+2*((qual & IEQUALIFIER_LSHIFT)||
  973.                                  (qual & IEQUALIFIER_RSHIFT)), 
  974.                                 PState.uwFColor, NULL,TRUE);
  975.                     else
  976.                     {
  977.                         DisplayKeyPress((char) code, TRUE); 
  978.                         lCacheChar = code;
  979.                         if (PState.uwRexxWaitMask & REXX_REPLY_KEYPRESS)
  980.                         {
  981.                             lCode = code;
  982.                             ((struct rxd_waitevent *) *(&RexxState.array))->res.type  = &lKeyType;
  983.                             ((struct rxd_waitevent *) *(&RexxState.array))->res.code1 = &lCode;
  984.                             SetStandardRexxReturns();
  985.                         }
  986.                     }
  987.                     break;
  988.                 
  989.             case IDCMP_MENUPICK:
  990.                 while( code != MENUNULL ) 
  991.                 {
  992.                     mItem = ItemAddress( Menu, code );
  993.                     ulItemCode = (ULONG) GTMENUITEM_USERDATA(mItem);
  994.                     switch(ulItemCode)
  995.                     {
  996.                         case P_OPEN:        LoadUserIFF(NULL);      break;
  997.                         case P_SAVE:        SaveUserIFF(NULL);      break;
  998.                          case P_ABOUT:         ShowAbout();          break;
  999.                          case P_QUIT:          CleanExit(RETURN_OK); break;
  1000.                          case T_CONNECT:        if (ConnectDrawSocket(TRUE)) Synch(); break;
  1001.                          case T_DISCONNECT:  CloseDrawSocket();      break;
  1002.                          case S_PLAYBACK:    PlayScriptFromDisk(); break;
  1003.                          case S_RECORD:      SaveScriptToDisk();      break;
  1004.                          case S_APPEND:        BAppendScripts = Not[BAppendScripts]; SetMenuValues(); break;
  1005.                          case M_LOADPALETTES:BLoadIFFPalettes = Not[BLoadIFFPalettes]; SetMenuValues(); break;
  1006.                         case M_EXPANDWINDOW:BExpandIFFWindow = Not[BExpandIFFWindow]; SetMenuValues(); break;
  1007.                         case M_PROTECTINTER:BProtectInter    = Not[BProtectInter];
  1008.                                     if (BProtectInter == TRUE) SaveScreenPalette(FALSE, 3);    /* Restore GUI pens */
  1009.                                     SetMenuValues(); 
  1010.                                     break;
  1011.                          case M_SAFEFLOOD:   ToggleSafeFlood();      break;
  1012.                          case M_LOCKPALETTES:ToggleLockPalettes(); break;
  1013.                          case M_RESYNCH:        SetWindowTitle("Requesting Screen Transmission from Remote"); 
  1014.                                      OutputAction(FROM_IDCMP, COMMAND, COMMAND_SENDSCREEN, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER); 
  1015.                                      break;
  1016.                          case M_RESETPALETTE:SaveScreenPalette(FALSE, -1); break;
  1017.                          case R_EXECREXX:    ExecuteRexxScript(NULL);  break;
  1018.                          case R_ABORTREXX:   BreakRexxScripts();   break;
  1019.                          default:          
  1020.                              if ((ulItemCode >= R_AREXX)&&(ulItemCode < (R_AREXX+10)))
  1021.                              {
  1022.                                  if (szRexxScripts[ulItemCode-R_AREXX][0] != '\0')
  1023.                                      ExecuteRexxScript(szRexxScripts[ulItemCode-R_AREXX]);
  1024.                              }
  1025.                              else
  1026.                              MakeReq(NULL, "Bad Menu Item", NULL); 
  1027.                              break;
  1028.                     }
  1029.                     code = mItem->NextSelect;
  1030.                 }
  1031.                 break;
  1032.                        
  1033.             default:        /* Printf("handleIDCMP: bad class\n");   */
  1034.                     break;
  1035.         }
  1036.     
  1037.         /* Only do the one message if it's a custom message */
  1038.         if (defaultMessage != NULL) return(BProgramDone);
  1039.  
  1040.         /* Get next message from the queue */
  1041.         if (nProc >= MAXIDCMPBATCH) return(BProgramDone);
  1042.                                 else message = (struct IntuiMessage *)GetMsg(DrawWindow->UserPort);
  1043.     }
  1044.     return(BProgramDone);
  1045. }
  1046.  
  1047.  
  1048.  
  1049.  
  1050. /* Changes colors according to keystrokes on the numeric keypad a la
  1051.    DeluxePaint! 
  1052.    
  1053.    If * uwPresetColor is non-NULL, use the value located there
  1054.    to set the color instead of the key pressed.  
  1055.    
  1056.    If BTransmit if FALSE, don't send the adjust back to the peer */
  1057. void AdjustColor(char cKeyPressed, int nStep, int nPaletteEntry, UWORD * uwPresetColor, BOOL BTransmit)
  1058. {
  1059.     UWORD uwThisColor = RGBComponents(nPaletteEntry);
  1060.     UBYTE ubThisBlue, ubThisGreen, ubThisRed, *pubTemp;
  1061.     int nInc;
  1062.     
  1063.     if (uwPresetColor == NULL)
  1064.     {
  1065.         /* Extract R, G, B from current foreground color */
  1066.         ubThisBlue  = (uwThisColor      & 0x000F); /* Right 4 bits */
  1067.         ubThisGreen = ((uwThisColor>>4) & 0x000F); /* 2nd 4 bits from right */
  1068.         ubThisRed   = ((uwThisColor>>8) & 0x000F); /* 3rd 4 bits from right */
  1069.     
  1070.         switch(cKeyPressed)
  1071.         {
  1072.             case '1':  pubTemp = &ubThisBlue;  nInc = -nStep; break;
  1073.             case '2':  pubTemp = &ubThisBlue;  nInc =  nStep; break;
  1074.             case '3':  pubTemp = &ubThisBlue;  nInc = -ubThisBlue;  break;
  1075.             case '4':  pubTemp = &ubThisGreen; nInc = -nStep; break;
  1076.             case '5':  pubTemp = &ubThisGreen; nInc =  nStep; break;
  1077.             case '6':  pubTemp = &ubThisGreen; nInc = -ubThisGreen; break;
  1078.             case '7':  pubTemp = &ubThisRed;   nInc = -nStep; break;
  1079.             case '8':  pubTemp = &ubThisRed;   nInc =  nStep; break;
  1080.             case '9':  pubTemp = &ubThisRed;   nInc = -ubThisRed;   break;
  1081.             default:   
  1082.                    /* Printf("AdjustColor:  invalid keypress!\n");    */
  1083.                    break;
  1084.         } 
  1085.         
  1086.         /* Adjust color level */
  1087.         *pubTemp += nInc;
  1088.         if (*pubTemp == 16) *pubTemp = 0;        /* Wrap around */
  1089.         if (*pubTemp == -1) *pubTemp = 15;
  1090.     }
  1091.     else
  1092.     {
  1093.         /* just set palette entry to our given color. */
  1094.         /* Extract R, G, B from current foreground color */
  1095.         ubThisBlue  = (*uwPresetColor      & 0x000F); /* Right 4 bits */
  1096.         ubThisGreen = ((*uwPresetColor>>4) & 0x000F); /* 2nd 4 bits from right */
  1097.         ubThisRed   = ((*uwPresetColor>>8) & 0x000F); /* 3rd 4 bits from right */
  1098.     }
  1099.             
  1100.     SetRGB4(&Scr->ViewPort, nPaletteEntry, ubThisRed, ubThisGreen, ubThisBlue);
  1101.                 
  1102.     if ((BPalettesLocked == TRUE)&&(BTransmit == TRUE))
  1103.     {
  1104.         /* Note that this only works with static transmission! */
  1105.         Wprint(COMMAND, DEST_PEER|DEST_FILE);
  1106.         Wprint(COMMAND_SETCOLOR, DEST_PEER|DEST_FILE);
  1107.         Wprint((UWORD) nPaletteEntry, DEST_PEER|DEST_FILE);    
  1108.         Wprint(RGBComponents(nPaletteEntry), DEST_PEER|DEST_FILE);
  1109.     }
  1110.     return;
  1111. }
  1112.     
  1113.     
  1114.     
  1115.     
  1116.  
  1117. /* Toggles BSafeFloods flag */
  1118. VOID ToggleSafeFlood(void)
  1119. {
  1120.     BSafeFloods = Not[BSafeFloods];
  1121.     SetMenuValues();
  1122.     return;
  1123. }
  1124.     
  1125.     
  1126.  
  1127.  
  1128.  
  1129. int CleanExit(LONG returnValue)
  1130. {
  1131.     const static LONG lType = REXX_REPLY_QUIT;
  1132.     
  1133.     /* If an ARexx waitevent() is pending, send it a QUIT message */
  1134.     if (PState.uwRexxWaitMask != 0)
  1135.     {
  1136.         ((struct rxd_waitevent *) *(&RexxState.array))->res.type = &lType;
  1137.         SetStandardRexxReturns();
  1138.     }
  1139.     
  1140.     if (rexxHost != NULL) CloseDownARexxHost(rexxHost);
  1141.     if (ChatFont != NULL) CloseFont(ChatFont);
  1142.     
  1143.     /* Free Output Queue */
  1144.     FreeQueue(); 
  1145.     
  1146.     if (BNetConnect == TRUE) CloseDrawSocket();
  1147.  
  1148.     /* If a picture was being held for transmission, free it */
  1149.     /* if (BIFFLoadPending == TRUE) */
  1150.     CleanUpIFF(NULL);
  1151.     
  1152.     /* Clean and close timer io */
  1153.     if (TimerIO != NULL)
  1154.     {
  1155.         if (!(CheckIO((struct IORequest *)TimerIO))) 
  1156.         {
  1157.             AbortIO((struct IORequest *)TimerIO);    /* Ask device to abort any pending requests */
  1158.             WaitIO((struct IORequest *)TimerIO);    /* proceed when ready */
  1159.         }
  1160.         CloseDevice((struct IORequest *) TimerIO);
  1161.         DeleteExtIO((struct IORequest *) TimerIO);
  1162.     }
  1163.     if (TimerMP != NULL) DeletePort(TimerMP);
  1164.     
  1165.     /* close window */
  1166.     if (DrawWindow != NULL)
  1167.     {
  1168.         CloseWindow(DrawWindow);    /* Close window if it's open */
  1169.         DrawWindow = NULL;        /* and tell the world it's closed */
  1170.     }
  1171.     
  1172.     /* Free Area-Draw's Bitplane o' Memory */
  1173.     if ((TempRasterBitPlane != NULL)&&(Scr != NULL))
  1174.          FreeRaster(TempRasterBitPlane, Scr->Width, Scr->Height);
  1175.     
  1176.     /* Free Menus */
  1177.     if (Menu != NULL) FreeMenus(Menu);
  1178.     
  1179.     /* close screen */
  1180.     if (Scr != NULL)                 
  1181.     {
  1182.         if (screentype == USE_CUSTOMSCREEN)
  1183.         {
  1184.             CloseScreen(Scr);
  1185.         }
  1186.         else
  1187.         {
  1188.                 SaveScreenPalette(FALSE,-1);    /* Restore original screen palette */
  1189.             UnlockPubScreen(NULL,Scr);
  1190.         }
  1191.     }
  1192.  
  1193.     
  1194.     /* Close the Library(s) */
  1195.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  1196.     if (IconBase)       CloseLibrary(IconBase);
  1197.     if (GraphicsBase)  CloseLibrary((struct Library *)GraphicsBase);
  1198.     if (GadToolsBase)  CloseLibrary(GadToolsBase);
  1199.     if (SocketBase)    CloseLibrary(SocketBase);
  1200.     if (AslBase)       CloseLibrary(AslBase);
  1201.     if (IFFParseBase)  CloseLibrary(IFFParseBase);
  1202.  
  1203.     /* don't close TimerBase, since we don't access it through OpenLibrary() */
  1204.     
  1205.     if ((fpOut != NULL)&&(fpOut != stdout)) fclose(fpOut);
  1206.     if ((fpIn != NULL)&&(fpIn != stdin)) fclose(fpIn);
  1207.     
  1208.     exit(returnValue);
  1209. }
  1210.  
  1211.  
  1212. int ScreenTitleHeight(void)
  1213. {
  1214.     return(Scr->WBorTop + Scr->RastPort.TxHeight + 1);
  1215. }    
  1216.  
  1217.  
  1218. void ResetState(struct PaintInfo *pi)
  1219. {
  1220.  
  1221.     /* clear send/recieve buffers */
  1222.     memset(szSendString,    '\0', sizeof(szSendString));
  1223.     memset(szReceiveString, '\0', sizeof(szReceiveString));
  1224.     
  1225.     pi->BPenDown     = FALSE;    
  1226.     pi->BDrawEnabled = TRUE;
  1227.  
  1228.     if (Scr != NULL)
  1229.             pi->ubDepth = Scr->RastPort.BitMap->Depth;
  1230.     else
  1231.             pi->ubDepth = 1;        /* minimum to assume! */
  1232.     
  1233.     if (DrawWindow != NULL)    pi->uwWidth    = DrawWindow->Width;
  1234.     else
  1235.     {
  1236.         if (BAcceptingTCP == FALSE)
  1237.         {
  1238.             if (nUserReqWidth == -1)
  1239.                 pi->uwWidth    = Scr->Width;
  1240.             else
  1241.                 pi->uwWidth    = nUserReqWidth;
  1242.         }
  1243.     }
  1244.     
  1245.     if (DrawWindow != NULL)
  1246.         pi->uwHeight   = DrawWindow->Height;
  1247.     else
  1248.     {
  1249.         if (BAcceptingTCP == FALSE)
  1250.         {
  1251.             if (nUserReqHeight == -1)
  1252.                 pi->uwHeight   = Scr->Height - ScreenTitleHeight();
  1253.             else
  1254.                 pi->uwHeight   = nUserReqHeight;
  1255.         }
  1256.     }
  1257.     
  1258.     pi->uwMode     = MODE_PEN;        
  1259.     pi->uwFColor   = 1;
  1260.     pi->uwBColor   = 0;
  1261.     pi->uwRemoteFColor = pi->uwFColor;
  1262.     pi->uwRemoteBColor = pi->uwBColor;
  1263.     pi->uwRemoteMode = MODE_DOT;
  1264.     
  1265.     if (BAcceptingTCP == FALSE)
  1266.     {
  1267.         pi->uwRemoteScreenWidth = -1;
  1268.         pi->uwRemoteScreenHeight = -1;
  1269.         pi->ubRemoteDepth = -1;
  1270.     }
  1271.     
  1272.     pi->uwRexxFColor = 1;
  1273.     pi->uwRexxBColor = 0;
  1274.     pi->uwRexxWaitMask = 0;
  1275.         
  1276.     pi->nToolBoxWidth = TOOLBOXH_WIDTH;
  1277.     pi->nToolBoxHeight = TOOLBOXH_HEIGHT;
  1278.     pi->nDefaultWidth = pi->uwWidth;
  1279.     pi->nDefaultHeight = pi->uwHeight;
  1280.  
  1281. };
  1282.  
  1283.  
  1284.  
  1285. int nGetToolBoxWidth(void)
  1286. {
  1287.     return(TOOLBOXH_WIDTH);
  1288. }
  1289.  
  1290. int nGetToolBoxHeight(void)
  1291. {
  1292.     return(TOOLBOXH_HEIGHT);
  1293. }
  1294.  
  1295.  
  1296. VOID UpperCase(char *sOldString)
  1297. {
  1298. char *i = sOldString;
  1299. const int diff = 'a' - 'A';
  1300.  
  1301.  if (sOldString == NULL) return();
  1302.  while (*i != '\0')
  1303.  {
  1304.     if ((*i >= 'a')&&(*i <= 'z')) *i = *i - diff;
  1305.     i++;
  1306.  }
  1307.  return;
  1308. }
  1309.  
  1310.  
  1311. VOID LowerCase(char *sOldString)
  1312. {
  1313. char *i = sOldString;
  1314. const int diff = 'a' - 'A';
  1315.  
  1316.  if (sOldString == NULL) return();
  1317.  while (*i != '\0')
  1318.  {
  1319.     if ((*i >= 'A')&&(*i <= 'Z')) *i += diff;
  1320.     i++;
  1321.  }
  1322.  return;
  1323. }
  1324.  
  1325. void SetGlobalDefaults(void)
  1326. {
  1327.     nUserReqHeight = 200;
  1328.     nUserReqWidth  = 320;
  1329.     return;
  1330. }
  1331.  
  1332. /* Sets all startup options from startup arguments, using ToolTypes if
  1333.    BStartedFromWB is TRUE, otherwise from command line */
  1334. /* Returns the result of the ParseRexx() function */
  1335. void ParseArgs(void)
  1336. {
  1337.     int nParam;
  1338.     char *szParam, *pcTemp;
  1339.     BOOL BSuccess;
  1340.     static char szIconName[150];
  1341.     static UWORD uwRexxArgsFound = 0L;        /* start empty */
  1342.     static BOOL BParsedBefore = FALSE;
  1343.         
  1344.     if (BStartedFromWB == TRUE) 
  1345.     {
  1346.         if (SetupToolTypeArg() == FALSE) return;
  1347.     }    /* can't proceed unless we can access the icon! */
  1348.     else
  1349.     {
  1350.         if ((argc == 1)||(BParsedBefore == TRUE))
  1351.         {
  1352.             szProgramName = argv[0];
  1353.             if ((szProgramName == NULL)||(strlen(szProgramName) == 0)||(strcmp(szProgramName," ") == 0)) szProgramName = "AmiSlate";
  1354.             *szIconName = '\0';
  1355.             
  1356.             /* Add path, if there isn't a base in the filename */
  1357.             pcTemp = strchr(szProgramName,':');
  1358.             if (pcTemp == NULL) strcpy(szIconName,"PROGDIR:");        
  1359.             
  1360.             strncat(szIconName, szProgramName, sizeof(szIconName));            
  1361.             szProgramName = szIconName;            
  1362.             if (SetupToolTypeArg() == FALSE) szProgramName = NULL;
  1363.         }
  1364.     }
  1365.     
  1366.     if (BParsedBefore == FALSE)
  1367.     {
  1368.         BSuccess = GetSlateArg("WIDTH",&nUserReqWidth, &szParam);
  1369.         if ((BSuccess)&&(nUserReqWidth < (nGetToolBoxWidth()+MIN_WIDTH_OFFSET))) 
  1370.             nUserReqWidth = nGetToolBoxWidth()+MIN_WIDTH_OFFSET;     /* Minimum width */
  1371.     
  1372.         BSuccess = GetSlateArg("HEIGHT",&nUserReqHeight, &szParam);
  1373.         if ((BSuccess)&&(nUserReqHeight < (nGetToolBoxHeight()+nTitleHeight+MIN_HEIGHT_OFFSET))) 
  1374.             nUserReqHeight = nGetToolBoxHeight()+nTitleHeight+MIN_HEIGHT_OFFSET; /* Minimum height */
  1375.  
  1376.     
  1377.         BSuccess = GetSlateArg("TOP",&nUserReqTop, &szParam);
  1378.         
  1379.         BSuccess = GetSlateArg("LEFT",&nUserReqLeft, &szParam);
  1380.         
  1381.         BSuccess = GetSlateArg("PUBSCREEN", &nParam, &szParam);
  1382.         if (!BSuccess) BSuccess = GetSlateArg("PUBLICSCREEN", &nParam, &szParam);
  1383.         if (BSuccess)
  1384.         {
  1385.            strncpy(szPubScreenName,szParam,sizeof(szPubScreenName));
  1386.            BUseCustomScreen = FALSE;
  1387.            screentype = USE_PUBLICSCREEN;
  1388.         }
  1389.         
  1390.         BSuccess = GetSlateArg("REXXOUTPUT", &nParam, &szParam);
  1391.         if (BSuccess) strncpy(szRexxOutputFile,szParam,sizeof(szRexxOutputFile));
  1392.     
  1393.         BSuccess = GetSlateArg("WBSCREEN", &nParam, &szParam);
  1394.         if (!BSuccess) BSuccess = GetSlateArg("WORKBENCHSCREEN", &nParam, &szParam);
  1395.         if (BSuccess)
  1396.         {
  1397.             BUseCustomScreen = FALSE;
  1398.             screentype = USE_WORKBENCHSCREEN;
  1399.         }
  1400.         
  1401.         BSuccess = GetSlateArg("OUTQUEUE", &nParam, &szParam);
  1402.         if (BSuccess == TRUE) lOutputQueueSize = nParam;
  1403.     }
  1404.         
  1405.     uwRexxArgsFound = ParseRexxMenu(uwRexxArgsFound);
  1406.     
  1407.     BParsedBefore = TRUE;
  1408.         if (AmiSlateIconDiskObject != NULL) FreeDiskObject(AmiSlateIconDiskObject);
  1409.     return;
  1410. }
  1411.  
  1412.  
  1413. /* returns a bit pattern with bit n set if option n was set.
  1414.    Argument is a bit pattern in the same format, will not set an
  1415.    option if that bit is set. */
  1416. UWORD ParseRexxMenu(UWORD uwMask)
  1417. {
  1418.     int nParam,i,j;
  1419.     char *szParam, *pcTemp, szRexxArg[12];
  1420.     BOOL BSuccess;
  1421.  
  1422.     /* Get names/locations of Rexx quickies */
  1423.     for (i=-1; i < 10; i++)
  1424.     { 
  1425.         sprintf(szRexxArg,"REXXMENU%i\0",i+1);
  1426.  
  1427.         if (i >= 0) j = i; else j = 9;
  1428.         
  1429.         if (!(uwMask & (1L << i)))
  1430.         {
  1431.             BSuccess = GetSlateArg(szRexxArg, &nParam, &szParam);
  1432.             if (BSuccess == TRUE)
  1433.             {
  1434.                 /* Get first letter in _file_name */
  1435.                 pcTemp = strrchr(szParam,'/');
  1436.                 if (pcTemp == NULL) pcTemp = strrchr(szParam,':');
  1437.                 if (pcTemp == NULL) pcTemp = szParam - 1;
  1438.                 pcTemp++;    /* move past symbol to first char in name */
  1439.     
  1440.                 strncpy(szRexxNames[j],pcTemp,REXXNAMELENGTH-1);
  1441.                 strncpy(szRexxScripts[j],szParam,REXXSCRIPTLENGTH-1);
  1442.     
  1443.                 /* Remove ugly .rexx extention from menu name */
  1444.                 pcTemp = strrchr(szRexxNames[j],'.');
  1445.                 if (pcTemp != NULL) *pcTemp = '\0';
  1446.                 
  1447.                 uwMask |= (1L << j);
  1448.             }
  1449.         }
  1450.     }
  1451.     return(uwMask);
  1452. }
  1453.     
  1454.  
  1455.  
  1456. BOOL GetSlateArg(char * szArg, int * nParam, char **szParam)
  1457. {
  1458.     if ((BStartedFromWB == TRUE)||(szProgramName != NULL))
  1459.         return(GetToolTypeArg(szArg,nParam,szParam));
  1460.     else
  1461.         return(GetCLIArg(szArg,nParam,szParam));
  1462. }
  1463.  
  1464. /* Searches command line arguments for an argument of the form
  1465.    ARG, ARG=PARAM, or arguments of the form ARG PARAM
  1466.    
  1467.    That is, if ARG is found, the next argument will be returned
  1468.    as PARAM */
  1469. BOOL GetCLIArg(char *szArg, int *nParam, char **szParam)
  1470. {
  1471.     int i;
  1472.     char *pcTemp;
  1473.     char szTemp[50];
  1474.         
  1475.     /* argc, argv must be defined globally! */
  1476.     
  1477.     for (i=1;i<argc;i++)
  1478.     {
  1479.         strncpy(szTemp,argv[i],sizeof(szTemp));
  1480.         UpperCase(szTemp);
  1481.         
  1482.         pcTemp = strchr(szTemp,'=');
  1483.         if (pcTemp != NULL) *pcTemp = '\0';
  1484.         
  1485.         if (strcmp(szTemp,szArg) == 0)
  1486.         {
  1487.             /* Found our argument! */
  1488.             
  1489.             /* Form is ARG=PARAM */
  1490.             if (pcTemp != NULL)
  1491.             {
  1492.                 *szParam = strchr(argv[i], '=') + 1;
  1493.                 *nParam  = atoi(pcTemp+1);
  1494.             }
  1495.             else
  1496.             {
  1497.                 if (argv[i+1] == NULL)
  1498.                 {
  1499.                     *szParam = "";
  1500.                     *nParam = 0;
  1501.                 }
  1502.                 else
  1503.                 {
  1504.                     *szParam = argv[i+1];
  1505.                     *nParam = atoi(argv[i+1]);
  1506.                 }
  1507.             }
  1508.             return(TRUE);
  1509.         }
  1510.     }
  1511.     return(FALSE);
  1512. }
  1513.  
  1514.  
  1515. BOOL SetupToolTypeArg(void)
  1516. {
  1517.     struct WBArg *wb_arg = ((struct WBStartup *) argv)->sm_ArgList;
  1518.  
  1519.     if (szProgramName != NULL)
  1520.         AmiSlateIconDiskObject = GetDiskObject((UBYTE *)szProgramName);
  1521.     else
  1522.         AmiSlateIconDiskObject = GetDiskObject((UBYTE *)wb_arg->wa_Name);
  1523.     return(AmiSlateIconDiskObject != NULL);
  1524. }
  1525.  
  1526.  
  1527.  
  1528.  
  1529. /* You must call SetupToolTypeArg before calling this function! */
  1530. BOOL GetToolTypeArg(char *szArg, int *nParam, char **szParam)
  1531. {
  1532.     static char sToolParam[200];
  1533.     char **toolarray = (char **) AmiSlateIconDiskObject->do_ToolTypes;
  1534.     char *sTemp;
  1535.  
  1536.     /* Clear default string */
  1537.     sToolParam[0] = '\0';
  1538.     *szParam = sToolParam;    /* Return pointer to it */
  1539.             
  1540.     if ((toolarray != NULL) &&
  1541.         ((sTemp = (char *) FindToolType(toolarray,szArg)) != NULL))
  1542.     {
  1543.         *nParam = atoi(sTemp);
  1544.         strncpy(sToolParam,sTemp,sizeof(sToolParam));
  1545.         return(TRUE);
  1546.     }                     
  1547.      return(FALSE);
  1548. }
  1549.  
  1550.     
  1551.  
  1552. /* If given BSaveIt == TRUE, saves Scr's palette to an internal array.  If
  1553.    BSaveIt == FALSE, restore palette to screen Scr. */
  1554. /* If nOptMaxPen is negative, save/restore all colors, else restore pens zero
  1555.    through nOptMaxPen. */
  1556. void SaveScreenPalette(BOOL BSaveIt, int nOptMaxPen)
  1557. {
  1558.     static UWORD OrigScreenPalette[256];
  1559.     int i;
  1560.     UBYTE ubBlue, ubGreen, ubRed;
  1561.     
  1562.     if (nOptMaxPen < 0) nOptMaxPen = (1<<Scr->RastPort.BitMap->Depth);
  1563.     
  1564.     if (BSaveIt == TRUE)
  1565.     {
  1566.         for (i=0;i<nOptMaxPen;i++)
  1567.             OrigScreenPalette[i] = RGBComponents(i);
  1568.     }
  1569.     else
  1570.     {
  1571.         for (i=0;i<nOptMaxPen;i++)
  1572.         {    
  1573.             /* Decipher 12 righthand bits of word into ints */
  1574.             ubBlue  = (OrigScreenPalette[i]     ) & 0x000F;
  1575.             ubGreen = (OrigScreenPalette[i] >> 4) & 0x000F;
  1576.             ubRed   = (OrigScreenPalette[i] >> 8) & 0x000F;
  1577.             SetRGB4(&Scr->ViewPort, i, ubRed, ubGreen, ubBlue);
  1578.         }
  1579.         if (BPalettesLocked == TRUE) SendPalette();
  1580.     }
  1581.     
  1582.     return;
  1583. }
  1584.  
  1585.  
  1586.  
  1587.  
  1588. BOOL InitAreaStuff(void)
  1589. {    
  1590.     /* Clear buffer */
  1591.     memset(AreaBuffer, '\0', sizeof(WORD)*INTUITION_AREA_SIZE);
  1592.     InitArea(&AreaInfo, AreaBuffer, (INTUITION_AREA_SIZE * sizeof(WORD)) /5);
  1593.     
  1594.     TempRasterBitPlane = AllocRaster(Scr->Width, Scr->Height);
  1595.     if (TempRasterBitPlane == NULL) return(FALSE);
  1596.     
  1597.     InitTmpRas(&TempRaster, TempRasterBitPlane, RASSIZE(Scr->Height, Scr->Width));
  1598.     
  1599.     DrawWindow->RPort->TmpRas   = &TempRaster;
  1600.     DrawWindow->RPort->AreaInfo = &AreaInfo;
  1601.  
  1602.     return(TRUE);
  1603. }
  1604.  
  1605.  
  1606.  
  1607. /* UniqueName -- searches the given directory & filename and returns */
  1608. /*               a unique filename based on that filename            */
  1609. char * UniqueName(char *szPath)
  1610. {
  1611.     static char szRawFileName[600];
  1612.     int nCurrentRev = 0, nTries = 0;
  1613.     char *cTemp = NULL;
  1614.     FILE *fpTestWrite = NULL;
  1615.  
  1616.     /* Return an empty string given an empty string... */
  1617.     if (strlen(szPath) == 0) return("");
  1618.  
  1619.     /* Make a copy of the user's string to return */
  1620.     strncpy(szRawFileName, szPath, sizeof(szRawFileName));
  1621.  
  1622.     /* If it ends in a colon, return the original string immediately */
  1623.     /* This way, if the user specifies CON: or SPEAK: or something,
  1624.        AmiSlate won't be foolishly opening CON:1, CON:2, etc. */
  1625.     cTemp = strchr(szRawFileName,'\0') - 1;
  1626.     if (*cTemp == ':') return(szRawFileName);
  1627.     
  1628.     /* First try it with the original filename */
  1629.     fpTestWrite = fopen(szRawFileName,"w");
  1630.     if (fpTestWrite != NULL) 
  1631.     {
  1632.         fclose(fpTestWrite);
  1633.         return(szRawFileName);
  1634.     }
  1635.  
  1636.     cTemp = strchr(szRawFileName, (char) 0);    /* now points to just after end of name */    
  1637.     cTemp--;  /* now points to last char */
  1638.     
  1639.     while ((cTemp >= szRawFileName)&&(*cTemp >= '0')&&(*cTemp <= '9')) cTemp--;
  1640.     cTemp++;    /* cTemp now points to the numerical extension of the name */
  1641.     
  1642.     nCurrentRev = atoi(cTemp);
  1643.     
  1644.     while (nTries < 300)
  1645.     {
  1646.         nCurrentRev++;
  1647.         nTries++;
  1648.  
  1649.         fpTestWrite = NULL;
  1650.         sprintf(cTemp,"%i",nCurrentRev);    
  1651.         fpTestWrite = fopen(szRawFileName,"w");
  1652.         if (fpTestWrite != NULL) 
  1653.         {
  1654.             fclose(fpTestWrite);
  1655.             return(szRawFileName);
  1656.         }        
  1657.     }
  1658.     return("");    /* Fail! */
  1659. }
  1660.  
  1661.  
  1662. VOID UserError(char *szErrorString)
  1663. {
  1664.     if (BStartedFromWB == TRUE)
  1665.         MakeReq("AmiSlate Aborting",szErrorString,NULL);
  1666.     else
  1667.         Printf("AmiSlate Abort: [%s]\n",szErrorString);
  1668.     return;
  1669. }
  1670.  
  1671.  
  1672.  
  1673. BOOL CheckForUserAbort(void)
  1674. {
  1675.     static int nReturn;
  1676.     static char szPrompt[50]="";
  1677.     static struct IntuiMessage *imsg;
  1678.     
  1679.     while (imsg = GT_GetIMsg(DrawWindow->UserPort)) 
  1680.     {
  1681.         switch (imsg->Class)
  1682.         {
  1683.             case IDCMP_CLOSEWINDOW:
  1684.                 GT_ReplyIMsg(imsg);
  1685.                 CleanExit(RETURN_OK);
  1686.                 break;
  1687.                 
  1688.             case IDCMP_VANILLAKEY: 
  1689.                 if (imsg->Code == CHAR_ESCAPE)
  1690.                 {
  1691.                     GT_ReplyIMsg(imsg);
  1692.                     sprintf(szPrompt,"Abort the %s?",pcWhatToAbort);
  1693.                     nReturn = (MakeReq("AmiSlate Abort Request",szPrompt,"Continue|Abort") == 0);
  1694.                     if (DrawWindow != NULL) SetPointer(DrawWindow, waitPointer, 16, 16, -6, 0);
  1695.                     PState.BPenDown = FALSE;
  1696.                     return(nReturn);
  1697.                 }
  1698.                 else GT_ReplyIMsg(imsg);
  1699.                 break;
  1700.                 
  1701.              case IDCMP_NEWSIZE: case IDCMP_REFRESHWINDOW:
  1702.                 HandleIDCMP(imsg);     /* do window resize, the regular way */
  1703.                  break;
  1704.  
  1705.             case IDCMP_MENUPICK:
  1706.                 SetMenuValues();    /* undo the damage */
  1707.                 GT_ReplyIMsg(imsg);
  1708.                 break;
  1709.  
  1710.              default:
  1711.                  GT_ReplyIMsg(imsg);
  1712.                  break;
  1713.         }
  1714.     }
  1715.     return(FALSE);
  1716. }
  1717.  
  1718.  
  1719.  
  1720.  
  1721.                 
  1722. VOID wbmain(struct WBStartup *wbargv)
  1723. {
  1724.     BStartedFromWB = TRUE;
  1725.     main(0,(char **)wbargv);
  1726.     return;
  1727. }
  1728.  
  1729.  
  1730. int main(int local_argc, char *local_argv[])
  1731. {
  1732. BOOL BQuitNow = FALSE;
  1733. int i;
  1734. UWORD penarray[7] = {~0};
  1735. UBYTE bToDo = 0;
  1736. struct Process *me;
  1737. struct DaemonMessage *dm;
  1738. char sBuffer[100];
  1739.  
  1740. /* Yep, set global vars... what style! */
  1741. argc = local_argc;
  1742. argv = local_argv;
  1743.  
  1744. memset(targethost,'\0',sizeof(targethost));
  1745.  
  1746. IntuitionBase = OpenLibrary("intuition.library",38);
  1747. if (IntuitionBase != NULL) BDos20 = FALSE;
  1748. else
  1749. {
  1750.     IntuitionBase = OpenLibrary("intuition.library",37);
  1751.     if (IntuitionBase == NULL)
  1752.     {
  1753.         Printf("Couldn't open intuition.library!\n");
  1754.         CleanExit(RETURN_FAIL);
  1755.     }        
  1756. }
  1757.  
  1758. SocketBase = OpenLibrary("bsdsocket.library", 2);
  1759. /* No need to check SocketBase now, if it is NULL 
  1760.    we just disable network functions later... */
  1761.    
  1762. /* See if we were started by inetd... if so, go into passive mode */
  1763. me = (struct Process *) FindTask(NULL);
  1764. if (me != NULL)
  1765. {
  1766.     dm = (struct DaemonMessage *)me->pr_ExitData;
  1767.     if (dm != NULL)
  1768.     {
  1769.          BAcceptingTCP = TRUE;            /* This means we're receiving, not necessarily that the user accepts */
  1770.           AcceptDrawSocket(dm);
  1771.          if (BNetConnect == FALSE) CleanExit(RETURN_FAIL);
  1772.          GetDrawPeerName(targethost, sizeof(targethost));
  1773.           sprintf(sBuffer, "AmiSlate connection requested by\n%s",targethost);
  1774.          if (MakeReq(NULL, sBuffer,"Accept|Deny") == 0)    
  1775.          {
  1776.              OutputAction(FROM_IDCMP, COMMAND, COMMAND_QUIT, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER);
  1777.              CleanExit(RETURN_OK);
  1778.          }
  1779.    }
  1780. }
  1781.  
  1782. /* If the first argument on the command line is ? then spit out info and exit */
  1783. if ((BAcceptingTCP == FALSE)&&(BStartedFromWB == FALSE)&&(argc > 1)&&(strcmp(argv[1],"?")==0))
  1784. {
  1785.     printf("Template:  AmiSlate WBSCREEN/S,TOP/K/N,LEFT/K/N,WIDTH/K/N,\
  1786. HEIGHT/K/N,PUBSCREEN/K,REXXOUTPUT/K,REXXOUTPUT/K,OUTQUEUE/K/N,REXXMENU1/K,\
  1787. REXXMENU2/K,{...}\n");
  1788.  
  1789.     CleanExit(RETURN_OK);
  1790. }
  1791.  
  1792.  
  1793.  
  1794. /* Sneaky test to see if we have OS3.x ? */
  1795. /* Accept TCP connection if appropriate */
  1796. GraphicsBase = OpenLibrary("graphics.library",37);
  1797. if (GraphicsBase == NULL)
  1798. {
  1799.     UserError("Couldn't open graphics.library!");
  1800.     CleanExit(RETURN_FAIL);
  1801. }
  1802.  
  1803. GadToolsBase = OpenLibrary("gadtools.library",36);
  1804.  if (GadToolsBase == NULL)
  1805.  {
  1806.      UserError("Couldn't open gadtools.library!");
  1807.      CleanExit(RETURN_FAIL);
  1808.  }
  1809.  
  1810. AslBase = OpenLibrary("asl.library",37L);
  1811. if (AslBase == NULL)
  1812. {
  1813.     UserError("Couldn't open asl.library!");
  1814.     CleanExit(RETURN_FAIL);
  1815. }
  1816.  
  1817. IconBase = OpenLibrary("icon.library",33);
  1818. if (IconBase == NULL) 
  1819. {
  1820.     UserError("Couldn't open icon.library!");
  1821.     CleanExit(RETURN_FAIL);
  1822. }
  1823.  
  1824.  
  1825. IFFParseBase = OpenLibrary("iffparse.library",37);
  1826. /* No user error/CleanExit bit--we'll just disable the IFF functions... */
  1827.  
  1828. /* Default to standard, non-functinal Rexx menu items */
  1829. memset(szRexxNames, '\0', sizeof(szRexxNames));
  1830. memset(szRexxScripts, '\0', sizeof(szRexxScripts));
  1831.  
  1832. ChatFont = (struct TextFont *) OpenDiskFont(&topaz8);
  1833.  if (ChatFont == NULL)
  1834.  {
  1835.      UserError("Couldn't open topaz 8 font!");
  1836.      CleanExit(RETURN_FAIL);
  1837.  }
  1838.  
  1839. InitToolBox();                /* SetUp ToolBox BitMap */
  1840. ParseArgs();                /* Get Startup arguments */
  1841.  
  1842. if (BStartedFromWB == FALSE) ParseArgs();    /* Do it again to fill any unused ARexx fields from ToolTypes */
  1843.  
  1844. /* Insert new ARexx menu items as per ToolTypes */
  1845. for (i=0; i<10; i++)
  1846. {
  1847.     if (szRexxNames[i][0] != '\0')     
  1848.     {
  1849.         nmMenus[i+FIRSTREXXITEM].nm_Label = szRexxNames[i];
  1850.         nmMenus[i+FIRSTREXXITEM].nm_Flags &= ~(NM_ITEMDISABLED);
  1851.     }
  1852. }
  1853.  
  1854. if (AllocQueue(lOutputQueueSize) == FALSE)
  1855. {
  1856.     UserError("Unable to allocate memory for send queue");
  1857.     CleanExit(RETURN_FAIL);
  1858. }
  1859.  
  1860. /* Setup timer.device I/O request for ARexx command timeouts */
  1861. if (!(TimerMP = CreatePort(0,0)))
  1862. {
  1863.     UserError("Couldn't create timer IO port");
  1864.     CleanExit(RETURN_FAIL);
  1865. }
  1866.  
  1867. if (!(TimerIO = (struct timerequest *) CreateExtIO(TimerMP, (sizeof (struct timerequest)))))
  1868. {
  1869.     UserError("Couldn't create timer IO request");
  1870.     CleanExit(RETURN_FAIL);
  1871. }
  1872. timerSignal = 1L << TimerMP->mp_SigBit;
  1873.  
  1874. /* Allow access to timer device's library functions */
  1875. TimerBase = (struct Library *) TimerIO->tr_node.io_Device;
  1876.  
  1877. /* Open the timer.device with UNIT_WAITUNTIL for ARexx timeouts */
  1878. if (OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerIO,0))
  1879. {
  1880.     UserError("Couldn't open timer.device");
  1881.     CleanExit(RETURN_FAIL);
  1882. }
  1883. TimerIO->tr_node.io_Message.mn_ReplyPort = TimerMP;
  1884. TimerIO->tr_node.io_Command = TR_ADDREQUEST;
  1885. TimerIO->tr_node.io_Flags = 0;
  1886. TimerIO->tr_node.io_Error = 0;
  1887. TimerIO->tr_time.tv_secs  = 0;
  1888. TimerIO->tr_time.tv_micro = 0; /* this won't be set until we actually do the req */
  1889.  
  1890. /* Get Screen Data for user's info when selecting a screen */
  1891. if (BAcceptingTCP == TRUE)
  1892. {
  1893.     if (GetRemoteScreenInfo(&PState.uwRemoteScreenHeight,
  1894.                             &PState.uwRemoteScreenWidth,
  1895.                             &PState.ubRemoteDepth,
  1896.                             &PState.uwHeight,
  1897.                             &PState.uwWidth) == FALSE) 
  1898.     {
  1899.         MakeReq("AmiSlate Error","Couldn't Get Remote Screen Info","Abort");
  1900.         CleanExit(RETURN_OK);
  1901.     }
  1902. }
  1903. else
  1904.     PState.ubRemoteDepth = -1;        /* Keeps Display requester from showing remote screen specs */
  1905.  
  1906. /* now open/lock the screen */
  1907. if (BUseCustomScreen == TRUE)
  1908. {
  1909.     Scr = GetDisplay(PState.uwRemoteScreenHeight, PState.uwRemoteScreenWidth, PState.ubRemoteDepth);    
  1910.      if ((Scr == NULL)&&(screentype == USE_CUSTOMSCREEN)) CleanExit(RETURN_OK);
  1911. }
  1912.  
  1913. if ((screentype == USE_WORKBENCHSCREEN)||(screentype == USE_PUBLICSCREEN))
  1914. {
  1915.     Scr = LockPubScreen(szPubScreenName);
  1916.     if (Scr == NULL)
  1917.     {
  1918.         sprintf(szRexxOutputFile,"Couldn't lock the screen: [%s]!\n",szPubScreenName);
  1919.         UserError(szRexxOutputFile);
  1920.         CleanExit(RETURN_FAIL);
  1921.     }
  1922.     BUseCustomScreen = FALSE;
  1923. }
  1924.  
  1925. nTitleHeight = ScreenTitleHeight();
  1926. ResetState(&PState);        /* Initialize to defaults */
  1927.  
  1928. if (BAcceptingTCP == TRUE)
  1929. {
  1930.     /* Correct for the obvious */
  1931.     if (PState.uwWidth  > PState.uwRemoteScreenWidth)  PState.uwWidth  = PState.uwRemoteScreenWidth;
  1932.     if (PState.uwHeight > PState.uwRemoteScreenHeight) PState.uwHeight = PState.uwRemoteScreenHeight;
  1933. }
  1934.  
  1935.  
  1936. if (nUserReqLeft == -1) nUserReqLeft = (Scr->Width-PState.uwWidth)/2;
  1937. if (nUserReqTop  == -1) nUserReqTop  = (Scr->Height-PState.uwHeight)/2 + ScreenTitleHeight();
  1938.  
  1939. if (BUseCustomScreen == TRUE)
  1940. {
  1941.     DrawWindow = OpenWindowTags(NULL,
  1942.          WA_Left,        nUserReqLeft,
  1943.          WA_Top,        nUserReqTop,
  1944.          WA_Width,        PState.uwWidth,
  1945.          WA_Height,        PState.uwHeight,
  1946.          WA_MinWidth,        PState.nToolBoxWidth+MIN_WIDTH_OFFSET,
  1947.          WA_MinHeight,        PState.nToolBoxHeight+nTitleHeight+MIN_HEIGHT_OFFSET,
  1948.          WA_MaxWidth,        PState.uwRemoteScreenWidth,
  1949.          WA_MaxHeight,        PState.uwRemoteScreenHeight,
  1950.          WA_CustomScreen,   Scr,
  1951.          WA_ScreenTitle,    sScreenTitle,
  1952.          WA_Title,        sWindowTitle,
  1953.          WA_CloseGadget,    TRUE,
  1954.          WA_DepthGadget,    TRUE,
  1955.          WA_SizeGadget,     TRUE,
  1956.          WA_Activate,        TRUE,
  1957.          WA_DragBar,        TRUE,
  1958.          WA_ReportMouse,    TRUE,
  1959.          WA_SizeBBottom,    TRUE,
  1960. /*         WA_RMBTrap,        TRUE, */
  1961.          /* Specify what events we want to be notified of */
  1962.          WA_IDCMP,        IDCMP_MENUPICK|IDCMP_MOUSEMOVE|
  1963.                             IDCMP_MOUSEBUTTONS|IDCMP_CLOSEWINDOW|
  1964.                             IDCMP_NEWSIZE|IDCMP_VANILLAKEY|IDCMP_RAWKEY,
  1965.          TAG_DONE);
  1966.     screentype = USE_CUSTOMSCREEN;
  1967. }
  1968. else
  1969. {
  1970.     /* Don't mess with the palette on IFF load if we're not on our own screen, at least by default */
  1971.     BLoadIFFPalettes = FALSE;
  1972.     
  1973.     if (strcmp(szPubScreenName,"Workbench") == 0)
  1974.     {
  1975.         DrawWindow = OpenWindowTags(NULL,
  1976.          WA_Left,        nUserReqLeft,
  1977.          WA_Top,        nUserReqTop,
  1978.          WA_Width,        PState.uwWidth,
  1979.          WA_Height,        PState.uwHeight,
  1980.          WA_MinWidth,        PState.nToolBoxWidth+MIN_WIDTH_OFFSET,
  1981.          WA_MinHeight,        PState.nToolBoxHeight+nTitleHeight+MIN_HEIGHT_OFFSET,
  1982.          WA_MaxWidth,        PState.uwRemoteScreenWidth,
  1983.          WA_MaxHeight,        PState.uwRemoteScreenHeight,
  1984.          WA_CloseGadget,    TRUE,
  1985.          WA_DepthGadget,    TRUE,
  1986.          WA_ScreenTitle,    sScreenTitle,
  1987.          WA_Title,        sWindowTitle,
  1988.          WA_SizeGadget,     TRUE,
  1989.          WA_Activate,        TRUE,
  1990.          WA_DragBar,        TRUE,
  1991.          WA_ReportMouse,    TRUE,
  1992.          WA_SizeBBottom,    TRUE,
  1993. /*         WA_RMBTrap,        TRUE,*/
  1994.          /* Specify what events we want to be notified of */
  1995.          WA_IDCMP,        IDCMP_MENUPICK|IDCMP_MOUSEMOVE|
  1996.                      IDCMP_MOUSEBUTTONS|IDCMP_CLOSEWINDOW|
  1997.                      IDCMP_NEWSIZE|IDCMP_VANILLAKEY|IDCMP_RAWKEY,
  1998.          TAG_DONE);                                         
  1999.         screentype = USE_WORKBENCHSCREEN;
  2000.     }
  2001.     else
  2002.     {
  2003.         DrawWindow = OpenWindowTags(NULL,
  2004.          WA_Left,           nUserReqLeft,
  2005.          WA_Top,           nUserReqTop,
  2006.          WA_Width,           PState.uwWidth,
  2007.          WA_Height,           PState.uwHeight,
  2008.          WA_MinWidth,           PState.nToolBoxWidth+MIN_WIDTH_OFFSET,
  2009.          WA_MinHeight,           PState.nToolBoxHeight+nTitleHeight+MIN_HEIGHT_OFFSET,
  2010.          WA_MaxWidth,           PState.uwRemoteScreenWidth,
  2011.          WA_MaxHeight,           PState.uwRemoteScreenHeight,
  2012.          WA_PubScreen,           Scr,
  2013.          WA_PubScreenFallBack, TRUE,
  2014.          WA_ScreenTitle,       sScreenTitle,
  2015.          WA_Title,           sWindowTitle,
  2016.          WA_CloseGadget,       TRUE,
  2017.          WA_DepthGadget,       TRUE,
  2018.          WA_SizeGadget,        TRUE,
  2019.          WA_Activate,           TRUE,
  2020.          WA_DragBar,           TRUE,
  2021.          WA_ReportMouse,       TRUE,
  2022.          WA_SizeBBottom,       TRUE,
  2023. /*         WA_RMBTrap,           TRUE,*/
  2024.          /* Specify what events we want to be notified of */
  2025.          WA_IDCMP,    IDCMP_MENUPICK    | IDCMP_MOUSEMOVE|
  2026.                         IDCMP_MOUSEBUTTONS| IDCMP_CLOSEWINDOW|
  2027.                         IDCMP_NEWSIZE     | IDCMP_VANILLAKEY|IDCMP_RAWKEY,
  2028.          TAG_DONE);    
  2029.         screentype = USE_PUBLICSCREEN;
  2030.     }
  2031. }
  2032.  
  2033. if ((DrawWindow==NULL)||(CreateDrawMenus() == FALSE)) CleanExit(RETURN_WARN);
  2034.  
  2035. /* Keep original palette values for when we Exit */
  2036. SaveScreenPalette(TRUE,-1);
  2037.  
  2038. if (BAcceptingTCP == TRUE) 
  2039. {
  2040.     Synch();
  2041.     sprintf(sBuf,"Connection to %s established.", targethost);
  2042.     SetWindowTitle(sBuf);
  2043.      OutputAction(FROM_IDCMP, COMMAND, COMMAND_HELLO, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER);
  2044. }
  2045.  
  2046. SetFont(DrawWindow->RPort, ChatFont);
  2047.  
  2048. /* Plonk down the ToolBox */
  2049. DrawToolBox();
  2050. DrawChatLines();
  2051.  
  2052. /* window IDCMP, timer IDCMP (when implemented), CTRL-C */
  2053. ulIDCMPmask =  (1L << DrawWindow->UserPort->mp_SigBit) | SIGBREAKF_CTRL_C | timerSignal;   
  2054. rexxHost = SetupARexxHost("AMISLATE",NULL);
  2055.  
  2056. if (rexxHost == NULL) Printf("Warning--couldn't open ARexx port!\n");
  2057.          else ulIDCMPmask |= (1L<<rexxHost->port->mp_SigBit);
  2058.  
  2059. SetMenuValues();
  2060.  
  2061.  
  2062. if (InitAreaStuff() == FALSE) 
  2063. {
  2064.     UserError("Couldn't allocate Temp Raster!\n");
  2065.     CleanExit(RETURN_FAIL);
  2066. }
  2067.                     
  2068. /* This is the main event loop. */
  2069. while (BProgramDone == FALSE)
  2070.  {
  2071.    if (PState.uwRexxWaitMask & REXX_REPLY_IMMEDIATE) SetStandardRexxReturns();
  2072.  
  2073.    bToDo |= DrawWait();
  2074.    if (bToDo & IDCMP_READY) {HandleIDCMP(NULL); bToDo &= ~(IDCMP_READY);}
  2075.    if (bToDo & READ_READY)  {RemoteHandler(NULL,FALSE); bToDo &= ~(READ_READY);}
  2076.    if ((bToDo & AREXX_READY)&&(PState.uwRexxWaitMask == 0)) 
  2077.                    {ARexxDispatch(rexxHost); bToDo &= ~(AREXX_READY);}
  2078.    if (bToDo & WRITE_READY) {ReduceQueue(); bToDo &= ~(WRITE_READY);}
  2079.  }    
  2080. CleanExit(RETURN_OK);        /* Exit the program */
  2081. }
  2082.