Subversion Repositories filter_foundry

Rev

Rev 193 | Rev 268 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.         This file is part of a common library
  3.     Copyright (C) 1990-2006 Toby Thain, toby@telegraphics.com.au
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by  
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License  
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. #include "carbonstuff.h"
  21.  
  22. #include <quickdraw.h>
  23. #include <controls.h>
  24. #include <dialogs.h>
  25. #include <events.h>
  26. #include <osutils.h> // Delay
  27. #include <palettes.h> // GetGray
  28. #include <resources.h>
  29. #include <textutils.h> // NumToString
  30. #include <ctype.h>
  31. #include <gestalt.h>
  32.  
  33. #include "dlg.h"
  34. #include "qd.h"
  35. #include "wind.h"
  36. #include "misc-mac.h"
  37.  
  38. #if 0 //TARGET_API_MAC_CARBON /* FIXME:KLUDGE */
  39. #define DisposeRoutineDescriptor
  40. #define NewRoutineDescriptor( theProc, theProcInfo, theISA) (theProc)
  41. #define NewDeviceLoopDrawingProc
  42. #endif
  43.  
  44. pascal void grey_item_dldp(short depth, short deviceFlags, GDHandle targetDevice, long userData);
  45.  
  46. DialogPtr get_centred_dialog(short id){ DialogRef d;
  47.         // assume the dialog is initially invisible; otherwise the centring process would be ugly
  48.         /*centre_window*/(d = GetNewDialog(id,0,(WindowPtr)-1));
  49.         ShowWindow(GetDialogWindow(d));
  50.         return d;
  51. }
  52.  
  53. void centre_alert(short id){
  54.         AlertTHndl a = (AlertTHndl)GetResource('ALRT',id);
  55.         centre_rect(&(*a)->boundsRect);
  56. }
  57.  
  58. Point centred(short id){ DialogTHndl t; Rect s;
  59.         t = (DialogTHndl)GetResource('DLOG',id);
  60.         s = (*t)->boundsRect;
  61.         ReleaseResource((Handle)t);
  62.         centre_rect(&s);
  63.         return TOPLEFT(s);
  64. }
  65.  
  66. /* dialog utilities */
  67.  
  68. Handle item_handle(DialogPtr d,short i){
  69.         short kind;
  70.         Handle item;
  71.         Rect box;
  72.  
  73.         GetDialogItem(d,i,&kind,&item,&box);
  74.         return item;
  75. }
  76.  
  77. void get_item_rect(DialogPtr d,short i,Rect*r){
  78.         short kind;
  79.         Handle item;
  80.  
  81.         GetDialogItem(d,i,&kind,&item,r);
  82. }
  83.  
  84. void inval_item(DialogPtr d,short i){
  85.         Rect r;
  86.         //GrafPtr gp;
  87.         get_item_rect(d,i,&r);
  88.         //GetPort(&gp);         SetPort(d);
  89.         InvalWindowRect(GetDialogWindow(d),&r);
  90.         //SetPort(gp);
  91. }
  92.  
  93. void hide_items(DialogPtr d,long v){ int i;
  94.         for(i=1;v>>=1;i++)
  95.                 if(v&1)
  96.                         HideDialogItem(d,i);
  97. }
  98. void show_items(DialogPtr d,long v){ int i;
  99.         for(i=1;v>>=1;i++)
  100.                 if(v&1)
  101.                         ShowDialogItem(d,i);
  102. }
  103.  
  104. void set_user_item(DialogPtr d,short i,UserItemUPP p){
  105.         short kind;
  106.         Handle item;
  107.         Rect box;
  108.  
  109.         GetDialogItem(d,i,&kind,&item,&box);
  110.         SetDialogItem(d,i,kind,(void*)p,&box);
  111. }
  112.  
  113. void set_item_value(DialogPtr d,short i,short v){
  114.         SetControlValue((ControlHandle)item_handle(d,i),v);
  115. }
  116.  
  117. void get_item_text(DialogPtr d,short i,Str255 s){
  118.         GetDialogItemText(item_handle(d,i),s);
  119. }
  120.  
  121. void set_item_text(DialogPtr d,short i,Str255 s){
  122.         SetDialogItemText(item_handle(d,i),s);
  123. }
  124.  
  125. void set_num_item(DialogPtr d,short i,long n){
  126.         Str255 s;
  127.  
  128.         NumToString(n,s);
  129.         SetDialogItemText(item_handle(d,i),s);
  130. }
  131.  
  132. long get_num_item(DialogPtr d,short i){
  133.         Str255 s;
  134.         long n;
  135.  
  136.         GetDialogItemText(item_handle(d,i),s);
  137.         StringToNum(s,&n);
  138.         return n;
  139. }
  140.  
  141. USER_ITEM(dimmed_item){ PenState ps; Rect r; Pattern pat;
  142.         get_item_rect(theDialog,itemNo,&r);
  143.         GetPenState(&ps);
  144.         GetQDGlobalsGray(&pat);
  145.         PenPat(&pat);
  146.         PenMode(patBic);
  147.         PaintRect(&r);
  148.         SetPenState(&ps);
  149. }
  150.  
  151. #if 0
  152. USER_ITEM(grey_item){ PenState ps; Rect r;
  153.         get_item_rect(theDialog,itemNo,&r);
  154.         GetPenState(&ps);
  155.         PenPat(&SAFE_QD(gray));
  156.         FrameRect(&r);
  157.         SetPenState(&ps);
  158. }
  159.  
  160. #else
  161.  
  162. pascal void grey_item_dldp(short depth, short deviceFlags, GDHandle targetDevice, long userData){
  163.         RGBColor save,fg,bg;
  164.         PenState ps;
  165.         int f;
  166.         Pattern pat;
  167.  
  168.         GetBackColor(&bg);
  169.         GetForeColor(&fg);
  170.         save = fg;
  171.  
  172.         if( f = GetGray(targetDevice, &bg, &fg) ){
  173.                 RGBForeColor(&fg);
  174.         }else{
  175.                 GetPenState(&ps);
  176.                 GetQDGlobalsGray(&pat);
  177.                 PenPat(&pat);
  178.         }
  179.         FrameRect((Rect*)userData);
  180.         f ? RGBForeColor(&save) : SetPenState(&ps);
  181. }
  182.  
  183. USER_ITEM(grey_item){
  184.         Rect r;
  185.         RgnHandle rgn;
  186.         DeviceLoopDrawingUPP proc = NewDeviceLoopDrawingUPP(grey_item_dldp);
  187.         GrafPtr gp;
  188.        
  189.         GetPort(&gp);
  190.         SetPort((GrafPtr)GetWindowPort(GetDialogWindow(theDialog)));
  191.  
  192.         get_item_rect(theDialog,itemNo,&r);
  193.         RectRgn(rgn = NewRgn(),&r);
  194.         DeviceLoop(rgn, proc, (long)&r, 0);
  195.         DisposeRgn(rgn);
  196.        
  197.         SetPort(gp);
  198.  
  199.         DisposeDeviceLoopDrawingUPP(proc);
  200. }
  201. #endif
  202.  
  203. USER_ITEM(framed_item){ Rect r;
  204.         get_item_rect(theDialog,itemNo,&r);
  205.         FrameRect(&r);
  206. }
  207.  
  208. USER_ITEM(label_frame_item){ Rect r; RgnHandle rgn,rgn2;
  209.         // draws a single-pixel frame around the item,
  210.         // leaving out the rectangle of the previous item
  211.         // (which is usually the label for the frame)
  212.        
  213.         GetClip(rgn = NewRgn());
  214.  
  215.         get_item_rect(theDialog,itemNo-1,&r);
  216.         RectRgn(rgn2 = NewRgn(),&r);
  217.         DiffRgn(rgn,rgn2,rgn2);
  218.         SetClip(rgn2);
  219.  
  220.         grey_item(theDialog, itemNo);
  221.  
  222.         SetClip(rgn);
  223.  
  224.         DisposeRgn(rgn);
  225.         DisposeRgn(rgn2);
  226. }
  227.  
  228. USER_ITEM(outlined_item){ PenState ps; Rect r; int k; Pattern pat;
  229.         get_item_rect(theDialog,itemNo,&r);
  230.         GetPenState(&ps);
  231.         PenSize(3,3);
  232.         if( GetControlHilite( (ControlHandle)item_handle(theDialog,GetDialogDefaultItem(theDialog)) ) ){
  233.                 GetQDGlobalsGray(&pat);
  234.                 PenPat(&pat);
  235.         }
  236.         k = (r.bottom-r.top)/2 + 2; // ???
  237.         FrameRoundRect(&r,k,k);
  238.         SetPenState(&ps);
  239. }
  240.  
  241. #if 0
  242. // determine what character a keypress would be had it not been modified by the command key
  243. // this code is absolutely useless
  244.  
  245. char unmodified_key(EventRecord*e){ short keycode; long state=0,c; char c1; void *transData;
  246.         if(transData = (void*)GetEnvirons(smKCHRCache)){
  247.                 keycode = (e->modifiers & (0xff00 & ~cmdKey)) | ((e->message & keyCodeMask) >> 8);
  248.                 c = KeyTrans(transData,keycode,&state);
  249.                 return (c1 = c>>16) ? c1 : c;
  250.         }else
  251.                 return e->message;
  252. }
  253.  
  254. /*
  255. You're wrong Phil. Command does in fact disable the shift modifier. See
  256. the tech note on International Cancelling. To properly handle the command
  257. key in your application, you should always strip the command-key bit out
  258. of the modifiers field and re-pass the keystroke through KeyTrans. Here's
  259. some source code for doing it with the cancel key, but you should use
  260. similar code for any command-key combination (like in MenuKey):
  261. */
  262. /* These both use Universal Headers. The second is for System 6 too. */
  263.  
  264. Boolean WasCancel(EventRecord *theEvent)
  265. {
  266.     short keyCode;
  267.     long state = 0L, test;
  268.     unsigned long keys;
  269.    
  270.     if(!(theEvent->modifiers & cmdKey))
  271.         return(false);
  272.     keyCode = (theEvent->modifiers & 0xFE00) |
  273.               ((theEvent->message & keyCodeMask) >> 8);
  274.     keys = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache),
  275.                         keyCode, &state);
  276.     return(((Byte)keys == '.') || ((Byte)(keys >>= 16) == '.'));
  277. }
  278.  
  279. Boolean WasCancelSystem6or7(EventRecord *theEvent)
  280. {
  281.     short keyCode, rsrcID, scriptID;
  282.     Ptr kchrPtr;
  283.     Handle kchrRsrc = nil;
  284.     long state = 0L;
  285.     unsigned long keys;
  286.    
  287.     if(!(theEvent->modifiers & cmdKey))
  288.         return(false);
  289.     keyCode = (theEvent->modifiers & 0xFE00) |
  290.               ((theEvent->message & keyCodeMask) >> 8);
  291.     if((kchrPtr = (Ptr)GetScriptManagerVariable(smKCHRCache)) == nil) {
  292.         scriptID = GetScriptManagerVariable(smKeyScript);
  293.         rsrcID = GetScriptVariable(scriptID, smScriptKeys);
  294.         kchrRsrc = GetResource('KCHR', rsrcID);
  295.         if(kchrRsrc != nil)
  296.             kchrPtr = *kchrRsrc;
  297.     }
  298.     if(kchrPtr != nil)
  299.         keys = KeyTranslate(kchrPtr, keyCode, &state);
  300.     if(kchrRsrc != nil)
  301.         ReleaseResource(kchrRsrc);
  302.     return(((Byte)keys == '.') || ((Byte)(keys >>= 16) == '.'));
  303. }
  304. // Pete Resnick    (...so what is a mojo, and why would one be rising?)
  305. #endif
  306.  
  307. Boolean is_a_button(DialogPtr d,int i){ KIND_ITEM_BOX
  308.         GetDialogItem(d,i,&kind,&item,&box);
  309.         return kind==ctrlItem|btnCtrl && !GetControlHilite((ControlHandle)item);
  310. }
  311.  
  312. // TO DO: modify is_cancel to use IsCmdChar (scripts.h)
  313.  
  314. Boolean is_cancel(EventRecord*e){ char c = e->message;
  315.         return e->what==keyDown && ((e->modifiers&cmdKey && c=='.') || c==27);
  316. }
  317. FILTER(filter_buttons){ int i=0,j; char c; Str255 s; WindowPtr w; Boolean f = false;
  318.         switch(theEvent->what){
  319.         case mouseDown:
  320.                 if(theEvent->modifiers & cmdKey && FindWindow(theEvent->where,&w) == inDrag){
  321.                         BitMap bm;
  322.                         GetQDGlobalsScreenBits(&bm);
  323.                         DragWindow(w,theEvent->where,&bm.bounds);
  324.                         theEvent->what = nullEvent;
  325.                 }
  326.                 break;
  327.         case keyDown:
  328.                 c = theEvent->message;
  329.                 if( (c==3 || c==13) && is_a_button(theDialog,GetDialogDefaultItem(theDialog)) )
  330.                         i = GetDialogDefaultItem(theDialog);
  331.                 else if(is_cancel(theEvent) && is_a_button(theDialog,cancel))
  332.                         i = cancel;
  333.                 else if(GetDialogKeyboardFocusItem(theDialog) == -1 /*|| theEvent->modifiers & cmdKey*/
  334.                                 && gestalt_attr(gestaltDITLExtAttr,gestaltDITLExtPresent)){
  335.                         c = tolower(c);
  336.                         for(j=CountDITL(theDialog);j;j--){ KIND_ITEM_BOX
  337.                                 GetDialogItem(theDialog,j,&kind,&item,&box);
  338.                                 if( (kind&(itemDisable|ctrlItem))==ctrlItem && !GetControlHilite((ControlHandle)item) ){
  339.                                         GetControlTitle((ControlHandle)item,s);
  340.                                         if(*s && tolower(s[1])==c)
  341.                                                 if(i){ // two buttons' titles begin with the same character
  342.                                                         i = 0;
  343.                                                         break;
  344.                                                 }else
  345.                                                         i = j;
  346.                                 }
  347.                         }
  348.                 }
  349.                 if(i){
  350.                         flash_button(theDialog,*itemHit = i);
  351.                         f = true;
  352.                 }
  353.         }
  354.         return f;
  355. }
  356.  
  357. /*      It would be nice to highlight the button until the user releases the key,
  358.         but if the key was released before the event mask is set to include key-up events,
  359.         the event won't be posted, and the button stays highlighted until a key is next released.
  360.        
  361.         The easy solution is to enable key-up events when the application starts up;
  362.         however, I'm not sure that the extra code to do this
  363.                 *(short*)SysEvtMask |= keyUpMask
  364.         and wait for the event
  365.                 while(!EventAvail(keyUpMask,&e)) ;
  366.         is justified.
  367.         (There's also the overhead of an extra event per keypress.)
  368.         We should only un-highlight the button if the SAME key was released as was pressed.
  369. */
  370. void flash_button(DialogPtr d,short i){
  371. #if 0 // I'm temporarily taking this code out, because "inButton" has disappeared from headers???
  372.         ControlHandle c; unsigned long t; int h;
  373.         c = (ControlHandle)item_handle(d,i);
  374.         h = (*c)->contrlHilite;
  375.         HiliteControl(c,inButton);
  376.         Delay(8,&t);
  377.         HiliteControl(c,h);
  378. #endif
  379. }
  380.