338 lines
7.1 KiB
C
338 lines
7.1 KiB
C
|
/*
|
|||
|
* tkMacMenus.c --
|
|||
|
*
|
|||
|
* These calls set up and manage the menubar for the
|
|||
|
* Macintosh version of Tk.
|
|||
|
*
|
|||
|
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
|
|||
|
*
|
|||
|
* See the file "license.terms" for information on usage and redistribution
|
|||
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|||
|
*
|
|||
|
* SCCS: @(#) tkMacMenus.c 1.27 96/09/05 11:21:55
|
|||
|
*/
|
|||
|
|
|||
|
#include "tcl.h"
|
|||
|
#include "tclMacInt.h"
|
|||
|
#include "tk.h"
|
|||
|
#include "tkInt.h"
|
|||
|
#include "tkMacInt.h"
|
|||
|
|
|||
|
/*
|
|||
|
* The define Status defined by Xlib.h conflicts with the function Status
|
|||
|
* defined by Devices.h. We undefine it here to compile.
|
|||
|
*/
|
|||
|
#undef Status
|
|||
|
#include <Devices.h>
|
|||
|
#include <Menus.h>
|
|||
|
#include <Memory.h>
|
|||
|
#include <SegLoad.h>
|
|||
|
#include <StandardFile.h>
|
|||
|
#include <ToolUtils.h>
|
|||
|
|
|||
|
#define kAppleMenu 256
|
|||
|
#define kAppleAboutItem 1
|
|||
|
#define kFileMenu 2
|
|||
|
#define kEditMenu 3
|
|||
|
|
|||
|
#define kSourceItem 1
|
|||
|
#define kCloseItem 2
|
|||
|
#define kQuitItem 4
|
|||
|
|
|||
|
#define EDIT_CUT 1
|
|||
|
#define EDIT_COPY 2
|
|||
|
#define EDIT_PASTE 3
|
|||
|
#define EDIT_CLEAR 4
|
|||
|
|
|||
|
static Tcl_Interp * gInterp; /* Interpreter for this application. */
|
|||
|
static MenuHandle gAppleM; /* Handles to menus */
|
|||
|
static MenuHandle gFileM; /* Handles to menus */
|
|||
|
static MenuHandle gEditM; /* Handles to menus */
|
|||
|
|
|||
|
Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin, int rootX,
|
|||
|
int rootY, int *newX, int *newY));
|
|||
|
static void GenerateEditEvent _ANSI_ARGS_((int flag));
|
|||
|
static void SourceDialog _ANSI_ARGS_((void));
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* TkMacHandleMenuSelect --
|
|||
|
*
|
|||
|
* Handles events that occur in the Menu bar.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
TkMacHandleMenuSelect(mResult, optionKeyPressed)
|
|||
|
long mResult;
|
|||
|
int optionKeyPressed;
|
|||
|
{
|
|||
|
short theItem = LoWord(mResult);
|
|||
|
short theMenu = HiWord(mResult);
|
|||
|
Str255 name;
|
|||
|
Tk_Window tkwin;
|
|||
|
Window window;
|
|||
|
|
|||
|
if (mResult == 0) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
switch (theMenu) {
|
|||
|
|
|||
|
case kAppleMenu:
|
|||
|
switch (theItem) {
|
|||
|
case kAppleAboutItem:
|
|||
|
{
|
|||
|
Tcl_CmdInfo dummy;
|
|||
|
|
|||
|
if (optionKeyPressed || gInterp == NULL ||
|
|||
|
Tcl_GetCommandInfo(gInterp,
|
|||
|
"tkAboutDialog", &dummy) == 0) {
|
|||
|
TkAboutDlg();
|
|||
|
} else {
|
|||
|
Tcl_Eval(gInterp, "tkAboutDialog");
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
default:
|
|||
|
GetItem(gAppleM, theItem, name);
|
|||
|
HiliteMenu(0);
|
|||
|
OpenDeskAcc(name);
|
|||
|
return;
|
|||
|
}
|
|||
|
break;
|
|||
|
case kFileMenu:
|
|||
|
switch (theItem) {
|
|||
|
case kSourceItem:
|
|||
|
/* TODO: source script */
|
|||
|
SourceDialog();
|
|||
|
break;
|
|||
|
case kCloseItem:
|
|||
|
/* Send close event */
|
|||
|
window = TkMacGetXWindow(FrontWindow());
|
|||
|
tkwin = Tk_IdToWindow(tkDisplayList->display, window);
|
|||
|
TkGenWMDestroyEvent(tkwin);
|
|||
|
break;
|
|||
|
case kQuitItem:
|
|||
|
/* Exit */
|
|||
|
if (optionKeyPressed || gInterp == NULL) {
|
|||
|
Tcl_Exit(0);
|
|||
|
} else {
|
|||
|
Tcl_Eval(gInterp, "exit");
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
case kEditMenu:
|
|||
|
/*
|
|||
|
* This implementation just send keysyms
|
|||
|
* the Tk thinks are associated with function keys that
|
|||
|
* do Cut, Copy & Paste on a Sun keyboard.
|
|||
|
*/
|
|||
|
GenerateEditEvent(theItem);
|
|||
|
break;
|
|||
|
default:
|
|||
|
/*
|
|||
|
* This will eventually evoke Tcl scripts
|
|||
|
* TODO: come up with frame work for this...
|
|||
|
*/
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Finally we unhighlight the menu.
|
|||
|
*/
|
|||
|
HiliteMenu(0);
|
|||
|
} /* TkMacHandleMenuSelect */
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* TkMacInitMenus --
|
|||
|
*
|
|||
|
* This procedure initializes the Macintosh menu bar.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
TkMacInitMenus(interp)
|
|||
|
Tcl_Interp *interp;
|
|||
|
{
|
|||
|
Handle mbarH;
|
|||
|
|
|||
|
gInterp = interp;
|
|||
|
|
|||
|
/*
|
|||
|
* At this point, InitMenus() should have already been called.
|
|||
|
*/
|
|||
|
|
|||
|
mbarH = (Handle) GetMenuBar();
|
|||
|
if (mbarH == NULL) {
|
|||
|
panic("memory - menu bar");
|
|||
|
}
|
|||
|
|
|||
|
gAppleM = NewMenu(256, "\p\024");
|
|||
|
if (gAppleM == NULL) {
|
|||
|
panic("memory - menus");
|
|||
|
}
|
|||
|
InsertMenu(gAppleM, 0);
|
|||
|
AppendMenu(gAppleM, "\pAbout Tcl & Tk<54>");
|
|||
|
AppendMenu(gAppleM, "\p(-");
|
|||
|
AddResMenu(gAppleM, 'DRVR');
|
|||
|
|
|||
|
gFileM = NewMenu(kFileMenu, "\pFile");
|
|||
|
if (gFileM == NULL) {
|
|||
|
panic("memory - menus");
|
|||
|
}
|
|||
|
InsertMenu(gFileM, 0);
|
|||
|
AppendMenu(gFileM, "\pSource<EFBFBD>");
|
|||
|
AppendMenu(gFileM, "\pClose/W");
|
|||
|
AppendMenu(gFileM, "\p(-");
|
|||
|
AppendMenu(gFileM, "\pQuit/Q");
|
|||
|
|
|||
|
gEditM = NewMenu(kEditMenu, "\pEdit");
|
|||
|
if (gEditM == NULL) {
|
|||
|
panic("memory - menus");
|
|||
|
}
|
|||
|
InsertMenu(gEditM, 0);
|
|||
|
AppendMenu(gEditM, "\pCut/X");
|
|||
|
AppendMenu(gEditM, "\pCopy/C");
|
|||
|
AppendMenu(gEditM, "\pPaste/V");
|
|||
|
AppendMenu(gEditM, "\pClear");
|
|||
|
|
|||
|
DrawMenuBar();
|
|||
|
|
|||
|
DisposeHandle(mbarH);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* GenerateEditEvent --
|
|||
|
*
|
|||
|
* Takes an edit menu item and posts the corasponding a virtual
|
|||
|
* event to Tk's event queue.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* May place events of queue.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
static void
|
|||
|
GenerateEditEvent(flag)
|
|||
|
int flag;
|
|||
|
{
|
|||
|
XVirtualEvent event;
|
|||
|
Point where;
|
|||
|
Tk_Window tkwin;
|
|||
|
|
|||
|
/*
|
|||
|
* We send the event to the focus window.
|
|||
|
*/
|
|||
|
tkwin = (Tk_Window) tkDisplayList->focusWinPtr;
|
|||
|
if (tkwin == NULL) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
event.type = VirtualEvent;
|
|||
|
event.serial = Tk_Display(tkwin)->request;
|
|||
|
event.send_event = false;
|
|||
|
event.display = Tk_Display(tkwin);
|
|||
|
event.event = Tk_WindowId(tkwin);
|
|||
|
event.root = XRootWindow(Tk_Display(tkwin), 0);
|
|||
|
event.subwindow = None;
|
|||
|
event.time = TkMacGenerateTime();
|
|||
|
|
|||
|
GetMouse(&where);
|
|||
|
tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v,
|
|||
|
&event.x, &event.y);
|
|||
|
LocalToGlobal(&where);
|
|||
|
event.x_root = where.h;
|
|||
|
event.y_root = where.v;
|
|||
|
event.state = TkMacButtonKeyState();
|
|||
|
event.state = 0;
|
|||
|
event.same_screen = true;
|
|||
|
|
|||
|
switch (flag) {
|
|||
|
case EDIT_CUT:
|
|||
|
event.name = Tk_GetUid("Cut");
|
|||
|
break;
|
|||
|
case EDIT_COPY:
|
|||
|
event.name = Tk_GetUid("Copy");
|
|||
|
break;
|
|||
|
case EDIT_PASTE:
|
|||
|
event.name = Tk_GetUid("Paste");
|
|||
|
break;
|
|||
|
case EDIT_CLEAR:
|
|||
|
event.name = Tk_GetUid("Clear");
|
|||
|
break;
|
|||
|
}
|
|||
|
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* SourceDialog --
|
|||
|
*
|
|||
|
* Presents a dialog to the user for selecting a Tcl file. The
|
|||
|
* selected file will be sourced into the main interpreter.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
static void
|
|||
|
SourceDialog()
|
|||
|
{
|
|||
|
StandardFileReply reply;
|
|||
|
OSType fileTypes[1];
|
|||
|
OSErr err;
|
|||
|
int length;
|
|||
|
Handle path;
|
|||
|
|
|||
|
if (gInterp == NULL) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
fileTypes[0] = 'TEXT';
|
|||
|
StandardGetFile(NULL, 1, fileTypes, &reply);
|
|||
|
if (reply.sfGood == false) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
err = FSpPathFromLocation(&reply.sfFile, &length, &path);
|
|||
|
if (err == noErr) {
|
|||
|
HLock(path);
|
|||
|
Tcl_EvalFile(gInterp, *path);
|
|||
|
HUnlock(path);
|
|||
|
DisposeHandle(path);
|
|||
|
}
|
|||
|
}
|