home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / PNL Libraries / MyMovableModal.p < prev    next >
Encoding:
Text File  |  1995-09-26  |  6.9 KB  |  265 lines  |  [TEXT/CWIE]

  1. unit MyMovableModal;
  2.  
  3. { This unit implements a MovableModalDialog routine similar to }
  4. { the Toolbox routine ModalDialog, to be used for movable modal dialogs }
  5.  
  6. { Based on code by Marco Piovanelli <piovanel@dsi.unimi.it> }
  7.  
  8. interface
  9.  
  10.     uses
  11.         Types;
  12.  
  13.     procedure DisableMenuBar (var saved_state: univ Ptr; hmnuID: Integer);
  14.     procedure ReEnableMenuBar (var saved_state: univ Ptr);
  15.     procedure MovableModalDialog (filterProc: ProcPtr; var itemHit: Integer);
  16.  
  17. implementation
  18.  
  19.     uses
  20.         Balloons, ToolUtils, Scrap, GestaltEqu, Memory, Menus, Dialogs, LowMem, 
  21.         MyTypes, MyDialogs, MyCursors, MySystemGlobals;
  22.  
  23.     const
  24.         kSystemMenuThreshold = -16000;        { menu IDs <= than this are used by the system }
  25.         kMovableModalEventMask = mDownMask + mUpMask + keyDownMask + keyUpMask + autoKeyMask + updateMask + activMask + osMask;
  26.  
  27.     const
  28.         EM_Cut = 3;
  29.         EM_Copy = 4;
  30.         EM_Paste = 5;
  31.  
  32.     type
  33.         MenuEntry = record
  34.                 hMenu: MenuHandle;
  35.                 leftEdge: Integer;
  36.             end;
  37.  
  38.         MenuList = record
  39.                 offsetToLastMenu: Integer;
  40.                 rightmostEdge: Integer;
  41.                 unused: Integer;
  42.                 theMenus: array[0..0] of MenuEntry;
  43.             end;
  44.         MenuListPtr = ^MenuList;
  45.         MenuListHandle = ^MenuListPtr;
  46.  
  47.         MenuBarState = record
  48.                 mbsBarEnable: LongInt;
  49.                 mbsEditEnable: LongInt;
  50.             end;
  51.         MenuBarStatePtr = ^MenuBarState;
  52.  
  53.     function HasHelpManager: Boolean;
  54.         var
  55.             response: LongInt;
  56.     begin
  57.         HasHelpManager := (Gestalt(gestaltHelpMgrAttr, response) = noErr) & TPbtst(response, gestaltHelpMgrPresent);
  58.     end;
  59.  
  60.     procedure DisableMenuBar (var saved_state: univ Ptr; hmnuID: Integer);
  61.         var
  62.             menuList: MenuListHandle;
  63.             i, nMenus: Integer;
  64.             theMenu: MenuHandle;
  65.             menuID: Integer;
  66.             theDialog: DialogPtr;
  67.             hasBalloons, needEditMenu: Boolean;
  68.             junk: OSErr;
  69.             state: MenuBarStatePtr;
  70.     begin
  71.         hasBalloons := HasHelpManager;
  72.  
  73.         theDialog := FrontWindow;
  74.         needEditMenu := (theDialog <> nil) & (SelectedTextItem(theDialog) > 0);
  75.  
  76.         menuList := MenuListHandle(LMGetMenuList);
  77.         nMenus := menuList^^.offsetToLastMenu div SizeOf(MenuEntry);
  78.  
  79.         saved_state := NewPtr(SizeOf(MenuBarState));
  80.         state := MenuBarStatePtr(saved_state);
  81.  
  82.         state^.mbsBarEnable := 0;
  83.         for i := 0 to nMenus - 1 do begin
  84.             theMenu := menuList^^.theMenus[i].hMenu;
  85.             menuID := theMenu^^.menuID;
  86.  
  87.             if (menuID > kSystemMenuThreshold) then begin { do nothing if this is a system menu }
  88.  
  89.                 if (menuID = M_Edit) then begin
  90.                     state^.mbsEditEnable := theMenu^^.enableFlags;
  91.                     if needEditMenu then begin
  92.                         theMenu^^.enableFlags := 1 + BSL(1, EM_Cut) + BSL(1, EM_Copy) + BSL(1, EM_Paste);
  93.                     end
  94.                     else begin
  95.                         DisableItem(theMenu, 0);
  96.                     end;
  97.                 end
  98.                 else begin { if this menu is enabled, disable it and set the corresponding bit  }
  99.                     if (TPbtst(theMenu^^.enableFlags, 0)) then begin
  100.                         BSET(state^.mbsBarEnable, i);
  101.                         DisableItem(theMenu, 0);
  102.                     end;
  103.  
  104.                     if (hasBalloons) then begin { remap the help strings for this menu }
  105.                         junk := HMSetMenuResID(menuID, hmnuID);
  106.                     end;
  107.                 end;
  108.             end;
  109.         end;
  110.  
  111.         HiliteMenu(0);
  112.         DrawMenuBar;
  113.         CursorSetProcessing(false);
  114.         CursorSetArrow;
  115.     end;
  116.  
  117.     procedure ReEnableMenuBar (var saved_state: univ Ptr);
  118.         var
  119.             menuList: MenuListHandle;
  120.             i, nMenus: Integer;
  121.             theMenu: MenuHandle;
  122.             menuID: Integer;
  123.             hasBalloons: Boolean;
  124.             err: OSErr;
  125.             state: MenuBarStatePtr;
  126.     begin
  127.         state := MenuBarStatePtr(saved_state);
  128.  
  129.         hasBalloons := HasHelpManager;
  130.  
  131.         menuList := MenuListHandle(LMGetMenuList);
  132.         nMenus := menuList^^.offsetToLastMenu div SizeOf(MenuEntry);
  133.  
  134.         for i := 0 to nMenus - 1 do begin
  135.             theMenu := menuList^^.theMenus[i].hMenu;
  136.             menuID := theMenu^^.menuID;
  137.  
  138.             if (menuID > kSystemMenuThreshold) then begin
  139.                 if (menuID = M_Edit) then begin
  140.                     theMenu^^.enableFlags := state^.mbsEditEnable;
  141.                 end
  142.                 else if (TPbtst(state^.mbsBarEnable, i)) then begin
  143.                     EnableItem(theMenu, 0);
  144.                 end;
  145.                 if (hasBalloons) then begin
  146.                     err := HMSetMenuResID(menuID, -1);
  147.                 end;
  148.             end;
  149.         end;
  150.  
  151.         DisposePtr(saved_state);
  152.         saved_state := nil;
  153.         DrawMenuBar;
  154.     end;
  155.  
  156.     function DoMenuChoice (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: Integer; menuChoice: LongInt): Boolean;
  157.         var
  158.             menuID, menuItem: Integer;
  159.             currentEditField, itemType: Integer;
  160.             junk: OSErr;
  161.     begin
  162.         theEvent:=theEvent; { UNUSED! }
  163.         DoMenuChoice := false;
  164.  
  165.         menuID := HiWord(menuChoice);
  166.         menuItem := LoWord(menuChoice);
  167.  
  168.         if (menuID = M_Edit) then begin
  169.             currentEditField := SelectedTextItem(theDialog);
  170.             GetDItemKind(theDialog, currentEditField, itemType);
  171.  
  172.             if (BAND(itemType, itemDisable) = 0) then begin { if the current edit field is an enabled item, exit from MovableModalDialog loop }
  173.                 DoMenuChoice := true;
  174.                 itemHit := currentEditField;
  175.             end;
  176.  
  177.             if (menuItem = EM_Cut) then begin
  178.                 DialogCut(theDialog);
  179.                 junk := ZeroScrap;
  180.                 junk := TEToScrap;
  181.             end
  182.             else if (menuItem = EM_Copy) then begin
  183.                 DialogCopy(theDialog);
  184.                 junk := ZeroScrap;
  185.                 junk := TEToScrap;
  186.             end
  187.             else if (menuItem = EM_Paste) then begin
  188.                 junk := TEFromScrap;
  189.                 DialogPaste(theDialog);
  190.             end;
  191.         end;
  192.  
  193.         HiliteMenu(0);
  194.     end;
  195.  
  196.     function HandleMouseDown (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: Integer): Boolean;
  197.         var
  198.             partCode: Integer;
  199.             wind: WindowPtr;
  200.             beeper: ProcPtr;
  201.             dragRect: Rect;
  202.     begin
  203.         HandleMouseDown := false;
  204.  
  205.         partCode := FindWindow(theEvent.where, wind);
  206.  
  207.         if (partCode = inMenuBar) then begin
  208.             HandleMouseDown := DoMenuChoice(theDialog, theEvent, itemHit, MenuSelect(theEvent.where));
  209.         end
  210.         else if (not PtInRgn(theEvent.where, WindowPeek(theDialog)^.strucRgn)) then begin
  211.             beeper := LMGetDABeeper;
  212.             if (beeper <> nil) then begin
  213.                 CallSoundProc(1, beeper);
  214.             end;
  215.         end
  216.         else if (partCode = inDrag) & (theDialog = wind) then begin { now, we have to handle the only thing DialogSelect doesn't do for us: dragging }
  217.             dragRect := GetGrayRgn^^.rgnBBox;
  218.             DragWindow(wind, theEvent.where, dragRect);
  219.             theEvent.what := nullEvent;
  220.         end;
  221.     end;
  222.  
  223.     procedure MovableModalDialog (filterProc: ProcPtr; var itemHit: Integer);
  224.         var
  225.             dlg, junk_dialog: DialogPtr;
  226.             er: EventRecord;
  227.             dummy: Boolean;
  228.             resume:Boolean;
  229.     begin
  230.         itemHit := 0;
  231.         dlg := FrontWindow;
  232.         if (dlg <> nil) then begin
  233.             SetPort(dlg);
  234.             repeat
  235.                 dummy := WaitNextEvent(kMovableModalEventMask, er, 0, nil);
  236.                 SetPort(dlg);
  237.  
  238.                 if (filterProc <> nil) & CallModalFilterProc(dlg, er, itemHit, filterProc) then begin
  239.                     Leave;
  240.                 end;
  241.  
  242.                 if er.what = kOSEvent then begin
  243.                     if BAND(BROTL(er.message, 8), $FF) = kSuspendResumeMessage then begin
  244.                         resume := (BAnd(er.message, kResumeMask) <> 0);
  245.                         SetInForeground(resume);
  246.                     end;
  247.                 end;
  248.  
  249.                 if (er.what = mouseDown) & HandleMouseDown(dlg, er, itemHit) then begin
  250.                     Leave;
  251.                 end;
  252.  
  253.                 if (er.what = keyDown) & (BAND(er.modifiers, cmdKey) <> 0) & DoMenuChoice(dlg, er, itemHit, MenuKey(CHR(BAND(er.message, charCodeMask)))) then begin
  254.                     Leave;
  255.                 end;
  256.  
  257.                 if IsDialogEvent(er) & DialogSelect(er, junk_dialog, itemHit) then begin
  258.                     Leave;
  259.                 end;
  260.             until false;
  261.         end;
  262.  
  263.     end;
  264.  
  265. end.