home *** CD-ROM | disk | FTP | other *** search
- /* See the file Distribution for distribution terms.
- (c) Copyright 1994 Ari Halberstadt */
-
- /* Application to demonstrate the use of the patch library. First, a
- dialog is displayed without patching any traps. Then, a second dialog
- is displayed with the patch SetDialogItemText patched. The patch
- replaces the text passed to SetDialogItemText with a string pointed
- to by the global variable gPatchText. */
-
- /* 941130 aih updated for universal headers
- 940418 aih created */
-
- #include <Dialogs.h>
- #include <Events.h>
- #include <Fonts.h>
- #include <Memory.h>
- #include <Menus.h>
- #include <OSEvents.h>
- #include <QuickDraw.h>
- #include <Traps.h>
- #include "PatchLib.h"
-
- /*----------------------------------------------------------------------------*/
- /* patch information */
- /*----------------------------------------------------------------------------*/
-
- static PatchType gPatchSetDialogItemText;
-
- typedef UniversalProcPtr SetDialogItemTextUPP;
-
- #if USESROUTINEDESCRIPTORS
-
- enum {
- uppSetDialogItemTextProcInfo = kPascalStackBased |
- RESULT_SIZE(kNoByteCode) |
- STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) |
- STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const unsigned char *)))
- };
-
- #define NewSetDialogItemTextProc(userRoutine) \
- (SetDialogItemTextUPP) NewRoutineDescriptor((ProcPtr) userRoutine, \
- uppSetDialogItemTextProcInfo, GetCurrentISA())
-
-
- #define CallSetDialogItemTextProc(patch, item, text) \
- CallUniversalProc(patch->trap, uppSetDialogItemTextProcInfo, item, text)
-
- #else /* USESROUTINEDESCRIPTORS */
-
- #define NewSetDialogItemTextProc(userRoutine) ((SetDialogItemTextUPP) userRoutine)
- #define CallSetDialogItemTextProc(patch, item, text) ((void) (0))
-
- #endif /* USESROUTINEDESCRIPTORS */
-
- /*----------------------------------------------------------------------------*/
- /* global definitions and declarations */
- /*----------------------------------------------------------------------------*/
-
- /* the test dialog */
- #define rDialog (128)
-
- /* dialog items */
- enum {
- iOK = 1,
- iTextTitle,
- iTextNoPatch,
- iTextPatch1,
- iTextPatch2,
- iTextPatch3,
- iLast
- };
-
- /* the text to set when the patch is executed */
- static const unsigned char *gPatchText;
-
- /*----------------------------------------------------------------------------*/
- /* standard Macintosh initializations */
- /*----------------------------------------------------------------------------*/
-
- /* initialize application heap */
- static void HeapInit(long stack, short masters)
- {
- SetApplLimit(GetApplLimit() - stack);
- MaxApplZone();
- while (masters-- > 0)
- MoreMasters();
- }
-
- /* initialize managers */
- static void ManagersInit(void)
- {
- EventRecord event;
- short i;
-
- /* standard initializations */
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0);
- FlushEvents(everyEvent, 0);
- InitCursor();
-
- /* so first window will be frontmost */
- for (i = 0; i < 4; i++)
- EventAvail(everyEvent, &event);
- }
-
- /*----------------------------------------------------------------------------*/
- /* the patch */
- /*----------------------------------------------------------------------------*/
-
- /* subsititute some global string for whatever string is passed in */
- static pascal void PatchSetDialogItemText(Handle hndl, const unsigned char *text)
- {
- PATCH_ENTER();
- text = gPatchText;
- #if USESROUTINEDESCRIPTORS
- CallSetDialogItemTextProc(gPatchSetDialogItemText, hndl, text);
- #endif
- PATCH_RETURN(gPatchSetDialogItemText);
- }
-
- /*----------------------------------------------------------------------------*/
- /* run the dialog */
- /*----------------------------------------------------------------------------*/
-
- /* exit on nil pointer */
- static void FailNIL(void *p, const unsigned char *msg)
- {
- if (! p) {
- DebugStr(msg);
- ExitToShell();
- }
- }
-
- /* create the patch */
- static PatchType PatchCreate(void)
- {
- static SetDialogItemTextUPP uppSetDialogItemText;
- PatchType patch;
-
- if (! uppSetDialogItemText) {
- uppSetDialogItemText = NewSetDialogItemTextProc(PatchSetDialogItemText);
- FailNIL(uppSetDialogItemText, (StringPtr) "\p nil uppSetDialogItemText");
- }
- patch = PatchBegin(uppSetDialogItemText, _SetDialogItemText);
- FailNIL(patch, (StringPtr) "\p nil patch");
- return(patch);
- }
-
- /* create the dialog */
- static DialogPtr CreateDialog(short id)
- {
- DialogPtr dlg;
-
- dlg = GetNewDialog(id, NULL, (WindowPtr) -1);
- FailNIL(dlg, (StringPtr) "\p nil dialog");
- return(dlg);
- }
-
- /* set up the dialog */
- static void SetupDialog(DialogPtr dlg, Boolean patch)
- {
- /* some strings to use in patches */
- const unsigned char *textStrings[] = {
- (StringPtr) "\p There isn't a patch in sight!",
- (StringPtr) "\p It's great to have a working patch!",
- (StringPtr) "\p This patch never made it to beta.",
- (StringPtr) "\p Thou Shalt Not Patch Unless Thou Hath A Flat.",
- };
- Handle text; /* handle to text item */
- Rect box; /* rectangle containing dialog item */
- short type; /* type of dialog item */
- short item; /* item in dialog */
- short textIndex; /* index to text strings */
-
- /* temporarily remove patch */
- if (patch)
- PatchRemove(gPatchSetDialogItemText);
-
- /* set title and first unpatched text string */
- GetDialogItem(dlg, iTextTitle, &type, &text, &box);
- if (patch)
- SetDialogItemText(text, (StringPtr) "\p Running Dialog And Patching SetDialogItemText");
- else
- SetDialogItemText(text, (StringPtr) "\p Running Dialog Without Patching SetDialogItemText");
- GetDialogItem(dlg, iTextNoPatch, &type, &text, &box);
- SetDialogItemText(text, textStrings[0]);
-
- /* reinstall patch */
- if (patch)
- PatchInstall(gPatchSetDialogItemText);
-
- /* set strings in the dialog */
- textIndex = 1;
- for (item = iTextNoPatch + 1; item < iLast; item++) {
- /* Even though we're always passing the same string to SetDialogItemText,
- the patch will use the string pointed to by gPatchText. */
- gPatchText = textStrings[textIndex++];
- GetDialogItem(dlg, item, &type, &text, &box);
- SetDialogItemText(text, textStrings[0]);
- }
- }
-
- /* create and run the dialog */
- static void Run(Boolean patch)
- {
- DialogPtr dlg;
- short item;
-
- /* create patch and dialog */
- if (patch)
- gPatchSetDialogItemText = PatchCreate();
- dlg = CreateDialog(rDialog);
- SetupDialog(dlg, patch);
-
- /* wait until user hits an enabled item */
- ModalDialog(NULL, &item);
-
- /* cleanup */
- DisposeDialog(dlg);
- if (patch) {
- PatchEnd(gPatchSetDialogItemText);
- gPatchSetDialogItemText = NULL;
- }
- }
-
- void main(void)
- {
- HeapInit(0, 4);
- ManagersInit();
- Run(false);
- Run(true);
- }
-