home *** CD-ROM | disk | FTP | other *** search
- /*
- * Task Priority Manager
- * Copyright 1993, 1994 Barry McConnell
- * bmccnnll@tcd.ie
- *
- * A library of little functions called from within the main program,
- * sorted alphabetically.
- *
- * Set tab stops to 4 when editing this file.
- */
-
- #include "PriMan.h"
-
- /*
- * My version of sprintf requires this define, for the function passed to
- * RawDoFmt(). Thanks to Eddy Carroll & SnoopDos for this...
- */
- #define RAWDOFMT_COPY (void (*))"\x16\xc0\x4e\x75" /* MOVE.B D0,(A3)+ ; RTS */
-
- /*
- * The BusyPointer() and NormalPointer() functions rely on these requester
- * structures. By declaring them as static, they aren't visible outside
- * this file and the calling functions need not worry about them.
- */
- static struct Requester req1, req2;
-
- /*
- * It is possible that BusyPointer() might be called twice (or more) in
- * succession, by some code that doesn't realise one is already up. So we
- * use a variable (again only visible to this file) to say how many times
- * it has been called. Only the first time round do we actually put up the
- * busy pointer (the system will crash if we try to re-use the blocking
- * requester structure).
- *
- * When NormalPointer() is called, the variable is decremented. Only once
- * it gets back down to zero do we restore the pointer.
- */
- static int busyCount;
-
- /*
- * This is an image of the standard Busy pointer, which the BusyPointer()
- * function uses when not running under V39.
- */
- UWORD __chip waitPointer[] =
- {
- 0x0000, 0x0000,
- 0x0400, 0x07c0,
- 0x0000, 0x07c0,
- 0x0100, 0x0380,
- 0x0000, 0x07e0,
- 0x07c0, 0x1ff8,
- 0x1ff0, 0x3fec,
- 0x3ff8, 0x7fde,
- 0x3ff8, 0x7fbe,
- 0x7ffc, 0xff7f,
- 0x7efc, 0xffff,
- 0x7ffc, 0xffff,
- 0x3ff8, 0x7ffe,
- 0x3ff8, 0x7ffe,
- 0x1ff0, 0x3ffc,
- 0x07c0, 0x1ff8,
- 0x0000, 0x07e0,
- 0x0000, 0x0000,
- };
-
- /*
- * Display a busy pointer in both windows, and prevent the user from
- * clicking on any gadgets. Also effectively disable the size gadget.
- * We are careful to make sure that each window is actually open before
- * putting up a busy pointer in it, and also that there isn't already a
- * busy pointer showing!
- */
- void BusyPointer()
- {
- if (++busyCount == 1)
- {
- if (mainWindow)
- {
- /*
- * To disable the size gadget, we make the minimum and maximum window
- * dimensions equal to the current window dimensions.
- */
- WindowLimits(mainWindow, mainWindow -> Width, mainWindow -> Height,
- mainWindow -> Width, mainWindow -> Height);
-
- /*
- * To disable the main window's gadgets, we put up an invisible
- * "blocking requester".
- */
- Request(&req1, mainWindow);
-
- /*
- * There are two different ways of putting up a busy pointer, depending
- * on which OS version we're running under.
- */
- if (osver < 39)
- SetPointer(mainWindow, waitPointer, 16, 16, -6, 0);
- else
- SetWindowPointer(mainWindow, WA_BusyPointer, TRUE,
- WA_PointerDelay, TRUE,
- TAG_END);
- }
-
- /*
- * The exact same things are done for the Settings window (except we
- * don't need to worry about the size gadget!).
- */
- if (setWindow)
- {
- Request(&req2, setWindow);
-
- if (osver < 39)
- SetPointer(setWindow, waitPointer, 16, 16, -6, 0);
- else
- SetWindowPointer(setWindow, WA_BusyPointer, TRUE,
- WA_PointerDelay, TRUE,
- TAG_END);
- }
- }
- }
-
-
- /*
- * Close the main window if it's open, freeing up its gadgets and menus if
- * necessary. Also remember its position and dimensions in case we later
- * want to re-open it.
- */
- void CloseMainWindow()
- {
- if (mainWindow)
- {
- if (menuStrip)
- {
- ClearMenuStrip(mainWindow);
- FreeMenus(menuStrip);
- }
- GetPos();
- CloseWindowSafely(mainWindow);
- mainWindow = NULL;
- }
-
- FreeGadgets(mainGads);
- mainGads = NULL;
-
- /*
- * Chances are we will also have opened some fonts. We close them here,
- * and then free up the VisualInfo structure, as well as releasing our
- * lock on the screen.
- */
- if (propFont)
- {
- CloseFont(propFont);
- propFont = NULL;
- }
-
- if (monoFont)
- {
- CloseFont(monoFont);
- monoFont = NULL;
- }
-
- if (visInfo)
- {
- FreeVisualInfo(visInfo);
- visInfo = NULL;
- }
-
- if (myScreen)
- {
- UnlockPubScreen(NULL, myScreen);
- myScreen = NULL;
- }
- }
-
-
- /*
- * Close the settings window if it's open. It's tricky to free up any
- * attached gadgets, since the last gadget in the list of gadgets pointed
- * to by setGads[3] (the Page gadget, and the buttons at the bottom of the
- * window) may have been modified to point to one of the other gadget
- * lists, depending on what is showing. So we first remove the "other"
- * gadget list (using the page variable to see what it is) which should
- * sever the link, before freeing each individual list. It should never
- * happen that the Settings window is open without a second set of gadgets
- * in it, but even if this occurs, RemoveGList() won't mind if it doesn't
- * find them.
- */
- void CloseSettingsWindow()
- {
- int i; /* page number */
-
- if (setWindow)
- {
- RemoveGList(setWindow, setGads[page], -1);
- CloseWindowSafely(setWindow);
- setWindow = NULL;
- }
- for (i = 0; i < 4; i++)
- {
- FreeGadgets(setGads[i]);
- setGads[i] = NULL;
- }
- }
-
-
- /*
- * Safely close a window that might have a shared IDCMP. This is done by
- * removing all messages from the window's MsgPort that refer to the
- * window. (We can't just remove every message, in case some of them are
- * actually meant for another window with the same IDCMP.)
- */
- void CloseWindowSafely(struct Window *window)
- {
- struct IntuiMessage *msg; /* message in window's port */
- struct Node *succ; /* next message */
-
- /*
- * First we need to disable multitasking, so we don't run into race
- * conditions with Intuition.
- */
- Forbid();
-
- /*
- * Next we get a pointer to the first message in the window's MsgPort.
- */
- msg = (struct IntuiMessage *)window -> UserPort -> mp_MsgList.lh_Head;
-
- /*
- * We loop around until we reach the last message.
- */
- while (succ = msg -> ExecMessage.mn_Node.ln_Succ)
- {
- if (msg -> IDCMPWindow == window)
- {
- /*
- * Once we have a message destined for this window, we remove
- * it from the MsgPort, and reply to it.
- */
- Remove((struct Node *)msg);
- ReplyMsg((struct Message *)msg);
- }
-
- /*
- * "msg" will be invalid if it was freed above, which is why we
- * took a copy of its successor at the start of the loop.
- */
- msg = (struct IntuiMessage *)succ;
- }
-
- /*
- * When we close the window, we don't want Intuition to free up the
- * MsgPort itself (in case another window uses it too), so we remove
- * all traces of it here. We also set the window's IDCMP to NULL so
- * Intuition doesn't try sending it any more messages.
- */
- window -> UserPort = NULL;
- ModifyIDCMP(window, NULL);
-
- /*
- * Finally we can re-enable multitasking, and close the window safely.
- */
- Permit();
- CloseWindow(window);
- }
-
-
- /*
- * Compare two strings. Like strcmp() but case-insensitive.
- */
- int Compare(char *s, char *t)
- {
- /*
- * This bit is tricky. The loop only continues as long as:
- *
- * - The upper-case versions of the current character in each string
- * match, and;
- *
- * - The current character in the first string is not NULL (if we have
- * reached a NULL in the second string instead, the first condition
- * above would not hold true!);
- *
- * (Okay, so I could have used K&R's slightly lengthier version...)
- */
- for (; ((*s & ~32) == (*t & ~32)) && *s; s++, t++)
- ; /* empty body */
-
- /*
- * To be true to the original strcmp() function, we return:
- *
- * - Zero if the strings match (in this case, we will have reached the
- * end of both strings, and subtracting the NULL terminators gives
- * zero), or;
- *
- * - A positive or negative number, indicating which string is
- * alphabetically greater.
- */
- return (*s & ~32) - (*t & ~32);
- }
-
-
- /*
- * Stub for Compare() which is used when inserting tasks into the task
- * list. This skips over opening brackets (for frozen tasks) in either
- * string.
- */
- int CompareTasks(char *s, char *t)
- {
- if (*s == '(')
- s++;
- if (*t == '(')
- t++;
- return Compare(s, t);
- }
-
-
- /*
- * Tiny function to draw the bevel box in the Settings window.
- */
- void DrawSettingsBox()
- {
- DrawBevelBox(setWindow -> RPort, INTERWIDTH, setGadStart - INTERHEIGHT,
- setWindow -> Width - INTERWIDTH * 2, setGadHeight + INTERHEIGHT * 2,
- GTBB_Recessed, TRUE,
- GT_VisualInfo, visInfo,
- TAG_END);
- }
-
-
- /*
- * Join together a font name and its size. The characters in the font name up
- * to the ".font" part are used.
- */
- void FontString(struct TextAttr *font, char *dest)
- {
- int i = 0; /* index into font name */
-
- while ((font -> ta_Name)[i] != '.')
- *(dest++) = (font -> ta_Name)[i++];
- sprintf(dest, " %ld", font -> ta_YSize);
- }
-
-
- /*
- * Check if a task has been frozen. Just looks at the State field and
- * compares against our two possible frozen states.
- */
- BOOL Frozen(struct Task *task)
- {
- switch (task -> tc_State)
- {
- case FROZEN:
- case FROZENREADY:
- return TRUE;
- break;
-
- default:
- return FALSE;
- break;
- }
- }
-
-
- /*
- * Remember the top entry in the ListView (used before regenerating it).
- * Under 2.x the best we can do is assume the top entry is the currently-
- * selected entry, but under 3.x we can find out exactly what it is.
- */
- void GetListTop()
- {
- if (osver < 39)
- {
- if (current)
- top = pos;
- else
- top = 0;
- }
- else
- GT_GetGadgetAttrs(listGad, mainWindow, NULL,
- GTLV_Top, &top,
- TAG_END);
- }
-
-
- /*
- * Remember the co-ordinates of the main window (used before closing it).
- */
- void GetPos()
- {
- if (mainWindow)
- {
- winLeft = mainWindow -> LeftEdge;
- winTop = mainWindow -> TopEdge;
- winWidth = mainWindow -> Width;
- winHeight = mainWindow -> Height;
- }
- }
-
-
- /*
- * Fire up the AmigaGuide file - this is PriMan's online help feature. If
- * we have not already opened amigaguide.library, we should do so now, and
- * refuse to continue if it's not around.
- */
- void Help()
- {
- static struct Screen *guideScreen; /* screen we're open on now */
-
- struct EasyStruct noHelp =
- {
- sizeof(struct EasyStruct),
- 0,
- "PriMan warning",
- "Can't open amigaguide.library -\nno online help available.",
- "Okay"
- };
-
- if (!AmigaGuideBase)
- if (!(AmigaGuideBase = OpenLibrary("amigaguide.library", 34)))
- {
- SimpleRequest(&noHelp, NULL);
- return;
- }
-
- /*
- * If this is the first time the user has asked for help, we tell
- * AmigaGuide to open the PriMan.guide file (which the user must have
- * placed either in the current directory or in the AmigaGuide search
- * path), note its signal bit (it uses one of our task's free signal
- * bits), and then return. PriMan's main loop listens for AmigaGuide
- * messages, and once it gets one that says AmigaGuide has finished
- * opening the file and is ready for further instructions, this
- * function is called again, and the next section of code is used
- * instead which actually opens the window...
- */
- if (!guideHandle)
- {
- /*
- * If PriMan's main window is not open (i.e. this is being called
- * as a result of a "?" argument from the Shell), then we won't
- * have a lock on any screen. In this case we check (but not lock)
- * whatever screen the user asked for in the settings, and open on
- * that. Otherwise we simply use the current screen. We always move
- * the chosen screen to the front in case it isn't already visible.
- */
- guideScreen = myScreen ? myScreen : LockOurScreen(FALSE);
-
- myGuide.nag_Screen = guideScreen;
- myGuide.nag_Name = "PriMan.guide";
-
- if (guideHandle = OpenAmigaGuideAsync(&myGuide, NULL))
- {
- guideSignal = AmigaGuideSignal(guideHandle);
- ScreenToFront(guideScreen);
- }
- }
-
- /*
- * The next alternative is that AmigaGuide is silently sitting in the
- * background with PriMan.guide loaded. Unless the main PriMan window
- * is not open (myScreen is null), we check if the AmigaGuide screen is
- * the same, and if it is, just ask AmigaGuide to display the first
- * node (Main). If the user has closed the AmigaGuide window himself,
- * or it hasn't been opened yet, this will have the effect of opening
- * the window. Otherwise, it will stay open and the first node will be
- * shown.
- */
- else if (!myScreen || guideScreen == myScreen)
- SendAmigaGuideCmd(guideHandle, "LINK Main", NULL);
-
- /*
- * If we got here, AmigaGuide is running on the wrong screen. So we
- * close it down and call Help() again, taking us right back to square
- * one...
- */
- else
- {
- CloseAmigaGuide(guideHandle);
- guideHandle = 0;
- guideSignal = 0;
- Help();
- }
- }
-
-
- /*
- * This closes down PriMan's interface, freeing up everything and
- * iconifying if necessary. If we're not running as a Commodity and can't
- * be iconified, it asserts the "all okay" error condition (which itself
- * will take care of freeing everything).
- */
- void Hide()
- {
- if (!(iconify || commodity))
- error = ALL_OKAY;
- else
- {
- CloseSettingsWindow();
- CloseMainWindow();
- FreeRemember(&memoryKey, TRUE);
- Iconify();
- }
- }
-
-
- /*
- * This tiny function adds PriMan's AppIcon to Workbench, if necessary.
- * For want of something better, we'll assign it an ID of 42...
- */
- void Iconify()
- {
- if (iconify)
- appIcon = AddAppIcon(42, NULL, "PriMan", appPort, NULL, wbIcon, TAG_END);
- }
-
-
- /*
- * Get a lock on the screen we should be open on now. Opening on the
- * default public screen is easy (just pass a NULL to the lock function),
- * but opening on the frontmost screen is tricky (it might not even be a
- * public screen!). To achieve this, we walk through the public screen list
- * trying to find a match for what Intuition says its frontmost screen is.
- * If we can't find one, we open on the default public screen. If that
- * fails, we open on the Workbench screen. (And as Eddy says, if _that_
- * fails, then we're really screwed!)
- *
- * If this function is only being used to check where we *should* be, pass
- * in FALSE to unlock the screen and just get back a pointer to what it was
- * (no guarantees that it won't have closed in the meantime!).
- */
- struct Screen *LockOurScreen(BOOL keepLock)
- {
- char *screenName; /* name of matching screen */
-
- struct List *pubList; /* Intuition's list of public screens */
- struct Screen *screen; /* frontmost screen which we're looking for */
- struct PubScreenNode *pubNode; /* current screen being examined in list */
-
- /*
- * We set screenName to NULL here, in the assumption that we'll be
- * opening on the default public screen. This only gets changed if we
- * want to open on the frontmost screen, and it is found in the public
- * screen list.
- */
- screenName = NULL;
-
- if (open == FRONTSCREEN)
- {
- pubList = LockPubScreenList();
- screen = IntuitionBase -> FirstScreen;
- FORLIST(pubList, pubNode)
- if (pubNode -> psn_Screen == screen)
- {
- screenName = pubNode -> psn_Node.ln_Name;
- break; /* found it, so drop out of loop */
- }
- UnlockPubScreenList();
- }
-
- /*
- * At this point, if screenName is NULL, then it is either because we
- * want to open on the default public screen, or because we didn't find
- * a match when walking through the public screen list. We try to lock
- * whatever it points to, and if that fails, lock the Workbench screen
- * as a last resort.
- */
- if (!(screen = LockPubScreen(screenName)))
- screen = LockPubScreen("Workbench");
-
- /*
- * If the caller just wants to see what screen PriMan *should* be open
- * on, we unlock it here.
- */
- if (!keepLock)
- UnlockPubScreen(NULL, screen);
-
- return screen;
- }
-
-
- /*
- * Add "..." after the Kill and Signal menu items as necessary. If reset
- * is TRUE, remove the menu strip from the main window first. The menu
- * strip gets rejigged appropriately and added back into the window.
- */
- void MenuEllipsis(struct Menu *menuStrip, BOOL reset)
- {
- static UBYTE *kill, *signal; /* pointers to Kill and Signal menu item text */
-
- if (reset)
- ClearMenuStrip(mainWindow);
-
- if (confirm)
- {
- kill = "Kill...";
- signal = "Signal...";
- }
- else
- {
- kill = "Kill";
- signal = "Signal";
- }
-
- ((struct IntuiText *)ItemAddress(menuStrip, FULLMENUNUM(M_TASK, I_KILL, NOSUB)) -> ItemFill) -> IText = kill;
- ((struct IntuiText *)ItemAddress(menuStrip, FULLMENUNUM(M_TASK, I_SIGNAL, NOSUB)) -> ItemFill) -> IText = signal;
-
- if (LayoutMenus(menuStrip, visInfo,
- GTMN_NewLookMenus, TRUE,
- TAG_END))
- SetMenuStrip(mainWindow, menuStrip);
- else
- error = MENU_ERROR;
- }
-
-
- /*
- * Put up a different gadget list in the Settings window. Uses the page
- * variable to see what is currently showing (or -1 if nothing). If this is
- * the same as what is being asked for, we don't need to do anything.
- * Otherwise, remove the old gadget list, replace it with the new one, and
- * update the page variable.
- */
- void NewPage(WORD newPage)
- {
- if (page != newPage)
- {
- if (page != -1)
- {
- /*
- * If there was something showing already, we need to remove
- * those gadgets, and blank that portion of the window.
- */
- RemoveGList(setWindow, setGads[page], -1);
- blank.Width = setWindow -> Width - INTERWIDTH * 4;
- blank.Height = setGadHeight;
- EraseImage(setWindow -> RPort, &blank, INTERWIDTH * 2, setGadStart);
- }
-
- page = newPage;
- AddGList(setWindow, setGads[page], ~0, -1, NULL);
- RefreshGList(setGads[page], setWindow, NULL, -1);
- GT_RefreshWindow(setWindow, NULL);
- }
- }
-
-
- /*
- * Restore the pointer to normal, enabling gadgets and window sizing. This
- * essentially reverses everything done in BusyPointer(). We don't do
- * anything if there are more pending calls to NormalPointer().
- */
- void NormalPointer()
- {
- if (--busyCount == 0)
- {
- if (mainWindow)
- {
- ClearPointer(mainWindow);
- EndRequest(&req1, mainWindow);
- WindowLimits(mainWindow, minWidth, minHeight, ~0, ~0);
- }
-
- if (setWindow)
- {
- ClearPointer(setWindow);
- EndRequest(&req2, setWindow);
- }
- }
- }
-
-
- /*
- * This tiny function is used whenever a task gets deselected. It simply
- * disables the Kill, Priority, Signal, Frozen and Wide Slider menu items,
- * as well as invalidating pos.
- */
- void OffTask()
- {
- OffMenu(mainWindow, FULLMENUNUM(M_TASK, I_KILL, NOSUB));
- OffMenu(mainWindow, FULLMENUNUM(M_TASK, I_PRIORITY, NOSUB));
- OffMenu(mainWindow, FULLMENUNUM(M_TASK, I_SIGNAL, NOSUB));
- OffMenu(mainWindow, FULLMENUNUM(M_TASK, I_FROZEN, NOSUB));
- OffMenu(mainWindow, FULLMENUNUM(M_TASK, I_WIDE, NOSUB));
- pos = -1;
- }
-
-
- /*
- * This function is used whenever a task gets selected. It updates the
- * slider gadget to reflect the task's priority, sets it to the correct
- * scale, and enables the Kill, Priority, Signal, Frozen and (if
- * appropriate) Wide Slider menu items.
- */
- void OnTask()
- {
- struct MenuItem *item; /* Wide Slider menu item */
-
- /*
- * First we want to temporarily remove the menu strip, and get the
- * address of the Wide Slider menu item. The menu strip gets put back
- * after updating the menu item.
- */
- ClearMenuStrip(mainWindow);
- item = ItemAddress(menuStrip, FULLMENUNUM(M_TASK, I_WIDE, NOSUB));
-
- if (current -> ln_Pri > -26 && current -> ln_Pri < 26)
- {
- /*
- * We can use a narrow scale, so reset the menu's
- * checkmark, enable the menu item (allowing the user
- * to move to a wide scale), then update the slider
- * gadget's scale.
- */
- item -> Flags &= ~CHECKED;
- item -> Flags |= ITEMENABLED;
- WideSlider(FALSE);
- }
- else
- {
- /*
- * We're forced into using a wide scale. Set the menu's
- * checkmark but don't allow the user to change it!
- */
- item -> Flags |= CHECKED;
- item -> Flags &= ~ITEMENABLED;
- WideSlider(TRUE);
- }
-
- ResetMenuStrip(mainWindow, menuStrip);
-
- /*
- * Now we change the value of the slider gadget.
- */
- GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,
- GTSL_Level, current -> ln_Pri,
- GA_Disabled, FALSE,
- TAG_END);
-
- /*
- * And finally, we make sure the appropriate menu items are enabled.
- */
- OnMenu(mainWindow, FULLMENUNUM(M_TASK, I_KILL, NOSUB));
- OnMenu(mainWindow, FULLMENUNUM(M_TASK, I_PRIORITY, NOSUB));
- OnMenu(mainWindow, FULLMENUNUM(M_TASK, I_SIGNAL, NOSUB));
- OnMenu(mainWindow, FULLMENUNUM(M_TASK, I_FROZEN, NOSUB));
- }
-
-
- /*
- * Simulate a gadget being pressed (when the keyboard shortcut is used).
- * The gadget is marked as "selected", there is a delay, and then it is put
- * back to normal again.
- */
- void PressGadget(struct Window *window, struct Gadget *gadget)
- {
- gadget -> Flags ^= GFLG_SELECTED;
- RefreshGList(gadget, window, NULL, 1);
-
- Delay(PressDelay);
-
- gadget -> Flags ^= GFLG_SELECTED;
- RefreshGList(gadget, window, NULL, 1);
- }
-
-
- /*
- * Make sure a variable lies within the specified range, by increasing or
- * decreasing it if necessary. Used to keep the main window's size inside
- * acceptable limits.
- */
- void Range(WORD *current, WORD min, WORD max)
- {
- if (*current < min)
- *current = min;
- else if (*current > max)
- *current = max;
- }
-
-
- /*
- * Request a font from the user. This function handles both the Gadget and
- * List font requesters, and initialises them beforehand if necessary. It
- * takes in the parameters below, and returns the result of AslRequest(),
- * after updating the Settings window's font box and related variables.
- *
- * mainReq pointer to a pointer of the requester to be used
- * otherReq pointer to the other requester
- * initialName name of the initially-selected font in the requester
- * initialSize pointer to the size of that font
- * fontGadget the text box showing the selected font's name
- * fontString the font name and size inside that text box
- * title title of the requester's window
- * flags flags to be passed (either zero or the fixed-width flag)
- */
- BOOL RequestFont(struct FontRequester **mainReq, struct FontRequester *otherReq,
- char *initialName, WORD *initialSize,
- struct Gadget *fontGadget, char *fontString,
- char *title, ULONG flags)
- {
- ULONG reqTag; /* says whether or not we're using width tag */
- WORD reqWidth, /* initial width of requester */
- reqHeight; /* initial height of requester */
- BOOL result; /* return value from AslRequest() */
-
- BusyPointer();
-
- /*
- * If this is the first time the user has played with the requester, we
- * need to allocate memory for it, and initialise it. We do this now
- * (rather than when PriMan is first launched) so we can make a good
- * guess at what height is best. If the other requester has been opened
- * before, we use its height and width, otherwise we use 2/3 of the
- * screen's height and the default width.
- */
- if (!*mainReq)
- {
- if (otherReq)
- {
- reqHeight = otherReq -> fo_Height;
- reqWidth = otherReq -> fo_Width;
- reqTag = ASLFO_InitialWidth;
- }
- else
- {
- reqHeight = myScreen -> Height * 2 / 3;
- reqWidth = 0; /* not strictly needed since it's ignored */
- reqTag = TAG_IGNORE;
- }
-
- *mainReq = AllocAslRequestTags(ASL_FontRequest,
- ASLFO_TitleText, title,
- ASLFO_InitialHeight, reqHeight,
- reqTag, reqWidth,
- ASLFO_Flags, flags,
- TAG_END);
- }
-
- /*
- * The requester gets offset from the Settings window in
- * same way as the Settings window gets offset from the
- * main window (by the dimensions of the close gadget).
- */
- if (result = AslRequestTags(*mainReq,
- ASLFO_Screen, myScreen,
- ASLFO_TextAttr, &propTA, /* use gadget font for imagery */
- ASLFO_InitialLeftEdge, setWindow -> LeftEdge + CloseBoxWidth,
- ASLFO_InitialTopEdge, setWindow -> TopEdge + windowTop,
- ASLFO_InitialName, initialName,
- ASLFO_InitialSize, *initialSize,
- TAG_END))
- {
- /*
- * Here we update the font text box in the Settings window, and
- * copy the font information from the requester. (This doesn't
- * happen if the user clicked Cancel.)
- */
- FontString(&((*mainReq) -> fo_Attr), fontString);
- GT_SetGadgetAttrs(fontGadget, setWindow, NULL,
- GTTX_Text, fontString,
- TAG_END);
- strcpy(initialName, (*mainReq) -> fo_Attr.ta_Name);
- *initialSize = (*mainReq) -> fo_Attr.ta_YSize;
- }
-
- NormalPointer();
- return result;
- }
-
-
- /*
- * Set up the Commodity interface. This involves creating a broker, and
- * attaching to it a filter, sender and translator.
- */
- void SetupCommodity()
- {
- LONG brokerError; /* error returned when creating a new broker */
-
- /*
- * This is the error requester in case something went wrong when setting up
- * the Commodity's hotkey.
- */
- struct EasyStruct badFilter =
- {
- sizeof(struct EasyStruct),
- 0,
- "PriMan warning",
- "Invalid hotkey - suggest you change it.",
- "Okay"
- };
-
- if (broker = CxBroker(&newBroker, &brokerError))
- {
- /*
- * Create the filter, which monitors input events for our hotkey.
- */
- if (filter = CxFilter(hotkey))
- {
- AttachCxObj(broker, filter);
-
- /*
- * Create the sender, which sends a message to our port once
- * the hotkey is spotted.
- */
- if (sender = CxSender(cxPort, 1))
- {
- AttachCxObj(filter, sender);
-
- /*
- * Create the translator. This one is a dummy translator,
- * and simply removes the hotkey from the input stream, so
- * no other application can use it.
- */
- if (translate = CxTranslate(NULL))
- {
- AttachCxObj(filter, translate);
- ActivateCxObj(broker, 1);
- if (CxObjError(filter) == COERR_BADFILTER)
- SimpleRequest(&badFilter, NULL);
- }
- else
- error = CX_ERROR;
- }
- else
- error = CX_ERROR;
- }
- else
- error = CX_ERROR;
- }
- else
- /*
- * Here, there are two possibilities:
- *
- * - A similar broker already exists. In this case, we silently
- * shut down (and let the copy of PriMan which must already be
- * running take control).
- *
- * - There was an error creating the broker. We do the same as when
- * there was an error creating anything else above: raise the
- * appropriate error condition.
- */
- error = brokerError == CBERR_DUP ? ALL_OKAY : CX_ERROR;
- }
-
-
- /*
- * Reveal PriMan's interface. There are several possibilities here:
- *
- * - No windows are showing. In this case, we remove the AppIcon if
- * necessary, then simply open the main window.
- *
- * - The main window is open, but it's not on the correct screen. So we
- * shut everything down and reopen, which will get us onto the correct
- * screen. It is important to remember if the Settings window is open,
- * so that can follow us around as well.
- *
- * - The main window is both open, and on the correct screen. All we need
- * to do is move both the main window and its screen to the front, and
- * the Settings window too if that's also open.
- */
- void Show()
- {
- BOOL reopenSettings; /* Settings window was open when we jumped screen */
- struct Screen *tempScreen; /* screen we should be on */
-
- if (!mainWindow)
- {
- if (appIcon)
- {
- RemoveAppIcon(appIcon);
- appIcon = NULL;
- }
- OpenMainWindow();
- }
- else
- {
- /*
- * Check what screen we should be on, but don't actually lock it.
- */
- tempScreen = LockOurScreen(FALSE);
- if (tempScreen != myScreen)
- {
- reopenSettings = (setWindow != NULL);
- CloseSettingsWindow();
- CloseMainWindow();
- OpenMainWindow();
- if (reopenSettings)
- OpenSettingsWindow();
- }
- else
- {
- WindowToFront(mainWindow);
- if (setWindow)
- {
- WindowToFront(setWindow);
- ActivateWindow(setWindow);
- }
- else
- ActivateWindow(mainWindow);
- ScreenToFront(myScreen);
- }
- }
- }
-
-
- /*
- * Put up a busy pointer and open the requester passed into this function.
- * If the requester structure requires further arguments, they can be
- * passed in as well.
- */
- LONG SimpleRequest(struct EasyStruct *easyReq, APTR args)
- {
- LONG result; /* return value from EasyRequest() */
-
- BusyPointer();
- result = EasyRequest(NULL, easyReq, NULL, args);
- NormalPointer();
- return result;
- }
-
-
- /*
- * This version of sprintf uses the exec routine, courtesy of Eddy Carroll
- * and SnoopDos. Saves pulling in a lot of unnecessary library routines.
- * The only difference between this and the one in stdio is that this
- * always returns 0 instead of the length of the string.
- */
- int __regargs sprintf(char *outstr, char *fmtstr, ...)
- {
- RawDoFmt(fmtstr, &fmtstr + 1, RAWDOFMT_COPY, outstr);
- return 0;
- }
-
-
- /*
- * Increment or decrement a value, making sure it stays within 0..range.
- * This is useful when using the keyboard shortcuts for a cycle gadget.
- */
- WORD Step(WORD value, WORD range, UWORD decrement)
- {
- if (decrement)
- {
- value--;
- if (value < 0)
- value = range;
- }
- else
- {
- value++;
- if (value > range)
- value = 0;
- }
- return value;
- }
-
-
- /*
- * Check to see if a task still exists. This works by checking the State
- * field, and comparing against a list of valid states. Hence it is not
- * 100% accurate (the task might not exist, but that particular byte of
- * memory happens to be set the way we want it), but it'll have to do...
- */
- BOOL ValidTask(struct Task *task)
- {
- switch (task -> tc_State)
- {
- case TS_RUN:
- case TS_READY:
- case TS_WAIT:
- case FROZEN:
- case FROZENREADY:
- return TRUE;
- break;
-
- default:
- return FALSE;
- break;
- }
- }
-
-
- /*
- * Change the slider gadget's scale to wide or narrow.
- */
- void WideSlider(BOOL wide)
- {
- if (wide)
- GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,
- GTSL_Min, -128,
- GTSL_Max, 127,
- TAG_END);
- else
- GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,
- GTSL_Min, -25,
- GTSL_Max, 25,
- TAG_END);
- }
-
-
- /*
- * Remove all remaining messages from a port, then delete it. Used when
- * shutting down PriMan's message ports. We do this while multitasking is
- * disabled, so no other messages can arrive in the meantime.
- */
- void WipePort(struct MsgPort *port)
- {
- struct Message *message; /* current message in port */
-
- Forbid();
- while (message = GetMsg(port))
- ReplyMsg(message);
- DeleteMsgPort(port);
- Permit();
- }
-