/* * SNOOPDOS.C vi:ts=4 * * Copyright (c) Eddy Carroll, September 1994. * * The mainline, where we co-ordinate everything. */ #define MAIN #define RAWDOFMT_COPY (void (*))"\x16\xc0\x4e\x75" /* MOVE.B D0,(A3)+ | RTS */ #include "system.h" #include "snoopdos.h" #define OldPrint(s) Write(Output(), s, strlen(s)) #define OldFPrint(f,s) Write(f, s, strlen(s)) #if _PROFILE #include "sprof.h" #else #define PROFILE_ON() #define PROFILE_OFF() #endif #define NAME "SnoopDos 3.0" #define DATENAME "September 1994" #define DATENUM "15.9.94" char Version[] = "$VER: " NAME " (" DATENUM ")"; char SnoopDosTitle[] = NAME " \251 Eddy Carroll, " DATENAME "."; char SnoopDosTitleKey[] = NAME " \251 Eddy Carroll, " DATENAME ". Hotkey=<%s>"; char CommodityTitle[] = NAME " by Eddy Carroll"; long __stack = MINSTACKSIZE; /* Ensure stack size is sufficient */ static ULONG StartPri; /* Start priority of our task */ /* * Cleanup(errcode) * * Frees all resources allocated by the program and exits with * the specified error code */ void Cleanup(int errcode) { CleanupHotKey(); CleanupWindows(); CleanupAGuide(); CleanupIcons(); CleanupLocale(); CleanupRexxPort(); CleanupPatches(); CleanupBuffers(); if (AslBase) CloseLibrary(AslBase); if (RexxSysBase) CloseLibrary(RexxSysBase); if (DiskfontBase) CloseLibrary(DiskfontBase); if (GadToolsBase) CloseLibrary(GadToolsBase); if (IntuitionBase) CloseLibrary(IntuitionBase); if (LayersBase) CloseLibrary(LayersBase); if (GfxBase) CloseLibrary(GfxBase); if (IconBase) CloseLibrary(IconBase); if (UtilityBase) CloseLibrary(UtilityBase); if (KeymapBase) CloseLibrary(KeymapBase); if (CxBase) CloseLibrary(CxBase); /* * Restore our requester status and task priority before we * exit, in case we were run from a CLI prompt */ *TaskWindowPtr = SaveWindowPtr; SetTaskPri(SysBase->ThisTask, StartPri); exit(errcode); } /* * OpenLibs() * * Opens all the main libraries we'll need. We must have intuition, * graphics, and gadtools, but everything else we can manage without. * * dos.library and exec.library will already be open at this point. * */ void OpenLibs(void) { APTR oldwinptr = *TaskWindowPtr; if (SysBase->LibNode.lib_Version < 37) { if (WBenchMsg) { /* * Open a text window to display error message in. */ BPTR file = Open("CON:0/0/520/80/SnoopDos 3.0", MODE_NEWFILE); if (file) { char ch; OldFPrint(file, "\nSorry, " NAME " requires Workbench 2.04 or above." "\n\nPress RETURN to close this window. "); Read(file, &ch, 1); Close(file); } } else { /* * Just print it in the CLI */ OldPrint("Sorry, " NAME " requires Workbench 2.04 or above.\n"); } Cleanup(50); } IntuitionBase = (void *)OpenLibrary("intuition.library", 37); GfxBase = (void *)OpenLibrary("graphics.library", 37); LayersBase = OpenLibrary("layers.library", 37); GadToolsBase = OpenLibrary("gadtools.library", 37); IconBase = OpenLibrary("icon.library", 0); RexxSysBase = OpenLibrary("rexxsyslib.library", 0); UtilityBase = OpenLibrary("utility.library", 0); KeymapBase = OpenLibrary("keymap.library", 37); /* * We don't need diskfont.library to run, but just in case we're * run after booting with no startup-sequence, we disable AmigaDOS * requesters so that diskfont.library doesn't ask us to insert * volume ENV: */ *TaskWindowPtr = (APTR)-1; DiskfontBase = OpenLibrary("diskfont.library", 0); *TaskWindowPtr = oldwinptr; CxBase = OpenLibrary("commodities.library", 37); if (!IntuitionBase || !GfxBase || !LayersBase) { OldPrint("Couldn't open intuition, graphics or layers libraries!\n"); Cleanup(50); } if (!GadToolsBase || !UtilityBase || !KeymapBase) { OldPrint("Couldn't open gadtools, utilities or keymap library!\n"); Cleanup(50); } } /* * My own version of sprintf, using the exec routine. Saves pulling * in a lot of unnecessary library routines (5-10K!) */ void mysprintf(char *outstr, char *fmtstr, ...) { RawDoFmt(fmtstr, &fmtstr+1, RAWDOFMT_COPY, outstr); } /* * InstallSettings(set, which) * * Installs the specified set of settings into CurSettings, and * adjusts any other variables that may be required to reflect * these new settings. * * This includes updating the appropriate windows if necessary. */ void InstallSettings(Settings *set, int which) { int resetwin = 0; int redrawwin = 0; if (which & SET_FUNC) { /* * First, go down through the new function options and * update the function window to match the new set of * options. For speed, we only update those that are * different. */ if (FuncWindow) { ShowFuncOpts(set->Func.Opts, FIRST_BOOL_GADGET, LAST_BOOL_GADGET); ResetFuncToSelected(); if (strcmp(CurSettings.Func.Pattern, set->Func.Pattern) != 0) { GT_SetGadgetAttrs(Gadget[GID_MATCHNAME], FuncWindow, NULL, GTST_String, set->Func.Pattern, TAG_DONE); } } CurSettings.Func = set->Func; LoadFuncSettings(&set->Func); } if (which & SET_SETUP) { struct SetupSettings *curset = &CurSettings.Setup; struct SetupSettings *newset = &set->Setup; char oldwinfont[MAX_SHORT_LEN+2]; char oldbuffont[MAX_SHORT_LEN+2]; int oldwinsize; int oldbufsize; if (!CxBase) newset->HideMethod = HIDE_NONE; if (SetWindow) { /* * Update settings window to reflect new gadget settings * * While we can optimise some of our update methods, we * have to blindly ALWAYS update string gadgets since * we have no way of knowing if they have been changed * by the user in a way that was not yet detected by * SnoopDos (e.g. entering a new value and forgetting * to press RETURN). */ if (curset->HideMethod != newset->HideMethod) GT_SetGadgetAttrs(Gadget[GID_HIDEMETHOD], SetWindow, NULL, GTCY_Active, newset->HideMethod, TAG_DONE); if (curset->ScreenType != newset->ScreenType) GT_SetGadgetAttrs(Gadget[GID_OPENON], SetWindow, NULL, GTCY_Active, newset->ScreenType, TAG_DONE); if (curset->LogMode != newset->LogMode) GT_SetGadgetAttrs(Gadget[GID_LOGMODE], SetWindow, NULL, GTCY_Active, newset->LogMode, TAG_DONE); if (curset->FileIOType != newset->FileIOType) GT_SetGadgetAttrs(Gadget[GID_FILEIO], SetWindow, NULL, GTCY_Active, newset->FileIOType, TAG_DONE); GT_SetGadgetAttrs(Gadget[GID_BUFFERSIZE], SetWindow, NULL, GTIN_Number, newset->BufferSize, TAG_DONE); GT_SetGadgetAttrs(Gadget[GID_HOTKEY], SetWindow, NULL, GTST_String, newset->HotKey, TAG_DONE); GT_SetGadgetAttrs(Gadget[GID_SCREENNAME], SetWindow, NULL, GTST_String, newset->ScreenName, TAG_DONE); GT_SetGadgetAttrs(Gadget[GID_LOGFILE], SetWindow, NULL, GTST_String, newset->LogFile, TAG_DONE); GT_SetGadgetAttrs(Gadget[GID_BUFFORMAT], SetWindow, NULL, GTST_String, newset->BufferFormat, TAG_DONE); GT_SetGadgetAttrs(Gadget[GID_LOGFORMAT], SetWindow, NULL, GTST_String, newset->LogfileFormat, TAG_DONE); } if (strcmp(curset->HotKey, newset->HotKey) != 0) { InstallHotKey(newset->HotKey); SetMainHideState(newset->HideMethod); } if (newset->HideMethod != curset->HideMethod) { if (newset->HideMethod == HIDE_NONE) CleanupHotKey(); else { curset->HideMethod = newset->HideMethod; InstallHotKey(newset->HotKey); } SetMainHideState(newset->HideMethod); } if (curset->BufferSize != newset->BufferSize) { ClearWindowBuffer(); if (!SetTotalBufferSize(newset->BufferSize * 1024, SETBUF_FORCENEW)) { ShowError(MSG(MSG_ERROR_NOBUFMEM), newset->BufferSize); Cleanup(20); } } if (strcmp(curset->BufferFormat, newset->BufferFormat)) { strcpy(curset->BufferFormat, newset->BufferFormat); InstallNewFormat(NEW_STRING); } /* * Since the font settings may have been reset to the default * fonts (i.e. size = 0) we need to change them to actual * font names before we check if they've changed. Thus, we * must save the existing names first (since InitFonts() * modifies the current settings directly and would trash * them). */ strcpy(oldwinfont, curset->WindowFont); strcpy(oldbuffont, curset->BufferFont); oldwinsize = curset->WinFontSize; oldbufsize = curset->BufFontSize; if (curset->LogMode != newset->LogMode) SetLogGadget(newset->LogMode, LG_REFRESH); *curset = *newset; /* Copy in new settings */ if (curset->WinFontSize == 0 || curset->BufFontSize == 0) InitFonts(); if (strcmp(oldbuffont, curset->BufferFont) != 0 || oldbufsize != curset->BufFontSize || strcmp(oldwinfont, curset->WindowFont) != 0 || oldwinsize != curset->WinFontSize) { /* * Got a font change so update font info * accordingly and set flag to say we need * to reset the main window. */ extern struct TextAttr WindowFontAttr; extern struct TextAttr BufferFontAttr; WindowFontAttr.ta_YSize = curset->WinFontSize; BufferFontAttr.ta_YSize = curset->BufFontSize; resetwin = 1; if (SetWindow) { GT_SetGadgetAttrs(Gadget[GID_WINDOWFONT], SetWindow, NULL, GTTX_Text, GetFontDesc(WindowFontDesc, WindowFontName, WindowFontSize), TAG_DONE); GT_SetGadgetAttrs(Gadget[GID_BUFFERFONT], SetWindow, NULL, GTTX_Text, GetFontDesc(BufferFontDesc, BufferFontName, BufferFontSize), TAG_DONE); } PurgeFuncGadgets = 1; /* Ensure function window gets updated */ if (!FuncWindow) CloseFunctionWindow(); /* Free gadgets now if window closed */ } /* * Now update everything to take advantage of the new settings */ } if ((which & SET_MAIN) == SET_MAIN) { int updatefunc = set->StackLimit != CurSettings.StackLimit; if (CurSettings.SimpleRefresh != set->SimpleRefresh) resetwin = 1; if (!resetwin && set->TextSpacing != BoxInterGap) SetTextSpacing(set->TextSpacing); else if (set->RightAlign != RightAligned && !resetwin && MainWindow) { RightAligned = set->RightAlign; ShowBuffer(TopSeq, DISPLAY_ALL); } if (set->ShowStatus != StatusLine || set->ShowGadgets != GadgetsLine) redrawwin = 1; CurSettings = *set; /* Copy all settings */ InitFonts(); /* Make sure fonts are current */ SetMenuOptions(); /* Update main menu if necessary */ if (updatefunc) { /* * If we changed our stack limit, re-install all the * function settings ... this has the side effect of * fixing up the stack on the way */ LoadFuncSettings(&set->Func); } } if (resetwin) { ReOpenMainWindow(); } else if (redrawwin) { RecalcMainWindow(MainWindow->Width, MainWindow->Height, REDRAW_GADGETS); } } /* * MainLoop() * * Opens the main window, then processes all incoming events */ void MainLoop(void) { if (QuitFlag) return; if (HideOnStartup) { HideSnoopDos(); } else { if (!ShowSnoopDos()) { ShowError(MSG(MSG_ERROR_INITGUI)); return; } } while (!QuitFlag) { ULONG mask; PROFILE_OFF(); mask = Wait(MainWindowMask | FuncWindowMask | FormWindowMask | SetWindowMask | NewEventMask | ScanDosListMask | AmigaGuideMask | CommodityMask | RexxPortMask | WorkbenchMask | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F); PROFILE_ON(); if (mask & MainWindowMask) HandleMainMsgs(); if (mask & FuncWindowMask) HandleFuncMsgs(); if (mask & FormWindowMask) HandleFormatMsgs(); if (mask & SetWindowMask) HandleSettingsMsgs(); if (mask & NewEventMask) HandleNewEvents(); if (mask & ScanDosListMask) UpdateDeviceList(SCANDEV_DELAY); if (mask & AmigaGuideMask) HandleAGuideMsgs(); if (mask & CommodityMask) HandleHotKeyMsgs(); if (mask & RexxPortMask) HandleRexxMsgs(); if (mask & WorkbenchMask) HandleWorkbenchMsgs(); if (mask & SIGBREAKF_CTRL_C) QuitFlag = 1; if (mask & SIGBREAKF_CTRL_D) SetMonitorMode(MONITOR_DISABLED); if (mask & SIGBREAKF_CTRL_E) SetMonitorMode(MONITOR_NORMAL); if (mask & SIGBREAKF_CTRL_F) ShowSnoopDos(); } CleanupWindows(); } int main(int argc, char **argv) { struct Process *myproc = (struct Process *)(SysBase->ThisTask); TaskWindowPtr = &(myproc->pr_WindowPtr); SaveWindowPtr = *TaskWindowPtr; StartPri = SysBase->ThisTask->tc_Node.ln_Pri; OpenLibs(); InitSettings(); InitTextTable(); InitRexxPort(); InitBuffers(); CheckSegTracker(); /* * Now parse our startup options, read default configuration files * and so on. */ if (!ParseStartupOpts(argc, argv)) Cleanup(0); RestoreSettings = CurSettings; /* Record for later restoration */ MainLoop(); SetMonitorMode(MONITOR_DISABLED); Cleanup(0); return (0); }