summaryrefslogtreecommitdiffstats
path: root/generic/qebind.c
diff options
context:
space:
mode:
authortreectrl <treectrl>2002-12-30 07:10:34 (GMT)
committertreectrl <treectrl>2002-12-30 07:10:34 (GMT)
commitda47041fd99a2580ce5847f7f684400ef74efc8d (patch)
tree7d84105af0ecb2affc3cde090d23b33180a36e9b /generic/qebind.c
parentc9984e0385a2836b26f0ea9ac081f73c3972bc1c (diff)
downloadtktreectrl-da47041fd99a2580ce5847f7f684400ef74efc8d.zip
tktreectrl-da47041fd99a2580ce5847f7f684400ef74efc8d.tar.gz
tktreectrl-da47041fd99a2580ce5847f7f684400ef74efc8d.tar.bz2
install event command allows %-command.
%-char/value args to generate command are passed to %-command. Allow '>' in event and detail names. Don't allow spaces or '-' in event or detail names.
Diffstat (limited to 'generic/qebind.c')
-rw-r--r--generic/qebind.c186
1 files changed, 139 insertions, 47 deletions
diff --git a/generic/qebind.c b/generic/qebind.c
index 1d12e87..7d0ce29 100644
--- a/generic/qebind.c
+++ b/generic/qebind.c
@@ -33,6 +33,14 @@
#define dbwin printf
#endif /* HAVE_DBWIN_H */
+/*
+ * The macro below is used to modify a "char" value (e.g. by casting
+ * it to an unsigned character) so that it can be used safely with
+ * macros such as isspace.
+ */
+
+#define UCHAR(c) ((unsigned char) (c))
+
int debug_bindings = 0;
/*
@@ -77,7 +85,7 @@ typedef struct Detail {
struct EventInfo *event; /* Associated event */
QE_ExpandProc expandProc; /* Callback to expand % in scripts */
#if ALLOW_INSTALL
- int dynamic;
+ int dynamic; /* Created by QE_InstallCmd() */
char *command; /* Tcl command to expand percents, or NULL */
#endif
struct Detail *next; /* List of Details for event */
@@ -91,6 +99,7 @@ typedef struct EventInfo {
int nextDetailId; /* Next unique Detail.code */
#if ALLOW_INSTALL
int dynamic; /* Created by QE_InstallCmd() */
+ char *command; /* Tcl command to expand percents, or NULL */
#endif
struct EventInfo *next; /* List of all EventInfos */
} EventInfo;
@@ -113,6 +122,12 @@ static int ParseEventDescription(BindingTable *bindPtr, char *eventPattern,
static int FindSequence(BindingTable *bindPtr, ClientData object,
char *eventString, int create, int *created, BindValue **result);
#if ALLOW_INSTALL
+typedef struct PercentsData {
+ ClientData clientData;
+ char *command;
+ EventInfo *eventPtr;
+ Detail *detailPtr;
+} PercentsData;
static void Percents_Install(QE_ExpandArgs *args);
#endif
static int DeleteBinding(BindingTable *bindPtr, BindValue *valuePtr);
@@ -130,6 +145,19 @@ int QE_BindInit(Tcl_Interp *interp)
return TCL_OK;
}
+static int CheckName(char *name)
+{
+ char *p = name;
+
+ if (*p == '\0')
+ return TCL_ERROR;
+ while ((*p != '\0') && (*p != '-') && !isspace(UCHAR(*p)))
+ p++;
+ if (*p == '\0')
+ return TCL_OK;
+ return TCL_ERROR;
+}
+
int QE_InstallEvent(QE_BindingTable bindingTable, char *name, QE_ExpandProc expandProc)
{
BindingTable *bindPtr = (BindingTable *) bindingTable;
@@ -138,6 +166,13 @@ int QE_InstallEvent(QE_BindingTable bindingTable, char *name, QE_ExpandProc expa
int isNew;
int type;
+ if (CheckName(name) != TCL_OK)
+ {
+ Tcl_AppendResult(bindPtr->interp, "bad event name \"", name, "\"",
+ (char *) NULL);
+ return 0;
+ }
+
hPtr = Tcl_CreateHashEntry(&bindPtr->eventTableByName, name, &isNew);
if (!isNew)
{
@@ -157,6 +192,7 @@ int QE_InstallEvent(QE_BindingTable bindingTable, char *name, QE_ExpandProc expa
eiPtr->nextDetailId = 1;
#ifdef ALLOW_INSTALL
eiPtr->dynamic = 0;
+ eiPtr->command = NULL;
#endif
Tcl_SetHashValue(hPtr, (ClientData) eiPtr);
@@ -181,6 +217,13 @@ int QE_InstallDetail(QE_BindingTable bindingTable, char *name, int eventType, QE
int isNew;
int code;
+ if (CheckName(name) != TCL_OK)
+ {
+ Tcl_AppendResult(bindPtr->interp, "bad detail name \"", name, "\"",
+ (char *) NULL);
+ return 0;
+ }
+
/* Find the event this detail goes with */
eiPtr = FindEvent(bindPtr, eventType);
if (eiPtr == NULL)
@@ -259,6 +302,10 @@ static void DeleteEvent(BindingTable *bindPtr, EventInfo *eiPtr)
/* Free EventInfo */
Tcl_Free(eiPtr->name);
+#ifdef ALLOW_INSTALL
+ if (eiPtr->command != NULL)
+ Tcl_Free(eiPtr->command);
+#endif
memset((char *) eiPtr, 0xAA, sizeof(EventInfo));
Tcl_Free((char *) eiPtr);
}
@@ -465,6 +512,10 @@ void QE_DeleteBindingTable(QE_BindingTable bindingTable)
/* Free EventInfo */
Tcl_Free(eiPtr->name);
+#ifdef ALLOW_INSTALL
+ if (eiPtr->command != NULL)
+ Tcl_Free(eiPtr->command);
+#endif
memset((char *) eiPtr, 0xAA, sizeof(EventInfo));
Tcl_Free((char *) eiPtr);
}
@@ -893,14 +944,33 @@ static void BindEvent(BindingTable *bindPtr, QE_Event *eventPtr, int wantDetail,
/*
* Call a Tcl script to expand the percents.
*/
- if (dPtr && (dPtr->command != NULL))
+ if ((dPtr != NULL) && (dPtr->command != NULL))
{
- ClientData oldClientData = eventPtr->clientData;
+ PercentsData data;
- eventPtr->clientData = (ClientData) dPtr;
+ data.clientData = eventPtr->clientData;
+ data.command = dPtr->command;
+ data.eventPtr = eiPtr;
+ data.detailPtr = dPtr;
+ eventPtr->clientData = (ClientData) &data;
ExpandPercents(bindPtr, valuePtr->object, valuePtr->command,
eventPtr, Percents_Install, &scripts);
- eventPtr->clientData = oldClientData;
+ eventPtr->clientData = data.clientData;
+ }
+ else if (((dPtr == NULL) ||
+ ((dPtr != NULL) && (dPtr->expandProc == NULL))) &&
+ (eiPtr->command != NULL))
+ {
+ PercentsData data;
+
+ data.clientData = eventPtr->clientData;
+ data.command = eiPtr->command;
+ data.eventPtr = eiPtr;
+ data.detailPtr = dPtr;
+ eventPtr->clientData = (ClientData) &data;
+ ExpandPercents(bindPtr, valuePtr->object, valuePtr->command,
+ eventPtr, Percents_Install, &scripts);
+ eventPtr->clientData = data.clientData;
}
else
#endif /* ALLOW_INSTALL */
@@ -1114,14 +1184,6 @@ int QE_BindEvent(QE_BindingTable bindingTable, QE_Event *eventPtr)
return TCL_OK;
}
-/*
- * The macro below is used to modify a "char" value (e.g. by casting
- * it to an unsigned character) so that it can be used safely with
- * macros such as isspace.
- */
-
-#define UCHAR(c) ((unsigned char) (c))
-
static char *GetField(char *p, char *copy, int size)
{
int ch = *p;
@@ -1350,10 +1412,14 @@ void QE_ExpandEvent(QE_BindingTable bindingTable, int eventType, Tcl_DString *re
void QE_ExpandDetail(QE_BindingTable bindingTable, int event, int detail, Tcl_DString *result)
{
BindingTable *bindPtr = (BindingTable *) bindingTable;
- Detail *detailPtr = FindDetail(bindPtr, event, detail);
+ Detail *dPtr;
- if (detailPtr != NULL)
- QE_ExpandString((char *) detailPtr->name, result);
+ if (detail == 0)
+ return;
+
+ dPtr = FindDetail(bindPtr, event, detail);
+ if (dPtr != NULL)
+ QE_ExpandString((char *) dPtr->name, result);
else
QE_ExpandString("unknown", result);
}
@@ -1453,7 +1519,7 @@ static void Percents_Generate(QE_ExpandArgs *args)
int i;
/* Reverse order to handle duplicate %-chars */
- for (i = data->count - 1; i >= 0 ; i--)
+ for (i = data->count - 1; i >= 0; i--)
{
if (args->which == data->field[i].which)
{
@@ -1706,39 +1772,54 @@ static void Percents_Install(QE_ExpandArgs *args)
{
BindingTable *bindPtr = (BindingTable *) args->bindingTable;
Tcl_Interp *interp = bindPtr->interp;
- Detail *dPtr = (Detail *) args->clientData;
+ PercentsData *data = (PercentsData *) args->clientData;
+ EventInfo *eiPtr = data->eventPtr;
+ Detail *dPtr = data->detailPtr;
Tcl_DString command;
Tcl_SavedResult state;
- if (dPtr->command != NULL)
- {
- Tcl_DStringInit(&command);
- Tcl_DStringAppend(&command, dPtr->command, -1);
- Tcl_DStringAppend(&command, " ", 1);
- Tcl_DStringAppend(&command, &args->which, 1);
- Tcl_DStringAppend(&command, " ", 1);
- Tcl_DStringAppend(&command, (char *) args->object, -1);
- Tcl_DStringAppend(&command, " ", 1);
- Tcl_DStringAppend(&command, dPtr->event->name, -1);
- Tcl_DStringAppend(&command, " ", 1);
+ Tcl_DStringInit(&command);
+ Tcl_DStringAppend(&command, data->command, -1);
+ Tcl_DStringAppend(&command, " ", 1);
+ Tcl_DStringAppend(&command, &args->which, 1);
+ Tcl_DStringAppend(&command, " ", 1);
+ Tcl_DStringAppend(&command, (char *) args->object, -1);
+ Tcl_DStringAppend(&command, " ", 1);
+ Tcl_DStringAppend(&command, eiPtr->name, -1);
+ Tcl_DStringAppend(&command, " ", 1);
+ if (dPtr != NULL)
Tcl_DStringAppend(&command, dPtr->name, -1);
-
- Tcl_SaveResult(interp, &state);
- if (Tcl_EvalEx(interp, Tcl_DStringValue(&command),
- Tcl_DStringLength(&command), TCL_EVAL_GLOBAL) == TCL_OK)
- {
- QE_ExpandString(Tcl_GetStringFromObj(Tcl_GetObjResult(interp),
- NULL), args->result);
- }
- else
+ else
+ Tcl_DStringAppend(&command, "{}", -1);
+ if ((eiPtr->expandProc == Percents_Generate) ||
+ ((dPtr != NULL) && (dPtr->expandProc == Percents_Generate)))
+ {
+ GenerateData *genData = (GenerateData *) data->clientData;
+ int i;
+ for (i = 0; i < genData->count; i++)
{
- Tcl_AddErrorInfo(interp, "\n (expanding percents)");
- Tcl_BackgroundError(interp);
+ GenerateField *genField = &genData->field[i];
+ Tcl_DStringAppend(&command, " ", 1);
+ Tcl_DStringAppend(&command, &genField->which, 1);
+ Tcl_DStringAppend(&command, " ", 1);
+ Tcl_DStringAppend(&command, genField->string, -1);
}
- Tcl_RestoreResult(interp, &state);
-
- Tcl_DStringFree(&command);
}
+ Tcl_SaveResult(interp, &state);
+ if (Tcl_EvalEx(interp, Tcl_DStringValue(&command),
+ Tcl_DStringLength(&command), TCL_EVAL_GLOBAL) == TCL_OK)
+ {
+ QE_ExpandString(Tcl_GetStringFromObj(Tcl_GetObjResult(interp),
+ NULL), args->result);
+ }
+ else
+ {
+ Tcl_AddErrorInfo(interp, "\n (expanding percents)");
+ Tcl_BackgroundError(interp);
+ }
+ Tcl_RestoreResult(interp, &state);
+
+ Tcl_DStringFree(&command);
}
int QE_InstallCmd(QE_BindingTable bindingTable, int objOffset, int objc,
@@ -1816,15 +1897,15 @@ int QE_InstallCmd(QE_BindingTable bindingTable, int objOffset, int objc,
case 1: /* event */
{
- char *eventName;
- int id;
+ char *eventName, *command;
+ int id, length;
EventInfo *eiPtr;
Tcl_HashEntry *hPtr;
- if (objc - objOffset != 3)
+ if (objc - objOffset < 3 || objc - objOffset > 4)
{
Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv,
- "name");
+ "name ?percentsCommand?");
return TCL_ERROR;
}
@@ -1842,6 +1923,17 @@ int QE_InstallCmd(QE_BindingTable bindingTable, int objOffset, int objc,
/* Mark as installed-by-script */
eiPtr->dynamic = 1;
+
+ if (objc - objOffset == 3)
+ break;
+
+ /* Set the Tcl command for this event */
+ command = Tcl_GetStringFromObj(objv[objOffset + 3], &length);
+ if (length)
+ {
+ eiPtr->command = Tcl_Alloc(length + 1);
+ (void) strcpy(eiPtr->command, command);
+ }
break;
}
}