home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 19 / AACD19.BIN / AACD / System / SnoopDos / SnoopDos_Src / SnoopDos_Source / snoopdos.c < prev    next >
C/C++ Source or Header  |  2001-02-04  |  23KB  |  522 lines

  1. /*
  2.  *              SNOOPDOS.C                                                                                              vi:ts=4
  3.  *
  4.  *      Copyright (c) Eddy Carroll, September 1994.
  5.  *
  6.  *              The mainline, where we co-ordinate everything.
  7.  */
  8.  
  9. #define MAIN
  10.  
  11. #define RAWDOFMT_COPY (void (*))"\x16\xc0\x4e\x75" /* MOVE.B D0,(A3)+ | RTS */
  12.  
  13. #include "system.h"
  14. #include "snoopdos.h"
  15.  
  16. #define OldPrint(s)             Write(Output(), s, strlen(s))
  17. #define OldFPrint(f,s)  Write(f, s, strlen(s))
  18.  
  19. #if _PROFILE
  20. #include "sprof.h"
  21. #else
  22. #define PROFILE_ON()
  23. #define PROFILE_OFF()
  24. #endif
  25.  
  26. #define NAME                    "SnoopDos 3.6"
  27. #define DATENAME                "February 2001"
  28. #define DATENUM                 "4.2.2001"
  29.  
  30. #define MINSTACKSIZE            12288
  31.  
  32. char Version[]              = "$VER: " NAME " (" DATENUM ")";
  33. char SnoopDosTitle[]    = NAME " \251 Eddy Carroll, " DATENAME ".";
  34. char SnoopDosTitleKey[] = NAME " \251 Eddy Carroll, " DATENAME ". Hotkey=<%s>";
  35. char CommodityTitle[]   = NAME " by Eddy Carroll";
  36.  
  37. long __stack = MINSTACKSIZE;                    /* Ensure stack size is sufficient      */
  38.  
  39. static ULONG StartPri;                          /* Start priority of our task           */
  40. static struct StackSwapStruct  StSw;            /* For providing a larger stack         */
  41.  
  42.  
  43. struct MsgPort *IoPort;
  44. struct timerequest *TimerRequest;
  45.  
  46.  
  47. struct DosLibrary *DOSBase;              /* Need a reference or the autoinit code will build one. THOR */
  48.  
  49. /*
  50.  *              Cleanup(errcode)
  51.  *
  52.  *              Frees all resources allocated by the program and exits with
  53.  *              the specified error code
  54.  */
  55. void Cleanup(int errcode)
  56. {
  57.         CleanupHotKey();
  58.         CleanupWindows();
  59.         CleanupAGuide();
  60.         CleanupIcons();
  61.         CleanupLocale();
  62.         CleanupRexxPort();
  63.         CleanupPatches();
  64.         CleanupBuffers();
  65.  
  66.         if (TimerRequest)               {
  67.                 CloseDevice(TimerRequest);
  68.                 DeleteIORequest((struct IORequest *)TimerRequest);
  69.         }
  70.         if (IoPort)                     DeleteMsgPort(IoPort);
  71.         if (AslBase)                    CloseLibrary(AslBase);
  72.         if (RexxSysBase)                CloseLibrary(RexxSysBase);
  73.         if (DiskfontBase)               CloseLibrary(DiskfontBase);
  74.         if (GadToolsBase)               CloseLibrary(GadToolsBase);
  75.         if (IntuitionBase)              CloseLibrary(IntuitionBase);
  76.         if (LayersBase)                 CloseLibrary(LayersBase);
  77.         if (GfxBase)                    CloseLibrary(GfxBase);
  78.         if (IconBase)                   CloseLibrary(IconBase);
  79.         if (UtilityBase)                CloseLibrary(UtilityBase);
  80.         if (KeymapBase)                 CloseLibrary(KeymapBase);
  81.         if (CxBase)                     CloseLibrary(CxBase);
  82.  
  83.         /*
  84.          *              Restore our requester status and task priority before we
  85.          *              exit, in case we were run from a CLI prompt
  86.          */
  87.         *TaskWindowPtr = SaveWindowPtr;
  88.         SetTaskPri(SysBase->ThisTask, StartPri);
  89.  
  90.         if (StSw.stk_Lower) {
  91.                 StackSwap(&StSw);
  92.                 FreeMem(StSw.stk_Lower,MINSTACKSIZE+8);
  93.         }
  94.  
  95.         exit(errcode);
  96. }
  97.  
  98. /*
  99.  *              OpenLibs()
  100.  *
  101.  *              Opens all the main libraries we'll need. We must have intuition,
  102.  *              graphics, and gadtools, but everything else we can manage without.
  103.  *
  104.  *              dos.library and exec.library will already be open at this point.
  105.  *
  106.  */
  107. void OpenLibs(void)
  108. {
  109.         APTR oldwinptr = *TaskWindowPtr;
  110.  
  111.         if (SysBase->LibNode.lib_Version < 37) {
  112.                 if (WBenchMsg) {
  113.                         /*
  114.                          *              Open a text window to display error message in.
  115.                          */
  116.                         BPTR file = Open("CON:0/0/520/80/" NAME, MODE_NEWFILE);
  117.  
  118.  
  119.                         if (file) {
  120.                                 char ch;
  121.  
  122.                                 OldFPrint(file,
  123.                                                   "\nSorry, " NAME " requires Workbench 2.04 or above."
  124.                                                   "\n\nPress RETURN to close this window. ");
  125.                                 Read(file, &ch, 1);
  126.                                 Close(file);
  127.                         }
  128.                 } else {
  129.                         /*
  130.                          *              Just print it in the CLI
  131.                          */
  132.                         OldPrint("Sorry, " NAME " requires Workbench 2.04 or above.\n");
  133.                 }
  134.                 Cleanup(50);
  135.         }
  136.  
  137.         IntuitionBase = (void *)OpenLibrary("intuition.library", 37);
  138.         GfxBase       = (void *)OpenLibrary("graphics.library",  37);
  139.         LayersBase        = OpenLibrary("layers.library",          37);
  140.         GadToolsBase  = OpenLibrary("gadtools.library",    37);
  141.         IconBase      = OpenLibrary("icon.library",        0);
  142.         RexxSysBase   = OpenLibrary("rexxsyslib.library",  0);
  143.         UtilityBase   = OpenLibrary("utility.library",     0);
  144.         KeymapBase        = OpenLibrary("keymap.library",          37);
  145.  
  146.         /*
  147.          *              We don't need diskfont.library to run, but just in case we're
  148.          *              run after booting with no startup-sequence, we disable AmigaDOS
  149.          *              requesters so that diskfont.library doesn't ask us to insert
  150.          *              volume ENV:
  151.          */
  152.         *TaskWindowPtr = (APTR)-1;
  153.         DiskfontBase   = OpenLibrary("diskfont.library",    0);
  154.         *TaskWindowPtr = oldwinptr;
  155.         CxBase             = OpenLibrary("commodities.library", 37);
  156.  
  157.         if (!IntuitionBase || !GfxBase || !LayersBase) {
  158.                 OldPrint("Couldn't open intuition, graphics or layers libraries!\n");
  159.                 Cleanup(50);
  160.         }
  161.         if (!GadToolsBase || !UtilityBase || !KeymapBase) {
  162.                 OldPrint("Couldn't open gadtools, utilities or keymap library!\n");
  163.                 Cleanup(50);
  164.         }
  165.  
  166.         IoPort        = CreateMsgPort();
  167.         if (IoPort == NULL) {
  168.                 OldPrint("Couldn't create a message port for the timer.device!\n");
  169.                 Cleanup(50);
  170.         }
  171.  
  172.         TimerRequest    = (struct timerequest *)CreateIORequest(IoPort,sizeof(struct timerequest));
  173.         if (IoPort == NULL) {
  174.                 OldPrint("Couldn't create an IORequest for the timer.device!\n");
  175.                 Cleanup(50);
  176.         }
  177.  
  178.         if (OpenDevice("timer.device",UNIT_VBLANK,TimerRequest,0)) {
  179.                 DeleteIORequest((struct IORequest *)TimerRequest);
  180.                 TimerRequest = NULL;
  181.                 OldPrint("Couldn't open the timer.device!\n");
  182.                 Cleanup(50);
  183.         }
  184.  
  185. }
  186.  
  187. /*
  188.  *              My own version of sprintf, using the exec routine. Saves pulling
  189.  *              in a lot of unnecessary library routines (5-10K!)
  190.  */
  191. void mysprintf(char *outstr, char *fmtstr, ...)
  192. {
  193.         RawDoFmt(fmtstr, &fmtstr+1, RAWDOFMT_COPY, outstr);
  194. }
  195.  
  196. /*
  197.  *              InstallSettings(set, which)
  198.  *
  199.  *              Installs the specified set of settings into CurSettings, and
  200.  *              adjusts any other variables that may be required to reflect
  201.  *              these new settings.
  202.  *
  203.  *              This includes updating the appropriate windows if necessary.
  204.  */
  205. void InstallSettings(Settings *set, int which)
  206. {
  207.         int resetwin    = 0;
  208.         int redrawwin   = 0;
  209.  
  210.         if (which & SET_FUNC) {
  211.                 /*
  212.                  *              First, go down through the new function options and
  213.                  *              update the function window to match the new set of
  214.                  *              options. For speed, we only update those that are
  215.                  *              different.
  216.                  */
  217.                 if (FuncWindow) {
  218.                         ShowFuncOpts(set->Func.Opts, FIRST_BOOL_GADGET, LAST_BOOL_GADGET);
  219.                         ResetFuncToSelected();
  220.                         if (strcmp(CurSettings.Func.Pattern, set->Func.Pattern) != 0) {
  221.                                 GT_SetGadgetAttrs(Gadget[GID_MATCHNAME], FuncWindow, NULL,
  222.                                                                   GTST_String,  set->Func.Pattern,
  223.                                                                   TAG_DONE);
  224.                         }
  225.                 }
  226.                 CurSettings.Func = set->Func;
  227.                 LoadFuncSettings(&set->Func);
  228.         }
  229.         if (which & SET_SETUP) {
  230.                 struct SetupSettings *curset = &CurSettings.Setup;
  231.                 struct SetupSettings *newset = &set->Setup;
  232.                 char oldwinfont[MAX_SHORT_LEN+2];
  233.                 char oldbuffont[MAX_SHORT_LEN+2];
  234.                 int  oldwinsize;
  235.                 int  oldbufsize;
  236.  
  237.                 if (!CxBase)
  238.                         newset->HideMethod = HIDE_NONE;
  239.  
  240.                 if (SetWindow) {
  241.                         /*
  242.                          *              Update settings window to reflect new gadget settings
  243.                          *
  244.                          *              While we can optimise some of our update methods, we
  245.                          *              have to blindly ALWAYS update string gadgets since
  246.                          *              we have no way of knowing if they have been changed
  247.                          *              by the user in a way that was not yet detected by
  248.                          *              SnoopDos (e.g. entering a new value and forgetting
  249.                          *              to press RETURN).
  250.                          */
  251.                         if (curset->HideMethod != newset->HideMethod)
  252.                                 GT_SetGadgetAttrs(Gadget[GID_HIDEMETHOD], SetWindow, NULL,
  253.                                                                   GTCY_Active,          newset->HideMethod,
  254.                                                                   TAG_DONE);
  255.  
  256.                         if (curset->ScreenType != newset->ScreenType)
  257.                                 GT_SetGadgetAttrs(Gadget[GID_OPENON], SetWindow, NULL,
  258.                                                                   GTCY_Active,          newset->ScreenType,
  259.                                                                   TAG_DONE);
  260.  
  261.                         if (curset->LogMode != newset->LogMode)
  262.                                 GT_SetGadgetAttrs(Gadget[GID_LOGMODE], SetWindow, NULL,
  263.                                                                   GTCY_Active,          newset->LogMode,
  264.                                                                   TAG_DONE);
  265.  
  266.                         if (curset->FileIOType != newset->FileIOType)
  267.                                 GT_SetGadgetAttrs(Gadget[GID_FILEIO], SetWindow, NULL,
  268.                                                                   GTCY_Active,          newset->FileIOType,
  269.                                                                   TAG_DONE);
  270.  
  271.                         GT_SetGadgetAttrs(Gadget[GID_BUFFERSIZE], SetWindow, NULL,
  272.                                                           GTIN_Number,          newset->BufferSize,
  273.                                                           TAG_DONE);
  274.  
  275.                         GT_SetGadgetAttrs(Gadget[GID_HOTKEY], SetWindow, NULL,
  276.                                                           GTST_String,          newset->HotKey,
  277.                                                           TAG_DONE);
  278.  
  279.                         GT_SetGadgetAttrs(Gadget[GID_SCREENNAME], SetWindow, NULL,
  280.                                                           GTST_String,          newset->ScreenName,
  281.                                                           TAG_DONE);
  282.  
  283.                         GT_SetGadgetAttrs(Gadget[GID_LOGFILE], SetWindow, NULL,
  284.                                                           GTST_String,          newset->LogFile,
  285.                                                           TAG_DONE);
  286.  
  287.                         GT_SetGadgetAttrs(Gadget[GID_BUFFORMAT], SetWindow, NULL,
  288.                                                           GTST_String,  newset->BufferFormat,
  289.                                                           TAG_DONE);
  290.  
  291.                         GT_SetGadgetAttrs(Gadget[GID_LOGFORMAT], SetWindow, NULL,
  292.                                                           GTST_String,  newset->LogfileFormat,
  293.                                                           TAG_DONE);
  294.                 }
  295.                 if (strcmp(curset->HotKey, newset->HotKey) != 0) {
  296.                         InstallHotKey(newset->HotKey);
  297.                         SetMainHideState(newset->HideMethod);
  298.                 }
  299.                 if (newset->HideMethod != curset->HideMethod) {
  300.                         if (newset->HideMethod == HIDE_NONE)
  301.                                 CleanupHotKey();
  302.                         else {
  303.                                 curset->HideMethod = newset->HideMethod;
  304.                                 InstallHotKey(newset->HotKey);
  305.                         }
  306.                         SetMainHideState(newset->HideMethod);
  307.                 }
  308.                 if (curset->BufferSize != newset->BufferSize) {
  309.                         ClearWindowBuffer();
  310.                         if (!SetTotalBufferSize(newset->BufferSize * 1024,
  311.                                                                                                                         SETBUF_FORCENEW)) {
  312.                                 ShowError(MSG(MSG_ERROR_NOBUFMEM), newset->BufferSize);
  313.                                 Cleanup(20);
  314.                         }
  315.                 }
  316.                 if (strcmp(curset->BufferFormat, newset->BufferFormat)) {
  317.                         strcpy(curset->BufferFormat, newset->BufferFormat);
  318.                         InstallNewFormat(NEW_STRING);
  319.                 }
  320.  
  321.                 /*
  322.                  *              Since the font settings may have been reset to the default
  323.                  *              fonts (i.e. size = 0) we need to change them to actual
  324.                  *              font names before we check if they've changed. Thus, we
  325.                  *              must save the existing names first (since InitFonts()
  326.                  *              modifies the current settings directly and would trash
  327.                  *              them).
  328.                  */
  329.                 strcpy(oldwinfont, curset->WindowFont);
  330.                 strcpy(oldbuffont, curset->BufferFont);
  331.                 oldwinsize = curset->WinFontSize;
  332.                 oldbufsize = curset->BufFontSize;
  333.  
  334.                 if (curset->LogMode != newset->LogMode)
  335.                         SetLogGadget(newset->LogMode, LG_REFRESH);
  336.  
  337.                 *curset = *newset;                              /* Copy in new settings */
  338.  
  339.                 if (curset->WinFontSize == 0 || curset->BufFontSize == 0)
  340.                         InitFonts();
  341.  
  342.                 if (strcmp(oldbuffont, curset->BufferFont) != 0 ||
  343.                                    oldbufsize != curset->BufFontSize    ||
  344.                         strcmp(oldwinfont, curset->WindowFont) != 0 ||
  345.                                    oldwinsize != curset->WinFontSize)
  346.                 {
  347.                         /*
  348.                          *              Got a font change so update font info
  349.                          *              accordingly and set flag to say we need
  350.                          *              to reset the main window.
  351.                          */
  352.                         extern struct TextAttr WindowFontAttr;
  353.                         extern struct TextAttr BufferFontAttr;
  354.  
  355.                         WindowFontAttr.ta_YSize = curset->WinFontSize;
  356.                         BufferFontAttr.ta_YSize = curset->BufFontSize;
  357.                         resetwin = 1;
  358.                         if (SetWindow) {
  359.                                 GT_SetGadgetAttrs(Gadget[GID_WINDOWFONT], SetWindow, NULL,
  360.                                                                   GTTX_Text, GetFontDesc(WindowFontDesc,
  361.                                                                                                                  WindowFontName,
  362.                                                                                                                  WindowFontSize),
  363.                                                                   TAG_DONE);
  364.  
  365.                                 GT_SetGadgetAttrs(Gadget[GID_BUFFERFONT], SetWindow, NULL,
  366.                                                                   GTTX_Text, GetFontDesc(BufferFontDesc,
  367.                                                                                                                  BufferFontName,
  368.                                                                                                                  BufferFontSize),
  369.                                                                   TAG_DONE);
  370.                         }
  371.                         PurgeFuncGadgets = 1;     /* Ensure function window gets updated */
  372.                         if (!FuncWindow)
  373.                                 CloseFunctionWindow();  /* Free gadgets now if window closed */
  374.                 }
  375.  
  376.                 /*
  377.                  *              Now update everything to take advantage of the new settings
  378.                  */
  379.         }
  380.         if ((which & SET_MAIN) == SET_MAIN) {
  381.                 int updatefunc = set->StackLimit != CurSettings.StackLimit;
  382.  
  383.                 if (CurSettings.SimpleRefresh != set->SimpleRefresh)
  384.                         resetwin = 1;
  385.  
  386.                 if (!resetwin && set->TextSpacing != BoxInterGap)
  387.                         SetTextSpacing(set->TextSpacing);
  388.                 else if (set->RightAlign != RightAligned && !resetwin && MainWindow) {
  389.                         RightAligned = set->RightAlign;
  390.                         ShowBuffer(TopSeq, DISPLAY_ALL);
  391.                 }
  392.                 if (set->ShowStatus != StatusLine || set->ShowGadgets != GadgetsLine)
  393.                         redrawwin = 1;
  394.  
  395.                 CurSettings = *set;                                     /* Copy all settings                     */
  396.                 InitFonts();                                            /* Make sure fonts are current   */
  397.                 SetMenuOptions();                                       /* Update main menu if necessary */
  398.  
  399.                 if (updatefunc) {
  400.                         /*
  401.                          *              If we changed our stack limit, re-install all the
  402.                          *              function settings ... this has the side effect of
  403.                          *              fixing up the stack on the way
  404.                          */
  405.                         LoadFuncSettings(&set->Func);
  406.                 }
  407.         }
  408.         if (resetwin) {
  409.                 ReOpenMainWindow();
  410.         } else if (redrawwin) {
  411.            RecalcMainWindow(MainWindow->Width, MainWindow->Height, REDRAW_GADGETS);
  412.         }
  413. }
  414.  
  415. /*
  416.  *              MainLoop()
  417.  *
  418.  *              Opens the main window, then processes all incoming events
  419.  */
  420. void MainLoop(void)
  421. {
  422.         if (QuitFlag)
  423.                 return;
  424.  
  425.         if (HideOnStartup) {
  426.                 HideSnoopDos();
  427.         } else {
  428.                 if (!ShowSnoopDos()) {
  429.                         ShowError(MSG(MSG_ERROR_INITGUI));
  430.                         return;
  431.                 }
  432.         }
  433.  
  434.         while (!QuitFlag) {
  435.                 ULONG mask;
  436.  
  437.                 PROFILE_OFF();
  438.                 mask = Wait(MainWindowMask              |
  439.                                         FuncWindowMask          |
  440.                                         FormWindowMask          |
  441.                                         SetWindowMask           |
  442.                                         NewEventMask            |
  443.                                         ScanDosListMask         |
  444.                                         AmigaGuideMask          |
  445.                                         CommodityMask           |
  446.                                         RexxPortMask        |
  447.                                         WorkbenchMask           |
  448.                                         SIGBREAKF_CTRL_C        |
  449.                                         SIGBREAKF_CTRL_D        |
  450.                                         SIGBREAKF_CTRL_E        |
  451.                                         SIGBREAKF_CTRL_F);
  452.                 PROFILE_ON();
  453.  
  454.                 if (mask & MainWindowMask)              HandleMainMsgs();
  455.                 if (mask & FuncWindowMask)              HandleFuncMsgs();
  456.                 if (mask & FormWindowMask)              HandleFormatMsgs();
  457.                 if (mask & SetWindowMask)               HandleSettingsMsgs();
  458.                 if (mask & NewEventMask)                HandleNewEvents();
  459.                 if (mask & ScanDosListMask)             UpdateDeviceList(SCANDEV_DELAY);
  460.                 if (mask & AmigaGuideMask)              HandleAGuideMsgs();
  461.                 if (mask & CommodityMask)               HandleHotKeyMsgs();
  462.                 if (mask & RexxPortMask)        HandleRexxMsgs();
  463.                 if (mask & WorkbenchMask)               HandleWorkbenchMsgs();
  464.                 if (mask & SIGBREAKF_CTRL_C)    QuitFlag = 1;
  465.                 if (mask & SIGBREAKF_CTRL_D)    SetMonitorMode(MONITOR_DISABLED);
  466.                 if (mask & SIGBREAKF_CTRL_E)    SetMonitorMode(MONITOR_NORMAL);
  467.                 if (mask & SIGBREAKF_CTRL_F)    ShowSnoopDos();
  468.         }
  469.         CleanupWindows();
  470. }
  471.  
  472. int main(int argc, char **argv)
  473. {
  474.         struct Process *myproc = (struct Process *)(SysBase->ThisTask);
  475.         ULONG  stacksize;
  476.  
  477.         TaskWindowPtr = &(myproc->pr_WindowPtr);
  478.         SaveWindowPtr = *TaskWindowPtr;
  479.         StartPri      = SysBase->ThisTask->tc_Node.ln_Pri;
  480.  
  481.         /*
  482.          * Because some people never read manuals...
  483.          * exchange the stack if we are too low.
  484.          *
  485.          */
  486.  
  487.         stacksize = (ULONG)myproc->pr_Task.tc_SPUpper-(ULONG)myproc->pr_Task.tc_SPLower;
  488.         if (stacksize < MINSTACKSIZE) {
  489.                 StSw.stk_Lower          =       AllocMem(MINSTACKSIZE+8,MEMF_PUBLIC);
  490.                 if (StSw.stk_Lower == NULL) {
  491.                         return 30;              /* Yikes! */
  492.                 }
  493.                 StSw.stk_Upper          =       (ULONG)StSw.stk_Lower + MINSTACKSIZE;
  494.                 StSw.stk_Pointer        =       (void *)StSw.stk_Upper;
  495.  
  496.                 StackSwap(&StSw);
  497.         } else  {
  498.                 StSw.stk_Lower          = NULL;
  499.         }
  500.  
  501.         OpenLibs();
  502.  
  503.         InitSettings();
  504.         InitTextTable();
  505.         InitRexxPort();
  506.         InitBuffers();
  507.         CheckSegTracker();
  508.         /*
  509.          *              Now parse our startup options, read default configuration files
  510.          *              and so on.
  511.          */
  512.         if (!ParseStartupOpts(argc, argv))
  513.                 Cleanup(0);
  514.  
  515.         RestoreSettings = CurSettings;  /* Record for later restoration */
  516.         MainLoop();
  517.         SetMonitorMode(MONITOR_DISABLED);
  518.         Cleanup(0);
  519.  
  520.         return 0;
  521. }
  522.