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