/*
 * $Source: $
 * $Revision: $
 * $Date: $
 * $State: $
 * $Author: $
 *
 *
 * $Log: $
 * Revision 3.1  3/10/92 wade
 * Added Baylor's changes
 * #include documentRec.h and cmd_read_gif_file()
 *
 * Revision 3.3 7/16/92
 * Changed menu_bar_init and menu_adjust to add the
 * FONT_SIZE submenu in the edit menu.
 * Changed menu_do_command to react to FONT_SIZE menu
 *
 * Revision 3.4 8/17/92 - mec
 * Modified menu_adjust to allow for uploading of image files and to disable
 * the close menu selection for the List window
 * Modified menu_do_command to move GIFFILEREAD and add GIFFILESEND
 *
 * modified 9/11/92 - mec
 * Modified menu_adjust to enable uploading of image windows
 * Modified menu_do_command to enable uploading of image windows
 *
 * Revision 3.6 10/8/92 - wade
 * Added menu_month() as a menu pop up
 * Made some menu switchs - removed SHOW item in the Look menu
 *   Moved WORD and AGAIN from the Look menu to the Edit menu
 *   Changed arguments passed for cmd_publish_document()
 *
 * Revision 3.7 10/221/92 - wade
 * Added KIOSK_ITEM to the File menu case statement in menu_do_command
 * Changed menu_adjust() to do enable/disable the quit menu item
 * 
 * Revision 3.10 1/8/93 - wade
 * changed the paste enable/disable function.  Was disabled if menu
 * was a "dynamic" menu (e.g. had no parent owner).  Removed this
 * restriction - did not see any need for it.
 *
 * Revision 4.0b3 2/19/93 - wade
 * Fixed a problem with SHOW_PATH not being enabled for gif items.
 *
 * Modified 4/30/93 - edward
 * Added defines to compile with or without TE32K
 * Incorporated changes that I made to version 4.0b1:
 * Changed the TextEdit calls to TE32K calls and changed various types to long as needed
 *
 * Revision 4.1 6/3/93 - edward
 * Added code to enable and disable Clear menu item in menu_adjust
 * Uncommented code to handle Clear menu item when text window is active in menu_do_command
 * Deleted code to handle Toys menu in menu_do_command
 * Put define for MENU_VIEW in pips.h
 *
 * Revision 4.1 6/7/93 - edward
 * Added code to enable and disable Select All menu item in menu_adjust
 * Added code to handle Select All in menu_do_command
 *
 * Revision 4.1 6/10/93 - edward
 * Moved prototypes.h after TE32K.h so prototypes.h recognizes TE32KHandle
 *
 * Revision 4.1 6/17/93 - edward
 * Check to make sure menuP is not NULL in menu_adjust
 *
 * Revision 4.1 6/24/93 - edward
 * menu_adjust disables the new and open provider items if the text window is open.  It enables them
 *  if the text window isn't
 * Got rid of the code that switched changed the new item to a clear item of the text window was open
 *
 * Revision 4.1b1 7/12/93 - edward
 * Added support for binhex items in menu_adjust.
 *
 * Revision 4.1b3 9/7/93 - edward
 * increased meta from 256 to 1024 chars
 *
 * Revision 4.1b3 10/1/93 - edward
 * Include node.h
 * Changed *_ITEM to node type from node.h
 *
 * Revision 4.1b3 11/12/93 - edward
 * In menu_adjust, when deciding whether to enable paste for when the list window is active
 *  it checks to see that the currently selected item is of type NT_MENU, not 's'
 * In menu_adjust, got rid of item_type.  It now uses type[0] and the new node types
 *
 * Revision 4.1b6 1/19/94 - edward
 * Fixed a bug in menu_adjust that disabled show path in the Look menu.
 *
 * Revision 4.1b8 2/16/94 - edward
 * I disabled the Open menu item when the text window was open which I should not have done.
 * Open is now enable when the text window is displayed as well as when it is not.
 *
 * Revision 4.2WWW 3/7/93 - edward
 * Replaced all references to list, text, gif, and binhex with NT_MENU, NT_ASCII, NT_GIF, 
 *  and NT_BINHEX
 * Added the procedure menu_node, which handles the node type popup.
 * Added the procedure menu_build_node_popup, which builds the node type popup
 *
 * Revision 4.2WWW 4/15/94 - edward
 * generalized the method used to decided whether or not to enable the SHOW_PATH menu item in
 *  menu_adjust
 * SEND_DOCUMENT is enabled if any kind of ascii node is selected
 *
 * Revision 4.2WWW 4/22/94 - edward
 * removed the call to text_clear when CLEAR_DOCUMENT is selected because text_clear is called
 *  in text_show_new_text
 *
 * Revision 4.2a2 5/27/94 - edward
 * menu_node_build_popup defaults to icon 255 instead of 256 if it can't find an icon for a
 *  node type
 *
 * Revision 4.2a3 6/3/94 - edward
 * menu_adjust enables and disables the Send Binhex File menu item in the Provider menu
 *
 * Revision 4.2a3 6/8/94 - edward
 * Included StandardFile
 *
 * Revision 4.2a3 6/9/94 - edward
 * Doesn't include sysequ.h anymore because it's obsolete and I'm using the universal headers
 * Included LowMem.h
 * In menu_adjust, next_window = LMGetWindowList()
 *
 * Revision 4.2a3 6/17/94 - edward
 * Included strings.h and string.h
 *
 * Revision 4.2a3 6/24/94 - edward
 * copy is not enable when NT_TECHINFO or NT_CSO_LIST is selected in menu_adjust
 * disabled Show Path when NT_TECHINFO or NT_CSO_LIST is selected in menu_adjust
 *
 * Revision 4.2a3 6/30/94 - edward
 * Commented out the code that puts icons in the popup menu in menu_build_node_popup
 * In menu_adjust Disable MODIFY_ITEM and REMOVE_ITEM when type NT_TECHINFO or NT_CSO_LIST 
 *  is selected
 *
 * Revision 4.2a4 7/5/94 - edward
 * Porting to MW C/C++ 68K.  The headers are only included if we're not using MW
 */

/*  
 *	Copyright (c) 1991 by the Massachusetts Institute of Technology,
 *	For copying and distribution information, see the file
 *	"mit-copyright.h".
 *
 * 	menuMgr.c  - WADE 8/23/89
 *	
 *	menu_bar_init
 *	menu_adjust
 *	menu_do_command
 *	menu_add
 *	menu_delete
 *
 */
 
// 7/5/94 edward - If we're compiling with MW all of these headers are precompiled in TIFast*
#ifndef __MWERKS__

#include <Limits.h>
#include <Types.h>
#include <QuickDraw.h>
#include <Fonts.h>
#include <Events.h>
#include <Controls.h>
#include <Windows.h>
#include <Menus.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Desk.h>
#include <Scrap.h>
#include <ToolUtils.h>
#include <Memory.h>
#include <SegLoad.h>
#include <Files.h>
#include <OSUtils.h>
#include <Traps.h>
#include <Lists.h>
#include <Resources.h>
#include <StandardFile.h>
#include <LowMem.h>
#include "pips.h" 
#include <stdio.h>
#include <string.h>
#include <Strings.h>
#ifdef TE32K
#include "TE32K.h"
#endif
#include "node.h"
#include "documentRec.h"
#include "prototype.h"

#endif

#include "mit-copyright.h"

extern WindowPtr	gTextWindow;
extern Boolean		gKiosk;
extern short 		node_int;
extern nodeinfo		node_types[];

/*     
 *
 * menu_bar_init:
 * 
 *	called from main program during initialization stage.
 *
 */
void
menu_bar_init(short menuResource)
{
	Handle			menuBar;	
	
	menuBar = GetNewMBar(menuResource);		/* read menus into menu bar */
	if ( menuBar == nil )
				BigBadError(NO_MEMORY);
	SetMenuBar(menuBar);					/* install menus */
	DisposHandle(menuBar);
	AddResMenu(GetMHandle(APPLE), 'DRVR');	/* add DA names to Apple menu */
	
	DrawMenuBar();
}	/* menu_bar_init */

/*     
 *
 *  menu_adjust:
 *
 *	Enable and disable menus based on the current state.
 *	The user can only select enabled menu items. We set up all the menu items
 *	before calling MenuSelect or MenuKey. 
 */
#pragma segment Main 
void menu_adjust(void)
{
	long		offset;
	Boolean		cutCopyClear;
	Boolean		paste;
	Boolean		undo;
#ifdef TE32K
	TE32KHandle	te;
#else
	TEHandle	te;
#endif
	MenuHandle	menuE;
	MenuHandle	menuB;
	MenuHandle	menuF;
	MenuHandle	menuP;
	Boolean		rc;
	Boolean		any_visible;
	Boolean		text_visible;
	Boolean		active_list_item;
	Str255		type;
	Str255		list_buffer;
	Str255		window_title;
	WindowPtr	front_window;
	WindowPtr	next_window;
	WindowPtr	list_window;
	short		ctr;
	short		num_items;
	int			window_type;
	short		sections;
	short		section;
	int			text_size;
	short		active;
	Boolean		owner;
	short		item;
	data_edit	undo_flags;
	wlist	window_list;

	enum{store,retrieve};
	
	front_window = FrontWindow();

	menuE = GetMHandle(EDIT);
	menuB = GetMHandle(BROWSER);
	menuF = GetMHandle(FILEM);
	menuP = GetMHandle(PROVIDER);
		
	/* Determine if there is a visible list or text window in the window list */
	any_visible = false;
	text_visible = false;
	next_window = FrontWindow();
	while( next_window != nil && IsAppWindow(next_window) ) {
		if (wind_visible(next_window)) {
			window_type = wind_type(next_window);
			any_visible = true;
			if (window_type == NT_ASCII)
				text_visible = true;
		}
		next_window = (WindowPtr)wind_next_window(next_window);
	}
		
	/* determine how the current menu was created */
	owner = cmd_menu_owner();

	/* determine if there is a highlighted list item in a visible list window */
	active_list_item = false;
	list_window = wind_find_window(NT_MENU);
	if (list_window != NULL && wind_visible(list_window) ) {
		active_list_item = list_get_list_select(&item);
		if (active_list_item)
			rc = list_last_click_buffer(list_buffer);
	}
						
	EnableItem(menuB,MAIN);
	DisableItem(menuF, CLOSE);
	
	// mec - twiddled with the following code quite thoroughly, to add support
	//	for saving GIF images
	/* is front window invisible */
	if ( !wind_visible(front_window)) {
		DisableItem(menuF, SAVE_TEXT);
		DisableItem(menuF, USERSTARTUP);
		DisableItem(menuE, WORD);
		DisableItem(menuE, AGAIN);
	} else {									// front window is visible
		switch (wind_type(front_window)) {
			case NT_ASCII:							// is it a text window?
				EnableItem(menuF, CLOSE);
			case NT_MENU:							// is it a list window?
				EnableItem(menuF, SAVE_TEXT);
				SetItem(menuF, SAVE_TEXT, "\pSave TextÉ");
				EnableItem(menuF, USERSTARTUP);
				EnableItem(menuE, WORD);
				EnableItem(menuE, AGAIN);
				break;
			case NT_GIF:							// how about a gif?
				EnableItem(menuF, CLOSE);
				EnableItem(menuF, SAVE_TEXT);
				SetItem(menuF, SAVE_TEXT, "\pSave ImageÉ");
				DisableItem(menuF, USERSTARTUP);
				DisableItem(menuE, WORD);
				DisableItem(menuE, AGAIN);
				break;
			default:
				EnableItem(menuF, CLOSE);					// or should we disable???
				DisableItem(menuF, SAVE_TEXT);
				SetItem(menuF, SAVE_TEXT, "\pSave TextÉ");	// not necessary, but maintains current behavior
				DisableItem(menuF, USERSTARTUP);
				DisableItem(menuE, WORD);
				DisableItem(menuE, AGAIN);
				break;
		}	// switch
	}	// else

	if ( wind_visible(front_window) && 
		(wind_type(front_window) == NT_ASCII || wind_type(front_window) == NT_MENU || 
		wind_type(front_window) == getinfo)) {
		EnableItem(menuF, PRINT);

	}
	else
		DisableItem(menuF, PRINT);

	if (gKiosk) {
		DisableItem(menuF, QUIT);
		if (menuP != NULL)				/* edward - Make sure provider menu is there */
			CheckItem(menuP, KIOSK_ITEM, true);
	}
	else {
		EnableItem(menuF, QUIT);
		if (menuP != NULL)				/* edward - Make sure provider menu is there */
			CheckItem(menuP, KIOSK_ITEM, false);
	}
	
	/* remove window list in browser menu, then add the current window list */
 	num_items = CountMItems(menuB);
	for (ctr = num_items; ctr != WINDOW_LIST; ctr--)
		DelMenuItem(menuB,ctr);
		
	ctr = -1;
	next_window = (WindowPtr)LMGetWindowList();		/* TechInfo 4.2a3 - now using LowMem.h */
	while(next_window != nil && IsAppWindow(next_window)) {
		if (wind_visible(next_window) || wind_type(next_window) == NT_MENU) {
			GetWTitle(next_window,&window_title);
			if (window_title[0] > 50) {
				window_title[51] = '.';
				window_title[52] = '.';
				window_title[0] = 52;
			}
		
			window_list.window = next_window;
			if ( wind_type(next_window) == NT_ASCII ) {
			
				data_text_size(retrieve,&text_size);
				data_text_active(retrieve,&active);
				
				/* get the number of text sections */
				if ( text_size > NETWORK_RECEIVE_SIZE )
					/* determine number of sections and change the window name */
					sections = text_size / NETWORK_RECEIVE_SIZE;
				else
					sections = 0;
					
				for (section=0;section<=sections;section++) {
					window_list.section = section;
					AppendMenu(menuB,"\p ");
					if ( sections > 0 )
						sprintf(&window_title[window_title[0]],"%d",section+1);

					SetItem(menuB,CountMItems(menuB),window_title);
					if ((front_window == next_window) && (active == section)) 
						CheckItem(menuB, CountMItems(menuB), true);
					rc = wind_windows_data(store,++ctr,&window_list);
				}
			}
			else {
				window_list.section = 0;	/* not used */
				AppendMenu(menuB,"\p ");
				SetItem(menuB,CountMItems(menuB),window_title);
				rc = wind_windows_data(store,++ctr,&window_list);
			}
				
		}
		
		/* check this menu item if it is this the FrontWindow() */
		if (front_window == next_window && wind_type(next_window) != NT_ASCII)
			CheckItem(menuB, CountMItems(menuB), true);

		next_window = (WindowPtr)wind_next_window(next_window);
	}
				
	if (active_list_item) {
		/* get type of list item */
		rc = get_field(list_buffer,TYPE,type);

		EnableItem(menuF, GETINFO);
		
		/* if there is a selected list item, and the list window is active, then ok */
		DisableItem(menuB,OUTLINE);
		DisableItem(menuB,SHOW_PATH);
		if (wind_type(front_window) == NT_MENU) {
			/* edward 4/15/94 - This used to enable SHOW_PATH for all types known to */
			/* version 4.0.  Now it is more general */
			if (type[0] == NT_MENU)
				EnableItem(menuB,OUTLINE);
			/* edward 6/24/94 - Neither worldwide TI nor CSO list items have paths */
			if (type[0] != NT_TECHINFO && type[0] != NT_CSO_LIST)
				EnableItem(menuB,SHOW_PATH);
		}
		
		if ( menuP != NULL )
		{
			/* edward 6/30/94 - Neither worldwide TI nor CSO list items can be modified */
			if (type[0] != NT_TECHINFO && type[0] != NT_CSO_LIST)
			{
				EnableItem(menuP,MODIFY_ITEM);
				EnableItem(menuP,REMOVE_ITEM);
			}
			
			/* edward - enable SEND_DOCUMENT if the selected node is an ascii type. */
			/* It doesn't matter if it's straight ascii, HTML, binhex, or whatever */
			if (type[1] == ascii && text_visible)
				EnableItem(menuP,SEND_DOCUMENT);
			else if (type[0] == NT_GIF && wind_visible(front_window) && 
				wind_type(front_window) == NT_GIF)
				EnableItem(menuP,SEND_DOCUMENT);
			else
				DisableItem(menuP,SEND_DOCUMENT);
				
			if (type[0] == NT_GIF)
				EnableItem(menuP, GIFFILESEND);
			else
				DisableItem(menuP, GIFFILESEND);

			if (type[0] == NT_BINHEX)				/* 4.2a3 - send binhex file */
				EnableItem(menuP, 15);
			else
				DisableItem(menuP, 15);

		}
		
	}
	else {
		DisableItem(menuF, GETINFO);
		/* DisableItem(menuB, SHOW); */
		DisableItem(menuB, OUTLINE );
		DisableItem(menuB, SHOW_PATH );
		if ( menuP != NULL ) {
			DisableItem(menuP, GIFFILESEND);
			DisableItem(menuP, 15);					/* 4.2a3 - disable send binhex file */
			DisableItem(menuP, MODIFY_ITEM);
			DisableItem(menuP, REMOVE_ITEM);
			DisableItem(menuP, SEND_DOCUMENT);
		}
	}
	
	/* enable/disable provider menu functions which don't depend on a selected cell */
	if ( menuP != NULL ) {
		DisableItem(menuF, PROVIDER_MENU);
		
		if (owner) 
			EnableItem(menuP,DEFINE_MENU_ITEM);
		else
			DisableItem(menuP,DEFINE_MENU_ITEM);
		
		/* edward 2/16/94 - If the text window is already open, disable the new item */
		/* Keep the open item enabled */
		if (text_visible)
			DisableItem(menuP, CLEAR_DOCUMENT);
		else
			EnableItem(menuP, CLEAR_DOCUMENT);
		EnableItem(menuP, OPEN_DOCUMENT);
	}
	else
		EnableItem(menuF, PROVIDER_MENU);
	
	/* is there anything on the "return to previous menu" stack? */
	if (util_check_stack())
		EnableItem(menuB,BACK);
	else
		DisableItem(menuB,BACK);
	
	/* enable/disable undo Edit menu functions */
	cutCopyClear = false;
	paste = false;
	undo = false;
	
	if ( IsDAWindow(front_window) ) {
		/* all editing is enabled for DA windows */
		cutCopyClear = true;
		paste = true;
	} 
	else 
		if ( IsAppWindow(front_window) && ( wind_type(front_window) == NT_ASCII )) {
			te = ((DocumentPeek) front_window)->docTE;
			/* Cut, Copy, and Clear is enabled for app. windows with selections */
			if ( (*te)->selStart < (*te)->selEnd )
				cutCopyClear = true;
			
			/* if thereÕs any text in the clipboard, paste is enabled */
			if ( GetScrap(nil, 'TEXT', &offset) )
				paste = true;			
		}
		else 
			/* enable edit functions for the list window only when in provider mode */
			if (IsAppWindow(front_window) && ( wind_type(front_window) == NT_MENU ) && menuP) {
				/* is there something to undo? */
				data_edits(retrieve,&undo_flags);
				undo = undo_flags.type; 
				
				/* Don't activate copy for Worldwide TI nodes and CSO list nodes */
				if (active_list_item && type[0] != NT_TECHINFO && type[0] != NT_CSO_LIST)
					cutCopyClear = true;
					
				/* did we preform a previous copy or paste and is the selected item a folder */
				/* TechInfo 4.2a3 - paste into the current folder, not the selected one */
				if ((undo_flags.type == edit_copy || undo_flags.type == edit_cut ) &&
					 owner) 
					paste = true;
			}
		
	/*
	if ( undo ) {
		EnableItem(menuE, UNDO);
		switch (undo) {
			case edit_cut:
				SetItem(menuE,UNDO,"\pUndo Cut");
				break;
			case edit_paste:
				SetItem(menuE,UNDO,"\pUndo Paste");
				break;
			case edit_move:
				SetItem(menuE,UNDO,"\pUndo Move");
				break;
			default:
				undo = 0;
				break;
		}
	}
	*/
	
	/* undo does not work yet */
	undo = false;
	
	if (!undo) {
		DisableItem(menuE, UNDO);
		SetItem(menuE,UNDO,"\pUndo");
	}
	
	/* exceptions - can not cut or paste an item that is the result of a search */
	if ( cutCopyClear ) {
		if (owner)
			EnableItem(menuE, CUT);
		else
			DisableItem(menuE, CUT);

		EnableItem(menuE, COPY);
		
/* edward 6/3/92 - support Clear item */
		if ( owner && ( wind_type(front_window) == NT_ASCII ))
			EnableItem(menuE, CLEAR);
		else
			DisableItem(menuE, CLEAR);
/* edward 6/3/92 - end */
	} 
	else {
		DisableItem(menuE, CUT);
		DisableItem(menuE, COPY);
		DisableItem(menuE, CLEAR);				/* edward 6/3/92 support clear item */
	}
	
	/* if ( paste && owner)  */  // we don't care if the menu is an owner menu   wade 1/8/93 
	if ( paste )
		EnableItem(menuE, PASTE);
	else
		DisableItem(menuE, PASTE);	
	
/* edward 6/7/93 - support Select All item */
	if (wind_type(front_window) == NT_ASCII)
		EnableItem(menuE, SELECT_ALL);
	else
		DisableItem(menuE, SELECT_ALL);
/* edward 6/7/93 - end */
} /*menu_adjust*/

/*     
 *
 *  menu_do_command:
 *
 *	This is called when an item is chosen from the menu bar (after calling
 *	MenuSelect or MenuKey). It does the right thing for each command. 
 */
#pragma segment Main 
void menu_do_command(long menuResult)
{
	short		menuID, menuItem;
	short		daRefNum;
	Str255		daName;
	OSErr		saveErr;
#ifdef TE32K
	TE32KHandle	te;
#else
	TEHandle	te;
#endif
	WindowPtr	window;
	Handle		aHandle;
	long		oldSize, newSize;
	long		total, contig;
	char		child_node[NODE_LENGTH];
	MenuHandle	window_handle;
	data_edit	undo_flags;
	
	extern Boolean	gDebug;
	
	window = FrontWindow();
	menuID = HiWord(menuResult);	/* use macros for efficiency to... */
	menuItem = LoWord(menuResult);	/* get menu item number and menu number */
	switch ( menuID ) {
		case APPLE:
			switch ( menuItem ) {
				case ABOUT:		/* bring up alert for About */
					dlog_about();
					break;
				default:			/* all non-About items in this menu are DAs et al */
					GetItem(GetMHandle(APPLE), menuItem, daName);
					daRefNum = OpenDeskAcc(daName);
					break;
			}
			break;
			
		case FILEM:
			switch ( menuItem ) {
				case CLOSE:
					DoCloseWindow(window,hide_window); 
					break;
				case SAVE_TEXT:
					cmd_generic_save(window);
					break;
				case HELP:
					dlog_help();
					break;
				case GETINFO:
					cmd_get_info(NULL);
					break; 
				case PROVIDER_MENU:
					cmd_get_provider();
					break;
				case PREFERENCE:
					PreferenceDialog();
					break;
				case USERSTARTUP:
					cmd_user_startup();
					break;
				case PAGE:
					print_page_dlog();
					break;
				case PRINT:
					print_cmd();
					break;
				case QUIT:
					Terminate();
					break;
			}
			break;
		case EDIT:					/* call SystemEdit for DA editing & MultiFinder */
			if ( !SystemEdit(menuItem-1) ) {
				switch( menuItem ) {
					case WORD:
						cmd_select_word(false);
						break;
					case AGAIN:
						cmd_select_word(true);
						break;
					case MENU_VIEW:
						cmd_menu_view();
						break;
				}

				switch(wind_type(window)) {
					case NT_MENU:
					 	switch (menuItem) {
							case UNDO:
								data_edits(retrieve,&undo_flags);
								switch (undo_flags.type) { 
									case edit_cut:
										cmd_cut_undo();
										break;
									case edit_paste:
										cmd_paste_undo();
										break;
									case edit_move:
										cmd_reorder_undo();
										break;
								}
								break;
							case CUT:
								cmd_unlink_child();
								break;
							case COPY:
								cmd_copy_edit();
								break;
							case PASTE:
								cmd_link_child_edit();
								break;
						}
						break;
					
					case NT_ASCII:
						te = ((DocumentPeek) FrontWindow())->docTE;
						switch ( menuItem ) {
							case UNDO:
								break;
							case CUT:
								if ( ZeroScrap() == noErr ) {
									PurgeSpace(&total, &contig);
									if ((*te)->selEnd - (*te)->selStart + kTESlop > contig)
										AlertUser(NO_SPACE_CUT);
									else {
#ifdef TE32K
										TE32KCut(te);
										if ( TE32KToScrap() != noErr ) {
#else
										TECut(te);
										if ( TEToScrap() != noErr ) {
#endif
											AlertUser(NO_CUT);
											ZeroScrap();
										}
										
									}
								}
								break;
							case COPY:
								if ( ZeroScrap() == noErr ) {
#ifdef TE32K
									TE32KCopy(te);	/* after copying, export the TE scrap */
									if ( TE32KToScrap() != noErr ) {
#else
									TECopy(te);	/* after copying, export the TE scrap */
									if ( TEToScrap() != noErr ) {
#endif
										AlertUser(NO_COPY);
										ZeroScrap();
									}
								}
								break;
							case PASTE:	/* import the TE scrap before pasting */
#ifdef TE32K
								if ( TE32KFromScrap() == noErr ) {
									if ( TE32KGetScrapLen() + ((*te)->teLength -
										((*te)->selEnd - (*te)->selStart)) > kMaxTELength )
										AlertUser(EXCEED_PASTE);
#else
								if ( TEFromScrap() == noErr ) {
									if ( TEGetScrapLen() + ((*te)->teLength -
										((*te)->selEnd - (*te)->selStart)) > kMaxTELength )
										AlertUser(EXCEED_PASTE);
#endif
									else {
#ifdef TE32K
										aHandle = (Handle) TE32KGetText(te);
										oldSize = GetHandleSize(aHandle);
										newSize = oldSize + TE32KGetScrapLen() + kTESlop;
#else
										aHandle = (Handle) TEGetText(te);
										oldSize = GetHandleSize(aHandle);
										newSize = oldSize + TEGetScrapLen() + kTESlop;
#endif
										SetHandleSize(aHandle, newSize);
										saveErr = MemError();
										SetHandleSize(aHandle, oldSize);
										if (saveErr != noErr)
											AlertUser(NO_SPACE_PASTE);
										else {
#ifdef TE32K
											TE32KPaste(te);
#else
											TEPaste(te);
#endif
											untabify(te); /* just in case there were tabs in the paste */
										}
									}
								}
								else
									AlertUser(NO_PASTE);
								break;
							case CLEAR:
#ifdef TE32K
								TE32KDelete(te);
#else
								TEDelete(te);
#endif
								break;
							case SELECT_ALL:
#ifdef TE32K
								TE32KSetSelect(0L, (**te).teLength, te);
#else
								TESetSelect(0, 32767, te);
#endif
								break;
							
						}
						AdjustScrollbars(window, false);
						AdjustTE(window);
					
						break;
					
				}	/* end of the window switch type  */
			} 		/* end of the if (!SystemEdit ... */
			break;
			
		case BROWSER:
			switch ( menuItem ) {
				case MAIN:
					cmd_main_menu();
					break;
				case BACK:
					cmd_back();
					break;
				/*  This has been removed 
				case SHOW:
					rc = cmd_show(NULL);
					break;
				*/
				case OUTLINE:
					cmd_content(true);  /* true = use the default depth setting */
					break;
				case SHOW_PATH:
					cmd_path();
					break;
				case KEYWORD:
					cmd_find(); 
					break;
				case WHATS_NEW:
					cmd_whats_new();
					break;
				default:
					window_handle = GetMHandle(BROWSER);
				 	cmd_show_window(menuItem - WINDOW_LIST - 1);
			}
			break;
			
		case SPECIAL:
			switch ( menuItem ) {
				case DIRECTORY:
					cmd_phone(NULL);
					break;
				case WORLDWIDE:
					cmd_get_other_servers();
					break;
				case UNBINHEX:
					binhex_decode_data(true);			/* unbinhex from file */
					break;
				case BINHEX_FILE:
					binhex_binhex(true);				/* binhex to a file */
					break;
			}
			break;
			
		case PROVIDER:
			switch ( menuItem ) {
				case CLOSE_SESSION:
					cmd_close_provider(true);
					break;
				case DEFINE_MENU_ITEM:
					cmd_define_item();
					break;
				case CLEAR_DOCUMENT:
					/* change banner */
					SetWTitle( gTextWindow,"\pUntitled" );
					text_show_new_text(gTextWindow);
					break;
				case MODIFY_ITEM:
					cmd_modify_item();
					break;
				case REMOVE_ITEM:
					cmd_remove();
					break;
				case OPEN_DOCUMENT:
					cmd_open_document();
					break;
				case SEND_DOCUMENT:
					child_node[0] = '\0'; 
					/* replace document/image for item user last clicked */
					/* we pass null for nodeid and item type so that the called */
					/* routine can determine this info */
					cmd_publish_document(child_node,0);
					break;
				case PROVIDER_OPTIONS:
					cmd_provider_options();
					break;
				case SOURCE_INFO:
					cmd_source_info();
					break;
				case KIOSK_ITEM:
					cmd_kiosk();
					break;
#ifdef GIFSTUFF
				case GIFFILEREAD:
					cmd_read_gif_file(true);
					break;
				case GIFFILESEND:
					child_node[0] = '\0';
					cmd_publish_GIF_file(child_node);
					break;
#endif
				case 15:						/* 4.2a3 - handle Send Binhex File */
					child_node[0] = '\0';
					cmd_publish_binhex_file(child_node);
					break;
			}
			break;
			
	}
									
	HiliteMenu(0);					/* unhighlight what MenuSelect (or MenuKey) hilited */
} /*menu_do_command*/

/*     
 *
 *  menu_add:
 *
 *	This function adds the menu resource provided thru the calling argument
 *	An example of this is adding the provider menu.
 *
 */
void menu_add(int menuRes)
{
	MenuHandle		whatMenu;
	
	whatMenu = GetMenu( menuRes );
	
	/* insert the menu before the provider menu (if it exists), else at the end of the list */
	InsertMenu( whatMenu, PROVIDER );
	
	DrawMenuBar();
}	/* menu_add */

/*     
 *
 *  menu_delete:
 *
 *	This function deletes the menu resource provided thru the calling argument
 *	An example of this is adding the provider menu.
 *
 */
void menu_delete( int menuRes )
{
	MenuHandle	menuHandle;
	
	DeleteMenu( menuRes );
	menuHandle = GetMHandle(menuRes);
	ReleaseResource((Handle)menuHandle);
	DrawMenuBar();
}	/* menu_delete */

/*     
 *
 *  menu_check:
 *
 *	This function check to see if we have the menu already installed.
 */
Boolean menu_check(int menuRes)
{

	MenuHandle	menuHandle;
	
	menuHandle = GetMHandle(menuRes);
	
	return (menuHandle ? true : false);
}

/*     
 *
 *  menu_show_popup:
 *
 *	Display a pop-up menu, used for the history function.
 */
void menu_show_popup(WindowPtr window)
{
	MenuHandle		whatMenu;
	long			menuResult;
	Point			top_left;
	Point			bot_right;
	short			menuItem, menuID;
	short			num_items, ctr;
	MenuHandle		menuPopUp;
	int				stack_items;
	int				rc;
	unsigned char	meta[1024];
	Str255			title;

	whatMenu = GetMenu( POP_UP_MENU );
	
	if (menu_check(POP_UP_MENU) == false)
		InsertMenu(whatMenu, -1);    /* -1 means hierarchical menu */
		
	/* get local coordinates of the window */
	SetPt(&top_left,window->portRect.left,window->portRect.top);
	SetPt(&bot_right,window->portRect.right,window->portRect.bottom);

	/* subtract the banner */
	top_left.v =- (kScrollbarWidth + 1);
	
	/* find start of title in window */
	top_left.h = top_left.h + ((bot_right.h - top_left.h) / 2) - (((WindowPeek) window) -> titleWidth) / 2;

	LocalToGlobal(&top_left);
	LocalToGlobal(&bot_right);

	/* build menu */
/* Revision 4.1 6/14/93 - edward
 * util_get_stack_count doesn't take any arguments!  This line is wrong
	stack_items = util_get_stack_count(0);
 * Here's my version: */
	stack_items = util_get_stack_count();
 	
	menuPopUp = GetMHandle(POP_UP_MENU);
	for (ctr=stack_items; ctr > 0; ctr--) {
		rc = util_get_stack_item(ctr,meta,title);
		if (rc) {
			AppendMenu(menuPopUp,"\p ");
			c2pstr(title);
			SetItem(menuPopUp,CountMItems(menuPopUp),title);
		}
	}
	
	/* highlight the last item in the list as a default */
	menuResult = PopUpMenuSelect(whatMenu,top_left.v,top_left.h,1);
	menuID = HiWord(menuResult);
	menuItem = LoWord(menuResult);
	
	/* bring up the requested window */
	/* don't do anything if the user selected the first item, since */
	/* we are already here */
	if (menuID > 0 && menuItem > 1) {
		/* since the menuitem numbers are in reverse order than the linked list */
		/* map the menu item to the right stack node item */
		menuItem = CountMItems(menuPopUp) - menuItem + 1;
		rc = util_get_stack_item(menuItem,meta,title);
		if (rc) {
			rc = cmd_new_display( meta, command, NT_MENU );
			
			/* think of this as a return to previous menu, decrement the stack */
			for (ctr = 1, menuItem = LoWord(menuResult); ctr < menuItem; ctr++)
				rc = util_pop_stack(meta);
		}
	}
	
	/* cleanup menu list for next call */
	num_items = CountMItems(menuPopUp);
	for (ctr = num_items; ctr > 0; ctr--)
		DelMenuItem(menuPopUp,ctr);

}

/*     
 *
 *  menu_month:
 *
 *	
 */
short menu_month(Point location, short *month_item)
{
	MenuHandle		whatMenu;
	long			menuResult;
	short			menuItem = 0;

	whatMenu = GetMenu( MONTH_MENU );
	
	if (whatMenu == NULL)
		BigBadError(NO_RESOURCE);

	/* add this to our menu list */
	if (menu_check(MONTH_MENU) == false)
		InsertMenu(whatMenu, -1);    /* -1 means hierarchical menu */
			
	/* check the current menu item */
	CheckItem(GetMHandle(MONTH_MENU), *month_item, true);
	
	/* we want the current menu item to overlay our useritem - location */
	location.v = location.v - ((*month_item - 1) * 16);
	
	/* highlight the last item in the list as a default */
	menuResult = PopUpMenuSelect(whatMenu,location.v,location.h,1);
	
	/* uncheck the item */
	CheckItem(GetMHandle(MONTH_MENU), *month_item, false);
	
	if (menuResult) {
		*month_item = LoWord(menuResult);
		menuItem = *month_item;
	}
	
	return(menuItem);
}

/*     
 *
 *  menu_font:
 *
 *	Display font size pop-up menu
 */
short menu_font(Point location, short *font_item)
{
	MenuHandle		whatMenu;
	long			menuResult;
	short			menuItem = 0;
	short			actual_menu_item;

	whatMenu = GetMenu( FONT_SIZE );
	
	if (whatMenu == NULL)
		BigBadError(NO_RESOURCE);

	/* add this to our menu list */
	if (menu_check(FONT_SIZE) == false)
		InsertMenu(whatMenu, -1);    /* -1 means hierarchical menu */
			
	/* let's map the font size to a menu item */
	switch(*font_item) {
		case 9:
			actual_menu_item = 1;
			break;
		case 10:
			actual_menu_item = 2;
			break;
		case 11:
			actual_menu_item = 3;
			break;
		case 12:
			actual_menu_item = 4;
			break;
		case 14:
			actual_menu_item = 5;
			break;
		case 18:
			actual_menu_item = 6;
			break;
		case 24:
			actual_menu_item = 7;
			break;
		case 36:
			actual_menu_item = 8;
			break;
		case 48:
			actual_menu_item = 9;
			break;
	}
	
	/* check the current menu item */
	CheckItem(GetMHandle(FONT_SIZE), actual_menu_item, true);
	
	/* we want the current menu item to overlay our useritem - location */
	location.v = location.v - ((actual_menu_item - 1) * 16);
	
	/* highlight the last item in the list as a default */
	menuResult = PopUpMenuSelect(whatMenu,location.v,location.h,1);
	
	/* uncheck the item */
	CheckItem(GetMHandle(FONT_SIZE), actual_menu_item, false);
	
	if (menuResult) {
		*font_item = LoWord(menuResult);

		/* let's map the font size to a menu item */
		switch(*font_item) {
			case 1:
				menuItem = 9;
				break;
			case 2:
				menuItem = 10;
				break;
			case 3:
				menuItem = 11;
				break;
			case 4:
				menuItem = 12;
				break;
			case 5:
				menuItem = 14;
				break;
			case 6:
				menuItem = 18;
				break;
			case 7:
				menuItem = 24;
				break;
			case 8:
				menuItem = 36;
				break;
			case 9:
				menuItem = 48;
				break;
			defalut:
				menuItem = 12;  /* just in case there is a problem */
				break;
		}
		
		*font_item = menuItem;
	}
	
	return(menuItem);
}

/*     
 *
 *  menu_node
 *
 *  make sure node_item is set correctly before calling this routine
 *
 */
short menu_node(Rect *menuRect, short *node_item, unsigned char node_id)
{
  MenuHandle	whatMenu;
  long			menuResult;
  short			menuItem = 0;
  Point			loc;
  
  whatMenu = menu_build_node_popup(node_id);
  
  if (whatMenu == NULL)
	BigBadError(NO_RESOURCE);   /* need a better message */
  
  /* add this to our menu list */
  if (menu_check(NODETYPE_POPUP) == false)
	InsertMenu(whatMenu, -1);    /* -1 means hierarchical menu */
  
  /* check the current menu item */
  CheckItem(whatMenu, *node_item, true);
  
  CalcMenuSize(whatMenu);		/* Work around a menu manager bug */
  loc.h = menuRect->left;
  loc.v = menuRect->top;
  LocalToGlobal(&loc);
  /* Make the menu the width of the user item */
  (**whatMenu).menuWidth = menuRect->right - menuRect->left;

  /* highlight the last item in the list as a default */
  menuResult = PopUpMenuSelect(whatMenu,loc.v,loc.h,*node_item);
  
  /* uncheck the item */
  CheckItem(whatMenu, *node_item, false);
  
  if (menuResult) 
	{
	  *node_item = LoWord(menuResult);
	  menuItem = *node_item;
	} 
  return(menuItem);
}

/*     
 *
 *  menu_build_node_popup
 *
 *	This creates the node popup and fills it in with items from node_types
 */

MenuHandle menu_build_node_popup(unsigned char node_id)
{
	short i;
	static MenuHandle menu = NULL;
	Str255 title;
	Handle icon;
	short iconID;
	Boolean inserted;	/* has node_id been inserted? */
	static short extra_id = 0;		/* id of added item (Number x) */
	static short num_items;		/* number of items in menu */
	
	inserted = false;

	if (menu == NULL)
	{
		menu = NewMenu(NODETYPE_POPUP, "Other");
		if (menu == NULL)
		{
			AlertUser(OUT_OF_MEM);
			return NULL;
		}
		
		num_items = 0;
		
		for (i = 1; i <= node_types[0].id; i++)
		{
			/* don't allow unprovidable nodes to be provided */
			if (node_types[i].trans != dont)
			{
				strcpy(title, node_types[i].name);
				c2pstr(title);
				AppendMenu(menu, title);
				num_items++;
/* This code puts each type's icon in the menu with the type's name.  It's commented
   out because we decided not to put icons in the menu */
/*
				icon = GetResource('ICON', node_types[i].id+256);
				if (icon == NULL)
					iconID = UNKNOWN_ICON - 256;
				else
				{
					iconID = node_types[i].id;
					ReleaseResource(icon);
				}
				SetItemIcon(menu, i, iconID);
*/

				if (node_types[i].id == node_id)
					inserted = true;
			}
		}
	}
	else
	{
		if (node_id == extra_id)
			return menu;
			
		for (i = 1; i <= node_types[0].id && !inserted; i++)
			if (node_types[i].id == node_id && node_types[i].trans != dont)
				inserted = true;
			
		if (extra_id != 0)
		{
			DelMenuItem(menu, num_items--);
			DelMenuItem(menu, num_items--);
			extra_id = 0;
		}
	}	

	if (!inserted && node_id != NT_ASCII && node_id != NT_MENU && 
		node_id != NT_GIF)
	{
		AppendMenu(menu, "\p-");
		num_items++;
		sprintf(title, "Number %u", node_id);
		c2pstr(title);
		AppendMenu(menu, title);
		num_items++;
		extra_id = node_id;

		icon = GetResource('ICON', node_id+256);
		if (icon == NULL)
			iconID = 255;
		else
		{
			iconID = node_id;
			ReleaseResource(icon);
		}
		SetItemIcon(menu, num_items, iconID);
	}

	return menu;
}