home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Carousel
/
CAROUSEL.cdr
/
mactosh
/
fonts
/
fontshow.sit
/
Menus.Pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-09-14
|
21KB
|
406 lines
UNIT Menus(4);
(* This unit contains menu handling routines for the FontShow program *)
(* Version 1.0 by Richard Clark, September 1988 *)
(* Version 1.1, September 13, 1988 -- Modified the Copy command so that it gets a new picture *)
(* each time Copy is selected instead of using the old WindowPict. Fixed the *)
(* field that specifies what type is being placed into the scrap -- using a *)
(* Pascal string was getting it confused. Also added a TEXT item to the scrap *)
(* containing the entire ASCII character set. *)
{$U-}
{$D+}
INTERFACE
{$U Globals}
{$U Windows}
USES
MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf,
Globals, Windows;
PROCEDURE InitMyMenus; (* Construct our menus and choose an initial font and size *)
PROCEDURE AdjustMenus (forceRedraw : Boolean); (* Hilight our menus according to the type of the frontmost window *)
PROCEDURE DoMenus (menuCode : LONGINT); (* Process a keypress or MouseDown in the menus *)
PROCEDURE SetFontMenu; (* Set the chack mark to our current font *)
PROCEDURE SetSizeMenu; (* Show the sizes available in our current font *)
IMPLEMENTATION
CONST
mApple = 128; (* Apple Menu *)
iaAbout = 1;
mFile = 129; (* File Menu *)
ifNew = 1;
ifClose = 2;
{ ------- }
ifQuit = 4;
mEdit = 130; (* Edit Menu *)
ieUndo = 1;
{ ------- }
ieCut = 3;
ieCopy = 4;
iePaste = 5;
ieClear = 6;
mFont = 131; (* Font Menu *)
(* Items to be added *)
mSize = 132; (* Size Menu *)
(* We don't use item numbers here since we'll use *)
(* the point sizes in the menu directly. You can *)
(* add other sizes directly by editing the menu *)
(* and re-compiling. *)
VAR
AppleMenu,
FileMenu,
EditMenu,
FontMenu,
SizeMenu : MenuHandle; (* Our menus *)
menuState : INTEGER; (* For which kind of window are the menus currently set? *)
PROCEDURE InitMyMenus;
(* This procedure loads in our menus and sets them to their initial state *)
BEGIN
AppleMenu := GetMenu(mApple); (* Load the Apple Menu *)
AddResMenu(AppleMenu, 'DRVR'); (* Append our list of desk accessories *)
InsertMenu(AppleMenu, 0); (* And append this to the menu bar *)
FileMenu := GetMenu(mFile); (* Load the File menu *)
InsertMenu(FIleMenu, 0);
EditMenu := GetMenu(mEdit); (* Load the Edit menu *)
InsertMenu(EditMenu, 0);
FontMenu := GetMenu(mFont); (* Load the (empty) Font menu *)
AddResMenu(FontMenu, 'FONT'); (* Ask the system to append a list of the available fonts *)
InsertMenu(FontMenu, 0);
SizeMenu := GetMenu(mSize); (* Load the Size menu *)
InsertMenu(SizeMenu, 0);
menuState := 0; (* The menus need to have their initial states set-up *)
DrawMenuBar; (* AdjustMenus expects that the menu bar has already been drawn *)
SetFontMenu; (* Put a check-mark by the current font *)
SetSizeMenu; (* Show which sizes of the current font are available *)
AdjustMenus(TRUE); (* Adjust the menus and force a redraw of the menu bar *)
END; (* InitMyMenus *)
PROCEDURE AdjustMenus;
(* Set up our menus according to which window is in front. The settings are: *)
(* *)
(* -- Window in front -- *)
(* Menu | No Windows | Font Window | About Window | Desk Accessory | *)
(* ------+---------------+---------------+----------------+-----------------| *)
(* Apple | Enabled | Enabled | Enabled | Enabled | *)
(* ------+---------------+---------------+----------------+-----------------| *)
(* File | Open & Quit | Enabled | Enabled | Enabled | *)
(* | are Enabled, | | | | *)
(* | Close is | | | | *)
(* | Disabled | | | | *)
(* ------+---------------+---------------+----------------+-----------------| *)
(* Edit | Disabled | Only "Copy" | Disabled | Enabled | *)
(* | | is Enabled | | | *)
(* ------+---------------+---------------+----------------+-----------------| *)
(* Font | Disabled | Enabled | Disabled | Disabled | *)
(* ------+---------------+---------------+----------------+-----------------| *)
(* Size | Disabled | Enabled | Disabled | Disabled | *)
(* ------+---------------+---------------+----------------+-----------------| *)
(* *)
CONST
NoWindows = 0; (* Codes which represent our current window state *)
FontWindowUp = 1;
AboutWindowUp = 2;
DeskAccUp = 3;
VAR
inFront : WindowPeek; (* The current frontmost window *)
lastState : INTEGER; (* The current state of our menus *)
BEGIN
lastState := menuState; (* record the last activation state of the menus *)
inFront := WindowPeek(FrontWindow); (* Get the front window *)
SetFontMenu; (* Place a check mark by the current font *)
SetSizeMenu; (* Mark off the currently available sizes *)
IF (inFront = NIL) THEN (* No windows are up *)
BEGIN
menuState := NoWindows;
DisableItem(FileMenu, ifClose); (* (the rest of the file menu is always enabled) *)
DisableItem(EditMenu, 0); (* This disables the whole menu *)
DisableItem(FontMenu, 0);
DisableItem(SizeMenu, 0);
END ELSE (* We have at least one window open *)
BEGIN
EnableItem(FileMenu, ifClose); (* Allow the user to close it from the File menu *)
IF (inFront^.refCon = wFont) THEN
BEGIN (* This is a Font window *)
menuState := FontWindowUp;
EnableItem(FontMenu, 0); (* Turn on the Font and Size Menus *)
EnableItem(SizeMenu, 0);
EnableItem(EditMenu, 0); (* Enable the Edit menu, and disable all items but "Copy" *)
DisableItem(EditMenu, ieUndo);
DisableItem(EditMenu, 2);
DisableItem(EditMenu, ieCut);
DisableItem(EditMenu, iePaste);
DisableItem(EditMenu, ieClear);
END ELSE (* It's a DA or the About window, *)
BEGIN (* so turn off the Font and Size menus *)
DisableItem(FontMenu, 0);
DisableItem(SizeMenu, 0);
IF (inFront^.windowKind < 0) THEN
BEGIN (* This is a desk accessory, *)
menuState := DeskAccUp; (* so supply the Edit menu *)
EnableItem(EditMenu, 0);
DisableItem(EditMenu, ieUndo); (* Turn on everything except the dividing line *)
DisableItem(EditMenu, 2);
EnableItem(EditMenu, ieCut);
EnableItem(EditMenu, ieCopy);
EnableItem(EditMenu, iePaste);
EnableItem(EditMenu, ieClear);
END ELSE
BEGIN (* If it's the About window, supply only the File menu *)
menuState := AboutWindowUp;
DisableItem(EditMenu, 0);
END;
END; (* We have a DA or the About window *)
END; (* else (inFront <> nil )*)
IF (menuState <> lastState) OR (forceRedraw) THEN
DrawMenuBar; (* Redraw if we've made some changes, or if we're told to *)
(* (we'll need to force a redraw if the current font or *)
(* font size is changed, otherwise the change won't be *)
(* displayed *)
END; (* AdjustMenus *)
PROCEDURE DoMenus;
(* This procedure takes the LONGINT value returned by MenuSelect and MenuKey, parses out the *)
(* requested menu and item numbers, then takes the appropriate action. *)
VAR
inMenu, (* The currently selected menu *)
inItem : INTEGER; (* The currently selected item *)
PROCEDURE DoAppleMenu (inItem : INTEGER);
(* This procedure processes requestds in the Apple menu *)
VAR
oldPort : GrafPtr; (* These are used when opening a Desk Accessory *)
DAName : Str255;
scratch : INTEGER;
BEGIN
IF (inItem = iaAbout) THEN (* The user select "About FontShow╔" *)
DoAbout (* Open the "About" window *)
ELSE
BEGIN (* The user chose a Desk Accessory *)
GetPort(oldPort); (* Save and restore the current GrafPort as some *)
(* Desk Accessories change the port and forget *)
(* to set it back. *)
GetItem(AppleMenu, inItem, DAName); (* Get the text of the selected menu item *)
scratch := OpenDeskAcc(DAName); (* Open the Desk Accessory. Scratch is the DA's *)
IF (scratch = 0) THEN (* reference number (if the open was successful),*)
SysBeep(5); (* or 0 if the open failed. *)
SetPort(oldPort); (* restore our GrafPort *)
END;
AdjustMenus(FALSE); (* Update the Menus, but don't force a redraw *)
END; (* DoAppleMenu *)
PROCEDURE DoFileMenu (inItem : INTEGER);
(* This procedure handles requests in the File menu *)
BEGIN
CASE inItem OF
ifNew : OpenAWindow; (* Open a new Font window using the current Font and Size values *)
ifClose : BEGIN
CloseAWindow(FrontWindow); (* Close the frontmost window *)
AdjustMenus(FALSE); (* And update the menus to reflect our new state *)
END;
ifQuit : Quit := TRUE; (* Tell the main loop that we are done *)
END; (* CASE *)
END; (* DoFileMenu *)
PROCEDURE DoEditMenu (inItem : INTEGER);
(* This procedure handles requests in the Edit menu *)
VAR
inFront : WindowPeek;
gridPict : PicHandle;
scrapErr : LONGINT;
scrapLen : LONGINT;
pType,
tType : resType;
allChars : Str255;
count : INTEGER;
BEGIN
IF (SystemEdit(inItem - 1) = FALSE) THEN (* Try to have the Desk Manager handle it *)
BEGIN (* Sorry, it must be a request for the application *)
inFront := WindowPeek(FrontWindow); (* Get the current window, so we can Copy its picture *)
IF (inItem = ieCopy) THEN (* We only accept Copy commands *)
BEGIN
IF (inFront^.refCon = wFont) THEN (* ...and only if it's a Font window *)
BEGIN
gridPict := CreateFontPict(inFront^.port.txFont, inFront^.port.txSize);
if (gridPict <> nil) THEN
BEGIN
scrapLen := ORD(GetHandleSize(Handle(gridPict))); (* Calculate the size of our picture *)
scrapErr := ZeroScrap; (* Erase the old entries in the clipboard *)
IF ((scrapErr = noErr) (* If we cleared out the Clipboard, and we have *)
AND (scrapLen <> 0)) THEN (* something to put in it, then... *)
BEGIN
HLock(Handle(gridPict)); (* Lock down our picture *)
PType[1] := 'P';
PType[2] := 'I';
PType[3] := 'C';
PType[4] := 'T';
scrapErr := PutScrap(scrapLen, pType, Ptr(gridPict^)); (* and place it into the clipboard *)
HUnlock(Handle(gridPict));(* Unlock our picture *)
{$R- Turn off range checking. (Warning -- Do not try this at home!)}
FOR count := 0 TO 255 DO
allChars[count] := CHR(count);
{$R+}
tType[1] := 'T';
tType[2] := 'E';
tType[3] := 'X';
tType[4] := 'T';
scrapErr := PutScrap(256, tType, @allChars); (* Add the same information as a text string *)
END;
KillPicture(gridPict);
END;
END;
END; (* if this is a COPY command *)
END; (* IF *)
END; (* DoEditMenu *)
PROCEDURE DoFontMenu (inItem : INTEGER);
(* This procedure handles requests in the Font menu *)
VAR
fName : Str255; (* The name of the selected font *)
fNum : integer; (* The number of the selected font *)
BEGIN
GetItem(FontMenu, inItem, fName); (* Get the text of the selected menu item *)
GetFNum(fName, fNum); (* Convert it to a font number *)
currFont := fNum; (* Set our font number to this *)
AttachWindowPict(WindowPeek(FrontWindow)); (* Replace the picture on the frontmost window *)
(* with a picture of the selected font. *)
AdjustMenus(TRUE); (* Update the menus (including the checkmark in *)
(* the Font menu and the information in the Size*)
(* menu) and redraw the menus (to show the changes) *)
END; (* DoFontMenu *)
PROCEDURE DoSizeMenu (inItem : integer);
(* This procedure handles requests in the Size menu *)
VAR
sizeString : Str255; (* The text of the selected item *)
scratch : LONGINT; (* The new size *)
count : INTEGER; (* Used when isolating the size number -- see below *)
BEGIN
GetItem(SizeMenu, inItem, sizeString); (* Get the selected text *)
INSERT(' ', sizeString, length(sizeString) + 1); (* Append a space *)
(* Since the entries in the Size menu are of the *)
(* form "<size> points", we need to search for *)
(* the first <space> character and delete every- *)
(* thing from that point forward. We appended *)
(* the spece (above) to guarantee that if the *)
(* menus are ever changed to numbers only, we *)
(* would still find something. *)
count := 1;
WHILE (sizeString[count] <> ' ') DO (* Scan for the first space character *)
count := count + 1;
DELETE(sizeString, count, length(sizeString) - count + 1); (* Get rid of everything from the *)
(* space to the end of the string (including the *)
(* space itself. *)
StringToNum(sizeString, scratch); (* Convert the new string (number only) into a *)
(* number. Since StringToNum wants a LONGINT, *)
(* we'll supply one. *)
currSize := scratch; (* Set the current size global *)
AttachWindowPict(WindowPeek(FrontWindow)); (* Change the frontmost window's PICT to reflect *)
(* the new size *)
AdjustMenus(TRUE); (* And update the size menu to match, forcing a *)
(* redraw when done. *)
END; (* DoSizeMenu *)
BEGIN (* DoMenus *)
IF (menuCode <> 0) THEN (* Only do this if the user selected an active item *)
BEGIN
inMenu := HiWord(menuCode); (* Extract the Menu and Item codes *)
inItem := LoWord(menuCode);
CASE inMenu OF (* Dispatch the menu request *)
mApple : DoAppleMenu(inItem);
mFile : DoFileMenu(inItem);
mEdit : DoEditMenu(inItem);
mFont : DoFontMenu(inItem);
mSize : DoSizeMenu(inItem);
END; (* CASE *)
END;
HiliteMenu(0); (* Un-hilite the selected menu *)
END; (* DoMenus *)
PROCEDURE SetFontMenu;
(* This procedure sets the checkmark in the Font menu to point to the currently selected font *)
VAR
fName, (* The current font's name *)
itemString : Str255; (* The text of the menu item being examined *)
numItems, (* How many entries are in this menu? *)
itemCount : INTEGER; (* Loop control *)
BEGIN
GetFontName(currFont, fName); (* Get the name of the current font *)
numItems := CountMItems(FontMenu);
FOR itemCount := 1 TO numItems DO (* Compare the name to each item in the Font *)
BEGIN (* menu, and place a checkmark if they match *)
GetItem(FontMenu, itemCount, itemString); (* Otherwise, remove any checkmark that may exist *)
CheckItem(FontMenu, itemCount, itemString = fName);
END;
END; (* SetFontMenu *)
PROCEDURE SetSizeMenu;
(* This procedure sets the entries in the size menu to reflect the available sizes of the current *)
(* font. It also places a checkmark by the currently selected size. *)
VAR
itemString : Str255; (* The menu item being examined *)
numItems, (* How many items are in our menu? *)
itemCount : INTEGER; (* Loop control *)
count : INTEGER; (* Used when scanning for a space *)
scratch : LONGINT; (* Used by StringToNum *)
BEGIN
numItems := CountMItems(SizeMenu);
FOR itemCount := 1 TO numItems DO (* For each entry in the Size menu... *)
BEGIN
GetItem(SizeMenu, itemCount, itemString); (* Get the item *)
(* Extract the number from the string (as in DoSizeMenu) *)
INSERT(' ', itemString, length(itemString) + 1);
count := 1;
WHILE (itemString[count] <> ' ') DO
count := count + 1;
DELETE(itemString, count, length(itemString) - count + 1);
StringToNum(itemString, scratch); (* Convert the string to a number *)
IF RealFont(currFont, scratch) THEN (* If this font exists at this size, *)
SetItemStyle(SizeMenu, itemCount, [outline]) (* then outline it in the menu. *)
ELSE
SetItemStyle(SizeMenu, itemCount, []); (* Otherwise, make it plain *)
CheckItem(SizeMenu, itemCount, scratch = currSize); (* Place a checkmark here if it's the *)
END; (* current size. Otherwise, remove any checkmark *)
END; (* SetSizeMenu *)
END.