home *** CD-ROM | disk | FTP | other *** search
- /*
- File: DlogUtil.cpp
-
- Contains: implementation of dialog utility functions
-
- Owned by: Tantek Çelik
-
- Copyright: © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <4> 1/5/96 eeh 1298401: don't disable keyboard changes
- <3> 1/4/96 eeh fix header
- <2> 1/4/96 eeh 1226961: make ActivateAllControls
- non-static
-
- To Do:
- */
-
- #ifndef _EXCEPT_
- #include <Except.h>
- #endif
-
- #ifndef SOM_Module_OpenDoc_Errors_defined
- #include <ErrorDef.xh>
- #endif
-
- #ifndef _DLOGUTIL_
- #include <DlogUtil.h>
- #endif
-
- #ifndef _PLFMDEF_
- #include <PlfmDef.h>
- #endif
-
- #ifndef _ODUTILS_
- #include <ODUtils.h>
- #endif
-
- #ifndef SOM_ODMenuBar_xh
- #include <MenuBar.xh>
- #endif
-
- #ifndef SOM_ODDispatcher_xh
- #include <Disptch.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef SOM_ODWindowState_xh
- #include <WinStat.xh>
- #endif
-
- #ifndef SOM_ODClipboard_xh
- #include <Clipbd.xh>
- #endif
-
- #ifndef _ODMEMORY_
- #include <ODMemory.h>
- #endif
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef _PASCLSTR_
- #include <PasclStr.h>
- #endif
-
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
-
- #ifndef __TEXTEDIT__
- #include <TextEdit.h>
- #endif
-
- #ifndef __PALETTES__
- #include <Palettes.h>
- #endif
-
- #ifndef _MEMMGR_
- #include <MemMgr.h>
- #endif
-
- #ifndef _ODDEBUG_
- #include <ODDebug.h>
- #endif
-
- #ifndef _USERSRCM_
- #include <UseRsrcM.h>
- #endif
-
- #ifndef SOM_ODNameSpaceManager_xh
- #include <NmSpcMg.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_Commands_defined
- #include <CmdDefs.xh>
- #endif
-
- #ifndef SOM_ODStorageSystem_xh
- #include <ODStor.xh>
- #endif
-
- #ifndef SOM_ODPlatformTypeList_xh
- #include <PfTypLs.xh>
- #endif
-
- #ifndef _TEMPOBJ_
- #include "TempObj.h"
- #endif
-
- // Types
- struct _MenuItemInfo
- {
- MenuHandle menu;
- short item;
- Str255 text;
- short cmdChar;
- short iconID;
- short markChar;
- Style textStyle;
- };
- typedef struct _MenuItemInfo MenuItemInfo;
-
- struct _DialogBoxInfo
- {
- MenuItemInfo redo;
- // Can put other things in here later on
- // like supporting movable modals, etc.
- };
- typedef struct _DialogBoxInfo DialogBoxInfo;
-
- // Key codes
- // const char kEscapeKey = 0x1B;
- // const char kUpArrowKey = 0x1E;
- // const char kDownArrowKey = 0x1F;
- const char kPageUpKey = 0x0B;
- const char kPageDownKey = 0x0C;
- const char kHomeKey = 0x01;
- const char kEndKey = 0x04;
-
- // Control settings
- const short kControlInactive = 255;
- const short kControlActive = 0;
-
- // Dialog item assumptions
- const short kOKButton = 1;
- const short kCancelButton = 2;
-
- // Memory requirements
- const size_t kODMinFreeSpaceToShowDialog = 4 * 1024;
-
- static Environment *sEv;
- static ODSession *sSession;
- static ModalFilterUPP sFilter = kODNULL;
- static ModalFilterUPP sButtonKeyFilter = kODNULL;
- static ModalFilterUPP sArrowKeyFilter = kODNULL;
- static UserItemUPP sOutlineDrawProc = kODNULL;
- static short sCmdKeyStrResID = 0;
- static DialogScriptData*
- sDlogScriptData = kODNULL;
- // Res ID of STR# that contains cmd-keys for buttons
-
- static DialogBoxInfo* sDialogInfo = kODNULL;
-
- // Private functions
- static void SaveAndDeleteMenuItem( MenuHandle menu, short item, MenuItemInfo *savedItem );
- static void RestoreMenuItem( MenuItemInfo *savedItem );
-
-
- //==============================================================================
- // Preflighting Dialogs and Alerts
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Centering
- //------------------------------------------------------------------------------
-
- static ODBoolean
- GetFrontWindowBounds( Rect &bounds )
- {
- WindowPtr wp;
- {
- TempODWindow win = sSession->GetWindowState(sEv)->AcquireActiveWindow(sEv);
- wp = win ? win->GetPlatformWindow(sEv) : FrontWindow();
- }
-
- if( wp ) {
- bounds = wp->portRect;
- Rect *mapBounds;
- if( wp->portBits.rowBytes & 0xC000 ) // Color port
- mapBounds= &(**((CGrafPtr)wp)->portPixMap).bounds;
- else
- mapBounds= &wp->portBits.bounds;
- OffsetRect(&bounds,-mapBounds->left,-mapBounds->top);
- return kODTrue;
- } else {
- bounds = ODQDGlobals.screenBits.bounds; // No win, use main screen
- bounds.top += GetMBarHeight();
- return kODFalse;
- }
- }
-
-
- static void
- GetWindowsMainScreen( const Rect &windowBounds, Rect &screenBounds )
- {
- long area=0;
-
- GDHandle gdh;
- Rect devBounds,sectBounds;
- long maxArea=0;
-
- for( gdh = GetDeviceList(); gdh; gdh = GetNextDevice(gdh) ) {
- devBounds = (**gdh).gdRect;
- if( gdh == GetMainDevice() )
- devBounds.top += GetMBarHeight();
- if( SectRect(&devBounds,&windowBounds,§Bounds) ) {
- area = (sectBounds.right-sectBounds.left) * (long)(sectBounds.bottom-sectBounds.top);
- if( area > maxArea ) {
- maxArea = area; // Best screen so far
- screenBounds = devBounds;
- if( gdh==GetMainDevice() )
- screenBounds.right -= 30; // Leave room for Finder disk icons
- }
- }
- }
- if( area==0 ) {
- screenBounds = ODQDGlobals.screenBits.bounds; // Default: use main screen
- screenBounds.top += GetMBarHeight();
- }
- }
-
-
- static void
- CenterDialog( short ¢erFlag, Rect &bounds )
- {
- /* Do centering manually. Why? Even though the Dialog Manager handles
- automatic centering, it calls FrontWindow to find the parent window.
- This will return an incorrect window (a floater) if there are floating
- windows. We have to reproduce the centering effect but using the
- actual frontmost non-floating window. */
- const short noAutoCenter = 0x0000;
- const short centerParentWindowScreen = 0x680A; // From Types.r
- const short alertPositionParentWindowScreen = 0x700A;
- const short centerParentWindow = 0xA80A;
- const short alertPositionParentWindow = 0xB00A;
- // We don't do anything for other flags.
-
- if( centerFlag == noAutoCenter )
- return;
-
- Rect centerBounds;
- if( GetFrontWindowBounds(centerBounds)
- && (centerFlag==centerParentWindowScreen ||
- centerFlag==alertPositionParentWindowScreen) ) {
- Rect screenBounds;
- GetWindowsMainScreen(centerBounds,screenBounds);
- centerBounds = screenBounds;
- }
-
- Point pos;
- pos.h = ((centerBounds.right-centerBounds.left)-(bounds.right-bounds.left)) >>1;
- pos.v = ((centerBounds.bottom-centerBounds.top)-(bounds.bottom-bounds.top));
- if( centerFlag==centerParentWindowScreen || centerFlag==centerParentWindow )
- pos.v /= 2;
- else if( centerFlag==alertPositionParentWindowScreen || centerFlag==alertPositionParentWindow )
- pos.v /= 3;
- else
- return; // Ignore other flags
-
- pos.h += centerBounds.left;
- pos.v += centerBounds.top;
- OffsetRect(&bounds, pos.h-bounds.left, pos.v-bounds.top);
- centerFlag = noAutoCenter; // It's already centered now
- }
-
-
- //------------------------------------------------------------------------------
- // PreflightDialog
- //------------------------------------------------------------------------------
-
- static Handle
- PreflightDialog( ODBoolean isDLOG, short id )
- {
- Handle rsrc;
- ODBoolean ok;
-
- if( isDLOG ) {
- // Load DLOG and DITL:
- rsrc = Get1Resource('DLOG', id);
- DialogTemplate** dlogTemplate = (DialogTemplate**)rsrc;
- ok = dlogTemplate && Get1Resource('DITL', (*dlogTemplate)->itemsID);
- if( ok ) {
- // Get the centering flag & adjust dialog centering:
- HLock(rsrc);
- size_t centerFlag = (size_t) &(**dlogTemplate).title;
- centerFlag += *(unsigned char*)centerFlag +1; // skip title
- centerFlag += (centerFlag & 1); // word align
- CenterDialog(*(short*)centerFlag, (**dlogTemplate).boundsRect);
- HUnlock(rsrc);
- }
- } else {
- // Load ALRT and DITL:
- rsrc = Get1Resource('ALRT', id);
- AlertTemplate** alrtTemplate = (AlertTemplate**)rsrc;
- ok = alrtTemplate && Get1Resource('DITL', (*alrtTemplate)->itemsID);
- if( ok ) {
- // Get the centering flag & adjust alert centering:
- HLock(rsrc);
- short *centerFlag = (short*)( (size_t)*alrtTemplate + sizeof(AlertTemplate) );
- CenterDialog(*centerFlag,(**alrtTemplate).boundsRect);
- HUnlock(rsrc);
- }
- }
-
- if( !ok ) {
- #if ODDebug
- OSErr err = ResError();
- if( err != noErr && err != resNotFound )
- WARN("Could not load dialog/alert %hd: error %hd",id,err);
- #endif
- SysBeep(2); // At least give some indication
- rsrc = kODNULL;
- } else {
- // Bail if space is really, really low. Don't even beep, this might cause
- // a large 'snd' to be loaded.
- if( !ODHaveFreeSpace(kODMinFreeSpaceToShowDialog,kODMinFreeSpaceToShowDialog,
- kODTrue) ) {
- WARN("Whoa, not enough memory to show a dialog/alert!");
- ReleaseResource(rsrc);
- rsrc = kODNULL;
- }
- }
-
- return rsrc;
- }
-
-
- //==============================================================================
- // Displaying Dialogs and Alerts
- //==============================================================================
-
- DialogPtr
- ODGetNewDialog( Environment *ev, short resID, ODSession *session, ODBoolean defaultButtons )
- {
- ASSERT(session!=kODNULL, kODErrIllegalNullInput);
-
- sEv = ev ?ev :somGetGlobalEnvironment();
- sSession = session;
-
- Handle dlogRsrc = PreflightDialog(kODTrue,resID);
- if( ! dlogRsrc )
- return kODNULL;
-
- DialogPtr dlog = ::GetNewDialog(resID,kODNULL,(WindowPtr)-1L);
- if( dlog ) {
- if( defaultButtons ) {
- ::SetDialogDefaultItem(dlog,kStdOkItemIndex);
- ::SetDialogCancelItem(dlog,kStdCancelItemIndex);
- }
- ::SetDialogTracksCursor(dlog,kODTrue);
-
- sCmdKeyStrResID = 0; // Don't use command-key lookup unless told to
-
- InitCursor(); // Show arrow
- }
-
- ReleaseResource(dlogRsrc);
-
- return dlog;
- }
-
- ODSShort
- ShowAlert(Environment *ev, ODSShort alertID, ModalFilterUPP modalFilter, ODSession *session)
- {
- ASSERT(session != kODNULL, kODErrIllegalNullInput);
-
- CUsingLibraryResources r;
-
- SetCursor(&(ODQDGlobals.arrow));
-
- sEv = ev ?ev :somGetGlobalEnvironment();
- sSession = session;
-
- Handle alrtRsrc = PreflightDialog(kODFalse,alertID);
- if( ! alrtRsrc )
- return cancel;
-
- // Success at last!
-
- short alertReturn = Alert(alertID, modalFilter);
-
- ReleaseResource(alrtRsrc);
-
- return alertReturn;
- }
-
- pascal Boolean
- ODDialogFilterProc( DialogPtr dp, EventRecord *event, short *item )
- {
- ODBoolean dispatch = kODFalse;
-
- if( event->what==updateEvt || event->what==activateEvt ) {
- if( (WindowPtr)event->message != dp ) // Dispatch updates/activates of other windows
- dispatch = kODTrue;
-
- } else if( event->what==nullEvent || event->what==osEvt ) // Ditto null/suspend/resume
- dispatch = kODTrue;
-
- else if( event->what==mouseDown ) {
- WindowPtr wp;
- if( ::FindWindow(event->where,&wp)==inDrag && wp==dp ) { // Dragging me!
- Rect bounds = ODQDGlobals.screenBits.bounds;
- DragWindow(dp,event->where,&bounds);
- event->what = nullEvent;
- }
-
- } else if( event->what==keyDown ) {
- // Cmd-A means select all if there is editable text:
- short curTextItem = ((DialogPeek)dp)->editField + 1;
- char key = event->message & charCodeMask;
- if( curTextItem>0 && (key=='a' || key=='A') && (event->modifiers & cmdKey) )
- SelectDialogItemText(dp, curTextItem, 0, 32767);
- #ifdef TO_BE_DELETED
- else
- {
- long scriptNum = GetScriptManagerVariable( smKeyScript );
- long curScript = FontToScript(dp->txFont);
- if ( curScript != scriptNum )
- {
- // DebugStr( "\pChanging system font;g" );
- short myFont = GetScriptVariable( scriptNum, smScriptAppFond );
- WindowPtr savePort;
- GetPort(&savePort);
- SetPort(dp);
- TextFont( myFont );
- SetPort(savePort);
- }
- }
- #endif /* TO_BE_DELETED */
- }
-
- if( dispatch ) {
- TRY{
- ODDispatcher* dispatcher = sSession->GetDispatcher(sEv);
- if (dispatcher)
- dispatcher->Dispatch(sEv, (ODEventData*)event);
- }CATCH_ALL{
- }ENDTRY
- }
-
- // Forward other events to the standard filter-proc:
- ModalFilterUPP proc;
- OSErr err= GetStdFilterProc(&proc);
- if( err==noErr )
- return CallModalFilterProc(proc, dp,event,item); // Call through to std filter-proc
- else {
- WARN("Couldn't get std filter proc!");
- return false;
- }
- }
-
-
- ModalFilterUPP
- GetODDialogFilter( )
- {
- if( !sFilter )
- sFilter = NewModalFilterProc(&ODDialogFilterProc);
- return sFilter;
- }
-
-
- //==============================================================================
- // Filter Procs & Such
- //==============================================================================
-
- static void
- ActivateControl(DialogPtr dialog, short item, Boolean isActivate)
- {
- short itemType;
- Rect itemRect;
- ControlHandle cntrlHandle;
-
- GetDialogItem(dialog, item, &itemType, (Handle*) &cntrlHandle, &itemRect);
- ASSERT_CONTROL_ITEM(itemType);
-
- CUsingLibraryResources r;
-
- if ( isActivate )
- {
- HiliteControl(cntrlHandle, GetControlReference(cntrlHandle));
- }
- else
- {
- SetControlReference(cntrlHandle, (**cntrlHandle).contrlHilite);
- HiliteControl(cntrlHandle, kControlInactive);
- }
- }
-
- void
- ActivateAllControls(DialogPtr dialog, Boolean isActivate)
- {
- short itemType;
- Rect itemRect;
- ControlHandle cntrlHandle;
- short item;
-
- for (item = 1; item <= CountDITL(dialog); ++item)
- {
- GetDialogItem(dialog, item, &itemType, (Handle*) &cntrlHandle, &itemRect);
- itemType &= ~kItemDisableBit;
- if ( itemType>=ctrlItem && itemType<=ctrlItem+resCtrl )
- ActivateControl(dialog, item, isActivate);
- }
- }
-
-
- pascal Boolean ODArrowKeyFilterProc( DialogPtr dlg, ODEventData* event,
- short* itemHit )
- {
- Boolean result;
- if ( event->what == keyDown || event->what == autoKey )
- {
- result = kODTrue;
- char key = event->message & charCodeMask;
- ODBoolean cmdKeyDown = (event->modifiers & cmdKey) != 0;
- ODBoolean optionKeyDown = (event->modifiers & optionKey) != 0;
- switch ( key )
- {
- case kUpArrowKey:
- *itemHit = cmdKeyDown ? optionKeyDown ? kODHomeArrowItem :
- kODPageUpArrowItem : kODUpArrowItem;
- break;
- case kDownArrowKey:
- *itemHit = cmdKeyDown ? optionKeyDown ? kODEndArrowItem :
- kODPageDownArrowItem : kODDownArrowItem;
- break;
-
- case kPageUpKey:
- *itemHit = kODPageUpArrowItem;
- break;
- case kPageDownKey:
- *itemHit = kODPageDownArrowItem;
- break;
- case kHomeKey:
- *itemHit = kODHomeArrowItem;
- break;
- case kEndKey:
- *itemHit = kODEndArrowItem;
- break;
-
- default:
- result = kODFalse;
- }
- }
- else
- result = kODFalse;
- return result || ODButtonKeyFilterProc( dlg, event, itemHit );
- }
-
-
- ModalFilterUPP
- GetODArrowKeyFilterProc( )
- {
- if( !sArrowKeyFilter )
- sArrowKeyFilter = NewModalFilterProc(&ODArrowKeyFilterProc);
- return sArrowKeyFilter;
- }
-
- // DMc: this debugging code disables use of enter to mean 'OK' when this var is set:
- // #if ODDebug
- // int gODButtonKeyNoEnterOkay = 0; // set to non-zero to disable enter for okay
- // #endif
-
- pascal Boolean
- ODButtonKeyFilterProc(DialogPtr dialog, EventRecord *event, short *itemHit)
- {
- Rect itemRect;
- short itemType;
- Handle itemHandle;
- short myItemHit = 0;
-
- const short kEscKeyCode = 0x35; // Virtual key code for the escape key
-
- if ( event->what == keyDown )
- {
- char key = event->message & charCodeMask;
- switch ( key )
- {
- case kReturnKey:
- case kEnterKey:
- GetDialogItem(dialog, kOKButton, &itemType, &itemHandle, &itemRect);
- ASSERT_CONTROL_ITEM(itemType);
-
- // DMc: this debugging code disables use of enter to mean 'OK' when a var is set:
- // #if ODDebug
- // if ( !gODButtonKeyNoEnterOkay || key != kEnterKey )
- // {
- // if ( (**(ControlHandle)itemHandle).contrlHilite == kControlActive )
- // myItemHit = kOKButton;
- // }
- // #else
- if ( (**(ControlHandle)itemHandle).contrlHilite == kControlActive )
- myItemHit = kOKButton;
- // #endif /*ODDebug*/
-
- break;
-
- case kEscapeKey:
- // Ensure that the escape key, not the clear key, was pressed
- if ( (event->message & keyCodeMask) == (kEscKeyCode << 8) )
- {
- GetDialogItem(dialog, kCancelButton, &itemType, &itemHandle, &itemRect);
- if ( (itemType & ~kItemDisableBit) == (ctrlItem+btnCtrl) )
- myItemHit = kCancelButton;
- }
- break;
-
- case '.': // cmd-period means cancel
- if ( event->modifiers & cmdKey )
- {
- GetDialogItem(dialog, kCancelButton, &itemType, &itemHandle, &itemRect);
- if ( (itemType & ~kItemDisableBit) == (ctrlItem+btnCtrl) )
- myItemHit = kCancelButton;
- }
- break;
-
- default:
- if ( (sCmdKeyStrResID != 0) && (event->modifiers & cmdKey) )
- {
- // Attempt to match the key to a key found in the STR# resource
- Handle stringsHandle = GetResource( 'STR#', sCmdKeyStrResID );
- if ( stringsHandle )
- {
- short i;
- short numStrings = **(short**)stringsHandle;
- Str255 cmdKeyCode;
- for ( i = 1; i <= numStrings; ++i )
- {
- GetIndString( cmdKeyCode, sCmdKeyStrResID, i );
- if ( cmdKeyCode[0] && cmdKeyCode[1] == key )
- {
- GetDialogItem(dialog, i, &itemType, &itemHandle, &itemRect);
- ASSERT_CONTROL_ITEM(itemType);
- if ( (**(ControlHandle)itemHandle).contrlHilite == kControlActive )
- {
- myItemHit = i; // Cool--record the item number that is hit
- break;
- }
- }
- }
- }
- }
- break;
- }
-
- if ( myItemHit != 0 ) // need to hilite a button
- {
- FlashButtonItem( dialog, myItemHit );
- *itemHit = myItemHit;
- return kODTrue;
- }
-
- }
- else if ( event->what == activateEvt )
- {
- Boolean isActivate = ((event->modifiers & activeFlag) != 0 );
- ActivateAllControls(dialog, isActivate);
- }
-
- // we only get here if we'd otherwise be returning false; all successes
- // exit at "return kODTrue" above
- return ODDialogFilterProc(dialog,event,itemHit);
- }
-
-
- ModalFilterUPP
- GetODButtonKeyFilterProc( )
- {
- if( !sButtonKeyFilter )
- sButtonKeyFilter = NewModalFilterProc(&ODButtonKeyFilterProc);
- return sButtonKeyFilter;
- }
-
-
- void
- ODUseCommandKeyStringsResource( short resID )
- {
- sCmdKeyStrResID = resID;
- }
-
-
- //==============================================================================
- // Updating the Menu Bar
- //==============================================================================
-
- void ODDialogBegin( Environment* ev, ODSession* session,
- ODMenuBar* currentMenuBar, DialogPtr dialog )
- {
- ODUnused(dialog); // Later on, we can use this to support movable modals
-
- if ( sEv == kODNULL )
- sEv = ev;
-
- if ( sSession == kODNULL )
- sSession = session;
-
- ASSERT(currentMenuBar!=kODNULL,kODErrIllegalNullInput);
- ASSERT(sSession!=kODNULL,kODErrIllegalNullInput);
-
- // Cleanup if needed
- if ( sDialogInfo )
- ODDisposePtr(sDialogInfo);
-
- // Allocate a new menu info record
- sDialogInfo = (DialogBoxInfo*)ODNewPtrClear(sizeof(DialogBoxInfo),kDefaultHeapID);
-
- if ( sDialogInfo )
- {
- ODMenuID editMenuID = 0;
- ODPlatformMenu editMenu = kODNULL;
- short redoItem;
-
- // Delete the Redo menu item so ModalDialog will handle the Edit menu right.
- if ( currentMenuBar->IsCommandRegistered( sEv, kODCommandRedo ) )
- {
- currentMenuBar->GetMenuAndItem(sEv, kODCommandRedo, &editMenuID, &redoItem);
- editMenu = currentMenuBar->GetMenu(sEv, editMenuID );
- }
- if ( editMenu )
- SaveAndDeleteMenuItem(editMenu, redoItem, &sDialogInfo->redo);
- else
- {
- ODDisposePtr(sDialogInfo);
- sDialogInfo = kODNULL;
- }
- }
-
- // Lastly, export the OD clipboard in case the user pastes into the dialog
- ODPlatformTypeList* types = session->GetStorageSystem(ev)->CreatePlatformTypeList(ev, kODNULL);
- types->AddLast(sEv, 'TEXT');
- types->AddLast(sEv, 'PICT');
- sSession->GetClipboard(sEv)->SetPlatformClipboard(sEv, types);
- ODDeleteObject(types);
- }
-
-
- void ODDialogEnd()
- {
- // Restore the Redo menu item deleted by DialogBegin
- if ( sDialogInfo )
- {
- RestoreMenuItem(&sDialogInfo->redo);
- ODDisposePtr(sDialogInfo);
- sDialogInfo = kODNULL; // Don't allow to be called again
- }
- }
-
-
- void SaveAndDeleteMenuItem( MenuHandle menu, short item, MenuItemInfo *savedItem )
- {
- savedItem->menu = menu;
- savedItem->item = item;
- GetMenuItemText(menu, item, savedItem->text);
- GetItemCmd(menu, item, &savedItem->cmdChar);
- GetItemIcon(menu, item, &savedItem->iconID);
- GetItemMark(menu, item, &savedItem->markChar);
- GetItemStyle(menu, item, &savedItem->textStyle);
- DeleteMenuItem(menu, item);
- InvalMenuBar();
- }
-
-
- void RestoreMenuItem( MenuItemInfo *savedItem )
- {
- InsertMenuItem(savedItem->menu, savedItem->text, savedItem->item -1);
- // Still set item text in case of non-meta meta-characters.
- SetMenuItemText(savedItem->menu, savedItem->item, savedItem->text);
- SetItemCmd(savedItem->menu, savedItem->item, savedItem->cmdChar);
- SetItemIcon(savedItem->menu, savedItem->item, savedItem->iconID);
- SetItemMark(savedItem->menu, savedItem->item, savedItem->markChar);
- SetItemStyle(savedItem->menu, savedItem->item, savedItem->textStyle);
- InvalMenuBar();
- }
-
-
- pascal void
- ODOutlineDefaultButtonDrawProc(DialogPtr theDialog, short theItem)
- {
- // NOTE: this proc only works on buttons whose DITL ID is 1. theItem
- // is unused, and so it doesn't matter whether the user item to which
- // this proc is assigned (via SetDialogItem) has any geographical
- // relation to the button.
-
- ODUnused(theItem);
- Rect itemRect;
- Handle itemHandle;
- short itemKind;
-
- WindowPtr buttonWindow;
- WindowPtr savePort;
- PenState savePen;
- short buttonOval;
- Boolean isColorPort;
-
- const short kColorPort = 0xC000;
-
- GetDialogItem(theDialog, kOKButton, &itemKind, &itemHandle, &itemRect);
- ASSERT_CONTROL_ITEM(itemKind);
-
- GetPort(&savePort);
- buttonWindow = (**(ControlHandle)itemHandle).contrlOwner;
- SetPort(buttonWindow);
- GetPenState(&savePen);
- PenNormal();
-
- InsetRect(&itemRect, -4, -4);
- FrameRoundRect(&itemRect, 16, 16);
- buttonOval = ((itemRect.bottom - itemRect.top)/2)+2;
-
- isColorPort = ((((CGrafPtr)buttonWindow)->portVersion & kColorPort) == kColorPort);
-
- if ( (**(ControlHandle)itemHandle).contrlHilite == kControlInactive )
- {
- // Button is inactive, so outline with gray
-
- RGBColor fgSaveColor;
- RGBColor fgNewColor;
- RGBColor bgColor;
- Boolean newGray = false;
-
- if ( isColorPort )
- {
- GetBackColor(&bgColor);
- GetForeColor(&fgSaveColor);
- fgNewColor = fgSaveColor;
-
- Rect globalRect = itemRect;
- LocalToGlobal((Point *)&(globalRect.top));
- LocalToGlobal((Point *)&(globalRect.bottom));
- GDHandle targetDevice = GetMaxDevice(&globalRect);
-
- newGray = GetGray(targetDevice, &bgColor, &fgNewColor);
- }
-
- if ( newGray )
- RGBForeColor(&fgNewColor);
- else
- #ifdef THINK_CPLUS
- PenPat(ODQDGlobals.gray);
- #else
- PenPat(&ODQDGlobals.gray);
- #endif
-
- PenSize(3, 3);
- FrameRoundRect(&itemRect, buttonOval, buttonOval);
-
- if ( isColorPort )
- RGBForeColor(&fgSaveColor);
- }
- else
- {
- // Button is active, so outline with black
- #ifdef THINK_CPLUS
- PenPat(ODQDGlobals.black);
- #else
- PenPat(&ODQDGlobals.black);
- #endif
- PenSize(3, 3);
- FrameRoundRect(&itemRect, buttonOval, buttonOval);
- }
-
- SetPenState(&savePen);
- SetPort(savePort);
- }
-
-
- UserItemUPP
- GetODOutlineDefaultButtonDrawProc( )
- {
- if( !sOutlineDrawProc )
- sOutlineDrawProc = NewUserItemProc(&ODOutlineDefaultButtonDrawProc);
- return sOutlineDrawProc;
- }
-
-
- void
- ODUseDialogScriptData( DialogScriptData* dsd, DialogPtr dialog )
- {
- sDlogScriptData = dsd;
- dsd->SetDialog( dialog );
- }
-
- pascal ODBoolean CheckKeyScriptChangeFilterProc( DialogPtr dialog,
- EventRecord *event, short *itemHit)
- {
- TEHandle teh = ((DialogPeek)dialog)->textH;
- DialogScriptData* dsd = sDlogScriptData;
- WASSERT( dsd );
-
- if ( dsd->Script() == ksmUninited )
- dsd->SetScriptAndLockKeyboard();
-
- if ( event->what == keyDown )
- {
- if ( !dsd->ScriptChanged() )
- {
- ODScriptCode newScript = GetScriptManagerVariable(smKeyScript);
- ODScriptCode fontScript = FontToScript((*teh)->txFont);
- WASSERT( fontScript == dsd->Script() );
- if ( fontScript != newScript )
- {
- short newFont = GetScriptVariable( newScript, smScriptAppFond );
- (*teh)->txFont = newFont;
- // TextFont(newFont);
-
- dsd->SetScriptAndLockKeyboard( FontToScript(newFont) );
- }
- }
- }
-
- // if this is the first time in this edit item, redraw in case
- // we've switched fonts/scripts.
- short currentItem = ((DialogPeek)dialog)->editField;
- if ( dsd->ScriptChanged() && !dsd->ItemRedrawn(currentItem) )
- {
- dsd->SetRedrawn(currentItem);
- short itemKind;
- Handle ignoreH;
- Rect ignoreR;
- GetDialogItem( dialog, currentItem+1, &itemKind, &ignoreH, &ignoreR );
- if ( itemKind == editText )
- {
- TECalText( teh );
- Rect viewRect = (*teh)->viewRect;
- TEUpdate( &viewRect, teh );
- }
- }
-
- // pass to the next filter proc. This one just changes state, never
- // consuming the event.
- return kODFalse;
- }
-
- void EnableOkButton(DialogPtr dlog, ODBoolean enable)
- {
- Environment* ev = somGetGlobalEnvironment();
- short itemType;
- Handle itemHandle;
- Rect itemRect;
- ODBoolean okEnabled;
-
- const short kButtonFrameInset = -4;
-
- GetDialogItem(dlog, kOKButton, &itemType, &itemHandle, &itemRect);
- ASSERT_CONTROL_ITEM(itemType);
- okEnabled = (**(ControlHandle)itemHandle).contrlHilite == kControlActive;
-
- // there's nothing to do if the button is as it should be already
- if ( enable != okEnabled )
- {
- HiliteControl((ControlHandle)itemHandle, enable ? kControlActive : kControlInactive);
-
- // Invalidate the default button frame so it will be redrawn dim
- WindowPtr savePort;
- GetPort(&savePort);
- SetPort(dlog);
- InsetRect(&itemRect, kButtonFrameInset, kButtonFrameInset);
- InvalRect(&itemRect);
- SetPort(savePort);
- }
- }
-
- // DrawGrayBox draws a gray box to be used as a separator.
- // On a ColorQD machine, a true-gray line is attempted.
- // On a B&W machine, a 50% pattern is used.
-
- static pascal void DrawGrayBox(Rect *theBox)
- {
- PenState penState;
- GetPenState(&penState);
-
- PixPatHandle ppat = kODNULL;
-
- /* check if Color QuickDraw is available */
- long response;
- if( Gestalt(gestaltQuickdrawFeatures, &response)==noErr
- && BitTst(&response, 31-gestaltHasColor) ) {
- const RGBColor gray = {0x7FFF,0x7FFF,0x7FFF};
- ppat = NewPixPat();
- if( ppat )
- MakeRGBPat(ppat,&gray);
- }
-
- if( ppat )
- PenPixPat(ppat);
- else
- PenPat(&ODQDGlobals.gray);
-
- FrameRect(theBox);
-
- SetPenState(&penState);
-
- if( ppat )
- DisposePixPat(ppat);
- }
-
- pascal void DrawGrayBoxItem(DialogPtr theDialog, short theItem)
- {
- Rect boxRect;
- Handle scratchHandle;
- short scratchKind;
-
- GetDialogItem(theDialog, theItem, &scratchKind, &scratchHandle, &boxRect);
- DrawGrayBox(&boxRect);
- }
-
- pascal void DrawItemFrame(DialogPtr theDialog, short theItem)
- {
- Rect frameRect;
- Handle scratchHandle;
- short scratchKind;
-
- GetDialogItem(theDialog, theItem, &scratchKind, &scratchHandle, &frameRect);
- FrameRect(&frameRect);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // DrawITextInDlogBox
- // Given a dialog, a rect and an ODIText*, truncate the text to fit in the
- // rect and then draw it in the dialog. Return result telling whether any
- // change was made.
- ////////////////////////////////////////////////////////////////////////////////
-
- ODBoolean DrawITextInDlogBox( ODIText* itext, const Rect* textRect,
- DialogPtr dlog, ODBoolean tryToTruncate )
- {
- WASSERT(dlog);
- WindowPtr savePort;
- GetPort(&savePort);
- SetPort(dlog);
-
- PenState savedPenState;
- GetPenState(&savedPenState);
- PenNormal();
-
- short saveFont = dlog->txFont;
- short savedTextMode = dlog->txMode;
-
- ODScriptCode scriptCode = GetITextScriptCode(itext);
- if ( scriptCode != FontToScript(saveFont) )
- TextFont(GetScriptVariable(scriptCode,smScriptAppFond));
-
- char buffer[256];
- ODSShort len = GetITextStringLength(itext);
- if ( len > 255 ) len = 255;
- ODBlockMove( GetITextPtr( itext ), buffer, len );
- short truncResult;
- if ( tryToTruncate )
- truncResult = TruncText( textRect->right - textRect->left - 1,
- buffer, &len, truncEnd);
- TETextBox( buffer, len, textRect, teFlushDefault );
-
- TextFont(saveFont);
- TextMode(savedTextMode);
- SetPenState(&savedPenState);
- SetPort(savePort);
- return tryToTruncate? truncResult == 1 : kODFalse; // 1 means truncation needed and successful
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // FlashButtonItem
- // Given a dialog and an item representing a button, flash that button,
- // highlighting it for 8 ticks and then reverting.
- ////////////////////////////////////////////////////////////////////////////////
- void FlashButtonItem( DialogPtr dialog, short itemHit )
- {
- Rect itemRect;
- short itemType;
- Handle itemHandle;
-
- GetDialogItem( dialog, itemHit, &itemType, &itemHandle, &itemRect);
- ASSERT_CONTROL_ITEM(itemType);
- HiliteControl((ControlHandle)itemHandle, kControlButtonPart);
- unsigned long ticks = TickCount() + 8;
- while ( TickCount() < ticks ) ;
- HiliteControl((ControlHandle)itemHandle, kControlActive); // Turn off hilite
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // ArrowKeyScrollList
- // Given an "item" representing an up or down arrow or any of the other keys
- // recognized by ODArrowKeyFilterProc above, a ListHandle indicating the list
- // in which scrolling is taking place, pageSize giving the number of entries to
- // be skipped by a "page down" command, and the zero-based index of the last
- // entry in the list, do the right thing for the key selected. So far this
- // routine is used for lists embedded in dialogs, and it's up to the caller
- // to determine which list is meant if there is more than one.
- // NOTE that nothing happens currently if no list item is selected. There needs
- // to be a starting point for scrolling.
- ////////////////////////////////////////////////////////////////////////////////
-
- void ArrowKeyScrollList( ODSShort arrowItem, ListHandle listH,
- ODSShort pageSize, ODSShort lastEntry )
- {
- ODSShort limitCell;
- ODSShort delta;
- switch( arrowItem )
- {
- case kODUpArrowItem:
- limitCell = 0;
- delta = -1;
- break;
-
- case kODDownArrowItem:
- limitCell = lastEntry;
- delta = 1;
- break;
-
- case kODPageUpArrowItem:
- limitCell = 0;
- delta = 0 - pageSize;
- break;
-
- case kODPageDownArrowItem:
- limitCell = lastEntry;
- delta = pageSize;
- break;
-
- case kODHomeArrowItem:
- limitCell = 0;
- delta = 0 - lastEntry;
- break;
-
- case kODEndArrowItem:
- limitCell = lastEntry;
- delta = lastEntry;
- break;
-
- default:
- WARN( "unknown arrow key/item" );
- return;
- }
-
- Cell selectedCell = {0,0};
- if ( !LGetSelect( true, &selectedCell, listH )
- || (selectedCell.v == limitCell) )
- return;
- LSetSelect( false, selectedCell, listH );
- selectedCell.v += delta;
- if ( selectedCell.v < 0 )
- selectedCell.v = 0;
- else if ( limitCell > 0 && selectedCell.v > limitCell )
- selectedCell.v = limitCell;
- LSetSelect( true, selectedCell, listH );
- LAutoScroll(listH);
- }
-
- //------------------------------------------------------------------------------
- // ReplaceIntoString
- //------------------------------------------------------------------------------
- // Substitutes str0 for all occurances of "^0", and str1 for "^1", in the string
- // retrieved from the 'STR ' resource identified by the first parameter. Either
- // str0 or str1 may be null. Uses the current resource chain to find the 'STR '
- // resource.
-
- void ReplaceIntoString(ODSShort strResourceID,
- ConstStr255Param str0,
- ConstStr255Param str1,
- Str255 destString)
- {
- StringHandle msgHandle = GetString(strResourceID);
- if ( msgHandle )
- {
- DetachResource((Handle) msgHandle);
-
- ODHandle textHandle;
-
- HLock((Handle) msgHandle);
- ODHandle templateText = PStrToText(*msgHandle);
- HUnlock((Handle) msgHandle);
-
- if ( str0 )
- {
- textHandle = PStrToText(str0);
- if ( textHandle )
- {
- ReplaceText((Handle) templateText, (Handle) textHandle, "\p^0");
- ODDisposeHandle(textHandle);
- }
- }
-
- if ( str1 )
- {
- textHandle = PStrToText(str1);
- if ( textHandle )
- {
- ReplaceText((Handle) templateText, (Handle) textHandle, "\p^1");
- ODDisposeHandle(textHandle);
- }
- }
-
- TextToPStr(templateText, destString);
-
- ODDisposeHandle(templateText);
- DisposeHandle((Handle) msgHandle);
- }
- else
- if( ResError() != memFullErr )
- {
- WARN("ReplaceIntoString didn't find STR %hd",strResourceID);
- destString[0] = 0;
- }
- }
-
-
- //--------------------------------------------------------------------
- // GetODITextInd
- // Gets string # (index) from the 'STR#' resource given by resID
- // into an IText* whose script and language codes are those of
- // the current system script.
- //--------------------------------------------------------------------
-
- ODIText* GetODITextInd(short resID, short index)
- {
- Str255 pStr = "\p";
- GetIndString(pStr, resID, index);
- ODScriptCode script = FontToScript( GetSysFont() );
- return CreateITextPString(script,
- GetScriptVariable(script, smScriptLang),
- pStr);
- }
-
-
- //--------------------------------------------------------------------
- // GetODIText
- // Turns an 'STR ' resource of the given resID into an ODIText* whose
- // language and script codes are those of the current system script.
- //--------------------------------------------------------------------
-
- ODIText* GetODIText(short resID)
- {
- Handle textHandle;
- ODIText* iText = kODNULL;
-
- textHandle = (Handle)GetString(resID);
-
- if ( textHandle != kODNULL )
- {
- // CreateIText copies the values passed into it, so we don't
- // have to worry about the resource handle moving outside of
- // the scope of this function.
-
- ODScriptCode script = GetScriptManagerVariable(smSysScript);
- ODLangCode lang = GetScriptVariable(script, smScriptLang);
- HLock(textHandle);
- iText = CreateIText( script, lang, (StringPtr)*textHandle );
-
- ReleaseResource(textHandle);
- }
-
- return iText;
- }
-
- //------------------------------------------------------------------------------
- // SetDialogTextStyle
- //------------------------------------------------------------------------------
-
- void SetDialogTextStyle(DialogPtr dlg, short finfResourceID,
- ODScriptCode script)
- {
- typedef struct {
- short count;
- short fontNumber;
- short fontStyl;
- short fontSize;
- } FontSpec;
-
- typedef FontSpec** FontSpecHandle;
-
- FontSpecHandle finfHandle = (FontSpecHandle) GetResource('finf', finfResourceID);
-
- if ( finfHandle )
- {
- SetPort(dlg);
-
- short font;
- if ( script != smCurrentScript )
- font = GetScriptVariable( script, smScriptAppFond ); // <eeh> smScriptSysFond better?
- else
- font = (**finfHandle).fontNumber;
-
- TextFont(font);
- TextFace((**finfHandle).fontStyl);
- TextSize((**finfHandle).fontSize);
- TEHandle te = ((DialogPeek)dlg)->textH;
- (**te).txFont = font;
- (**te).txSize = (**finfHandle).fontSize;
- (**te).txFace = (**finfHandle).fontStyl;
- TECalText(te);
- ReleaseResource((Handle) finfHandle);
- } else
- if( ResError() != memFullErr )
- WARN("SetDialogTextStyle didn't find 'finf' %hd",finfResourceID);
- }
-
- //-------------------------------------------------------------------------------------
- // SetPopupItemScript
- //-------------------------------------------------------------------------------------
- // "scriptID" should be a true script code, not an implicit script code
- //
- // This routine assumes the popup is drawn using the font of the current port.
- //
- // Setting the script of a popup menu item has two bad consequences:
- // The title and item appear in bold face, and the width of the
- // menu is increased. This is true even if the script specified
- // is the same as the default script! So only specify a script if its different.
-
- void SetPopupItemScript(MenuHandle menu, short itemNum, short scriptID)
- {
- const ODSShort kUseSpecificScript = 0x1c;
-
- ODSLong savedSMFontForceFlag = GetScriptManagerVariable(smFontForce);
- SetScriptManagerVariable(smFontForce, false);
-
- // Since the popup is drawn using the window font, compare the argument
- // script to the script of the current graphics port.
- GrafPtr curPort;
- GetPort(&curPort);
-
- if ( scriptID == smSystemScript )
- scriptID = (short) GetScriptManagerVariable(smSysScript);
-
- if ( scriptID != FontToScript(curPort->txFont) )
- {
- SetItemCmd(menu, itemNum, kUseSpecificScript);
- SetItemIcon(menu, itemNum, scriptID);
- }
-
- SetScriptManagerVariable(smFontForce, savedSMFontForceFlag);
- }
-
-
- //-------------------------------------------------------------------------------------
- // Implementation of DialogScriptData class
- //-------------------------------------------------------------------------------------
-
- DialogScriptData::DialogScriptData()
- {
- fItemRedrawn = 0L;
- fMustUnlock = kODFalse;
- fScript = ksmUninited;
- }
-
- DialogScriptData::~DialogScriptData()
- {
- if ( fMustUnlock )
- this->ReleaseLockout();
- }
-
- void DialogScriptData::SetScriptAndLockKeyboard()
- {
- // this->SetScriptAndLockKeyboard( FontToScript( GetAppFont() ) );
- WASSERT( FontToScript( GetSysFont()) == FontToScript( GetAppFont() ));
- this->SetScriptAndLockKeyboard( FontToScript( GetSysFont() ) );
- }
-
- // There are two cases we need to be aware of here when the script passed
- // in comes from an existing IText* and isn't Roman. First, it's possible
- // that the keyscript is not yet set to that script (that it's still Roman).
- // Second, the dialog may not be in a state to properly display that text.
-
- void DialogScriptData::SetScriptAndLockKeyboard( ODScriptCode script )
- {
- if ( script != smRoman ) // lock all changes out: switch to Roman will
- { // result in non-Roman text being garbage
- if ( GetScriptManagerVariable(smKeyScript) != script )
- KeyScript( script ); // script may not yet have been set
-
- WASSERT(fDialog);
- TEHandle teh = ((DialogPeek)fDialog)->textH;
- if ( FontToScript( (*teh)->txFont ) != script )
- {
- (*teh)->txFont = GetScriptVariable( script, smScriptSysFond );
- }
-
- // KeyScript( smKeyDisableKybdSwitch ); // <eeh> 1/6
- fMustUnlock = kODTrue;
- }
- fScript = script;
- }
-
- void DialogScriptData::ReleaseLockout()
- {
- if ( fMustUnlock != kODFalse )
- {
- // KeyScript( smKeyEnableKybds ); // <eeh> 1/6
- fMustUnlock = kODFalse;
- }
- }
-
- ODBoolean DialogScriptData::ItemRedrawn( short item )
- {
- WASSERT( item < kMaxNumItems );
- return (fItemRedrawn & 1L<<(item-1)) != 0;
- }
-
- void DialogScriptData::SetRedrawn( short item )
- {
- WASSERT( item < kMaxNumItems );
- fItemRedrawn |= 1L<<(item-1);
- }
-