home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / wdefptch.cpt / WDEFPatch21 / wdefpatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-20  |  10.1 KB  |  436 lines

  1. /*******************************************
  2.  
  3.     WDEF Patcher
  4.     Steve Falkenburg MacDTS
  5.     ⌐1991 Apple Computer
  6.     
  7.     This snippet shows how you can add a simple extra part to a WDEF without
  8.     writing an entire WDEF.  It also shows how to access the new part via
  9.     FindWindow().
  10.     
  11.     Roberto Avanzi (independent programmer), June 18, 1992
  12.     Added support for tracking the extra part, in a way similar to the one used
  13.     by the system.
  14.     given back to Apple as an enhanced snippet (mmmh, sounds quite absurd)
  15.     
  16. *******************************************/
  17.  
  18. #include <Windows.h>
  19.  
  20. /* add 2 to this when checking with FindWindow() ! */
  21.  
  22. #define kOurHit    32
  23.  
  24. Boolean gInBackground;
  25. Boolean gDone;
  26.  
  27. void InitStuff(void);
  28. void EventLoop(WindowPtr window);
  29. void DoDrag(WindowPtr window,Point globMouse);
  30. void HandleMouseDowns(EventRecord *ev);
  31. void HandleContent(WindowPtr theWindow,EventRecord *ev);
  32. void HandleUpdates(WindowPtr wind);
  33. void DoDeActivate(WindowPtr window,Boolean chFlag);
  34. void DoActivate(WindowPtr window,Boolean chFlag);
  35. void HandleActivates(EventRecord *ev);
  36. void HandleSREvt(long message);
  37. void DoGrow(WindowPtr window,Point globMouse);
  38. void PatchWindowWDEF(WindowPtr window);
  39. pascal long MyWDEFPatch(short varCode,WindowPtr window,short message,long param);
  40. void HandleOurPart(WindowPtr window);
  41. /* roberto avanzi, june 18, 1992 */
  42. Boolean TrackMyPart(WindowPtr window);
  43.  
  44.  
  45. /* this struct allows us to insert a WDEF patch safely.  It contains a jump instruction
  46.     and stores the old handle to the WDEF
  47. */
  48.  
  49. typedef struct {
  50.     short jmpInst;
  51.     ProcPtr patchAddr;
  52.     Handle oldAddr;
  53.     Boolean partState;    /* roberto avanzi jun 18 1992 */
  54. } WDEFPatch, *WDEFPatchPtr, **WDEFPatchHndl;
  55.  
  56.  
  57. void main(void)
  58. {
  59.     WindowPtr mainWindow;
  60.     Rect bounds = {100,100,150,300};
  61.     
  62.     gInBackground = false;
  63.     gDone = false;
  64.     
  65.     InitStuff();
  66.     mainWindow = NewWindow(nil,&bounds,"\pWDEF Patcher",false,zoomDocProc,(WindowPtr)-1,true,0);
  67.     PatchWindowWDEF(mainWindow);
  68.     ShowWindow(mainWindow);
  69.     EventLoop(mainWindow);
  70. }
  71.  
  72.  
  73. void InitStuff(void)
  74. {
  75.     InitGraf(&qd.thePort);
  76.     InitFonts();
  77.     InitWindows();
  78.     InitMenus();
  79.     TEInit();
  80.     InitDialogs(nil);
  81.     InitCursor();
  82.     FlushEvents(everyEvent,0);
  83. }
  84.  
  85.  
  86. void EventLoop(WindowPtr window)
  87. {
  88.     EventRecord ev;
  89.     
  90.     do {
  91.         if (WaitNextEvent(everyEvent,&ev,10,nil)) {
  92.             switch (ev.what) {
  93.                 case mouseDown:
  94.                     HandleMouseDowns(&ev);
  95.                     break;
  96.                 case updateEvt:
  97.                     HandleUpdates((WindowPtr)ev.message);
  98.                     break;
  99.                 case activateEvt:
  100.                     HandleActivates(&ev);
  101.                     break;
  102.                 case app4Evt:
  103.                     HandleSREvt(ev.message);
  104.                     break;
  105.             }
  106.         }
  107.     } while (!gDone);
  108. }
  109.  
  110.  
  111. void HandleMouseDowns(EventRecord *ev)
  112. {
  113.     WindowPtr theWindow;
  114.     short part;
  115.     
  116.     part = FindWindow(ev->where,&theWindow);
  117.  
  118.     switch (part) {
  119.         case inMenuBar:
  120.             break;
  121.         case inSysWindow:
  122.             SystemClick(ev,theWindow);
  123.             break;
  124.         case inDrag:
  125.             DoDrag(theWindow,ev->where);
  126.             break;
  127.         case inGoAway:
  128.             if (TrackGoAway(theWindow,ev->where)) {
  129.                 gDone = true;
  130.             }
  131.             break;
  132.         case inContent:
  133.             HandleContent(theWindow,ev);
  134.             break;
  135.         case inGrow:
  136.             DoGrow(theWindow,ev->where);
  137.             break;
  138.         case kOurHit+2:                        // remember, we're adding 2 so the FindWindow/WDEF
  139.             HandleOurPart(theWindow);        // codes match
  140.             break;
  141.         case inZoomIn:
  142.         case inZoomOut:
  143.             SetPort(theWindow);    // important
  144.             if (TrackBox(theWindow,ev->where, part))
  145.                 ZoomWindow(theWindow, part, true);
  146.             break;
  147.     }
  148. }
  149.  
  150.  
  151.  
  152. /* handles a mouse down in our added window part */
  153. /*    here you should do something more intelligent than beep, if you really want */
  154.  
  155. void HandleOurPart(WindowPtr window)
  156. {
  157.     // then track the Part (Roberto Avanzi 18-06-1992)
  158.  
  159.     if (TrackMyPart(window))
  160.         SysBeep(10);
  161.  
  162. }
  163.  
  164. /*    Roberto Avanzi , june 18, 1992
  165.     here i decide to track the control and mimic the system's behavior.
  166.     I can as well decide to make a popup appear near the box.
  167.     This is more consistent with the rest of the User Interface
  168. */
  169.  
  170. Boolean TrackMyPart(WindowPtr window)
  171. {
  172.     long r;
  173.     Point pt;
  174.     WindowPtr wind;
  175.     pascal long MyWDEFPatch(short varCode,WindowPtr window,short message,long param);
  176.  
  177. #define pstate (**(WDEFPatchHndl) ((WindowPeek)window)->windowDefProc).partState
  178.  
  179.     /* hilite control */
  180.     pstate = true; (void) MyWDEFPatch(zoomDocProc ,window,wDraw,kOurHit);
  181.  
  182.     while (Button())
  183.     {
  184.         GetMouse(&pt);
  185.         LocalToGlobal(&pt);
  186.         r = FindWindow(pt,&wind);
  187.         if ( ( (wind == window) && ( r == kOurHit+2) ) != pstate )
  188.         {
  189.             pstate = ! pstate; (void) MyWDEFPatch(zoomDocProc ,window,wDraw,kOurHit);
  190.         }
  191.     }
  192.     
  193.     if (! pstate ) return false;    /* yawn, changed idea */
  194.     /* un-hilite control */
  195.     pstate = false; (void) MyWDEFPatch(zoomDocProc,window,wDraw,kOurHit);
  196.     return true;    /* OK, we HIT !!! */
  197.  
  198. #undef pstate
  199. }
  200.  
  201. /* DoDrag: Handles drag window events */
  202.  
  203. void DoDrag(WindowPtr window,Point globMouse)
  204. {
  205.     Rect dragRect;
  206.     
  207.     SetRect(&dragRect,-32000,-32000,32000,32000);
  208.     
  209.     DragWindow(window,globMouse,&dragRect);
  210.     SetPort(window);
  211. }
  212.  
  213.  
  214. /* DoGrow: Handles grow window events */
  215.  
  216. void DoGrow(WindowPtr window,Point globMouse)
  217. {
  218.     long newSize;
  219.     Rect windLimits;
  220.     GrafPtr tempPort;
  221.     
  222.     SetRect(&windLimits,64,64,32000,32000);
  223.     
  224.     if ((newSize = GrowWindow(window,globMouse,&windLimits)) != 0) {
  225.         GetPort(&tempPort);
  226.         SetPort(window);
  227.         SizeWindow(window,LoWord(newSize),HiWord(newSize),true);
  228.         InvalRect(&window->portRect);
  229.         SetPort(tempPort);
  230.     }
  231. }
  232.  
  233.  
  234. void HandleContent(WindowPtr theWindow,EventRecord *ev)
  235. {
  236.     GrafPtr savePort;
  237.     Point where;
  238.     
  239.     where = ev->where;
  240.     SetPort(theWindow);
  241.     
  242.     if (theWindow != FrontWindow()) {
  243.         SelectWindow(theWindow);
  244.         return;
  245.     }
  246. }
  247.  
  248.  
  249. void HandleUpdates(WindowPtr wind)
  250. {
  251.     GrafPtr savePort;
  252.     
  253.     GetPort(&savePort);
  254.     SetPort(wind);
  255.     BeginUpdate(wind);
  256.     EraseRect(&wind->portRect);
  257.     DrawGrowIcon(wind);
  258.     EndUpdate(wind);
  259.     SetPort(savePort);
  260. }
  261.  
  262.  
  263. void HandleActivates(EventRecord *ev)
  264. {
  265.     if ((ev->modifiers & activeFlag) != 0) {
  266.         DoActivate((WindowPtr)ev->message,((ev->modifiers & 0x0002) != 0));
  267.     }
  268.     else {
  269.         DoDeActivate((WindowPtr)ev->message,((ev->modifiers & 0x0002) != 0));
  270.     }
  271. }
  272.  
  273.  
  274. /* DoActivate: Performs activate tasks */
  275.  
  276. void DoActivate(WindowPtr window,Boolean chFlag)
  277. {
  278.     DrawGrowIcon(window);
  279. }
  280.  
  281.  
  282. /* DoDeActivate: Performs deactivate tasks */
  283.  
  284. void DoDeActivate(WindowPtr window,Boolean chFlag)
  285. {
  286.     DrawGrowIcon(window);
  287. }
  288.  
  289.  
  290. void HandleSREvt(long message)
  291. {
  292.     if ((message >> 24) == 1)
  293.         if ((message & 1) != 0) {
  294.             gInBackground = false;
  295.             SetCursor(&arrow);
  296.             if (FrontWindow()) {  
  297.                 HiliteWindow(FrontWindow(),true);
  298.                 DoActivate(FrontWindow(),true);
  299.             }
  300.         }
  301.         else if (FrontWindow()) {
  302.             gInBackground = true;
  303.             HiliteWindow(FrontWindow(),false);
  304.             DoDeActivate(FrontWindow(),true);
  305.         }
  306. }
  307.  
  308.  
  309.  
  310.  
  311. /* this installs the WDEF patch into a window */
  312.  
  313. void PatchWindowWDEF(WindowPtr window)
  314. {
  315.     WDEFPatchHndl wdefHndl;
  316.     WDEFPatchPtr wdefPatch;
  317.     
  318.     wdefHndl = (WDEFPatchHndl)NewHandle(sizeof(WDEFPatch));
  319.     HLock(wdefHndl);
  320.     wdefPatch = *wdefHndl;
  321.     wdefPatch->oldAddr = ((WindowPeek)window)->windowDefProc;
  322.     wdefPatch->jmpInst = 0x4ef9; /*JMP*/
  323.     wdefPatch->patchAddr = MyWDEFPatch;
  324.  
  325.     HUnlock(wdefHndl);
  326.     ((WindowPeek)window)->windowDefProc = (Handle)wdefHndl;
  327. }
  328.  
  329.  
  330. pascal long MyWDEFPatch(short varCode,WindowPtr window,short message,long param)
  331. {
  332.     long    thisA5;
  333.     WDEFPatchHndl wdPatch;
  334.     pascal long (*wdefProc)(short varCode,WindowPtr window,short message,long param);
  335.     Handle oldWDEF;
  336.     long result;
  337.     Rect ourRect,ourElementRect;
  338.     Point *hitPt;
  339.     Point mouse;
  340.     Point pt;
  341.     GrafPtr    savePort;
  342.     GrafPtr aPort;
  343.     RgnHandle    aRgn;
  344.     Rect    aRect;
  345.     
  346.     ourRect = (**((WindowPeek)window)->strucRgn).rgnBBox;
  347.     SetRect(&ourElementRect,ourRect.right-38,ourRect.top+4,ourRect.right-26,ourRect.top+15);
  348.     
  349.     wdPatch = (WDEFPatchHndl) ((WindowPeek)window)->windowDefProc;
  350.  
  351.     oldWDEF = (**wdPatch).oldAddr;
  352.     HLock(oldWDEF);
  353.     wdefProc = (void *)*oldWDEF;
  354.     wdefProc = (void *)StripAddress(wdefProc);
  355.  
  356.     /* now, folks, WHY do I check it, u'll ask me ? Heh, it's a funny quirk in
  357.         the sys WDEF (at least, sys 7's, dunno whattabout older ones) .
  358.         Suppose You click once in the grow icon and DO NOT resize the window.
  359.         (remember, just click and do not move the mouse in the meantime).
  360.         Then you click on the added part. That part is tracked in the right way,
  361.                                     *    BUT   *
  362.         ALSO the zoom box gets hilited. Dunno why should happen, but It's a lot
  363.         of FUN. Sadly, cannot find its place in any useful app. Therefore we
  364.         do this check.
  365.         APPLE says: if you write your own WDEF and receive unknown messages, do not
  366.                     do anything. pass along and do NOTHING.
  367.         APPLE does: we get something new ? therefore we process it anyway, just to
  368.                     keep developers writing workarounds and keep their minds afresh.
  369.         What else can we say ? Thanks !!!!! (Roberto Avanzi june 19, 1992)
  370.     */
  371.     if ( (message == wDraw) ? (((short)param) != kOurHit ) : true )
  372.         result = (wdefProc)(varCode,window,message,param);
  373.  
  374.     if (((WindowPeek)window)->visible)
  375.     if (((WindowPeek)window)->hilited)
  376.     {
  377.         switch (message) {
  378.             case wDraw:
  379.                 GetPort(&savePort);
  380.                 GetWMgrPort(&aPort);
  381.                 SetPort(aPort);
  382.                 aRgn = NewRgn();
  383.                 GetClip(aRgn);
  384.                 SetRect(&aRect,-32000,-32000,32000,32000);
  385.                 ClipRect(&aRect);
  386.                 switch ( (short) param ) {    // Roberto Avanzi 18-06-1992: support for 
  387.                                             // tracking of the new part
  388.                     case 0:
  389.                         (**wdPatch).partState = false;
  390.                     case kOurHit:
  391.                         PenNormal();                            // draw our part
  392.                         if ( (**wdPatch).partState )
  393.                         {
  394.                             InsetRect(&ourElementRect,-1,0);
  395.                             EraseRect(&ourElementRect);
  396.                             InsetRect(&ourElementRect,1,0);
  397.                             FrameRect(&ourElementRect);
  398.                             MoveTo(ourElementRect.left+2,ourElementRect.top+2);
  399.                             Line(2,2);   Move(-2,0);   Line(2,-2);
  400.                             Move(3,0);   Line(2,2);    Move(-2,0);   Line(2,-2);
  401.                             Move(0,4);   Line(-2,2);   Line(-3,0);   Line(-2,-2);
  402.                         }
  403.                         else
  404.                         {
  405.                             InsetRect(&ourElementRect,-1,0);
  406.                             EraseRect(&ourElementRect);
  407.                             InsetRect(&ourElementRect,1,0);
  408.                             FrameRect(&ourElementRect);
  409.                             InsetRect(&ourElementRect,2,2);
  410.                             FrameRect(&ourElementRect);
  411.                         }
  412.                         break;
  413.                     default:
  414.                         break;
  415.                 }
  416.                 SetClip(aRgn);
  417.                 DisposeRgn(aRgn);
  418.                 SetPort(savePort);
  419.                 break;
  420.             case wHit:
  421.                 hitPt = (Point *)¶m;                    // hit test our part
  422.                 if (PtInRect(*hitPt,&ourElementRect))
  423.                 {
  424.                     result =  kOurHit;
  425.                 }
  426.                 break;
  427.             default:
  428.                 break;
  429.         }    // switch
  430.     }    //    if hilited (otherwise we dont see the new box, addition by Roberto Avanzi)
  431.     HUnlock(oldWDEF);
  432.     
  433.     return result;
  434. }
  435.  
  436.