[patch 06/11] call_func()/call_func_with_args() macros

Bert Wesarg wesarg at informatik.uni-halle.de
Sat Jan 27 16:15:35 CET 2007


This patch isn't realy needed, but with the define_func() macro it
completes the generic macro callback framework

---

 source/macro.c |  176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 174 insertions(+), 2 deletions(-)

diff --quilt old/source/macro.c new/source/macro.c
--- old/source/macro.c
+++ new/source/macro.c
@@ -410,10 +410,14 @@ static int getStyleAtPosMS(WindowInfo *w
         DataValue *result, char **errMsg);
 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
         DataValue* result, char** errMsg);
 static int typeofMS(WindowInfo* window, DataValue* argList, int nArgs,
         DataValue* result, char** errMsg);
+static int callFuncMS(WindowInfo *window, DataValue *argList,
+        int nArgs, DataValue *result, char **errMsg);
+static int callFuncWithArgsMS(WindowInfo *window, DataValue *argList,
+        int nArgs, DataValue *result, char **errMsg);
 
 static int dictinsertMS(WindowInfo *window, DataValue *argList, int nArgs,
         DataValue *result, char **errMsg);
 static int dictcompleteMS(WindowInfo *window, DataValue *argList, int nArgs,
         DataValue *result, char **errMsg);
@@ -443,11 +447,12 @@ static BuiltInSubr MacroSubrs[] = {lengt
         rangesetGetByNameMS,
         getPatternByNameMS, getPatternAtPosMS,
         getStyleByNameMS, getStyleAtPosMS, filenameDialogMS,
         typeofMS,
         dictinsertMS, dictcompleteMS, dictsaveMS,
-        dictappendMS, dictiselementMS
+        dictappendMS, dictiselementMS,
+        callFuncMS, callFuncWithArgsMS
     };
 #define N_MACRO_SUBRS (sizeof MacroSubrs/sizeof *MacroSubrs)
 static const char *MacroSubrNames[N_MACRO_SUBRS] = {"length", "get_range", "t_print",
         "dialog", "string_dialog", "replace_range", "replace_selection",
         "set_cursor_pos", "get_character", "min", "max", "search",
@@ -466,11 +471,12 @@ static const char *MacroSubrNames[N_MACR
         "rangeset_get_by_name",
         "get_pattern_by_name", "get_pattern_at_pos",
         "get_style_by_name", "get_style_at_pos", "filename_dialog",
         "typeof",
         "dict_insert", "dict_complete", "dict_save",
-        "dict_append", "dict_is_element"
+        "dict_append", "dict_is_element",
+        "call_func", "call_func_with_args"
     };
 static BuiltInSubr SpecialVars[] = {cursorMV, lineMV, columnMV,
         fileNameMV, filePathMV, lengthMV, selectionStartMV, selectionEndMV,
         selectionLeftMV, selectionRightMV, wrapMarginMV, tabDistMV,
         emTabDistMV, useTabsMV, languageModeMV, modifiedMV,
@@ -3554,10 +3560,176 @@ static int filenameDialogMS(WindowInfo* 
     }
 
     return True;
 }
 
+static int callFuncMS(WindowInfo *window, DataValue *argList,
+        int nArgs, DataValue *result, char **errMsg)
+{
+    char stringStorage[TYPE_INT_STR_SIZE(int)];
+    char *func = NULL;
+    Symbol *sym;
+
+    if (!nArgs) {
+        *errMsg = "subroutine %s called with too few arguments";
+        return False;
+    }
+    if (!readStringArg(argList[0], &func, stringStorage, errMsg)) {
+        return False;
+    }
+
+    /* remove function name from argument list */
+    nArgs--;
+    argList++;
+
+    sym = LookupSymbol(func);
+    if (!sym)
+    {
+        *errMsg = "Function not found.";
+        return False;
+    }
+
+    switch (sym->type) {
+    case MACRO_FUNCTION_SYM:
+    {
+        Program *prog = sym->value.val.prog;
+        RestartData* restartData;
+        int status;
+
+        /*  Let 'er rip  */
+        status = ExecuteMacro(window, prog, nArgs, argList, result,
+                &restartData, errMsg);
+
+        while (status == MACRO_TIME_LIMIT)
+        {
+            status = ContinueMacro(restartData, result, errMsg);
+        }
+
+        if (status == MACRO_ERROR)
+        {
+            fprintf(stderr, "nedit: \"%s\" error: %s\n", func, *errMsg);
+            return False;
+        }
+
+        return True;
+    }
+    break;
+
+    case C_FUNCTION_SYM:
+    {
+        BuiltInSubr subr = sym->value.val.subr;
+        return subr(window, argList, nArgs, result, errMsg);
+    }
+    break;
+
+    case ACTION_ROUTINE_SYM:
+    {
+        XtActionProc xtproc = sym->value.val.xtproc;
+        String argListString[nArgs];
+        Cardinal nArgsString = 0;
+        XKeyEvent key_event;
+        Display *disp;
+        Window win;
+        int i;
+
+        /* Create a fake event with a timestamp suitable for actions which need
+           timestamps, a marker to indicate that the call was from a macro
+           (to stop shell commands from putting up their own separate banner) */
+        disp = XtDisplay(window->shell);
+        win  = XtWindow(window->shell);
+
+        key_event.type = KeyPress;
+        key_event.send_event = MACRO_EVENT_MARKER;
+        key_event.time=XtLastTimestampProcessed(disp);
+
+        /* The following entries are just filled in to avoid problems
+           in strange cases, like calling "self_insert()" directly from the
+           macro menu. In fact the display was sufficient to cure this crash. */
+        key_event.display = disp;
+        key_event.window = key_event.root = key_event.subwindow = win;
+
+        for (i = 0; i < nArgs; i--)
+        {
+            char *stringArg = NULL;
+            if (!readStringArg(argList[i], &stringArg, stringStorage, errMsg))
+            {
+                for (i = 0; i < nArgsString; i++)
+                {
+                    free(argListString[i]);
+                }
+                *errMsg = "Try to call an action routine with an none string argument.";
+                return False;
+            }
+            argListString[nArgsString++] = strdup(stringArg);
+        }
+
+        /* Call the action routine */
+        xtproc(window->lastFocus, (XEvent *)&key_event, argListString,
+               &nArgsString);
+
+        for (i = 0; i < nArgsString; i++)
+        {
+            free(argListString[i]);
+        }
+
+        return True;
+    }
+    break;
+
+    default:
+        *errMsg = "Try to call an uncallable function.";
+        return False;
+
+    }
+}
+
+static int callFuncWithArgsMS(WindowInfo *window, DataValue *argList,
+        int nArgs, DataValue *result, char **errMsg)
+{
+    DataValue *argListNew = NULL;
+    int nArgsNew = 0, i;
+    DataValue *args;
+    char keyStorage[TYPE_INT_STR_SIZE(int)];
+    int ret;
+
+    if (nArgs < 1) {
+        *errMsg = "subroutine %s called with too few arguments";
+        return False;
+    }
+    if (nArgs > 2) {
+        *errMsg = "subroutine %s called with too many arguments";
+        return False;
+    }
+    if (argList[1].tag != ARRAY_TAG) {
+        *errMsg = "subroutine %s called with wrong second argument";
+        return False;
+    }
+
+    args = &argList[1];
+    /* one for the function name */
+    nArgsNew = 1 + ArraySize(args);
+
+    argListNew = (DataValue *)XtMalloc(nArgsNew * sizeof(DataValue));
+
+    /* copy the firs arg to new arg, this is the function name */
+    argListNew[0] = argList[0];
+
+    for (i = 1; i < nArgsNew; i++) {
+        sprintf(keyStorage, "%d", i);
+        if (!ArrayGet(args, keyStorage, &argListNew[i])) {
+            *errMsg = "subroutine %s called with wrong array argument";
+            XtFree((char *)argListNew);
+            return False;
+        }
+    }
+
+    ret = callFuncMS(window, argListNew, nArgsNew, result, errMsg);
+    XtFree((char *)argListNew);
+
+    return ret;
+}
+
 /* T Balinski */
 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
       DataValue *result, char **errMsg)
 {
     macroCmdInfo *cmdData;

-- 



More information about the Develop mailing list