Pat noted that I neglected to drop the SCCS lines on the files I've been committing, so clean up those and any others I could find where the SCCS line date is out of date.
3299 lines
76 KiB
C
3299 lines
76 KiB
C
/* NetHack 3.5 macwin.c $Date$ $Revision$ */
|
|
/* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
|
|
/**********************************************************************
|
|
* Imported variables and functions
|
|
*/
|
|
|
|
#include "hack.h"
|
|
#include "func_tab.h"
|
|
#include "macwin.h"
|
|
#include "mactty.h"
|
|
#include "wintty.h"
|
|
|
|
#if 1 /*!TARGET_API_MAC_CARBON*/
|
|
#include <LowMem.h>
|
|
#include <AppleEvents.h>
|
|
#include <Gestalt.h>
|
|
#include <TextUtils.h>
|
|
#include <DiskInit.h>
|
|
#include <ControlDefinitions.h>
|
|
#endif
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Local variables and functions
|
|
*/
|
|
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
static EventTypeSpec baseevents[] = {
|
|
{ kEventClassKeyboard, kEventRawKeyDown },
|
|
{ kEventClassKeyboard, kEventRawKeyRepeat },
|
|
{ kEventClassMouse, kEventMouseMoved },
|
|
{ kEventClassWindow, kEventWindowDrawContent },
|
|
{ kEventClassWindow, kEventWindowHandleContentClick },
|
|
{ kEventClassWindow, kEventWindowClose }
|
|
};
|
|
|
|
static EventTypeSpec msgevents[] = {
|
|
{ kEventClassControl, kEventControlHit },
|
|
{ kEventClassKeyboard, kEventRawKeyDown },
|
|
{ kEventClassKeyboard, kEventRawKeyRepeat },
|
|
{ kEventClassWindow, kEventWindowDrawContent },
|
|
{ kEventClassWindow, kEventWindowHandleContentClick },
|
|
{ kEventClassWindow, kEventWindowClose }
|
|
};
|
|
|
|
static EventTypeSpec menwevents[] = {
|
|
{ kEventClassControl, kEventControlHit },
|
|
{ kEventClassKeyboard, kEventRawKeyDown },
|
|
{ kEventClassKeyboard, kEventRawKeyRepeat },
|
|
{ kEventClassWindow, kEventWindowDrawContent },
|
|
{ kEventClassWindow, kEventWindowHandleContentClick },
|
|
{ kEventClassWindow, kEventWindowClose }
|
|
};
|
|
|
|
static EventTypeSpec textevents[] = {
|
|
{ kEventClassControl, kEventControlHit },
|
|
{ kEventClassKeyboard, kEventRawKeyDown },
|
|
{ kEventClassKeyboard, kEventRawKeyRepeat },
|
|
{ kEventClassWindow, kEventWindowDrawContent },
|
|
{ kEventClassWindow, kEventWindowClose }
|
|
};
|
|
|
|
static EventTypeSpec globalevents[] = {
|
|
{ kEventClassCommand, kEventCommandProcess }
|
|
};
|
|
|
|
EventTargetRef dispatcher;
|
|
EventHandlerUPP baseupp, msgupp, menwupp, textupp;
|
|
|
|
static pascal OSStatus BaseEvent(EventHandlerCallRef, EventRef, void *);
|
|
static void MsgUpdate(NhWindow *wind);
|
|
static pascal OSStatus MsgEvent(EventHandlerCallRef, EventRef, void *);
|
|
static void MenwUpdate(NhWindow *wind);
|
|
static pascal OSStatus MenwEvent(EventHandlerCallRef, EventRef, void *);
|
|
static void TextUpdate(NhWindow *wind);
|
|
static pascal OSStatus TextEvent(EventHandlerCallRef, EventRef, void *);
|
|
static pascal OSStatus GlobalEvent(EventHandlerCallRef, EventRef, void *);
|
|
|
|
#else
|
|
|
|
static void FDECL(GeneralKey, (EventRecord *, WindowPtr));
|
|
static void FDECL(macKeyMenu, (EventRecord *, WindowPtr));
|
|
static void FDECL(macKeyText, (EventRecord *, WindowPtr));
|
|
|
|
static void FDECL(macClickMessage, (EventRecord *, WindowPtr));
|
|
static void FDECL(macClickTerm, (EventRecord *, WindowPtr));
|
|
static void FDECL(macClickMenu, (EventRecord *, WindowPtr));
|
|
static void FDECL(macClickText, (EventRecord *, WindowPtr));
|
|
|
|
static short FDECL(macDoNull, (EventRecord *, WindowPtr));
|
|
static short FDECL(macUpdateMessage, (EventRecord *, WindowPtr));
|
|
static short FDECL(macUpdateMenu, (EventRecord *, WindowPtr));
|
|
static short FDECL(GeneralUpdate, (EventRecord *, WindowPtr));
|
|
|
|
static void FDECL(macCursorTerm, (EventRecord *, WindowPtr, RgnHandle));
|
|
static void FDECL(GeneralCursor, (EventRecord *, WindowPtr, RgnHandle));
|
|
#endif
|
|
|
|
static void TextUpdate(NhWindow *wind);
|
|
|
|
|
|
NhWindow *theWindows = (NhWindow *) 0;
|
|
Cursor qdarrow;
|
|
|
|
/* Borrowed from the Mac tty port */
|
|
extern WindowPtr _mt_window;
|
|
|
|
/* Some useful #defines for the scroll bar width and height */
|
|
#define SBARWIDTH 15
|
|
#define SBARHEIGHT 15
|
|
|
|
/*
|
|
* We put a TE on the message window for the "top line" queries.
|
|
* top_line is the TE that holds both the query and the user's
|
|
* response. The first topl_query_len characters in top_line are
|
|
* the query, the rests are the response. topl_resp is the valid
|
|
* response to a yn query, while topl_resp[topl_def_idx] is the
|
|
* default response to a yn query.
|
|
*/
|
|
static TEHandle top_line = (TEHandle) nil;
|
|
static int topl_query_len;
|
|
static int topl_def_idx = -1;
|
|
static char topl_resp[10] = "";
|
|
|
|
#define CHAR_ANY '\n'
|
|
|
|
/*
|
|
* inSelect means we have a menu window up for selection or
|
|
* something similar. It makes the window with win number ==
|
|
* inSelect a movable modal (unfortunately without the border)
|
|
* and clicking the close box forces an RET into the key
|
|
* buffer. Don't forget to set inSelect to WIN_ERR when you're
|
|
* done...
|
|
*/
|
|
static winid inSelect = WIN_ERR;
|
|
|
|
/*
|
|
* The key queue ring buffer where Read is where to take from,
|
|
* Write is where next char goes and count is queue depth.
|
|
*/
|
|
static unsigned char keyQueue [QUEUE_LEN];
|
|
static int keyQueueRead = 0,
|
|
keyQueueWrite = 0,
|
|
keyQueueCount = 0;
|
|
|
|
static Boolean gClickedToMove = 0; /* For ObscureCursor */
|
|
|
|
static Point clicked_pos; /* For nh_poskey */
|
|
static int clicked_mod;
|
|
static Boolean cursor_locked = false;
|
|
|
|
static ControlActionUPP MoveScrollUPP; /* scrolling callback, init'ed in InitMac */
|
|
|
|
void
|
|
lock_mouse_cursor(Boolean new_cursor_locked) {
|
|
cursor_locked = new_cursor_locked;
|
|
}
|
|
|
|
|
|
/*
|
|
* Add key to input queue, force means flush left and replace if full
|
|
*/
|
|
void
|
|
AddToKeyQueue (unsigned char ch, Boolean force) {
|
|
if (keyQueueCount < QUEUE_LEN) {
|
|
keyQueue [keyQueueWrite++] = ch;
|
|
keyQueueCount++;
|
|
}
|
|
else if (force) {
|
|
keyQueue [keyQueueWrite++] = ch;
|
|
keyQueueRead++;
|
|
if (keyQueueRead >= QUEUE_LEN)
|
|
keyQueueRead = 0;
|
|
keyQueueCount = QUEUE_LEN;
|
|
}
|
|
if (keyQueueWrite >= QUEUE_LEN)
|
|
keyQueueWrite = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Get key from queue
|
|
*/
|
|
unsigned char
|
|
GetFromKeyQueue (void) {
|
|
unsigned char ret;
|
|
|
|
if (keyQueueCount) {
|
|
ret = keyQueue [keyQueueRead++];
|
|
keyQueueCount--;
|
|
if (keyQueueRead >= QUEUE_LEN)
|
|
keyQueueRead = 0;
|
|
}
|
|
else
|
|
ret = 0;
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
* Cursor movement
|
|
*/
|
|
static RgnHandle gMouseRgn = (RgnHandle) 0;
|
|
|
|
/*
|
|
* _Gestalt madness - we rely heavily on the _Gestalt glue, since we
|
|
* don't check for the trap...
|
|
*/
|
|
MacFlags macFlags;
|
|
|
|
/*
|
|
* The screen layouts on the small 512x342 screen need special cares.
|
|
*/
|
|
Boolean small_screen = 0;
|
|
|
|
#ifdef NHW_BASE
|
|
# undef NHW_BASE
|
|
#endif
|
|
#define NHW_BASE 0
|
|
|
|
static int FDECL(filter_scroll_key,(const int, NhWindow *));
|
|
|
|
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
static void FDECL(DoScrollBar,(Point, short, ControlHandle, NhWindow *));
|
|
#endif
|
|
static pascal void FDECL(MoveScrollBar, (ControlHandle, short));
|
|
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
typedef void (*CbFunc) (EventRecord *, WindowPtr);
|
|
typedef short (*CbUpFunc) (EventRecord *, WindowPtr);
|
|
typedef void (*CbCursFunc) (EventRecord *, WindowPtr, RgnHandle);
|
|
|
|
#define NUM_FUNCS 6
|
|
static const CbFunc winKeyFuncs [NUM_FUNCS] = {
|
|
GeneralKey, GeneralKey, GeneralKey, GeneralKey, macKeyMenu, macKeyText
|
|
};
|
|
|
|
static const CbFunc winClickFuncs [NUM_FUNCS] = {
|
|
(CbFunc)macDoNull, macClickMessage, macClickTerm, macClickTerm, macClickMenu,
|
|
macClickText
|
|
};
|
|
|
|
static const CbUpFunc winUpdateFuncs [NUM_FUNCS] = {
|
|
macDoNull, macUpdateMessage, image_tty, image_tty,
|
|
macUpdateMenu, GeneralUpdate
|
|
};
|
|
|
|
static const CbCursFunc winCursorFuncs [NUM_FUNCS] = {
|
|
(CbCursFunc) macDoNull, GeneralCursor, macCursorTerm, macCursorTerm,
|
|
GeneralCursor, GeneralCursor
|
|
};
|
|
#endif
|
|
|
|
|
|
static NhWindow *
|
|
GetNhWin(WindowPtr mac_win) {
|
|
if (mac_win == _mt_window) /* term window is still maintained by both systems, and */
|
|
return theWindows; /* WRefCon still refers to tty struct, so we have to map it */
|
|
else {
|
|
NhWindow *aWin = (NhWindow *)GetWRefCon (mac_win);
|
|
if (aWin >= theWindows && aWin < &theWindows[NUM_MACWINDOWS])
|
|
return aWin;
|
|
}
|
|
return ((NhWindow *) nil);
|
|
}
|
|
|
|
|
|
Boolean CheckNhWin (WindowPtr mac_win) {
|
|
return GetNhWin (mac_win) != nil;
|
|
}
|
|
|
|
|
|
static pascal OSErr
|
|
AppleEventHandler (const AppleEvent* inAppleEvent, AppleEvent* outAEReply, long inRefCon) {
|
|
#if defined(__SC__) || defined(__MRC__)
|
|
# pragma unused(outAEReply,inRefCon)
|
|
#endif
|
|
Size actualSize;
|
|
DescType typeCode;
|
|
AEEventID EventID;
|
|
OSErr err;
|
|
|
|
/* Get Event ID */
|
|
err = AEGetAttributePtr (inAppleEvent, keyEventIDAttr, typeType, &typeCode,
|
|
&EventID, sizeof (EventID), &actualSize);
|
|
if (err == noErr) {
|
|
switch (EventID) {
|
|
default :
|
|
case kAEOpenApplication :
|
|
macFlags.gotOpen = 1;
|
|
/* fall through */
|
|
case kAEPrintDocuments :
|
|
err = errAEEventNotHandled;
|
|
break;
|
|
case kAEQuitApplication :
|
|
/* Flush key queue */
|
|
keyQueueCount = keyQueueWrite = keyQueueRead = 0;
|
|
AddToKeyQueue ('S', 1);
|
|
break;
|
|
case kAEOpenDocuments : {
|
|
FSSpec fss;
|
|
FInfo fndrInfo;
|
|
AEKeyword keywd;
|
|
AEDescList docList;
|
|
long index, itemsInList;
|
|
|
|
if((err = AEGetParamDesc(inAppleEvent, keyDirectObject, typeAEList, &docList)) != noErr ||
|
|
(err = AECountItems(&docList, &itemsInList)) != noErr){
|
|
if (err == errAEDescNotFound)
|
|
itemsInList = 0;
|
|
else
|
|
break;
|
|
}
|
|
|
|
for(index = 1; index <= itemsInList; index++){
|
|
err = AEGetNthPtr(&docList, index, typeFSS, &keywd, &typeCode, (Ptr)&fss,
|
|
sizeof(FSSpec), &actualSize);
|
|
if(noErr != err)
|
|
break;
|
|
|
|
err = FSpGetFInfo (&fss, &fndrInfo);
|
|
if (noErr != err)
|
|
break;
|
|
|
|
if (fndrInfo.fdType != SAVE_TYPE)
|
|
continue; /* only look at save files */
|
|
|
|
process_openfile (fss.vRefNum, fss.parID, fss.name, fndrInfo.fdType);
|
|
if (macFlags.gotOpen)
|
|
break; /* got our save file */
|
|
}
|
|
err = AEDisposeDesc(&docList);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Check to see if all required parameters for this type of event are present */
|
|
if (err == noErr) {
|
|
err = AEGetAttributePtr (inAppleEvent, keyMissedKeywordAttr,
|
|
typeWildCard, &typeCode, NULL, 0, &actualSize);
|
|
if (err == errAEDescNotFound)
|
|
err = noErr; /* got all the required parameters */
|
|
else if (err == noErr) /* missed a required parameter */
|
|
err = errAEEventNotHandled;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
short win_fonts [NHW_TEXT + 1];
|
|
|
|
void
|
|
InitMac(void) {
|
|
short i;
|
|
long l;
|
|
Str255 volName;
|
|
|
|
|
|
#if !TARGET_API_MAC_CARBON
|
|
if (LMGetDefltStack() < 50 * 1024L) {
|
|
SetApplLimit ((void *) ((long) LMGetCurStackBase() - (50 * 1024L)));
|
|
}
|
|
MaxApplZone ();
|
|
for (i = 0; i < 5; i ++)
|
|
MoreMasters ();
|
|
|
|
InitGraf (&qd.thePort);
|
|
InitFonts ();
|
|
InitWindows ();
|
|
InitMenus ();
|
|
InitDialogs (0L);
|
|
TEInit ();
|
|
#endif
|
|
|
|
memset (&macFlags, 0, sizeof(macFlags));
|
|
if (!Gestalt (gestaltOSAttr, & l)) {
|
|
macFlags.processes = (l & (1 << gestaltLaunchControl)) ? 1 : 0;
|
|
macFlags.tempMem = (l & (1 << gestaltRealTempMemory)) ? 1 : 0;
|
|
macFlags.hasDebugger = (l & (1 << gestaltSysDebuggerSupport)) ? 1 : 0;
|
|
}
|
|
if (!Gestalt (gestaltQuickdrawVersion, & l))
|
|
macFlags.color = (l >= gestalt8BitQD) ? 1 : 0;
|
|
|
|
if (!Gestalt (gestaltFindFolderAttr, & l))
|
|
macFlags.folders = (l & (1 << gestaltFindFolderPresent)) ? 1 : 0;
|
|
|
|
if (!Gestalt (gestaltHelpMgrAttr, & l))
|
|
macFlags.help = (l & (1 << gestaltHelpMgrPresent)) ? 1 : 0;
|
|
|
|
if (!Gestalt (gestaltFSAttr, & l))
|
|
macFlags.fsSpec = (l & (1 << gestaltHasFSSpecCalls)) ? 1 : 0;
|
|
|
|
if (!Gestalt (gestaltFontMgrAttr, & l))
|
|
macFlags.trueType = (l & (1 << gestaltOutlineFonts)) ? 1 : 0;
|
|
|
|
if (!Gestalt (gestaltAUXVersion, & l))
|
|
macFlags.aux = (l >= 0x200) ? 1 : 0;
|
|
|
|
if (!Gestalt (gestaltAliasMgrAttr, & l))
|
|
macFlags.alias = (l & (1 << gestaltAliasMgrPresent)) ? 1 : 0;
|
|
|
|
if (!Gestalt (gestaltStandardFileAttr, & l))
|
|
macFlags.standardFile = (l & (1 << gestaltStandardFile58)) ? 1 : 0;
|
|
|
|
gMouseRgn = NewRgn ();
|
|
InitCursor();
|
|
GetQDGlobalsArrow(&qdarrow);
|
|
ObscureCursor();
|
|
|
|
MoveScrollUPP = NewControlActionUPP(MoveScrollBar);
|
|
|
|
/* Set up base fonts for all window types */
|
|
GetFNum("\pHackFont", &i);
|
|
if (i == 0)
|
|
i = kFontIDMonaco;
|
|
win_fonts [NHW_BASE] = win_fonts [NHW_MAP] = win_fonts [NHW_STATUS] = i;
|
|
GetFNum("\pPSHackFont", &i);
|
|
if (i == 0)
|
|
i = kFontIDGeneva;
|
|
win_fonts[NHW_MESSAGE] = i;
|
|
win_fonts[NHW_TEXT] = kFontIDGeneva;
|
|
|
|
macFlags.hasAE = 0;
|
|
if(!Gestalt(gestaltAppleEventsAttr, &l) && (l & (1L << gestaltAppleEventsPresent))){
|
|
if (AEInstallEventHandler (kCoreEventClass, typeWildCard,
|
|
NewAEEventHandlerUPP(AppleEventHandler),
|
|
0,
|
|
FALSE) == noErr)
|
|
macFlags.hasAE = 1;
|
|
}
|
|
|
|
#if TARGET_API_MAC_CARBON
|
|
HGetVol(volName, &theDirs.dataRefNum, &theDirs.dataDirID);
|
|
#else
|
|
/*
|
|
* We should try to get this data from a rsrc, in the profile file
|
|
* the user double-clicked... This data should be saved with the
|
|
* save file in the resource fork, AND be saveable in "stationary"
|
|
*/
|
|
GetVol (volName, &theDirs.dataRefNum );
|
|
GetWDInfo (theDirs.dataRefNum, &theDirs.dataRefNum, &theDirs.dataDirID, &l);
|
|
#endif
|
|
if (volName [0] > 31) volName [0] = 31;
|
|
for (l = 1; l <= volName [0]; l++) {
|
|
if (volName [l] == ':') {
|
|
volName [l] = 0;
|
|
volName [0] = l - 1;
|
|
break;
|
|
}
|
|
}
|
|
BlockMove (volName, theDirs.dataName, l);
|
|
BlockMove (volName, theDirs.saveName, l);
|
|
BlockMove (volName, theDirs.levelName, l);
|
|
theDirs.saveRefNum = theDirs.levelRefNum = theDirs.dataRefNum;
|
|
theDirs.saveDirID = theDirs.levelDirID = theDirs.dataDirID;
|
|
|
|
/* Create the "record" file, if necessary */
|
|
check_recordfile("");
|
|
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
/* Create event handler universal procedure pointers */
|
|
dispatcher = GetEventDispatcherTarget();
|
|
baseupp = NewEventHandlerUPP(BaseEvent);
|
|
msgupp = NewEventHandlerUPP(MsgEvent);
|
|
menwupp = NewEventHandlerUPP(MenwEvent);
|
|
textupp = NewEventHandlerUPP(TextEvent);
|
|
InstallApplicationEventHandler(NewEventHandlerUPP(GlobalEvent),
|
|
sizeof(globalevents)/sizeof(EventTypeSpec), globalevents, NULL, NULL);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* Change default window fonts.
|
|
*/
|
|
short
|
|
set_tty_font_name (int window_type, char *font_name) {
|
|
short fnum;
|
|
Str255 new_font;
|
|
|
|
if (window_type < NHW_BASE || window_type > NHW_TEXT)
|
|
return general_failure;
|
|
|
|
C2P (font_name, new_font);
|
|
GetFNum (new_font, &(fnum));
|
|
if (!fnum)
|
|
return general_failure;
|
|
win_fonts [window_type] = fnum;
|
|
return noErr;
|
|
}
|
|
|
|
|
|
static void
|
|
DrawScrollbar (NhWindow *aWin)
|
|
{
|
|
WindowPtr theWindow = aWin->its_window;
|
|
Rect crect, wrect;
|
|
Boolean vis;
|
|
short val, lin, win_height;
|
|
|
|
|
|
if (!aWin->scrollBar)
|
|
return;
|
|
GetControlBounds(aWin->scrollBar, &crect);
|
|
GetWindowBounds(aWin->its_window, kWindowContentRgn, &wrect);
|
|
OffsetRect(&wrect, -wrect.left, -wrect.top);
|
|
win_height = wrect.bottom - wrect.top;
|
|
|
|
if (crect.top != wrect.top - 1 ||
|
|
crect.left != wrect.right - SBARWIDTH) {
|
|
MoveControl (aWin->scrollBar, wrect.right - SBARWIDTH, wrect.top - 1);
|
|
}
|
|
if (crect.bottom != wrect.bottom - SBARHEIGHT ||
|
|
crect.right != wrect.right + 1) {
|
|
SizeControl (aWin->scrollBar, SBARWIDTH+1, win_height - SBARHEIGHT + 2);
|
|
}
|
|
vis = (win_height > (50 + SBARHEIGHT));
|
|
if (vis != IsControlVisible(aWin->scrollBar)) {
|
|
/* current status != control */
|
|
if (vis)/* if visible, show */
|
|
ShowControl (aWin->scrollBar);
|
|
else /* else hide */
|
|
HideControl (aWin->scrollBar);
|
|
}
|
|
lin = aWin->y_size;
|
|
if (aWin == theWindows + WIN_MESSAGE) {
|
|
/* calculate how big scroll bar is for message window */
|
|
lin -= (win_height - SBARHEIGHT) / aWin->row_height;
|
|
if (lin < 0)
|
|
lin = 0;
|
|
val = 0; /* always have message scrollbar active */
|
|
}
|
|
else {
|
|
/* calculate how big scroll bar is for other windows */
|
|
lin -= win_height / aWin->row_height;
|
|
if (lin < 0)
|
|
lin = 0;
|
|
if (lin) val = 0; /* if there are 1+ screen lines, activate scrollbar */
|
|
else val = 255; /* else grey it out */
|
|
}
|
|
SetControlMaximum (aWin->scrollBar, lin);
|
|
HiliteControl (aWin->scrollBar, val);
|
|
val = GetControlValue (aWin->scrollBar);
|
|
if (val != aWin->scrollPos) {
|
|
InvalWindowRect(theWindow, &wrect);
|
|
aWin->scrollPos = val;
|
|
}
|
|
}
|
|
|
|
|
|
#define MAX_HEIGHT 100
|
|
#define MIN_HEIGHT 50
|
|
#define MIN_WIDTH 300
|
|
|
|
/*
|
|
* This function could be overloaded with any amount of intelligence...
|
|
*/
|
|
int
|
|
SanePositions (void)
|
|
{
|
|
#if TARGET_API_MAC_CARBON
|
|
Rect rbase, rmsg;
|
|
SInt16 i, width, height;
|
|
|
|
|
|
ConstrainWindowToScreen(_mt_window, kWindowContentRgn,
|
|
kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
|
|
GetWindowBounds(_mt_window, kWindowContentRgn, &rbase);
|
|
if (RetrievePosition(kMapWindow, &rbase.top, &rbase.left))
|
|
MoveWindow(_mt_window, rbase.left, rbase.top, TRUE);
|
|
|
|
GetWindowBounds(theWindows[NHW_MESSAGE].its_window, kWindowContentRgn, &rmsg);
|
|
height = rmsg.bottom - rmsg.top;
|
|
rmsg.top = rbase.bottom+2;
|
|
rmsg.bottom = rmsg.top + height;
|
|
rmsg.left = rbase.left;
|
|
rmsg.right = rbase.right;
|
|
RetrievePosition(kMessageWindow, &rmsg.top, &rmsg.left);
|
|
if (RetrieveSize(kMessageWindow, rmsg.top, rmsg.left, &height, &width)) {
|
|
rmsg.right = rmsg.left + width;
|
|
rmsg.bottom = rmsg.top + height;
|
|
}
|
|
SetWindowBounds(theWindows[NHW_MESSAGE].its_window, kWindowContentRgn, &rmsg);
|
|
ConstrainWindowToScreen(theWindows[NHW_MESSAGE].its_window, kWindowContentRgn,
|
|
kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
|
|
DrawScrollbar(&theWindows[NHW_MESSAGE]);
|
|
|
|
for (i = 0; i < NUM_MACWINDOWS; i++)
|
|
if (i != WIN_STATUS && i != WIN_MESSAGE && i != WIN_MAP &&
|
|
i != BASE_WINDOW && theWindows[i].its_window) {
|
|
/* FIXME */
|
|
ConstrainWindowToScreen(theWindows[i].its_window, kWindowContentRgn,
|
|
kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
|
|
}
|
|
#else
|
|
short left, top, width, height;
|
|
int ix, numText = 0, numMenu = 0;
|
|
int mbar_height = GetMBarHeight();
|
|
BitMap qbitmap;
|
|
Rect screenArea;
|
|
WindowPtr theWindow;
|
|
NhWindow *nhWin;
|
|
|
|
|
|
screenArea = GetQDGlobalsScreenBits(&qbitmap)->bounds;
|
|
OffsetRect (&screenArea, - screenArea.left, - screenArea.top);
|
|
|
|
/* Map Window */
|
|
height = _mt_window->portRect.bottom - _mt_window->portRect.top;
|
|
width = _mt_window->portRect.right - _mt_window->portRect.left;
|
|
|
|
if (!RetrievePosition (kMapWindow, &top, &left)) {
|
|
top = mbar_height + (small_screen ? 2 : 20);
|
|
left = (screenArea.right - width) / 2;
|
|
}
|
|
MoveWindow (_mt_window, left, top, 1);
|
|
|
|
/* Message Window */
|
|
if (!RetrievePosition (kMessageWindow, &top, &left)) {
|
|
top += height;
|
|
if (!small_screen)
|
|
top += 20;
|
|
}
|
|
|
|
if (!RetrieveSize (kMessageWindow, top, left, &height, &width)) {
|
|
height = screenArea.bottom - top - (small_screen ? 2-SBARHEIGHT : 2);
|
|
if (height > MAX_HEIGHT) {
|
|
height = MAX_HEIGHT;
|
|
} else if (height < MIN_HEIGHT) {
|
|
height = MIN_HEIGHT;
|
|
width = MIN_WIDTH;
|
|
left = screenArea.right - width;
|
|
top = screenArea.bottom - MIN_HEIGHT;
|
|
}
|
|
}
|
|
|
|
/* Move these windows */
|
|
nhWin = theWindows + WIN_MESSAGE;
|
|
theWindow = nhWin->its_window;
|
|
|
|
MoveWindow (theWindow, left, top, 1);
|
|
SizeWindow (theWindow, width, height, 1);
|
|
if (nhWin->scrollBar)
|
|
DrawScrollbar (nhWin);
|
|
|
|
/* Handle other windows */
|
|
for (ix = 0; ix < NUM_MACWINDOWS; ix ++) {
|
|
if (ix != WIN_STATUS && ix != WIN_MESSAGE && ix != WIN_MAP && ix != BASE_WINDOW) {
|
|
theWindow = theWindows [ix].its_window;
|
|
if (theWindow && ((WindowPeek) theWindow)->visible) {
|
|
int shift;
|
|
if (((WindowPeek)theWindow)->windowKind == WIN_BASE_KIND + NHW_MENU) {
|
|
if (!RetrievePosition (kMenuWindow, &top, &left)) {
|
|
top = mbar_height * 2;
|
|
left = 2;
|
|
}
|
|
top += (numMenu * mbar_height);
|
|
numMenu++;
|
|
shift = 20;
|
|
} else {
|
|
if (!RetrievePosition (kTextWindow, &top, &left)) {
|
|
top = mbar_height * 2;
|
|
left = screenArea.right - 3 -
|
|
(theWindow->portRect.right - theWindow->portRect.left);
|
|
}
|
|
top += (numText * mbar_height);
|
|
numText++;
|
|
shift = -20;
|
|
}
|
|
while (top > screenArea.bottom - MIN_HEIGHT) {
|
|
top -= screenArea.bottom - mbar_height * 2;
|
|
left += shift;
|
|
}
|
|
MoveWindow (theWindow, left, top, 1);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return (0);
|
|
}
|
|
|
|
|
|
void
|
|
mac_init_nhwindows (int *argcp, char **argv)
|
|
{
|
|
Rect r;
|
|
#if !TARGET_API_MAC_CARBON
|
|
Rect scr = (*GetGrayRgn())->rgnBBox;
|
|
small_screen = scr.bottom - scr.top <= (iflags.large_font ? 12*40 : 9*40);
|
|
#endif
|
|
|
|
|
|
InitMenuRes();
|
|
|
|
theWindows = (NhWindow *) NewPtrClear (NUM_MACWINDOWS * sizeof (NhWindow));
|
|
if (MemError())
|
|
error("mac_init_nhwindows: Couldn't allocate memory for windows.");
|
|
|
|
DimMenuBar();
|
|
|
|
tty_init_nhwindows(argcp, argv);
|
|
iflags.window_inited = TRUE;
|
|
|
|
/* Some ugly hacks to make both interfaces happy:
|
|
* Mac port uses both tty interface (for main map) and extra windows. The winids need to
|
|
* be kept in synch for both interfaces to map. Also, the "blocked" display_nhwindow case
|
|
* for the map automatically calls the tty interface for the message box, so some version
|
|
* of the message box has to exist in the tty world to prevent a meltdown, even though most
|
|
* messages are handled in mac window.
|
|
*/
|
|
mac_create_nhwindow(NHW_BASE);
|
|
tty_create_nhwindow(NHW_MESSAGE);
|
|
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
/* Resize and reposition the message window */
|
|
RetrievePosition(kMessageWindow, &r.top, &r.left);
|
|
RetrieveSize(kMessageWindow, r.top, r.left, &r.bottom, &r.right);
|
|
MoveWindow(theWindows[NHW_MESSAGE].its_window, r.left, r.top, false);
|
|
SizeWindow(theWindows[NHW_MESSAGE].its_window, r.right, r.bottom, true);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
|
|
winid
|
|
mac_create_nhwindow (int kind) {
|
|
int i;
|
|
NhWindow *aWin;
|
|
FontInfo fi;
|
|
|
|
if (kind < NHW_BASE || kind > NHW_TEXT) {
|
|
error ("cre_win: Invalid kind %d.", kind);
|
|
return WIN_ERR;
|
|
}
|
|
|
|
for (i = 0; i < NUM_MACWINDOWS; i ++) {
|
|
if (!theWindows [i].its_window)
|
|
break;
|
|
}
|
|
if (i >= NUM_MACWINDOWS) {
|
|
error ("cre_win: Win full; freeing extras");
|
|
for (i = 0; i < NUM_MACWINDOWS; i ++) {
|
|
if (IsWindowVisible(theWindows [i].its_window) || i == WIN_INVEN ||
|
|
GetWindowKind(theWindows [i].its_window) != WIN_BASE_KIND + NHW_MENU &&
|
|
GetWindowKind(theWindows [i].its_window) != WIN_BASE_KIND + NHW_TEXT)
|
|
continue;
|
|
mac_destroy_nhwindow(i);
|
|
goto got1;
|
|
}
|
|
error ("cre_win: Out of ids!");
|
|
return WIN_ERR;
|
|
}
|
|
|
|
got1 :
|
|
aWin = &theWindows [i];
|
|
aWin->windowTextLen = 0L;
|
|
aWin->scrollBar = (ControlHandle) 0;
|
|
aWin->menuInfo = 0;
|
|
aWin->menuSelected = 0;
|
|
aWin->miLen = 0;
|
|
aWin->miSize = 0;
|
|
aWin->menuChar = 'a';
|
|
|
|
dprintf ("cre_win: New kind %d", kind);
|
|
|
|
if (kind == NHW_BASE || kind == NHW_MAP || kind == NHW_STATUS) {
|
|
short x_sz, x_sz_p, y_sz, y_sz_p;
|
|
if (kind != NHW_BASE) {
|
|
if (i != tty_create_nhwindow(kind)) {
|
|
dprintf ("cre_win: error creating kind %d", kind);
|
|
}
|
|
if (kind == NHW_MAP) {
|
|
wins[i]->offy = 0; /* the message box is in a separate window */
|
|
}
|
|
}
|
|
aWin->its_window = _mt_window;
|
|
get_tty_metrics(aWin->its_window, &x_sz, &y_sz, &x_sz_p, &y_sz_p,
|
|
&aWin->font_number, &aWin->font_size,
|
|
&aWin->char_width, &aWin->row_height);
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
InstallWindowEventHandler(aWin->its_window, baseupp,
|
|
sizeof(baseevents)/sizeof(EventTypeSpec), baseevents,
|
|
(void *)aWin, NULL);
|
|
#endif
|
|
return i;
|
|
}
|
|
|
|
aWin->its_window = GetNewWindow (WIN_BASE_RES + kind, (WindowPtr) 0L, (WindowPtr) -1L);
|
|
SetWindowKind(aWin->its_window, WIN_BASE_KIND + kind);
|
|
SetWRefCon(aWin->its_window, (long) aWin);
|
|
if (!(aWin->windowText = NewHandle (TEXT_BLOCK))) {
|
|
error ("cre_win: NewHandle fail(%ld)", (long) TEXT_BLOCK);
|
|
DisposeWindow (aWin->its_window);
|
|
aWin->its_window = (WindowPtr) 0;
|
|
return WIN_ERR;
|
|
}
|
|
aWin->x_size = aWin->y_size = 0;
|
|
aWin->x_curs = aWin->y_curs = 0;
|
|
aWin->drawn = TRUE;
|
|
mac_clear_nhwindow (i);
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
switch (kind) {
|
|
case NHW_MESSAGE:
|
|
InstallWindowEventHandler(aWin->its_window, msgupp,
|
|
sizeof(msgevents)/sizeof(EventTypeSpec), msgevents,
|
|
(void *)aWin, NULL);
|
|
break;
|
|
case NHW_MENU:
|
|
InstallWindowEventHandler(aWin->its_window, menwupp,
|
|
sizeof(menwevents)/sizeof(EventTypeSpec), menwevents,
|
|
(void *)aWin, NULL);
|
|
break;
|
|
case NHW_TEXT:
|
|
InstallWindowEventHandler(aWin->its_window, textupp,
|
|
sizeof(textevents)/sizeof(EventTypeSpec), textevents,
|
|
(void *)aWin, NULL);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
SetPortWindowPort(aWin->its_window);
|
|
|
|
if (kind == NHW_MESSAGE) {
|
|
aWin->font_number = win_fonts [NHW_MESSAGE];
|
|
aWin->font_size = iflags.wc_fontsiz_message? iflags.wc_fontsiz_message :
|
|
iflags.large_font ? 12 : 9;
|
|
if (!top_line) {
|
|
const Rect out_of_scr = {10000, 10000, 10100, 10100};
|
|
TextFont(aWin->font_number);
|
|
TextSize(aWin->font_size);
|
|
TextFace(bold);
|
|
top_line = TENew(&out_of_scr, &out_of_scr);
|
|
TEActivate(top_line);
|
|
TextFace(normal);
|
|
}
|
|
} else {
|
|
aWin->font_number = win_fonts [NHW_TEXT];
|
|
aWin->font_size = iflags.wc_fontsiz_text ? iflags.wc_fontsiz_text : 9;
|
|
}
|
|
|
|
TextFont (aWin->font_number);
|
|
TextSize (aWin->font_size);
|
|
|
|
GetFontInfo (&fi);
|
|
aWin->ascent_height = fi.ascent + fi.leading;
|
|
aWin->row_height = aWin->ascent_height + fi.descent;
|
|
aWin->char_width = fi.widMax;
|
|
|
|
if (kind == NHW_MENU || kind == NHW_TEXT || kind == NHW_MESSAGE) {
|
|
Rect r;
|
|
|
|
GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
|
|
r.right -= (r.left - 1);
|
|
r.left = r.right - SBARWIDTH;
|
|
r.bottom -= (r.top + SBARHEIGHT);
|
|
r.top = -1;
|
|
aWin->scrollBar = NewControl(aWin->its_window, &r, "\p", (r.bottom > r.top + 50),
|
|
0, 0, 0, 16, 0L);
|
|
aWin->scrollPos = 0;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
|
|
void
|
|
mac_clear_nhwindow (winid win) {
|
|
long l;
|
|
Rect r;
|
|
NhWindow *aWin = &theWindows [win];
|
|
WindowPtr theWindow = aWin->its_window;
|
|
|
|
if (win < 0 || win >= NUM_MACWINDOWS || !theWindow) {
|
|
error ("clr_win: Invalid win %d.", win);
|
|
return;
|
|
}
|
|
if (theWindow == _mt_window) {
|
|
tty_clear_nhwindow(win);
|
|
return;
|
|
}
|
|
if (!aWin->drawn)
|
|
return;
|
|
|
|
SetPortWindowPort(theWindow);
|
|
GetWindowBounds(theWindow, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
if (aWin->scrollBar)
|
|
r.right -= SBARWIDTH;
|
|
|
|
switch (GetWindowKind(theWindow) - WIN_BASE_KIND) {
|
|
case NHW_MESSAGE :
|
|
if (aWin->scrollPos == aWin->y_size - 1) /* if no change since last clear */
|
|
return; /* don't bother with redraw */
|
|
r.bottom -= SBARHEIGHT;
|
|
for (l = 0; aWin->y_size > iflags.msg_history;) {
|
|
const char cr = CHAR_CR;
|
|
l = Munger(aWin->windowText, l, &cr, 1, nil, 0) + 1;
|
|
--aWin->y_size;
|
|
}
|
|
if (l) {
|
|
aWin->windowTextLen -= l;
|
|
BlockMove(*aWin->windowText + l, *aWin->windowText, aWin->windowTextLen);
|
|
}
|
|
aWin->last_more_lin = aWin->y_size;
|
|
aWin->save_lin = aWin->y_size;
|
|
aWin->scrollPos = aWin->y_size ? aWin->y_size - 1 : 0;
|
|
break;
|
|
case NHW_MENU:
|
|
if (aWin->menuInfo) {
|
|
DisposeHandle((Handle)aWin->menuInfo);
|
|
aWin->menuInfo = NULL;
|
|
}
|
|
if (aWin->menuSelected) {
|
|
DisposeHandle((Handle)aWin->menuSelected);
|
|
aWin->menuSelected = NULL;
|
|
}
|
|
aWin->menuChar = 'a';
|
|
aWin->miSelLen = 0;
|
|
aWin->miLen = 0;
|
|
aWin->miSize = 0;
|
|
/* Fall-Through */
|
|
default :
|
|
SetHandleSize (aWin->windowText, TEXT_BLOCK);
|
|
aWin->windowTextLen = 0L;
|
|
aWin->x_size = 0;
|
|
aWin->y_size = 0;
|
|
aWin->scrollPos = 0;
|
|
break;
|
|
}
|
|
if (aWin->scrollBar) {
|
|
SetControlMaximum (aWin->scrollBar, aWin->y_size);
|
|
SetControlValue(aWin->scrollBar, aWin->scrollPos);
|
|
}
|
|
aWin->y_curs = 0;
|
|
aWin->x_curs = 0;
|
|
aWin->drawn = FALSE;
|
|
InvalWindowRect(theWindow, &r);
|
|
}
|
|
|
|
|
|
static Boolean
|
|
ClosingWindowChar(const int c) {
|
|
return (c == CHAR_ESC || c == CHAR_BLANK || c == CHAR_LF || c == CHAR_CR);
|
|
}
|
|
|
|
|
|
static Boolean
|
|
in_topl_mode(void)
|
|
{
|
|
Rect rect;
|
|
|
|
|
|
GetWindowBounds(theWindows[WIN_MESSAGE].its_window, kWindowContentRgn, &rect);
|
|
OffsetRect(&rect, -rect.left, -rect.top);
|
|
return (WIN_MESSAGE != WIN_ERR && top_line &&
|
|
(*top_line)->viewRect.left < rect.right);
|
|
}
|
|
|
|
|
|
#define BTN_IND 2
|
|
#define BTN_W 40
|
|
#define BTN_H (SBARHEIGHT-3)
|
|
|
|
static void
|
|
topl_resp_rect(int resp_idx, Rect *r)
|
|
{
|
|
Rect rect;
|
|
|
|
|
|
GetWindowBounds(theWindows[WIN_MESSAGE].its_window, kWindowContentRgn, &rect);
|
|
OffsetRect(&rect, -rect.left, -rect.top);
|
|
r->left = (BTN_IND + BTN_W) * resp_idx + BTN_IND;
|
|
r->right = r->left + BTN_W;
|
|
r->bottom = rect.bottom - 1;
|
|
r->top = r->bottom - BTN_H;
|
|
return;
|
|
}
|
|
|
|
|
|
void
|
|
enter_topl_mode(char *query) {
|
|
if (in_topl_mode())
|
|
return;
|
|
|
|
putstr(WIN_MESSAGE, ATR_BOLD, query);
|
|
|
|
topl_query_len = strlen(query);
|
|
(*top_line)->selStart = topl_query_len;
|
|
(*top_line)->selEnd = topl_query_len;
|
|
(*top_line)->viewRect.left = 0;
|
|
PtrToXHand(query, (*top_line)->hText, topl_query_len);
|
|
TECalText(top_line);
|
|
|
|
DimMenuBar();
|
|
mac_display_nhwindow(WIN_MESSAGE, FALSE);
|
|
}
|
|
|
|
|
|
void
|
|
leave_topl_mode(char *answer) {
|
|
/*unsigned*/ char *ap, *bp;
|
|
|
|
int ans_len = (*top_line)->teLength - topl_query_len;
|
|
NhWindow *aWin = theWindows + WIN_MESSAGE;
|
|
|
|
if (!in_topl_mode())
|
|
return;
|
|
|
|
/* Cap length of reply */
|
|
if (ans_len >= BUFSZ)
|
|
ans_len = BUFSZ-1;
|
|
|
|
/* remove unprintables from the answer */
|
|
for (ap = *(*top_line)->hText + topl_query_len, bp = answer; ans_len > 0; ans_len--, ap++) {
|
|
if (*ap >= ' ' && *ap < 128) {
|
|
*bp++ = *ap;
|
|
}
|
|
}
|
|
*bp = 0;
|
|
|
|
if (aWin->windowTextLen && (*aWin->windowText)[aWin->windowTextLen-1] == CHAR_CR) {
|
|
-- aWin->windowTextLen;
|
|
-- aWin->y_size;
|
|
}
|
|
putstr(WIN_MESSAGE, ATR_BOLD, answer);
|
|
|
|
(*top_line)->viewRect.left += 10000;
|
|
UndimMenuBar();
|
|
}
|
|
|
|
/*
|
|
* TESetSelect flushes out all the pending key strokes. I hate it.
|
|
*/
|
|
static void
|
|
topl_set_select(short selStart, short selEnd) {
|
|
TEDeactivate(top_line);
|
|
(*top_line)->selStart = selStart;
|
|
(*top_line)->selEnd = selEnd;
|
|
TEActivate(top_line);
|
|
}
|
|
|
|
|
|
static void
|
|
topl_replace(char *new_ans) {
|
|
topl_set_select(topl_query_len, (*top_line)->teLength);
|
|
TEDelete(top_line);
|
|
TEInsert(new_ans, strlen(new_ans), top_line);
|
|
}
|
|
|
|
|
|
Boolean
|
|
topl_key(unsigned char ch, Boolean ext) {
|
|
switch (ch) {
|
|
case CHAR_ESC:
|
|
topl_replace("\x1b");
|
|
case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
|
|
return false;
|
|
|
|
case 0x1f & 'P':
|
|
mac_doprev_message();
|
|
return true;
|
|
case '\x1e'/* up arrow */:
|
|
topl_replace ("");
|
|
return true;
|
|
case CHAR_BS: case '\x1c'/* left arrow */:
|
|
if ((*top_line)->selEnd <= topl_query_len)
|
|
return true;
|
|
else if (ext) {
|
|
topl_replace ("");
|
|
return true;
|
|
}
|
|
default:
|
|
TEKey(ch, top_line);
|
|
if (ext) {
|
|
int com_index = -1, oindex = 0;
|
|
while(extcmdlist[oindex].ef_txt != (char *)0) {
|
|
if(!strncmpi(*(*top_line)->hText + topl_query_len,
|
|
extcmdlist[oindex].ef_txt,
|
|
(*top_line)->teLength - topl_query_len)) {
|
|
if(com_index == -1) /* No matches yet*/
|
|
com_index = oindex;
|
|
else /* More than 1 match */ {
|
|
com_index = -2;
|
|
break;
|
|
}
|
|
}
|
|
oindex++;
|
|
}
|
|
if(com_index >= 0)
|
|
topl_replace((char *) extcmdlist[com_index].ef_txt);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
topl_flash_resp(int resp_idx) {
|
|
unsigned long dont_care;
|
|
Rect frame;
|
|
SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
|
|
topl_resp_rect(resp_idx, &frame);
|
|
InsetRect(&frame, 1, 1);
|
|
InvertRect(&frame);
|
|
Delay(GetDblTime() / 2, &dont_care);
|
|
InvertRect(&frame);
|
|
}
|
|
|
|
|
|
static void
|
|
topl_set_def(int new_def_idx) {
|
|
Rect frame;
|
|
SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
|
|
topl_resp_rect(topl_def_idx, &frame);
|
|
InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
|
|
topl_def_idx = new_def_idx;
|
|
topl_resp_rect(new_def_idx, &frame);
|
|
InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
|
|
}
|
|
|
|
|
|
void
|
|
topl_set_resp(char *resp, char def) {
|
|
char *loc;
|
|
Rect frame;
|
|
int r_len, r_len1;
|
|
|
|
if (!resp) {
|
|
const char any_str[2] = {CHAR_ANY, '\0'};
|
|
resp = (char *) any_str;
|
|
def = CHAR_ANY;
|
|
}
|
|
|
|
SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
|
|
r_len1 = strlen(resp);
|
|
r_len = strlen(topl_resp);
|
|
if (r_len < r_len1)
|
|
r_len = r_len1;
|
|
topl_resp_rect(0, &frame);
|
|
frame.right = (BTN_IND + BTN_W) * r_len;
|
|
InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
|
|
|
|
strcpy(topl_resp, resp);
|
|
loc = strchr (resp, def);
|
|
topl_def_idx = loc ? loc - resp : -1;
|
|
}
|
|
|
|
|
|
static char
|
|
topl_resp_key(char ch) {
|
|
if (strlen(topl_resp) > 0) {
|
|
char *loc = strchr(topl_resp, ch);
|
|
|
|
if (!loc) {
|
|
if (ch == '\x9'/* tab */) {
|
|
topl_set_def(topl_def_idx<=0 ? strlen(topl_resp)-1 : topl_def_idx-1);
|
|
ch = '\0';
|
|
} else if (ch == CHAR_ESC) {
|
|
loc = strchr(topl_resp, 'q');
|
|
if (!loc) {
|
|
loc = strchr(topl_resp, 'n');
|
|
if (!loc && topl_def_idx >= 0)
|
|
loc = topl_resp + topl_def_idx;
|
|
}
|
|
} else if (ch == (0x1f & 'P')) {
|
|
mac_doprev_message();
|
|
ch = '\0';
|
|
} else if (topl_def_idx >= 0) {
|
|
if (ch == CHAR_ENTER || ch == CHAR_CR || ch == CHAR_LF ||
|
|
ch == CHAR_BLANK || topl_resp[topl_def_idx] == CHAR_ANY)
|
|
loc = topl_resp + topl_def_idx;
|
|
|
|
else if (strchr(topl_resp, '#')) {
|
|
if (digit(ch)) {
|
|
topl_set_def(strchr(topl_resp, '#') - topl_resp);
|
|
TEKey(ch, top_line);
|
|
ch = '\0';
|
|
|
|
} else if (topl_resp[topl_def_idx] == '#') {
|
|
if (ch == '\x1e'/* up arrow */) {
|
|
topl_set_select(topl_query_len, topl_query_len);
|
|
ch = '\0';
|
|
} else if (ch == '\x1d'/* right arrow */ ||
|
|
ch == '\x1f'/* down arrow */ ||
|
|
ch == CHAR_BS || ch == '\x1c'/* left arrow */ &&
|
|
(*top_line)->selEnd > topl_query_len) {
|
|
TEKey(ch, top_line);
|
|
ch = '\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (loc) {
|
|
topl_flash_resp(loc - topl_resp);
|
|
if (*loc != CHAR_ANY)
|
|
ch = *loc;
|
|
TEKey(ch, top_line);
|
|
}
|
|
}
|
|
|
|
return ch;
|
|
}
|
|
|
|
|
|
static void
|
|
adjust_window_pos(NhWindow *aWin, short width, short height)
|
|
{
|
|
WindowRef theWindow = aWin->its_window;
|
|
#if TARGET_API_MAC_CARBON
|
|
Rect r;
|
|
|
|
|
|
GetWindowBounds(theWindow, kWindowContentRgn, &r);
|
|
RetrieveWinPos(theWindow, &r.top, &r.left);
|
|
MoveWindow(theWindow, r.left, r.top, false);
|
|
SizeWindow(theWindow, width, height, true);
|
|
ConstrainWindowToScreen(theWindow, kWindowStructureRgn,
|
|
kWindowConstrainMayResize|kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
|
|
#else
|
|
Rect scr_r = (*GetGrayRgn())->rgnBBox;
|
|
const Rect win_ind = {2, 2, 3, 3};
|
|
const short min_w = theWindow->portRect.right - theWindow->portRect.left,
|
|
max_w = scr_r.right - scr_r.left - win_ind.left - win_ind.right;
|
|
Point pos;
|
|
short max_h;
|
|
|
|
SetPortWindowPort(theWindow);
|
|
if (!RetrieveWinPos(theWindow, &pos.v, &pos.h)) {
|
|
pos.v = 0; /* take window's existing position */
|
|
pos.h = 0;
|
|
LocalToGlobal(&pos);
|
|
}
|
|
|
|
max_h = scr_r.bottom - win_ind.bottom - pos.v;
|
|
if (height > max_h) height = max_h;
|
|
if (height < MIN_HEIGHT) height = MIN_HEIGHT;
|
|
if (width < min_w) width = min_w;
|
|
if (width > max_w) width = max_w;
|
|
SizeWindow(theWindow, width, height, true);
|
|
|
|
if (pos.v + height + win_ind.bottom > scr_r.bottom)
|
|
pos.v = scr_r.bottom - height - win_ind.bottom;
|
|
if (pos.h + width + win_ind.right > scr_r.right)
|
|
pos.h = scr_r.right - width - win_ind.right;
|
|
MoveWindow(theWindow, pos.h, pos.v, false);
|
|
#endif
|
|
if (aWin->scrollBar)
|
|
DrawScrollbar(aWin);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* display/select/update the window.
|
|
* If f is true, this window should be "modal" - don't return
|
|
* until presumed seen.
|
|
*/
|
|
void
|
|
mac_display_nhwindow (winid win, BOOLEAN_P f) {
|
|
NhWindow *aWin = &theWindows [win];
|
|
WindowPtr theWindow = aWin->its_window;
|
|
|
|
if (win < 0 || win >= NUM_MACWINDOWS || !theWindow) {
|
|
error ("disp_win: Invalid window %d.", win);
|
|
return;
|
|
}
|
|
|
|
if (theWindow == _mt_window) {
|
|
tty_display_nhwindow(win, f);
|
|
return;
|
|
}
|
|
|
|
if (f && inSelect == WIN_ERR && win == WIN_MESSAGE) {
|
|
topl_set_resp ((char *)0, 0);
|
|
if (aWin->windowTextLen > 0 &&
|
|
(*aWin->windowText) [aWin->windowTextLen - 1] == CHAR_CR) {
|
|
-- aWin->windowTextLen;
|
|
-- aWin->y_size;
|
|
}
|
|
putstr (win, flags.standout ? ATR_INVERSE : ATR_NONE, " --More--");
|
|
}
|
|
|
|
if (!IsWindowVisible(theWindow)) {
|
|
if (win != WIN_MESSAGE)
|
|
adjust_window_pos(aWin, aWin->x_size + SBARWIDTH+1, aWin->y_size *aWin->row_height);
|
|
|
|
SelectWindow (theWindow);
|
|
ShowWindow (theWindow);
|
|
}
|
|
|
|
if (f && inSelect == WIN_ERR) {
|
|
int ch;
|
|
|
|
DimMenuBar();
|
|
inSelect = win;
|
|
do {
|
|
ch = mac_nhgetch ();
|
|
} while (!ClosingWindowChar (ch));
|
|
inSelect = WIN_ERR;
|
|
UndimMenuBar();
|
|
|
|
if (win == WIN_MESSAGE)
|
|
topl_set_resp ("", '\0');
|
|
else
|
|
HideWindow (theWindow);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
mac_destroy_nhwindow (winid win) {
|
|
WindowPtr theWindow;
|
|
NhWindow *aWin = &theWindows [win];
|
|
int kind;
|
|
|
|
if (win < 0 || win >= NUM_MACWINDOWS) {
|
|
if (iflags.window_inited) error ("dest_win: Invalid win %d.", win);
|
|
return;
|
|
}
|
|
theWindow = aWin->its_window;
|
|
if (!theWindow) {
|
|
error ("dest_win: Not allocated win %d.", win);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Check special windows. The base window should never go away.
|
|
* Other "standard" windows should not go away unless we've exitted nhwindows.
|
|
*/
|
|
if (theWindow == _mt_window) {
|
|
return;
|
|
}
|
|
if (win == WIN_INVEN || win == WIN_MESSAGE) {
|
|
if (iflags.window_inited) {
|
|
if (flags.tombstone && killer[0]) {
|
|
/* Prepare for the coming of the tombstone window. */
|
|
win_fonts [NHW_TEXT] = kFontIDMonaco;
|
|
}
|
|
return;
|
|
}
|
|
if (win == WIN_MESSAGE)
|
|
WIN_MESSAGE = WIN_ERR;
|
|
}
|
|
|
|
kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
|
|
|
|
if ((!IsWindowVisible(theWindow) || (kind != NHW_MENU && kind != NHW_TEXT))) {
|
|
DisposeWindow (theWindow);
|
|
if (aWin->windowText) {
|
|
DisposeHandle(aWin->windowText);
|
|
}
|
|
aWin->its_window = (WindowPtr) 0;
|
|
aWin->windowText = (Handle) 0;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
mac_number_pad (int pad) { /* no effect */
|
|
#if defined(__SC__) || defined(__MRC__)
|
|
# pragma unused(pad)
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
|
|
void
|
|
trans_num_keys(EventRecord *theEvent) {
|
|
#if defined(__SC__) || defined(__MRC__)
|
|
# pragma unused(theEvent)
|
|
#endif
|
|
/* KMH -- Removed this translation.
|
|
* Number pad keys should always emit digit characters.
|
|
* That's consistent with the default MacOS behavior.
|
|
* The number_pad option controls how digits are interpreted.
|
|
*/
|
|
#if 0
|
|
if (Cmd.num_pad) {
|
|
Handle h = GetResource('Nump', theEvent->modifiers & shiftKey ? 129 : 128);
|
|
if (h) {
|
|
short inkey = (theEvent->message & keyCodeMask), *ab = (short *)*h;
|
|
int i = ab[0];
|
|
for (; i; i--) {
|
|
if (inkey == (ab[i] & keyCodeMask)) {
|
|
theEvent->message = ab[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* Routine used to select and de-select elements in a menu window, used by KeyMenu,
|
|
* ClickMenu, and UpdateMenu. Takes the NhWindow and a line ref relative to the scrollbar.
|
|
*/
|
|
static void ToggleMenuSelect (NhWindow *aWin, int line) {
|
|
Rect r;
|
|
|
|
|
|
GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
if (aWin->scrollBar)
|
|
r.right -= SBARWIDTH;
|
|
r.top = line * aWin->row_height;
|
|
r.bottom = r.top + aWin->row_height;
|
|
|
|
LMSetHiliteMode((UInt8) (LMGetHiliteMode() & 0x7F));
|
|
InvertRect(&r);
|
|
}
|
|
|
|
/*
|
|
* Check to see if given item is selected, return index if it is
|
|
*/
|
|
static int
|
|
ListItemSelected (NhWindow *aWin, int item) {
|
|
int i;
|
|
|
|
HLock ((char**)aWin->menuSelected);
|
|
/* Find item in selection list */
|
|
for (i = aWin->miSelLen - 1; i >= 0; i--) {
|
|
if ((*aWin->menuSelected) [i] == item)
|
|
break;
|
|
}
|
|
HUnlock ((char**)aWin->menuSelected);
|
|
return i;
|
|
}
|
|
|
|
/*
|
|
* Add item to selection list if it's not selected already
|
|
* If it is selected already, remove it from the list.
|
|
*/
|
|
static void
|
|
ToggleMenuListItemSelected (NhWindow *aWin, short item) {
|
|
int i = ListItemSelected (aWin, item);
|
|
|
|
HLock ((char**)aWin->menuSelected);
|
|
if (i < 0) { /* not there, so add */
|
|
(*aWin->menuSelected) [aWin->miSelLen] = item;
|
|
aWin->miSelLen++;
|
|
}
|
|
else { /* there, so remove */
|
|
short *mi = &(*aWin->menuSelected)[i];
|
|
aWin->miSelLen --;
|
|
memcpy (mi, mi + 1, (aWin->miSelLen - i)*sizeof(short));
|
|
}
|
|
HUnlock ((char**)aWin->menuSelected);
|
|
}
|
|
|
|
|
|
/*
|
|
* Find menu item in list given a line number on the window
|
|
*/
|
|
static short
|
|
ListCoordinateToItem (NhWindow *aWin, short Row) {
|
|
int i, item = -1;
|
|
MacMHMenuItem * mi;
|
|
|
|
HLock ((char**)aWin->menuInfo);
|
|
for (i = 0, mi = *aWin->menuInfo; i < aWin->miLen; i++, mi++) {
|
|
if (mi->line == Row + aWin->scrollPos) {
|
|
item = i;
|
|
break;
|
|
}
|
|
}
|
|
HUnlock ((char**)aWin->menuInfo);
|
|
return item;
|
|
}
|
|
|
|
|
|
static pascal void
|
|
MoveScrollBar (ControlHandle theBar, short part) {
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
EventRecord fake;
|
|
#endif
|
|
Rect r;
|
|
RgnHandle rgn;
|
|
int now, amtToScroll;
|
|
WindowPtr theWin;
|
|
NhWindow *winToScroll;
|
|
|
|
if (!part)
|
|
return;
|
|
|
|
theWin = GetControlOwner(theBar);
|
|
GetWindowBounds(theWin, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
winToScroll = (NhWindow*)(GetWRefCon(theWin));
|
|
now = GetControlValue (theBar);
|
|
|
|
if (part == kControlPageUpPart || part == kControlPageDownPart)
|
|
amtToScroll = (r.bottom - r.top) / winToScroll->row_height;
|
|
else
|
|
amtToScroll = 1;
|
|
|
|
if (part == kControlPageUpPart || part == kControlUpButtonPart) {
|
|
int bound = GetControlMinimum (theBar);
|
|
if (now - bound < amtToScroll)
|
|
amtToScroll = now - bound;
|
|
amtToScroll = -amtToScroll;
|
|
} else {
|
|
int bound = GetControlMaximum (theBar);
|
|
if (bound - now < amtToScroll)
|
|
amtToScroll = bound - now;
|
|
}
|
|
|
|
if (!amtToScroll)
|
|
return;
|
|
|
|
SetControlValue (theBar, now + amtToScroll);
|
|
winToScroll->scrollPos = now + amtToScroll;
|
|
r.right -= SBARWIDTH;
|
|
if (winToScroll == theWindows + WIN_MESSAGE)
|
|
r.bottom -= SBARHEIGHT;
|
|
rgn = NewRgn ();
|
|
ScrollRect (&r, 0, -amtToScroll * winToScroll->row_height, rgn);
|
|
if (rgn) {
|
|
InvalWindowRgn(theWin, rgn);
|
|
BeginUpdate(theWin);
|
|
}
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
switch (GetWindowKind(theWin) - WIN_BASE_KIND) {
|
|
case NHW_MESSAGE:
|
|
MsgUpdate(GetNhWin(theWin));
|
|
break;
|
|
case NHW_MENU:
|
|
MenwUpdate(GetNhWin(theWin));
|
|
break;
|
|
case NHW_TEXT:
|
|
TextUpdate(GetNhWin(theWin));
|
|
break;
|
|
}
|
|
#else
|
|
winUpdateFuncs [GetWindowKind(theWin) - WIN_BASE_KIND] (&fake, theWin);
|
|
#endif
|
|
if (rgn) {
|
|
EndUpdate(theWin);
|
|
DisposeRgn(rgn);
|
|
}
|
|
}
|
|
|
|
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
static void
|
|
DoScrollBar (Point p, short code, ControlHandle theBar, NhWindow *aWin)
|
|
{
|
|
ControlActionUPP func = NULL;
|
|
Rect rect;
|
|
|
|
if (code == kControlUpButtonPart || code == kControlPageUpPart ||
|
|
code == kControlDownButtonPart || code == kControlPageDownPart)
|
|
func = MoveScrollUPP;
|
|
(void) TrackControl(theBar, p, func);
|
|
if (!func) {
|
|
if (aWin->scrollPos != GetControlValue (theBar)) {
|
|
aWin->scrollPos = GetControlValue (theBar);
|
|
GetWindowBounds(aWin->its_window, kWindowContentRgn, &rect);
|
|
OffsetRect(&rect, -rect.left, -rect.top);
|
|
InvalWindowRect(aWin->its_window, &rect);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
static int
|
|
filter_scroll_key(const int ch, NhWindow *aWin) {
|
|
if (aWin->scrollBar && GetControlValue(aWin->scrollBar) < GetControlMaximum(aWin->scrollBar)) {
|
|
short part = 0;
|
|
if (ch == CHAR_BLANK) {
|
|
part = kControlPageDownPart;
|
|
}
|
|
else if (ch == CHAR_CR || ch == CHAR_LF) {
|
|
part = kControlDownButtonPart;
|
|
}
|
|
if (part) {
|
|
SetPortWindowPort(aWin->its_window);
|
|
MoveScrollBar(aWin->scrollBar, part);
|
|
return 0;
|
|
}
|
|
}
|
|
return ch;
|
|
}
|
|
|
|
|
|
int
|
|
mac_doprev_message(void) {
|
|
if (WIN_MESSAGE) {
|
|
NhWindow *winToScroll = &theWindows[WIN_MESSAGE];
|
|
mac_display_nhwindow(WIN_MESSAGE, FALSE);
|
|
SetPortWindowPort(winToScroll->its_window);
|
|
MoveScrollBar(winToScroll->scrollBar, kControlUpButtonPart);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
draw_growicon_vert_only(WindowPtr wind)
|
|
{
|
|
GrafPtr org_port;
|
|
RgnHandle org_clip = NewRgn();
|
|
Rect r;
|
|
|
|
GetPort(&org_port);
|
|
SetPortWindowPort(wind);
|
|
GetClip(org_clip);
|
|
GetWindowBounds(wind, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
r.left = r.right - SBARWIDTH;
|
|
ClipRect(&r);
|
|
DrawGrowIcon(wind);
|
|
SetClip(org_clip);
|
|
DisposeRgn(org_clip);
|
|
SetPort(org_port);
|
|
}
|
|
|
|
|
|
/* NOT_IN_CARBON */
|
|
static void
|
|
WindowGoAway (EventRecord *theEvent, WindowPtr theWindow) {
|
|
NhWindow *aWin = GetNhWin(theWindow);
|
|
|
|
if (!theEvent || TrackGoAway (theWindow, theEvent->where)) {
|
|
if (aWin - theWindows == BASE_WINDOW && !iflags.window_inited) {
|
|
AddToKeyQueue ('\033', 1);
|
|
} else {
|
|
HideWindow (theWindow);
|
|
if (aWin - theWindows != inSelect)
|
|
mac_destroy_nhwindow (aWin - theWindows);
|
|
else /* if this IS the inSelect window put a close char */
|
|
AddToKeyQueue (CHAR_CR, 1); /* in queue to exit and maintain inSelect */
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
mac_get_nh_event(void) {
|
|
EventRecord anEvent;
|
|
|
|
|
|
/* KMH -- Don't proceed if the window system isn't set up */
|
|
if (!iflags.window_inited)
|
|
return;
|
|
|
|
#if TARGET_API_MAC_CARBON
|
|
QDFlushPortBuffer(GetWindowPort(_mt_window), NULL);
|
|
#endif
|
|
(void) WaitNextEvent (everyEvent, &anEvent, 1, gMouseRgn);
|
|
HandleEvent(&anEvent);
|
|
return;
|
|
}
|
|
|
|
|
|
int
|
|
mac_nhgetch(void) {
|
|
int ch;
|
|
long doDawdle = 1L;
|
|
EventRecord anEvent;
|
|
|
|
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
/* We want to take care of keys in the buffer as fast as
|
|
* possible
|
|
*/
|
|
if (keyQueueCount)
|
|
doDawdle = 0L;
|
|
else {
|
|
long total, contig;
|
|
static char warn = 0;
|
|
|
|
doDawdle = (in_topl_mode() ? GetCaretTime () : 120L);
|
|
/* Since we have time, check memory */
|
|
PurgeSpace(&total, &contig);
|
|
if (contig < 25000L || total < 50000L) {
|
|
if (!warn) {
|
|
pline ("Low Memory!");
|
|
warn = 1;
|
|
}
|
|
} else {
|
|
warn = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
do {
|
|
#if TARGET_API_MAC_CARBON
|
|
QDFlushPortBuffer(GetWindowPort(_mt_window), NULL);
|
|
#endif
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
EventRef event;
|
|
|
|
if (ReceiveNextEvent(0, NULL, kEventDurationForever, TRUE, &event) == noErr) {
|
|
SendEventToEventTarget(event, dispatcher);
|
|
ReleaseEvent(event);
|
|
}
|
|
#else
|
|
(void) WaitNextEvent(everyEvent, &anEvent, doDawdle, gMouseRgn);
|
|
HandleEvent(&anEvent);
|
|
#endif
|
|
ch = GetFromKeyQueue();
|
|
} while (!ch && !gClickedToMove);
|
|
|
|
if (!gClickedToMove)
|
|
ObscureCursor();
|
|
else
|
|
gClickedToMove = 0;
|
|
|
|
#ifdef THINK_C
|
|
if (ch == '\r') ch = '\n';
|
|
#endif
|
|
|
|
return (ch);
|
|
}
|
|
|
|
|
|
void
|
|
mac_delay_output(void) {
|
|
long destTicks = TickCount () + 1;
|
|
|
|
while (TickCount () < destTicks) {
|
|
mac_get_nh_event ();
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CLIPPING
|
|
static void
|
|
mac_cliparound (int x, int y) {
|
|
#if defined(__SC__) || defined(__MRC__)
|
|
# pragma unused(x,y)
|
|
#endif
|
|
/* TODO */
|
|
}
|
|
#endif
|
|
|
|
void
|
|
mac_exit_nhwindows (const char *s) {
|
|
clear_screen ();
|
|
tty_exit_nhwindows (s);
|
|
mac_destroy_nhwindow (WIN_MESSAGE);
|
|
mac_destroy_nhwindow (WIN_INVEN);
|
|
}
|
|
|
|
|
|
/*
|
|
* Don't forget to decrease in_putstr before returning...
|
|
*/
|
|
void
|
|
mac_putstr (winid win, int attr, const char *str) {
|
|
long len, slen;
|
|
NhWindow *aWin = &theWindows [win];
|
|
static char in_putstr = 0;
|
|
short newWidth, maxWidth;
|
|
Rect r;
|
|
char *src, *sline, *dst, ch;
|
|
|
|
if (win < 0 || win >= NUM_MACWINDOWS || !aWin->its_window) {
|
|
error ("putstr: Invalid win %d (Max %d).", win, NUM_MACWINDOWS, attr);
|
|
return;
|
|
}
|
|
|
|
if (aWin->its_window == _mt_window) {
|
|
tty_putstr(win, attr, str);
|
|
return;
|
|
}
|
|
|
|
if (in_putstr > 3)
|
|
return;
|
|
|
|
in_putstr ++;
|
|
slen = strlen (str);
|
|
|
|
SetPortWindowPort(aWin->its_window);
|
|
GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
if (win == WIN_MESSAGE) {
|
|
r.right -= SBARWIDTH;
|
|
r.bottom -= SBARHEIGHT;
|
|
if (flags.page_wait &&
|
|
aWin->last_more_lin <= aWin->y_size - (r.bottom - r.top) / aWin->row_height) {
|
|
aWin->last_more_lin = aWin->y_size;
|
|
mac_display_nhwindow(win, TRUE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* A "default" text window - uses TETextBox
|
|
* We just add the text, without attributes for now
|
|
*/
|
|
len = GetHandleSize (aWin->windowText);
|
|
while (aWin->windowTextLen + slen + 1 > len) {
|
|
len = (len > 2048) ? (len + 2048) : (len * 2);
|
|
SetHandleSize (aWin->windowText, len);
|
|
if (MemError ()) {
|
|
error ("putstr: SetHandleSize");
|
|
aWin->windowTextLen = 0L;
|
|
aWin->save_lin = 0;
|
|
aWin->y_curs = 0;
|
|
aWin->y_size = 0;
|
|
}
|
|
}
|
|
|
|
len = aWin->windowTextLen;
|
|
dst = *(aWin->windowText) + len;
|
|
sline = src = (char *)str;
|
|
maxWidth = newWidth = 0;
|
|
for (ch = *src; ch; ch = *src) {
|
|
if (ch == CHAR_LF)
|
|
ch = CHAR_CR;
|
|
*dst++ = ch;
|
|
if (ch == CHAR_CR) {
|
|
aWin->y_curs ++;
|
|
aWin->y_size ++;
|
|
aWin->x_curs = 0;
|
|
newWidth = TextWidth (sline, 0, src - sline);
|
|
if (newWidth > maxWidth) {
|
|
maxWidth = newWidth;
|
|
}
|
|
sline = src+1; /* keep track of where new line begins */
|
|
}
|
|
else
|
|
aWin->x_curs ++;
|
|
src++;
|
|
}
|
|
|
|
newWidth = TextWidth (sline, 0, src - sline);
|
|
if (newWidth > maxWidth) {
|
|
maxWidth = newWidth;
|
|
}
|
|
|
|
aWin->windowTextLen += slen;
|
|
|
|
if (ch != CHAR_CR) {
|
|
(*(aWin->windowText)) [len + slen] = CHAR_CR;
|
|
aWin->windowTextLen ++;
|
|
aWin->y_curs ++;
|
|
aWin->y_size ++;
|
|
aWin->x_curs = 0;
|
|
}
|
|
|
|
if (win == WIN_MESSAGE) {
|
|
short min = aWin->y_size - (r.bottom - r.top) / aWin->row_height;
|
|
if (aWin->scrollPos < min) {
|
|
aWin->scrollPos = min;
|
|
SetControlMaximum (aWin->scrollBar, aWin->y_size);
|
|
SetControlValue(aWin->scrollBar, min);
|
|
}
|
|
InvalWindowRect(aWin->its_window, &r);
|
|
}
|
|
else /* Message has a fixed width, other windows base on content */
|
|
if (maxWidth > aWin->x_size)
|
|
aWin->x_size = maxWidth;
|
|
in_putstr --;
|
|
}
|
|
|
|
|
|
void
|
|
mac_curs (winid win, int x, int y) {
|
|
NhWindow *aWin = &theWindows [win];
|
|
|
|
if (aWin->its_window == _mt_window) {
|
|
tty_curs(win, x, y);
|
|
return;
|
|
}
|
|
|
|
SetPortWindowPort(aWin->its_window);
|
|
MoveTo (x * aWin->char_width, (y * aWin->row_height) + aWin->ascent_height);
|
|
aWin->x_curs = x;
|
|
aWin->y_curs = y;
|
|
}
|
|
|
|
|
|
int
|
|
mac_nh_poskey (int *a, int *b, int *c) {
|
|
int ch = mac_nhgetch();
|
|
*a = clicked_pos.h;
|
|
*b = clicked_pos.v;
|
|
*c = clicked_mod;
|
|
return ch;
|
|
}
|
|
|
|
|
|
void
|
|
mac_start_menu (winid win) {
|
|
HideWindow (theWindows [win].its_window);
|
|
mac_clear_nhwindow (win);
|
|
}
|
|
|
|
|
|
void
|
|
mac_add_menu (winid win, int glyph, const anything *any, CHAR_P menuChar, CHAR_P groupAcc, int attr, const char *inStr, int preselected) {
|
|
#if defined(__SC__) || defined(__MRC__)
|
|
# pragma unused(glyph)
|
|
#endif
|
|
NhWindow *aWin = &theWindows [win];
|
|
const char *str;
|
|
char locStr[4+BUFSZ];
|
|
MacMHMenuItem *item;
|
|
|
|
if (!inStr) return;
|
|
|
|
if (any->a_void != 0) {
|
|
|
|
#define kMenuSizeBump 26
|
|
if (!aWin->miSize) {
|
|
aWin->menuInfo = (MacMHMenuItem **)NewHandle(sizeof(MacMHMenuItem) * kMenuSizeBump);
|
|
if (!aWin->menuInfo) {
|
|
error("Can't alloc menu handle");
|
|
return;
|
|
}
|
|
aWin->menuSelected = (short **)NewHandle(sizeof(short) * kMenuSizeBump);
|
|
if (!aWin->menuSelected) {
|
|
error("Can't alloc menu select handle");
|
|
return;
|
|
}
|
|
aWin->miSize = kMenuSizeBump;
|
|
}
|
|
|
|
if (aWin->miLen >= aWin->miSize) {
|
|
SetHandleSize((Handle)aWin->menuInfo, sizeof(MacMHMenuItem) * (aWin->miLen+kMenuSizeBump));
|
|
if (MemError()) {
|
|
error("Can't resize menu handle");
|
|
return;
|
|
}
|
|
SetHandleSize((Handle)aWin->menuSelected, sizeof(short) * (aWin->miLen+kMenuSizeBump));
|
|
if (MemError()) {
|
|
error("Can't resize menu select handle");
|
|
return;
|
|
}
|
|
aWin->miSize += kMenuSizeBump;
|
|
}
|
|
|
|
if (menuChar == 0) {
|
|
if (('a' <= aWin->menuChar && aWin->menuChar <= 'z') ||
|
|
('A' <= aWin->menuChar && aWin->menuChar <= 'Z')) {
|
|
menuChar = aWin->menuChar++;
|
|
if (menuChar == 'z')
|
|
aWin->menuChar = 'A';
|
|
}
|
|
}
|
|
|
|
Sprintf(locStr, "%c - %s", (menuChar ? menuChar : ' '), inStr);
|
|
str = locStr;
|
|
HLock ((char**)aWin->menuInfo);
|
|
HLock ((char**)aWin->menuSelected);
|
|
(*aWin->menuSelected)[aWin->miLen] = preselected;
|
|
item = &(*aWin->menuInfo)[aWin->miLen];
|
|
aWin->miLen++;
|
|
item->id = *any;
|
|
item->accelerator = menuChar;
|
|
item->groupAcc = groupAcc;
|
|
item->line = aWin->y_size;
|
|
HUnlock ((char**)aWin->menuInfo);
|
|
HUnlock ((char**)aWin->menuSelected);
|
|
} else
|
|
str = inStr;
|
|
|
|
putstr (win, attr, str);
|
|
}
|
|
|
|
|
|
/*
|
|
* End a menu in this window, window must a type NHW_MENU.
|
|
* str is a list of cancel characters (values that may be input)
|
|
* morestr is a prompt to display, rather than the default.
|
|
* str and morestr might be ignored by some ports.
|
|
*/
|
|
void
|
|
mac_end_menu (winid win, const char *morestr) {
|
|
Str255 buf;
|
|
NhWindow *aWin = &theWindows [win];
|
|
|
|
buf [0] = 0;
|
|
if (morestr)
|
|
C2P (morestr, buf);
|
|
SetWTitle (aWin->its_window, buf);
|
|
}
|
|
|
|
|
|
int
|
|
mac_select_menu (winid win, int how, menu_item **selected_list) {
|
|
int c;
|
|
NhWindow *aWin = &theWindows [win];
|
|
WindowPtr theWin = aWin->its_window;
|
|
|
|
inSelect = win;
|
|
|
|
mac_display_nhwindow (win, FALSE);
|
|
|
|
aWin->how = (short) how;
|
|
for (;;) {
|
|
c = map_menu_cmd (mac_nhgetch());
|
|
if (c == CHAR_ESC) {
|
|
/* deselect everything */
|
|
aWin->miSelLen = 0;
|
|
break;
|
|
} else if (ClosingWindowChar(c)) {
|
|
break;
|
|
} else {
|
|
nhbell();
|
|
}
|
|
}
|
|
|
|
HideWindow (theWin);
|
|
|
|
if (aWin->miSelLen) {
|
|
menu_item *mp;
|
|
MacMHMenuItem *mi;
|
|
*selected_list = mp = (menu_item *) alloc(aWin->miSelLen * sizeof(menu_item));
|
|
HLock ((char**)aWin->menuInfo);
|
|
HLock ((char**)aWin->menuSelected);
|
|
for (c = 0; c < aWin->miSelLen; c++) {
|
|
mi = &(*aWin->menuInfo)[(*aWin->menuSelected) [c]];
|
|
mp->item = mi->id;
|
|
mp->count = -1L;
|
|
mp++;
|
|
}
|
|
HUnlock ((char**)aWin->menuInfo);
|
|
HUnlock ((char**)aWin->menuSelected);
|
|
} else
|
|
*selected_list = 0;
|
|
|
|
inSelect = WIN_ERR;
|
|
|
|
return aWin->miSelLen;
|
|
}
|
|
|
|
#include "dlb.h"
|
|
|
|
static void
|
|
mac_display_file (name, complain)
|
|
const char *name; /* not ANSI prototype because of boolean parameter */
|
|
boolean complain;
|
|
{
|
|
Ptr buf;
|
|
int win;
|
|
dlb *fp = dlb_fopen(name, "r");
|
|
|
|
if (fp) {
|
|
long l = dlb_fseek(fp, 0, SEEK_END);
|
|
(void) dlb_fseek(fp, 0, 0L);
|
|
buf = NewPtr(l+1);
|
|
if (buf) {
|
|
l = dlb_fread(buf, 1, l, fp);
|
|
if (l > 0) {
|
|
buf[l] = '\0';
|
|
win = create_nhwindow(NHW_TEXT);
|
|
if (WIN_ERR == win) {
|
|
if (complain) error ("Cannot make window.");
|
|
} else {
|
|
putstr(win, 0, buf);
|
|
display_nhwindow(win, FALSE);
|
|
}
|
|
}
|
|
DisposePtr(buf);
|
|
}
|
|
dlb_fclose(fp);
|
|
} else if (complain)
|
|
error("Cannot open %s.", name);
|
|
}
|
|
|
|
|
|
void
|
|
port_help () {
|
|
display_file (PORT_HELP, TRUE);
|
|
}
|
|
|
|
|
|
static void
|
|
mac_unimplemented (void) {
|
|
}
|
|
|
|
|
|
static void
|
|
mac_suspend_nhwindows (const char *foo) {
|
|
#if defined(__SC__) || defined(__MRC__)
|
|
# pragma unused(foo)
|
|
#endif
|
|
/* Can't really do that :-) */
|
|
}
|
|
|
|
|
|
int
|
|
try_key_queue (char *bufp) {
|
|
if (keyQueueCount) {
|
|
char ch;
|
|
for (ch = GetFromKeyQueue(); ; ch = GetFromKeyQueue()) {
|
|
if (ch == CHAR_LF || ch == CHAR_CR)
|
|
ch = 0;
|
|
*bufp++ = ch;
|
|
if (ch == 0)
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Base window
|
|
*/
|
|
|
|
static void
|
|
BaseClick(NhWindow *wind, Point pt, UInt32 modifiers)
|
|
{
|
|
pt.h = pt.h / wind->char_width + 1;
|
|
pt.v = pt.v / wind->row_height;
|
|
clicked_mod = (modifiers & shiftKey) ? CLICK_2 : CLICK_1;
|
|
|
|
if (strchr(topl_resp, *click_to_cmd(pt.h, pt.v, clicked_mod)))
|
|
nhbell();
|
|
else {
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
if (cursor_locked)
|
|
while (WaitMouseUp())
|
|
/*SystemTask()*/;
|
|
#endif
|
|
|
|
gClickedToMove = TRUE;
|
|
clicked_pos = pt;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
BaseCursor(NhWindow *wind, Point pt)
|
|
{
|
|
char *dir_bas, *dir;
|
|
CursHandle ch;
|
|
|
|
|
|
if (cursor_locked)
|
|
dir = (char *)0;
|
|
else {
|
|
dir_bas = (char *)Cmd.dirchars;
|
|
dir = strchr(dir_bas, *click_to_cmd(pt.h / wind->char_width + 1 ,
|
|
pt.v / wind->row_height, CLICK_1));
|
|
}
|
|
ch = GetCursor(dir ? dir - dir_bas + 513 : 512);
|
|
if (ch) {
|
|
HLock((Handle) ch);
|
|
SetCursor(*ch);
|
|
HUnlock((Handle) ch);
|
|
} else {
|
|
SetCursor(&qdarrow);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
static pascal OSStatus
|
|
BaseEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
|
|
{
|
|
NhWindow *wind = (NhWindow *) userdata;
|
|
|
|
|
|
switch (GetEventClass(event)) {
|
|
case kEventClassKeyboard: {
|
|
char ch;
|
|
UInt32 modifiers;
|
|
|
|
|
|
GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL,
|
|
sizeof(char), NULL, &ch);
|
|
GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
|
|
sizeof(UInt32), NULL, &modifiers);
|
|
if (modifiers & cmdKey)
|
|
return (eventNotHandledErr);
|
|
AddToKeyQueue(topl_resp_key(ch), TRUE);
|
|
return (noErr);
|
|
}
|
|
|
|
case kEventClassMouse: {
|
|
CGrafPtr saveport;
|
|
GDHandle savedev;
|
|
Point pt;
|
|
|
|
switch (GetEventKind(event)) {
|
|
case kEventMouseMoved:
|
|
GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
|
|
NULL, sizeof(Point), NULL, &pt);
|
|
GetGWorld(&saveport, &savedev);
|
|
SetPortWindowPort(wind->its_window);
|
|
GlobalToLocal(&pt);
|
|
SetGWorld(saveport, savedev);
|
|
BaseCursor(wind, pt);
|
|
return (eventNotHandledErr);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case kEventClassWindow:
|
|
switch (GetEventKind(event)) {
|
|
case kEventWindowDrawContent:
|
|
CallNextEventHandler(nexthandler, event);
|
|
image_tty(NULL, wind->its_window);
|
|
return (noErr);
|
|
|
|
case kEventWindowHandleContentClick: {
|
|
CGrafPtr saveport;
|
|
GDHandle savedev;
|
|
Point pt;
|
|
UInt32 modifiers;
|
|
|
|
GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
|
|
NULL, sizeof(Point), NULL, &pt);
|
|
GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
|
|
sizeof(UInt32), NULL, &modifiers);
|
|
GetGWorld(&saveport, &savedev);
|
|
SetPortWindowPort(wind->its_window);
|
|
GlobalToLocal(&pt);
|
|
SetGWorld(saveport, savedev);
|
|
BaseClick(wind, pt, modifiers);
|
|
return (noErr);
|
|
}
|
|
|
|
case kEventWindowClose:
|
|
/* TODO... */
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return (eventNotHandledErr);
|
|
}
|
|
|
|
#else
|
|
|
|
static void
|
|
macClickTerm (EventRecord *theEvent, WindowPtr theWindow) {
|
|
Point where = theEvent->where;
|
|
|
|
GlobalToLocal(&where);
|
|
BaseClick(GetNhWin(theWindow), where, theEvent->modifiers);
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
macCursorTerm (EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn) {
|
|
GrafPtr gp;
|
|
Point where = theEvent->where;
|
|
Rect r = {0, 0, 1, 1};
|
|
|
|
|
|
GetPort(&gp);
|
|
SetPortWindowPort(theWindow);
|
|
GlobalToLocal(&where);
|
|
BaseCursor(GetNhWin(theWindow), where);
|
|
OffsetRect(&r, theEvent->where.h, theEvent->where.v);
|
|
RectRgn(mouseRgn, &r);
|
|
SetPort(gp);
|
|
return;
|
|
}
|
|
|
|
#endif /* !TARGET_API_MAC_CARBON */
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Status subwindow
|
|
*/
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Map subwindow
|
|
*/
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Message window
|
|
*/
|
|
|
|
static void
|
|
MsgClick(NhWindow *wind, Point pt)
|
|
{
|
|
int r_idx = 0;
|
|
|
|
|
|
while (topl_resp[r_idx]) {
|
|
Rect frame;
|
|
topl_resp_rect(r_idx, &frame);
|
|
InsetRect(&frame, 1, 1);
|
|
if (PtInRect(pt, &frame)) {
|
|
Boolean in_btn = true;
|
|
|
|
InvertRect(&frame);
|
|
while (WaitMouseUp()) {
|
|
#if !TARGET_API_MAC_CARBON
|
|
SystemTask();
|
|
#endif
|
|
GetMouse(&pt);
|
|
if (PtInRect(pt, &frame) != in_btn) {
|
|
in_btn = !in_btn;
|
|
InvertRect(&frame);
|
|
}
|
|
}
|
|
if (in_btn) {
|
|
InvertRect(&frame);
|
|
AddToKeyQueue (topl_resp [r_idx], 1);
|
|
}
|
|
return;
|
|
|
|
}
|
|
++r_idx;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
MsgUpdate(NhWindow *wind)
|
|
{
|
|
RgnHandle org_clip = NewRgn(), clip = NewRgn();
|
|
Rect r;
|
|
int l;
|
|
|
|
|
|
GetClip(org_clip);
|
|
GetWindowBounds(wind->its_window, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
|
|
DrawControls(wind->its_window);
|
|
DrawGrowIcon(wind->its_window);
|
|
|
|
for (l = 0; topl_resp[l]; l++) {
|
|
StringPtr name;
|
|
unsigned char tmp[2];
|
|
FontInfo font;
|
|
Rect frame;
|
|
topl_resp_rect(l, &frame);
|
|
switch (topl_resp[l]) {
|
|
case 'y':
|
|
name = "\pyes";
|
|
break;
|
|
case 'n':
|
|
name = "\pno";
|
|
break;
|
|
case 'N':
|
|
name = "\pNone";
|
|
break;
|
|
case 'a':
|
|
name = "\pall";
|
|
break;
|
|
case 'q':
|
|
name = "\pquit";
|
|
break;
|
|
case CHAR_ANY:
|
|
name = "\pany key";
|
|
break;
|
|
default:
|
|
tmp[0] = 1;
|
|
tmp[1] = topl_resp[l];
|
|
name = tmp;
|
|
break;
|
|
}
|
|
TextFont(kFontIDGeneva);
|
|
TextSize(9);
|
|
GetFontInfo(&font);
|
|
MoveTo ((frame.left + frame.right - StringWidth(name)) / 2,
|
|
(frame.top + frame.bottom + font.ascent-font.descent-font.leading-1) / 2);
|
|
DrawString(name);
|
|
PenNormal();
|
|
if (l == topl_def_idx)
|
|
PenSize(2, 2);
|
|
FrameRoundRect(&frame, 4, 4);
|
|
}
|
|
|
|
r.right -= SBARWIDTH;
|
|
r.bottom -= SBARHEIGHT;
|
|
/* Clip to the portrect - scrollbar/growicon *before* adjusting the rect
|
|
to be larger than the size of the window (!) */
|
|
RectRgn(clip, &r);
|
|
SectRgn(clip, org_clip, clip);
|
|
if (r.right < MIN_RIGHT)
|
|
r.right = MIN_RIGHT;
|
|
r.top -= wind->scrollPos * wind->row_height;
|
|
|
|
#if 0
|
|
/* If you enable this band of code (and disable the next band), you will get
|
|
fewer flickers but a slower performance while drawing the dot line. */
|
|
{ RgnHandle dotl_rgn = NewRgn();
|
|
Rect dotl;
|
|
dotl.left = r.left;
|
|
dotl.right = r.right;
|
|
dotl.bottom = r.top + aWin->save_lin * aWin->row_height;
|
|
dotl.top = dotl.bottom - 1;
|
|
FillRect(&dotl, &qd.gray);
|
|
RectRgn(dotl_rgn, &dotl);
|
|
DiffRgn(clip, dotl_rgn, clip);
|
|
DisposeRgn(dotl_rgn);
|
|
SetClip(clip);
|
|
}
|
|
#endif
|
|
|
|
if (in_topl_mode()) {
|
|
RgnHandle topl_rgn = NewRgn();
|
|
Rect topl_r = r;
|
|
topl_r.top += (wind->y_size - 1) * wind->row_height;
|
|
l = (*top_line)->destRect.right - (*top_line)->destRect.left;
|
|
(*top_line)->viewRect = topl_r;
|
|
(*top_line)->destRect = topl_r;
|
|
if (l != topl_r.right - topl_r.left)
|
|
TECalText(top_line);
|
|
TEUpdate(&topl_r, top_line);
|
|
RectRgn(topl_rgn, &topl_r);
|
|
DiffRgn(clip, topl_rgn, clip);
|
|
DisposeRgn(topl_rgn);
|
|
SetClip(clip);
|
|
}
|
|
|
|
DisposeRgn(clip);
|
|
|
|
TextFont (wind->font_number);
|
|
TextSize (wind->font_size);
|
|
HLock (wind->windowText);
|
|
TETextBox (*wind->windowText, wind->windowTextLen, &r, teJustLeft);
|
|
HUnlock (wind->windowText);
|
|
|
|
#if !TARGET_API_MAC_CARBON
|
|
r.bottom = r.top + aWin->save_lin * aWin->row_height;
|
|
r.top = r.bottom - 1;
|
|
FillRect(&r, (void *) &qd.gray);
|
|
#endif
|
|
|
|
SetClip(org_clip);
|
|
DisposeRgn(org_clip);
|
|
return;
|
|
}
|
|
|
|
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
static pascal OSStatus
|
|
MsgEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
|
|
{
|
|
NhWindow *wind = (NhWindow *) userdata;
|
|
|
|
|
|
switch (GetEventClass(event)) {
|
|
case kEventClassControl: {
|
|
ControlRef control;
|
|
ControlID id;
|
|
|
|
switch (GetEventKind(event)) {
|
|
case kEventControlHit:
|
|
GetEventParameter(event, kEventParamDirectObject,
|
|
typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
|
|
GetControlID(control, &id);
|
|
/* TODO... */
|
|
return (noErr);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case kEventClassKeyboard: {
|
|
char ch;
|
|
UInt32 modifiers;
|
|
|
|
|
|
GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL,
|
|
sizeof(char), NULL, &ch);
|
|
GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
|
|
sizeof(UInt32), NULL, &modifiers);
|
|
if (modifiers & cmdKey)
|
|
return (eventNotHandledErr);
|
|
AddToKeyQueue(topl_resp_key(ch), TRUE);
|
|
return (noErr);
|
|
}
|
|
|
|
case kEventClassWindow:
|
|
switch (GetEventKind(event)) {
|
|
case kEventWindowDrawContent:
|
|
CallNextEventHandler(nexthandler, event);
|
|
MsgUpdate(wind);
|
|
return (noErr);
|
|
|
|
case kEventWindowHandleContentClick: {
|
|
CGrafPtr saveport;
|
|
GDHandle savedev;
|
|
Point pt;
|
|
|
|
GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
|
|
NULL, sizeof(Point), NULL, &pt);
|
|
GetGWorld(&saveport, &savedev);
|
|
SetPortWindowPort(wind->its_window);
|
|
GlobalToLocal(&pt);
|
|
SetGWorld(saveport, savedev);
|
|
MsgClick(wind, pt);
|
|
return (noErr);
|
|
}
|
|
|
|
case kEventWindowClose:
|
|
/* TODO... */
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return (eventNotHandledErr);
|
|
}
|
|
|
|
#else
|
|
|
|
static void
|
|
macClickMessage (EventRecord *theEvent, WindowPtr theWindow) {
|
|
Point mouse = theEvent->where;
|
|
|
|
GlobalToLocal(&mouse);
|
|
MsgClick(GetNhWin(theWindow), mouse);
|
|
macClickText(theEvent, theWindow);
|
|
}
|
|
|
|
|
|
static short
|
|
macUpdateMessage (EventRecord *theEvent, WindowPtr theWindow)
|
|
{
|
|
if (!theEvent)
|
|
return 0;
|
|
MsgUpdate(GetNhWin(theWindow));
|
|
return 0;
|
|
}
|
|
|
|
#endif /* !TARGET_API_MAC_CARBON */
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Menu windows
|
|
*/
|
|
|
|
static void
|
|
MenwKey(NhWindow *wind, char ch)
|
|
{
|
|
MacMHMenuItem *mi;
|
|
int i;
|
|
|
|
|
|
ch = filter_scroll_key(ch, wind);
|
|
if (!ch)
|
|
return;
|
|
if (ClosingWindowChar(ch)) {
|
|
AddToKeyQueue(CHAR_CR, 1);
|
|
return;
|
|
}
|
|
|
|
if (!wind || !wind->menuInfo)
|
|
return;
|
|
HLock((char**)wind->menuInfo);
|
|
for (i = 0, mi = *wind->menuInfo; i < wind->miLen; i++, mi++) {
|
|
if (mi->accelerator == ch) {
|
|
ToggleMenuListItemSelected (wind, i);
|
|
if (mi->line >= wind->scrollPos && mi->line <= wind->y_size) {
|
|
SetPortWindowPort(wind->its_window);
|
|
ToggleMenuSelect(wind, mi->line - wind->scrollPos);
|
|
}
|
|
/* Dismiss window if only picking one item */
|
|
if (wind->how != PICK_ANY)
|
|
AddToKeyQueue(CHAR_CR, 1);
|
|
break;
|
|
}
|
|
}
|
|
HUnlock ((char**)wind->menuInfo);
|
|
/* add key if didn't find it in menu and not filtered */
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
MenwClick(NhWindow *wind, Point pt)
|
|
{
|
|
Rect wrect;
|
|
|
|
|
|
GetWindowBounds(wind->its_window, kWindowContentRgn, &wrect);
|
|
OffsetRect(&wrect, -wrect.left, -wrect.top);
|
|
if (inSelect != WIN_ERR && wind->how != PICK_NONE) {
|
|
short currentRow = -1, previousRow = -1;
|
|
short previousItem = -1, item = -1;
|
|
Boolean majorSelectState, firstRow = TRUE;
|
|
|
|
do {
|
|
#if !TARGET_API_MAC_CARBON
|
|
SystemTask ();
|
|
#endif
|
|
GetMouse (&pt);
|
|
currentRow = pt.v / wind->row_height;
|
|
if (pt.h < wrect.left || pt.h > wrect.right ||
|
|
pt.v < 0 || pt.v > wrect.bottom || currentRow >= wind->y_size) {
|
|
continue; /* not in window range */
|
|
}
|
|
|
|
item = ListCoordinateToItem(wind, currentRow);
|
|
|
|
if (item != previousItem) {
|
|
/* Implement typical Mac multiple-selection behavior
|
|
* (ie, not the UI implemented by the Finder)
|
|
*/
|
|
Boolean itemIsSelected = (ListItemSelected(wind,item) >= 0);
|
|
|
|
if (firstRow) {
|
|
/* this is first valid row, so major state is opposite of what this row is */
|
|
majorSelectState = !itemIsSelected;
|
|
firstRow = FALSE;
|
|
}
|
|
|
|
if (wind->how == PICK_ONE && previousItem != -1) {
|
|
/* if previous row was selected and we're only selecting one object,
|
|
* deselect previous row!
|
|
*/
|
|
ToggleMenuListItemSelected(wind, previousItem);
|
|
ToggleMenuSelect(wind, previousRow);
|
|
previousItem = -1;
|
|
}
|
|
|
|
if (item == -1)
|
|
continue; /* header line */
|
|
|
|
if (majorSelectState != itemIsSelected) {
|
|
ToggleMenuListItemSelected(wind, item);
|
|
ToggleMenuSelect(wind, currentRow);
|
|
}
|
|
|
|
previousRow = currentRow;
|
|
previousItem = item;
|
|
}
|
|
} while (StillDown());
|
|
|
|
/* Dismiss window if only picking one item */
|
|
if (wind->how == PICK_ONE)
|
|
AddToKeyQueue(CHAR_CR, 1);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
MenwUpdate(NhWindow *wind)
|
|
{
|
|
int i, line;
|
|
MacMHMenuItem *mi;
|
|
|
|
|
|
TextUpdate(wind);
|
|
HLock((Handle) wind->menuInfo);
|
|
HLock((Handle) wind->menuSelected);
|
|
for (i = 0; i < wind->miSelLen; i++) {
|
|
mi = &(*wind->menuInfo)[(*wind->menuSelected)[i]];
|
|
line = mi->line;
|
|
if (line > wind->scrollPos && line <= wind->y_size)
|
|
ToggleMenuSelect(wind, line - wind->scrollPos);
|
|
}
|
|
HUnlock((Handle) wind->menuInfo);
|
|
HUnlock((Handle) wind->menuSelected);
|
|
return;
|
|
}
|
|
|
|
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
static pascal OSStatus
|
|
MenwEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
|
|
{
|
|
NhWindow *wind = (NhWindow *) userdata;
|
|
|
|
|
|
switch (GetEventClass(event)) {
|
|
case kEventClassControl: {
|
|
ControlRef control;
|
|
ControlID id;
|
|
|
|
switch (GetEventKind(event)) {
|
|
case kEventControlHit:
|
|
GetEventParameter(event, kEventParamDirectObject,
|
|
typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
|
|
GetControlID(control, &id);
|
|
/* TODO... */
|
|
return (noErr);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case kEventClassKeyboard: {
|
|
char ch;
|
|
UInt32 modifiers;
|
|
|
|
|
|
GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL,
|
|
sizeof(char), NULL, &ch);
|
|
GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
|
|
sizeof(UInt32), NULL, &modifiers);
|
|
if (modifiers & cmdKey)
|
|
return (eventNotHandledErr);
|
|
MenwKey(wind, ch);
|
|
return (noErr);
|
|
}
|
|
|
|
case kEventClassWindow:
|
|
switch (GetEventKind(event)) {
|
|
case kEventWindowDrawContent:
|
|
CallNextEventHandler(nexthandler, event);
|
|
MenwUpdate(wind);
|
|
return (noErr);
|
|
|
|
case kEventWindowHandleContentClick: {
|
|
CGrafPtr saveport;
|
|
GDHandle savedev;
|
|
Point pt;
|
|
|
|
GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
|
|
NULL, sizeof(Point), NULL, &pt);
|
|
GetGWorld(&saveport, &savedev);
|
|
SetPortWindowPort(wind->its_window);
|
|
GlobalToLocal(&pt);
|
|
SetGWorld(saveport, savedev);
|
|
MenwClick(wind, pt);
|
|
return (noErr);
|
|
}
|
|
|
|
case kEventWindowClose:
|
|
/* TODO... */
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return (eventNotHandledErr);
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
static void
|
|
macKeyMenu (EventRecord *theEvent, WindowPtr theWindow) {
|
|
MenwKey(GetNhWin(theWindow), theEvent->message & 0xff);
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
macClickMenu (EventRecord *theEvent, WindowRef theWindow) {
|
|
Point p;
|
|
NhWindow *aWin = GetNhWin(theWindow);
|
|
|
|
|
|
if (aWin->scrollBar && IsControlVisible(aWin->scrollBar)) {
|
|
short code;
|
|
ControlHandle theBar;
|
|
|
|
p = theEvent->where;
|
|
GlobalToLocal (&p);
|
|
code = FindControl (p, theWindow, &theBar);
|
|
if (code) {
|
|
DoScrollBar (p, code, theBar, aWin);
|
|
return;
|
|
}
|
|
}
|
|
MenwClick(aWin, theEvent->where);
|
|
}
|
|
|
|
|
|
static short
|
|
macUpdateMenu (EventRecord *theEvent, WindowPtr theWindow) {
|
|
MenwUpdate(GetNhWin(theWindow));
|
|
return 0;
|
|
}
|
|
|
|
#endif /* !TARGET_API_MAC_CARBON */
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Text windows
|
|
*/
|
|
|
|
static void
|
|
TextKey(NhWindow *wind, char ch)
|
|
{
|
|
ch = filter_scroll_key(ch, wind);
|
|
if (!ch)
|
|
return;
|
|
if (inSelect == WIN_ERR && ClosingWindowChar(ch)) {
|
|
HideWindow (wind->its_window);
|
|
mac_destroy_nhwindow(wind - theWindows);
|
|
} else
|
|
AddToKeyQueue(topl_resp_key(ch), TRUE);
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
TextUpdate(NhWindow *wind)
|
|
{
|
|
Rect r, r2;
|
|
RgnHandle h;
|
|
Boolean vis;
|
|
|
|
|
|
GetWindowBounds(wind->its_window, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
r2 = r;
|
|
r2.left = r2.right - SBARWIDTH;
|
|
r2.right += 1;
|
|
r2.top -= 1;
|
|
vis = (r2.bottom > r2.top + 50);
|
|
|
|
draw_growicon_vert_only(wind->its_window);
|
|
DrawControls(wind->its_window);
|
|
|
|
h = (RgnHandle) 0;
|
|
if (vis && (h = NewRgn())) {
|
|
RgnHandle tmp = NewRgn();
|
|
if (!tmp) {
|
|
DisposeRgn(h);
|
|
h = (RgnHandle) 0;
|
|
} else {
|
|
GetClip(h);
|
|
RectRgn(tmp, &r2);
|
|
DiffRgn(h, tmp, tmp);
|
|
SetClip(tmp);
|
|
DisposeRgn(tmp);
|
|
}
|
|
}
|
|
if (r.right < MIN_RIGHT)
|
|
r.right = MIN_RIGHT;
|
|
r.top -= wind->scrollPos * wind->row_height;
|
|
r.right -= SBARWIDTH;
|
|
HLock(wind->windowText);
|
|
TETextBox(*wind->windowText, wind->windowTextLen, &r, teJustLeft);
|
|
HUnlock(wind->windowText);
|
|
if (h) {
|
|
SetClip(h);
|
|
DisposeRgn(h);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
static pascal OSStatus
|
|
TextEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
|
|
{
|
|
NhWindow *wind = (NhWindow *) userdata;
|
|
|
|
|
|
switch (GetEventClass(event)) {
|
|
case kEventClassControl: {
|
|
ControlRef control;
|
|
ControlID id;
|
|
|
|
switch (GetEventKind(event)) {
|
|
case kEventControlHit:
|
|
GetEventParameter(event, kEventParamDirectObject,
|
|
typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
|
|
GetControlID(control, &id);
|
|
/* TODO... */
|
|
return (noErr);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case kEventClassKeyboard: {
|
|
char ch;
|
|
UInt32 modifiers;
|
|
|
|
|
|
GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL,
|
|
sizeof(char), NULL, &ch);
|
|
GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
|
|
sizeof(UInt32), NULL, &modifiers);
|
|
if (modifiers & cmdKey)
|
|
return (eventNotHandledErr);
|
|
TextKey(wind, ch);
|
|
return (noErr);
|
|
}
|
|
|
|
case kEventClassWindow:
|
|
switch (GetEventKind(event)) {
|
|
case kEventWindowDrawContent:
|
|
CallNextEventHandler(nexthandler, event);
|
|
TextUpdate(wind);
|
|
return (noErr);
|
|
|
|
case kEventWindowClose:
|
|
/* TODO... */
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return (eventNotHandledErr);
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
static void
|
|
macKeyText (EventRecord *theEvent, WindowPtr theWindow) {
|
|
TextKey(GetNhWin(theWindow), theEvent->message & 0xff);
|
|
return;
|
|
}
|
|
|
|
static void
|
|
macClickText (EventRecord *theEvent, WindowPtr theWindow) {
|
|
NhWindow *aWin = GetNhWin (theWindow);
|
|
|
|
if (aWin->scrollBar && IsControlVisible(aWin->scrollBar)) {
|
|
short code;
|
|
Point p = theEvent->where;
|
|
ControlHandle theBar;
|
|
|
|
GlobalToLocal (&p);
|
|
code = FindControl (p, theWindow, &theBar);
|
|
if (code) {
|
|
DoScrollBar (p, code, theBar, aWin);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* !TARGET_API_MAC_CARBON */
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Global events
|
|
*/
|
|
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
static pascal OSStatus
|
|
GlobalEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
|
|
{
|
|
switch (GetEventClass(event)) {
|
|
case kEventClassCommand:
|
|
return (eventNotHandledErr);
|
|
}
|
|
return (eventNotHandledErr);
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
static short
|
|
macDoNull (EventRecord *theEvent, WindowPtr theWindow) {
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Note; theWindow may very well be null here, since keyDown may call
|
|
* it when theres no window !!!
|
|
*/
|
|
/* NOT_IN_CARBON */
|
|
static void
|
|
GeneralKey (EventRecord *theEvent, WindowPtr theWindow) {
|
|
#if defined(__SC__) || defined(__MRC__)
|
|
# pragma unused(theWindow)
|
|
#endif
|
|
#if 0
|
|
trans_num_keys (theEvent);
|
|
#endif
|
|
AddToKeyQueue (topl_resp_key (theEvent->message & 0xff), TRUE);
|
|
}
|
|
|
|
|
|
static void
|
|
HandleKey (EventRecord *theEvent) {
|
|
WindowPtr theWindow = FrontWindow ();
|
|
|
|
if (theEvent->modifiers & cmdKey) {
|
|
if (theEvent->message & 0xff == '.') {
|
|
/* Flush key queue */
|
|
keyQueueCount = keyQueueWrite = keyQueueRead = 0;
|
|
theEvent->message = '\033';
|
|
goto dispatchKey;
|
|
} else {
|
|
UndimMenuBar ();
|
|
DoMenuEvt (MenuKey (theEvent->message & 0xff));
|
|
}
|
|
} else {
|
|
|
|
dispatchKey :
|
|
if (theWindow) {
|
|
int kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
|
|
winKeyFuncs [kind] (theEvent, theWindow);
|
|
} else {
|
|
GeneralKey (theEvent, (WindowPtr) 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* !TARGET_API_MAC_CARBON */
|
|
|
|
|
|
static void
|
|
HandleClick (EventRecord *theEvent) {
|
|
int code;
|
|
unsigned long l;
|
|
WindowPtr theWindow;
|
|
NhWindow *aWin;
|
|
Rect r;
|
|
Boolean not_inSelect;
|
|
|
|
InsetRect(GetRegionBounds(GetGrayRgn(), &r), 4, 4);
|
|
|
|
code = FindWindow (theEvent->where, &theWindow);
|
|
aWin = GetNhWin (theWindow);
|
|
not_inSelect = (inSelect == WIN_ERR || aWin - theWindows == inSelect);
|
|
|
|
switch (code) {
|
|
case inContent :
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
if (not_inSelect) {
|
|
int kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
|
|
winCursorFuncs [kind] (theEvent, theWindow, gMouseRgn);
|
|
SelectWindow (theWindow);
|
|
SetPortWindowPort(theWindow);
|
|
winClickFuncs [kind] (theEvent, theWindow);
|
|
} else {
|
|
nhbell ();
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case inDrag :
|
|
if (not_inSelect) {
|
|
SetCursor(&qdarrow);
|
|
DragWindow (theWindow, theEvent->where, &r);
|
|
SaveWindowPos(theWindow);
|
|
} else {
|
|
nhbell ();
|
|
}
|
|
break;
|
|
|
|
case inGrow :
|
|
if (not_inSelect) {
|
|
SetCursor(&qdarrow);
|
|
SetRect (&r, 80, 2 * aWin->row_height + 1, r.right, r.bottom);
|
|
if (aWin == theWindows + WIN_MESSAGE)
|
|
r.top += SBARHEIGHT;
|
|
l = GrowWindow (theWindow, theEvent->where, &r);
|
|
SizeWindow (theWindow, l & 0xffff, l >> 16, FALSE);
|
|
SaveWindowSize(theWindow);
|
|
SetPortWindowPort(theWindow);
|
|
GetWindowBounds(theWindow, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
InvalWindowRect(theWindow, &r);
|
|
if (aWin->scrollBar) {
|
|
DrawScrollbar (aWin);
|
|
}
|
|
} else {
|
|
nhbell ();
|
|
}
|
|
break;
|
|
|
|
case inGoAway :
|
|
WindowGoAway(theEvent, theWindow);
|
|
break;
|
|
|
|
case inMenuBar :
|
|
DoMenuEvt (MenuSelect (theEvent->where));
|
|
break;
|
|
|
|
#if !TARGET_API_MAC_CARBON
|
|
case inSysWindow :
|
|
SystemClick(theEvent, theWindow);
|
|
#endif
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
|
|
static short
|
|
GeneralUpdate (EventRecord *theEvent, WindowPtr theWindow) {
|
|
if (!theEvent)
|
|
return 0;
|
|
TextUpdate(GetNhWin(theWindow));
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
static void
|
|
HandleUpdate (EventRecord *theEvent) {
|
|
WindowPtr theWindow = (WindowPtr) theEvent->message;
|
|
NhWindow *aWin = GetNhWin (theWindow);
|
|
Rect r;
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
EventRecord fake;
|
|
#endif
|
|
|
|
|
|
char existing_update_region = FALSE;
|
|
Rect rect;
|
|
|
|
if (theWindow == _mt_window) {
|
|
existing_update_region = (get_invalid_region (theWindow, &rect) == noErr);
|
|
}
|
|
BeginUpdate (theWindow);
|
|
SetPortWindowPort(theWindow);
|
|
GetWindowBounds(theWindow, kWindowContentRgn, &r);
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
EraseRect(&r);
|
|
#if 0//TARGET_API_MAC_CARBON
|
|
switch (GetWindowKind(theWindow) - WIN_BASE_KIND) {
|
|
case NHW_BASE:
|
|
case NHW_MAP:
|
|
case NHW_STATUS:
|
|
image_tty(NULL, theWindow);
|
|
break;
|
|
case NHW_MESSAGE:
|
|
MsgUpdate(GetNhWin(theWindow));
|
|
break;
|
|
case NHW_MENU:
|
|
MenwUpdate(GetNhWin(theWindow));
|
|
break;
|
|
case NHW_TEXT:
|
|
TextUpdate(GetNhWin(theWindow));
|
|
break;
|
|
}
|
|
#else
|
|
winUpdateFuncs[GetWindowKind(theWindow) - WIN_BASE_KIND](&fake, theWindow);
|
|
#endif
|
|
|
|
if (theWindow == _mt_window && existing_update_region) {
|
|
set_invalid_region (theWindow, &rect);
|
|
}
|
|
aWin->drawn = TRUE;
|
|
EndUpdate (theWindow);
|
|
}
|
|
|
|
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
|
|
static void
|
|
GeneralCursor (EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn) {
|
|
#if defined(__SC__) || defined(__MRC__)
|
|
# pragma unused(theWindow)
|
|
#endif
|
|
Rect r = {-1, -1, 2, 2};
|
|
|
|
SetCursor(&qdarrow);
|
|
OffsetRect (&r, theEvent->where.h, theEvent->where.v);
|
|
RectRgn (mouseRgn, &r);
|
|
}
|
|
|
|
|
|
static void
|
|
DoOsEvt (EventRecord *theEvent) {
|
|
WindowRef win;
|
|
short code;
|
|
|
|
if ((theEvent->message & 0xff000000) == 0xfa000000) {
|
|
/* Mouse Moved */
|
|
|
|
code = FindWindow (theEvent->where, &win);
|
|
if (code != inContent) {
|
|
Rect r = {-1, -1, 2, 2};
|
|
|
|
SetCursor(&qdarrow);
|
|
OffsetRect (&r, theEvent->where.h, theEvent->where.v);
|
|
RectRgn (gMouseRgn, &r);
|
|
} else {
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
int kind = GetWindowKind(win) - WIN_BASE_KIND;
|
|
if (kind >= 0 && kind <= NHW_TEXT) {
|
|
winCursorFuncs [kind] (theEvent, win, gMouseRgn);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* !TARGET_API_MAC_CARBON */
|
|
|
|
|
|
void
|
|
HandleEvent (EventRecord *theEvent) {
|
|
switch (theEvent->what) {
|
|
#if 1//!TARGET_API_MAC_CARBON
|
|
case autoKey:
|
|
case keyDown:
|
|
HandleKey(theEvent);
|
|
break;
|
|
#endif
|
|
case updateEvt:
|
|
HandleUpdate(theEvent);
|
|
break;
|
|
case mouseDown:
|
|
HandleClick(theEvent);
|
|
break;
|
|
#if !TARGET_API_MAC_CARBON
|
|
case diskEvt:
|
|
if ((theEvent->message & 0xffff0000) != 0) {
|
|
Point p = {150, 150};
|
|
(void) DIBadMount(p, theEvent->message);
|
|
}
|
|
break;
|
|
#endif
|
|
#if !TARGET_API_MAC_CARBON
|
|
case osEvt:
|
|
DoOsEvt(theEvent);
|
|
break;
|
|
#endif
|
|
case kHighLevelEvent:
|
|
AEProcessAppleEvent(theEvent);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Interface definition, for windows.c
|
|
*/
|
|
|
|
struct window_procs mac_procs = {
|
|
"mac",
|
|
WC_COLOR | WC_HILITE_PET |
|
|
WC_FONT_MAP | WC_FONT_MENU | WC_FONT_MESSAGE | WC_FONT_STATUS | WC_FONT_TEXT |
|
|
WC_FONTSIZ_MAP | WC_FONTSIZ_MENU | WC_FONTSIZ_MESSAGE | WC_FONTSIZ_STATUS | WC_FONTSIZ_TEXT,
|
|
0L,
|
|
mac_init_nhwindows,
|
|
mac_unimplemented, /* see macmenu.c:mac_askname() for player selection */
|
|
mac_askname,
|
|
mac_get_nh_event,
|
|
mac_exit_nhwindows,
|
|
mac_suspend_nhwindows,
|
|
mac_unimplemented,
|
|
mac_create_nhwindow,
|
|
mac_clear_nhwindow,
|
|
mac_display_nhwindow,
|
|
mac_destroy_nhwindow,
|
|
mac_curs,
|
|
mac_putstr,
|
|
genl_putmixed,
|
|
mac_display_file,
|
|
mac_start_menu,
|
|
mac_add_menu,
|
|
mac_end_menu,
|
|
mac_select_menu,
|
|
genl_message_menu,
|
|
mac_unimplemented,
|
|
mac_get_nh_event,
|
|
mac_get_nh_event,
|
|
#ifdef CLIPPING
|
|
mac_cliparound,
|
|
#endif
|
|
#ifdef POSITIONBAR
|
|
donull,
|
|
#endif
|
|
tty_print_glyph,
|
|
tty_raw_print,
|
|
tty_raw_print_bold,
|
|
mac_nhgetch,
|
|
mac_nh_poskey,
|
|
tty_nhbell,
|
|
mac_doprev_message,
|
|
mac_yn_function,
|
|
mac_getlin,
|
|
mac_get_ext_cmd,
|
|
mac_number_pad,
|
|
mac_delay_output,
|
|
#ifdef CHANGE_COLOR
|
|
tty_change_color,
|
|
tty_change_background,
|
|
set_tty_font_name,
|
|
tty_get_color_string,
|
|
#endif
|
|
/* other defs that really should go away (they're tty specific) */
|
|
0, // mac_start_screen,
|
|
0, // mac_end_screen,
|
|
genl_outrip,
|
|
genl_preference_update,
|
|
genl_can_suspend_no,
|
|
};
|
|
|
|
/*macwin.c*/
|