functions.c revision 0bbfda8a
10bbfda8aSnia/*
20bbfda8aSnia * Dispatcher for our f.whatever functions
30bbfda8aSnia */
40bbfda8aSnia
50bbfda8aSnia
60bbfda8aSnia#include "ctwm.h"
70bbfda8aSnia
80bbfda8aSnia#include <stdio.h>
90bbfda8aSnia
100bbfda8aSnia#include "events.h"
110bbfda8aSnia#include "functions.h"
120bbfda8aSnia#include "functions_defs.h"
130bbfda8aSnia#include "functions_deferral.h"  // Generated deferral table
140bbfda8aSnia#include "functions_internal.h"
150bbfda8aSnia#include "screen.h"
160bbfda8aSnia
170bbfda8aSnia
180bbfda8aSniastatic DFHANDLER(nop);
190bbfda8aSniastatic DFHANDLER(separator);
200bbfda8aSniastatic DFHANDLER(title);
210bbfda8aSniastatic DFHANDLER(deltastop);
220bbfda8aSniastatic DFHANDLER(function);
230bbfda8aSnia
240bbfda8aSnia/*
250bbfda8aSnia * The generated dispatch table.  Have to do this after the preceeding
260bbfda8aSnia * prototypes for the handers in this file, since those funcs are ref'd
270bbfda8aSnia * in this table.
280bbfda8aSnia */
290bbfda8aSnia#include "functions_dispatch_execution.h"
300bbfda8aSnia
310bbfda8aSnia
320bbfda8aSnia/*
330bbfda8aSnia * Various functions can be executed "from the root" (which generally
340bbfda8aSnia * means "from a menu"), but apply to a specific window (e.g., f.move,
350bbfda8aSnia * f.identify, etc).  You obviously can't be selecting it from a menu and
360bbfda8aSnia * pointing at the window to target at the same time, so we have to
370bbfda8aSnia * 2-step those calls.  This happens via the DeferExecution() call in the
380bbfda8aSnia * implementations of those functions, which stashes the "in progress"
390bbfda8aSnia * function in RootFunction.  The HandleButtonPress() event handler will
400bbfda8aSnia * later notice that and loop events back around into ExecuteFunction()
410bbfda8aSnia * again to pick up where it left off.
420bbfda8aSnia *
430bbfda8aSnia * (a more descriptive name might be in order)
440bbfda8aSnia */
450bbfda8aSniaint RootFunction = 0;
460bbfda8aSnia
470bbfda8aSnia
480bbfda8aSnia/*
490bbfda8aSnia * Track whether a window gets moved by move operations: used for
500bbfda8aSnia * f.deltastop handling.
510bbfda8aSnia */
520bbfda8aSniabool WindowMoved = false;
530bbfda8aSnia
540bbfda8aSnia/*
550bbfda8aSnia * Whether the cursor needs to be reset from a way we've altered it in
560bbfda8aSnia * the process of running functions.  This is used to determine whether
570bbfda8aSnia * we're ungrabbing the pointer to reset back from setting the WaitCursor
580bbfda8aSnia * early on in the execution process.  X-ref the XXX comment on that;
590bbfda8aSnia * it's unclear as to whether we should even be doing this anymore, but
600bbfda8aSnia * since we are, we use a global to ease tracking whether we need to
610bbfda8aSnia * unset it.  There are cases deeper down in function handling that may
620bbfda8aSnia * do their own fudgery and want the pointer left alone after they
630bbfda8aSnia * return.
640bbfda8aSnia */
650bbfda8aSniabool func_reset_cursor;
660bbfda8aSnia
670bbfda8aSnia/*
680bbfda8aSnia * Time of various actions: used in ConstrainedMoveTime related bits in
690bbfda8aSnia * some window moving/resizing.
700bbfda8aSnia */
710bbfda8aSniaTime last_time = 0;
720bbfda8aSnia
730bbfda8aSnia
740bbfda8aSniastatic bool EF_main(EF_FULLPROTO);
750bbfda8aSnia
760bbfda8aSniastatic bool DeferExecution(int context, int func, Cursor cursor);
770bbfda8aSniastatic bool should_defer(int func);
780bbfda8aSniastatic Cursor defer_cursor(int func);
790bbfda8aSniastatic Cursor NeedToDefer(MenuRoot *root);
800bbfda8aSnia
810bbfda8aSnia
820bbfda8aSnia/***********************************************************************
830bbfda8aSnia *
840bbfda8aSnia *  Procedure:
850bbfda8aSnia *      ExecuteFunction - execute a twm root function
860bbfda8aSnia *
870bbfda8aSnia *  Inputs:
880bbfda8aSnia *      func    - the function to execute
890bbfda8aSnia *      action  - the menu action to execute
900bbfda8aSnia *      w       - the window to execute this function on
910bbfda8aSnia *      tmp_win - the twm window structure
920bbfda8aSnia *      event   - the event that caused the function
930bbfda8aSnia *      context - the context in which the button was pressed
940bbfda8aSnia *      pulldown- flag indicating execution from pull down menu
950bbfda8aSnia *
960bbfda8aSnia ***********************************************************************
970bbfda8aSnia */
980bbfda8aSniavoid
990bbfda8aSniaExecuteFunction(EF_FULLPROTO)
1000bbfda8aSnia{
1010bbfda8aSnia	EF_main(EF_ARGS);
1020bbfda8aSnia}
1030bbfda8aSnia
1040bbfda8aSnia/*
1050bbfda8aSnia * Main ExecuteFunction body; returns true if we should continue a
1060bbfda8aSnia * f.function's progress, false if we should stop.
1070bbfda8aSnia *
1080bbfda8aSnia * This is separate because only the recursive calls in f.function
1090bbfda8aSnia * handling care about that return.  The only possible way to get to a
1100bbfda8aSnia * false return is via f.deltastop triggering.  We can't do it just with
1110bbfda8aSnia * a global, since f.function can at least in theory happen recursively;
1120bbfda8aSnia * I don't know how well it would actually work, but it has a chance.
1130bbfda8aSnia */
1140bbfda8aSniastatic bool
1150bbfda8aSniaEF_main(EF_FULLPROTO)
1160bbfda8aSnia{
1170bbfda8aSnia	/* This should always start out clear when we come in here */
1180bbfda8aSnia	RootFunction = 0;
1190bbfda8aSnia
1200bbfda8aSnia	/* Early escape for cutting out of things */
1210bbfda8aSnia	if(Cancel) {
1220bbfda8aSnia		/*
1230bbfda8aSnia		 * Strictly, this could probably be false, since if it's set it
1240bbfda8aSnia		 * would mean it'll just happen again when we iterate back
1250bbfda8aSnia		 * through for the next action.  Once set, it only gets unset in
1260bbfda8aSnia		 * the ButtonRelease handler, which I don't think would ever get
1270bbfda8aSnia		 * called in between pieces of a f.function call.  But I can't be
1280bbfda8aSnia		 * sure, so just go ahead and return true, and we'll eat a few
1290bbfda8aSnia		 * extra loops of function calls and insta-returns if it happens.
1300bbfda8aSnia		 */
1310bbfda8aSnia		return true;
1320bbfda8aSnia	}
1330bbfda8aSnia
1340bbfda8aSnia
1350bbfda8aSnia	/*
1360bbfda8aSnia	 * More early escapes; some "functions" don't actually do anything
1370bbfda8aSnia	 * when executed, and exist for magical purposes elsewhere.  So just
1380bbfda8aSnia	 * skip out early if we try running them.
1390bbfda8aSnia	 */
1400bbfda8aSnia	switch(func) {
1410bbfda8aSnia		case F_NOP:
1420bbfda8aSnia		case F_SEPARATOR:
1430bbfda8aSnia		case F_TITLE:
1440bbfda8aSnia			return true;
1450bbfda8aSnia
1460bbfda8aSnia		default:
1470bbfda8aSnia			; /* FALLTHRU */
1480bbfda8aSnia	}
1490bbfda8aSnia
1500bbfda8aSnia
1510bbfda8aSnia	/*
1520bbfda8aSnia	 * Is this a function that needs some deferring?  If so, go ahead and
1530bbfda8aSnia	 * do that.  Note that this specifically doesn't handle the special
1540bbfda8aSnia	 * case of f.function; it has to do its own checking for whether
1550bbfda8aSnia	 * there's something to defer.
1560bbfda8aSnia	 */
1570bbfda8aSnia	if(should_defer(func)) {
1580bbfda8aSnia		/* Figure the cursor */
1590bbfda8aSnia		Cursor dc = defer_cursor(func);
1600bbfda8aSnia		if(dc == None) {
1610bbfda8aSnia			dc = Scr->SelectCursor;
1620bbfda8aSnia		}
1630bbfda8aSnia
1640bbfda8aSnia		/* And defer (if we're in a context that needs to) */
1650bbfda8aSnia		if(DeferExecution(context, func, dc)) {
1660bbfda8aSnia			return true;
1670bbfda8aSnia		}
1680bbfda8aSnia	}
1690bbfda8aSnia
1700bbfda8aSnia
1710bbfda8aSnia	/*
1720bbfda8aSnia	 * For most functions with a few exceptions, grab the pointer.
1730bbfda8aSnia	 *
1740bbfda8aSnia	 * This is actually not a grab so much to take control of the
1750bbfda8aSnia	 * pointer, as to set the cursor.  Apparently, xlib doesn't
1760bbfda8aSnia	 * distinguish the two.  The functions that need it in a "take
1770bbfda8aSnia	 * control" sense (like the move and resize bits) should all be doing
1780bbfda8aSnia	 * their own explicit grabs to handle that.
1790bbfda8aSnia	 *
1800bbfda8aSnia	 * XXX I have no idea why there's the exclusion list.  Apart from
1810bbfda8aSnia	 * adding 1 or 2 functions, this code comes verbatim from twm, which
1820bbfda8aSnia	 * has no history or documentation as to why it's happening.
1830bbfda8aSnia	 *
1840bbfda8aSnia	 * XXX I'm not sure this is even worth doing anymore.  The point of
1850bbfda8aSnia	 * the WaitCursor is to let the user know "yeah, I'm working on it",
1860bbfda8aSnia	 * during operations that may take a while.  On 1985 hardware, that
1870bbfda8aSnia	 * would be "almost anything you do".  But in the 21st century, what
1880bbfda8aSnia	 * functions could fall into that category, and need to give some
1890bbfda8aSnia	 * user feedback before either finishing or doing something that
1900bbfda8aSnia	 * gives other user feedback anyway?
1910bbfda8aSnia	 */
1920bbfda8aSnia	func_reset_cursor = false;
1930bbfda8aSnia	switch(func) {
1940bbfda8aSnia		case F_UPICONMGR:
1950bbfda8aSnia		case F_LEFTICONMGR:
1960bbfda8aSnia		case F_RIGHTICONMGR:
1970bbfda8aSnia		case F_DOWNICONMGR:
1980bbfda8aSnia		case F_FORWICONMGR:
1990bbfda8aSnia		case F_BACKICONMGR:
2000bbfda8aSnia		case F_NEXTICONMGR:
2010bbfda8aSnia		case F_PREVICONMGR:
2020bbfda8aSnia		case F_NOP:
2030bbfda8aSnia		case F_TITLE:
2040bbfda8aSnia		case F_DELTASTOP:
2050bbfda8aSnia		case F_RAISELOWER:
2060bbfda8aSnia		case F_WARPTOSCREEN:
2070bbfda8aSnia		case F_WARPTO:
2080bbfda8aSnia		case F_WARPRING:
2090bbfda8aSnia		case F_WARPTOICONMGR:
2100bbfda8aSnia		case F_COLORMAP:
2110bbfda8aSnia		case F_ALTKEYMAP:
2120bbfda8aSnia		case F_ALTCONTEXT:
2130bbfda8aSnia			break;
2140bbfda8aSnia
2150bbfda8aSnia		default: {
2160bbfda8aSnia			XGrabPointer(dpy, Scr->Root, True,
2170bbfda8aSnia			             ButtonPressMask | ButtonReleaseMask,
2180bbfda8aSnia			             GrabModeAsync, GrabModeAsync,
2190bbfda8aSnia			             Scr->Root, Scr->WaitCursor, CurrentTime);
2200bbfda8aSnia			func_reset_cursor = true;
2210bbfda8aSnia			break;
2220bbfda8aSnia		}
2230bbfda8aSnia	}
2240bbfda8aSnia
2250bbfda8aSnia
2260bbfda8aSnia	/*
2270bbfda8aSnia	 * Main dispatching/executing.
2280bbfda8aSnia	 *
2290bbfda8aSnia	 * _Most_ f.things are dispatched to individual handler functions,
2300bbfda8aSnia	 * but we keep the magic related to f.function/f.deltastop out here
2310bbfda8aSnia	 * to free the inner bits from having to care about the magic
2320bbfda8aSnia	 * returns.
2330bbfda8aSnia	 */
2340bbfda8aSnia	switch(func) {
2350bbfda8aSnia		case F_DELTASTOP:
2360bbfda8aSnia			if(WindowMoved) {
2370bbfda8aSnia				/*
2380bbfda8aSnia				 * If we're returning false here, it's because we were in
2390bbfda8aSnia				 * the midst of a f.function, and we should stop.  That
2400bbfda8aSnia				 * means when we return from here it'll be into the false
2410bbfda8aSnia				 * case in the F_FUNCTION handler below, which will break
2420bbfda8aSnia				 * right out and fall through to the end of this
2430bbfda8aSnia				 * function, which will do the post-function cleanup
2440bbfda8aSnia				 * bits.  That means we don't need to try and break out
2450bbfda8aSnia				 * to them here, we can just return straight off.
2460bbfda8aSnia				 */
2470bbfda8aSnia				return false;
2480bbfda8aSnia			}
2490bbfda8aSnia			break;
2500bbfda8aSnia
2510bbfda8aSnia		case F_FUNCTION: {
2520bbfda8aSnia			MenuRoot *mroot;
2530bbfda8aSnia			MenuItem *mitem;
2540bbfda8aSnia			Cursor curs;
2550bbfda8aSnia
2560bbfda8aSnia			if((mroot = FindMenuRoot(action)) == NULL) {
2570bbfda8aSnia				if(!action) {
2580bbfda8aSnia					action = "undef";
2590bbfda8aSnia				}
2600bbfda8aSnia				fprintf(stderr, "%s: couldn't find function \"%s\"\n",
2610bbfda8aSnia				        ProgramName, (char *)action);
2620bbfda8aSnia				return true;
2630bbfda8aSnia			}
2640bbfda8aSnia
2650bbfda8aSnia			if((curs = NeedToDefer(mroot)) != None
2660bbfda8aSnia			                && DeferExecution(context, func, curs)) {
2670bbfda8aSnia				return true;
2680bbfda8aSnia			}
2690bbfda8aSnia			else {
2700bbfda8aSnia				for(mitem = mroot->first; mitem != NULL; mitem = mitem->next) {
2710bbfda8aSnia					bool r = EF_main(mitem->func, mitem->action, w,
2720bbfda8aSnia					                 tmp_win, eventp, context, pulldown);
2730bbfda8aSnia					if(r == false) {
2740bbfda8aSnia						/* pebl FIXME: the focus should be updated here,
2750bbfda8aSnia						 or the function would operate on the same window */
2760bbfda8aSnia						break;
2770bbfda8aSnia					}
2780bbfda8aSnia				}
2790bbfda8aSnia			}
2800bbfda8aSnia
2810bbfda8aSnia			break;
2820bbfda8aSnia		}
2830bbfda8aSnia
2840bbfda8aSnia
2850bbfda8aSnia		/*
2860bbfda8aSnia		 * Everything else is programmatically dispatched.
2870bbfda8aSnia		 */
2880bbfda8aSnia		default: {
2890bbfda8aSnia			if(func >= 0 && func < num_f_dis && func_dispatch[func] != NULL) {
2900bbfda8aSnia				(*func_dispatch[func])(EF_ARGS);
2910bbfda8aSnia				break;
2920bbfda8aSnia			}
2930bbfda8aSnia
2940bbfda8aSnia			/*
2950bbfda8aSnia			 * Getting here means somehow it wasn't in the dispatch
2960bbfda8aSnia			 * table, which shouldn't be possible without a big bug
2970bbfda8aSnia			 * somewhere...
2980bbfda8aSnia			 */
2990bbfda8aSnia			fprintf(stderr, "Internal error: no handler for function %d\n",
3000bbfda8aSnia			        func);
3010bbfda8aSnia			break;
3020bbfda8aSnia		}
3030bbfda8aSnia	}
3040bbfda8aSnia
3050bbfda8aSnia
3060bbfda8aSnia
3070bbfda8aSnia	/*
3080bbfda8aSnia	 * Release the pointer.  This should mostly mean actually "reset
3090bbfda8aSnia	 * cursor", and be the complementary op to setting the cursor earlier
3100bbfda8aSnia	 * up top.
3110bbfda8aSnia	 *
3120bbfda8aSnia	 * ButtonPressed == -1 means that we didn't get here via some sort of
3130bbfda8aSnia	 * mouse clickery.  If we did, then we presume that has some
3140bbfda8aSnia	 * ownership of the pointer we don't want to relinquish yet.  And we
3150bbfda8aSnia	 * don't have to, as the ButtonRelease handler will take care of
3160bbfda8aSnia	 * things when it fires anyway.
3170bbfda8aSnia	 *
3180bbfda8aSnia	 * This has a similar XXX to the cursor setting earlier, as to
3190bbfda8aSnia	 * whether it ought to exist.
3200bbfda8aSnia	 */
3210bbfda8aSnia	if(func_reset_cursor && ButtonPressed == -1) {
3220bbfda8aSnia		XUngrabPointer(dpy, CurrentTime);
3230bbfda8aSnia		func_reset_cursor = false;
3240bbfda8aSnia	}
3250bbfda8aSnia
3260bbfda8aSnia	return true;
3270bbfda8aSnia}
3280bbfda8aSnia
3290bbfda8aSnia
3300bbfda8aSnia
3310bbfda8aSnia/*
3320bbfda8aSnia * Implementation of function deferral
3330bbfda8aSnia */
3340bbfda8aSnia
3350bbfda8aSnia/*
3360bbfda8aSnia * Setting a last cursor and re-grabbing to it.  This is used in the
3370bbfda8aSnia * AddWindow() process.  It might grab the mouse and re-set the
3380bbfda8aSnia * cursor away from us, and so it needs a way to set it back.
3390bbfda8aSnia *
3400bbfda8aSnia * XXX This begs for renaming...
3410bbfda8aSnia */
3420bbfda8aSniastatic Cursor LastCursor;
3430bbfda8aSnia
3440bbfda8aSniavoid
3450bbfda8aSniaReGrab(void)
3460bbfda8aSnia{
3470bbfda8aSnia	XGrabPointer(dpy, Scr->Root, True,
3480bbfda8aSnia	             ButtonPressMask | ButtonReleaseMask,
3490bbfda8aSnia	             GrabModeAsync, GrabModeAsync,
3500bbfda8aSnia	             Scr->Root, LastCursor, CurrentTime);
3510bbfda8aSnia}
3520bbfda8aSnia
3530bbfda8aSnia
3540bbfda8aSnia/*
3550bbfda8aSnia * Check to see if a function (implicitly, a window-targetting function)
3560bbfda8aSnia * is happening in a context away from an actual window, and if so stash
3570bbfda8aSnia * up info about what's in progress and return true to tell the caller to
3580bbfda8aSnia * end processing the function (for now).  X-ref comment on RootFunction
3590bbfda8aSnia * variable definition for details.
3600bbfda8aSnia *
3610bbfda8aSnia *  Inputs:
3620bbfda8aSnia *      context - the context in which the mouse button was pressed
3630bbfda8aSnia *      func    - the function to defer
3640bbfda8aSnia *      cursor  - the cursor to display while waiting
3650bbfda8aSnia */
3660bbfda8aSniastatic bool
3670bbfda8aSniaDeferExecution(int context, int func, Cursor cursor)
3680bbfda8aSnia{
3690bbfda8aSnia	if((context == C_ROOT) || (context == C_ALTERNATE)) {
3700bbfda8aSnia		LastCursor = cursor;
3710bbfda8aSnia		XGrabPointer(dpy,
3720bbfda8aSnia		             Scr->Root,
3730bbfda8aSnia		             True,
3740bbfda8aSnia		             ButtonPressMask | ButtonReleaseMask,
3750bbfda8aSnia		             GrabModeAsync,
3760bbfda8aSnia		             GrabModeAsync,
3770bbfda8aSnia		             (func == F_ADOPTWINDOW) ? None : Scr->Root,
3780bbfda8aSnia		             cursor,
3790bbfda8aSnia		             CurrentTime);
3800bbfda8aSnia		RootFunction = func;
3810bbfda8aSnia
3820bbfda8aSnia		return true;
3830bbfda8aSnia	}
3840bbfda8aSnia
3850bbfda8aSnia	return false;
3860bbfda8aSnia}
3870bbfda8aSnia
3880bbfda8aSnia
3890bbfda8aSnia/*
3900bbfda8aSnia * Various determinates of whether a function should be deferred if its
3910bbfda8aSnia * called in a general (rather than win-specific) context, and what
3920bbfda8aSnia * cursor should be used in the meantime.
3930bbfda8aSnia *
3940bbfda8aSnia * We define a big lookup array to do it.  We have to indirect through an
3950bbfda8aSnia * intermediate enum value instead of just the cursor since it isn't
3960bbfda8aSnia * available at compile time, and we can't just make it a pointer into
3970bbfda8aSnia * Scr since there are [potentially] multiple Scr's anyway.  And we need
3980bbfda8aSnia * an explicit unused DC_NONE value so our real values are all non-zero;
3990bbfda8aSnia * the ones we don't explicitly set get initialized to 0, which we can
4000bbfda8aSnia * then take as a flag saying "we don't defer this func".
4010bbfda8aSnia *
4020bbfda8aSnia * fdef_table in functions_deferral.h generated from functions_defs.list.
4030bbfda8aSnia */
4040bbfda8aSnia
4050bbfda8aSniastatic bool
4060bbfda8aSniashould_defer(int func)
4070bbfda8aSnia{
4080bbfda8aSnia	/* Outside the table -> "No" */
4090bbfda8aSnia	if(func < 0 || func >= fdef_table_max) {
4100bbfda8aSnia		return false;
4110bbfda8aSnia	}
4120bbfda8aSnia
4130bbfda8aSnia	if(fdef_table[func] != DC_NONE) {
4140bbfda8aSnia		return true;
4150bbfda8aSnia	}
4160bbfda8aSnia	return false;
4170bbfda8aSnia}
4180bbfda8aSnia
4190bbfda8aSniastatic Cursor
4200bbfda8aSniadefer_cursor(int func)
4210bbfda8aSnia{
4220bbfda8aSnia	/* Outside the table -> "No" */
4230bbfda8aSnia	if(func < 0 || func >= fdef_table_max) {
4240bbfda8aSnia		return None;
4250bbfda8aSnia	}
4260bbfda8aSnia
4270bbfda8aSnia	switch(fdef_table[func]) {
4280bbfda8aSnia		case DC_SELECT:
4290bbfda8aSnia			return Scr->SelectCursor;
4300bbfda8aSnia		case DC_MOVE:
4310bbfda8aSnia			return Scr->MoveCursor;
4320bbfda8aSnia		case DC_DESTROY:
4330bbfda8aSnia			return Scr->DestroyCursor;
4340bbfda8aSnia
4350bbfda8aSnia		default:
4360bbfda8aSnia			/* Is there a better choice? */
4370bbfda8aSnia			return None;
4380bbfda8aSnia	}
4390bbfda8aSnia
4400bbfda8aSnia	/* NOTREACHED */
4410bbfda8aSnia	return None;
4420bbfda8aSnia}
4430bbfda8aSnia
4440bbfda8aSnia
4450bbfda8aSnia/*
4460bbfda8aSnia * Checks each function in a user-defined Function list called via
4470bbfda8aSnia * f.function to see any of them need to be defered.  The Function config
4480bbfda8aSnia * action creates pseudo-menus to store the items in that call, so we
4490bbfda8aSnia * loop through the "items" in that "menu".  Try not to think about that
4500bbfda8aSnia * too much.
4510bbfda8aSnia *
4520bbfda8aSnia * This previously used a hardcoded list of functions to defer, which was
4530bbfda8aSnia * substantially smaller than the list it's currently checking.  It now
4540bbfda8aSnia * checks all the same functions that are themselves checked
4550bbfda8aSnia * individually, which is almost certainly how it should have always
4560bbfda8aSnia * worked anyway.
4570bbfda8aSnia */
4580bbfda8aSniastatic Cursor
4590bbfda8aSniaNeedToDefer(MenuRoot *root)
4600bbfda8aSnia{
4610bbfda8aSnia	MenuItem *mitem;
4620bbfda8aSnia
4630bbfda8aSnia	for(mitem = root->first; mitem != NULL; mitem = mitem->next) {
4640bbfda8aSnia		if(should_defer(mitem->func)) {
4650bbfda8aSnia			Cursor dc = defer_cursor(mitem->func);
4660bbfda8aSnia			if(dc == None) {
4670bbfda8aSnia				return Scr->SelectCursor;
4680bbfda8aSnia			}
4690bbfda8aSnia			return dc;
4700bbfda8aSnia		}
4710bbfda8aSnia	}
4720bbfda8aSnia	return None;
4730bbfda8aSnia}
4740bbfda8aSnia
4750bbfda8aSnia
4760bbfda8aSnia
4770bbfda8aSnia/*
4780bbfda8aSnia * Faked up handlers for functions that shouldn't ever really get to
4790bbfda8aSnia * them.  These are handled in various hard-coded ways before we get to
4800bbfda8aSnia * automatic dispatch, so there shouldn't be any way these functions
4810bbfda8aSnia * actually get called.  But, just in case, return instead of dying.
4820bbfda8aSnia *
4830bbfda8aSnia * It's easier to just write these than to try and long-term parameterize
4840bbfda8aSnia * which we expect to exist.
4850bbfda8aSnia */
4860bbfda8aSnia
4870bbfda8aSnia/* f.nop, f.title, f.separator really only exist to make lines in menus */
4880bbfda8aSniastatic
4890bbfda8aSniaDFHANDLER(nop)
4900bbfda8aSnia{
4910bbfda8aSnia	fprintf(stderr, "%s(): Shouldn't get here.\n", __func__);
4920bbfda8aSnia	return;
4930bbfda8aSnia}
4940bbfda8aSniastatic
4950bbfda8aSniaDFHANDLER(separator)
4960bbfda8aSnia{
4970bbfda8aSnia	fprintf(stderr, "%s(): Shouldn't get here.\n", __func__);
4980bbfda8aSnia	return;
4990bbfda8aSnia}
5000bbfda8aSniastatic
5010bbfda8aSniaDFHANDLER(title)
5020bbfda8aSnia{
5030bbfda8aSnia	fprintf(stderr, "%s(): Shouldn't get here.\n", __func__);
5040bbfda8aSnia	return;
5050bbfda8aSnia}
5060bbfda8aSnia
5070bbfda8aSnia/* f.deltastop and f.function are magic */
5080bbfda8aSniastatic
5090bbfda8aSniaDFHANDLER(deltastop)
5100bbfda8aSnia{
5110bbfda8aSnia	fprintf(stderr, "%s(): Shouldn't get here.\n", __func__);
5120bbfda8aSnia	return;
5130bbfda8aSnia}
5140bbfda8aSniastatic
5150bbfda8aSniaDFHANDLER(function)
5160bbfda8aSnia{
5170bbfda8aSnia	fprintf(stderr, "%s(): Shouldn't get here.\n", __func__);
5180bbfda8aSnia	return;
5190bbfda8aSnia}
520