home *** CD-ROM | disk | FTP | other *** search
- /*
- * TmWidget.c --
- * This module contains the main set of functions
- * common to all widget types. ie it implements the
- * Tm Core widget stuff.
- *
- * Copyright 1993 Jan Newmarch, University of Canberra.
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The author
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #include "tm.h"
- #include "tmFuncs.h"
- #include <Xm/List.h>
- #include <Xm/Xm.h>
-
- XEvent *Tm_HackXEvent; /* needed for D&D to pass X event into XDragStart */
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_ParentWidgetFromPath --
- *
- * Given a Tm widget pathname, finds the parent Xt widget.
- *
- * Results:
- *
- * returns the Xt parent
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-
- Widget Tm_ParentWidgetFromPath (interp, pathName)
- Tcl_Interp *interp;
- char *pathName;
- {
- char *p;
- int numChars;
- Tm_Widget *info;
- Tcl_HashEntry *hPtr;
- Tcl_CmdInfo cmdInfo;
-
- /*
- * Strip the parent's name out of pathName (it's everything up
- * to the last dot). There are two tricky parts: (a) must
- * copy the parent's name somewhere else to avoid modifying
- * the pathName string (for large names, space for the copy
- * will have to be malloc'ed); (b) must special-case the
- * situation where the parent is ".".
- */
-
- p = strrchr(pathName, '.');
- if (p == NULL) {
- Tcl_AppendResult(interp, "bad window path name \"", pathName,
- "\"", (char *) NULL);
- return NULL;
- }
-
- numChars = p-pathName;
-
- p = (char *) XtMalloc((unsigned) (numChars+2));
- if (numChars == 0) {
- *p = '.';
- p[1] = '\0';
- } else {
- strncpy(p, pathName, numChars);
- p[numChars] = '\0';
- }
-
- /*
- hPtr = Tcl_FindHashEntry(&WidgetTable, p);
- if (hPtr == NULL) {
- */
- if (Tcl_GetCommandInfo(interp, p, &cmdInfo) == 0) {
- Tcl_AppendResult(interp, "no such widget \"", pathName,
- "\"", (char *) NULL);
- return NULL;
- }
- XtFree(p);
- /*
- info = (Tm_Widget *) Tcl_GetHashValue(hPtr);
- return (info->widget);
- */
- return ( ((Tm_Widget *) (cmdInfo.clientData))->widget);
- }
-
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_WidgetInfoFromPath --
- *
- * looks up the hash table to find the info about the widget
- *
- * Results:
- *
- * returns the widget info record.
- *
- * Side effects:
- *
- * none
- *--------------------------------------------------------------
- */
-
- Tm_Widget *
- Tm_WidgetInfoFromPath (interp, pathName)
- Tcl_Interp *interp;
- char *pathName;
- {
- #define FIXED_SPACE 5
- Tm_Widget *info;
- Tcl_HashEntry *hPtr;
- Tcl_CmdInfo cmdInfo;
-
- /*
- hPtr = Tcl_FindHashEntry(&WidgetTable, pathName);
- if (hPtr == NULL) {
- */
- if (Tcl_GetCommandInfo(interp, pathName, &cmdInfo) == 0) {
- Tcl_AppendResult(interp, "no such widget \"", pathName,
- "\"", (char *) NULL);
- return NULL;
- }
- /*
- info = (Tm_Widget *) Tcl_GetHashValue(hPtr);
- return (info);
- */
- return (Tm_Widget *) (cmdInfo.clientData);
- }
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_ActionsHandler --
- *
- * All actions are vectored through here.
- * It calls the Tcl command contained in the args
- *
- * Results:
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-
- void
- Tm_ActionsHandler(w, event, argv, argc)
- Widget w;
- XEvent *event;
- char **argv;
- Cardinal *argc;
- {
- Tm_Widget *wPtr;
- Tcl_Interp *interp;
- char *orig_command, *new_command;
- char *p_orig, *p_new;
- int size;
- int n;
- char *msg;
-
- XtVaGetValues(w, XmNuserData, &wPtr, NULL);
- interp = wPtr->interp;
-
- if (*argc < 1) {
- fprintf(stderr, "action must have an arg\n");
- }
-
- Tm_HackXEvent = event; /* hack to get value into XmDragStart */
-
- size = 128;
- orig_command = XtMalloc(size);
- *orig_command = '\0';
-
- for (n = 0; n < *argc; n++) {
- if (strlen(orig_command) + strlen(argv[n]) + 2 > size) {
- size = 2*size + strlen(argv[n]);
- orig_command = XtRealloc(orig_command, size);
- }
- strcat(orig_command, argv[n]);
- strcat(orig_command, " ");
- }
- p_orig = orig_command;
-
- new_command = Tm_ExpandPercents(wPtr->pathName, w, event,
- NULL, orig_command);
-
- if (Tcl_GlobalEval(interp, new_command) != TCL_OK) {
- msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if (msg == NULL) {
- msg = interp->result;
- }
- XtAppWarningMsg(XtWidgetToApplicationContext(w),
- "TclError", "TclError", "TclError", msg, NULL, 0);
- }
-
- /* record result in case callActionProc invoked this */
- if (Tm_SaveResult(interp))
- Tm_AppendResult(interp, interp->result);
-
- XtFree(orig_command);
- XtFree(new_command);
- }
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_WidgetCallbackHandler --
- *
- * nearly all callbacks are vectored through here.
- * It calls the appropriate callback with right
- * Tcl command
- *
- * Results:
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-
- void
- Tm_WidgetCallbackHandler(w, client_data, call_data)
- Widget w;
- XtPointer client_data;
- XtPointer call_data;
- {
- Tm_ClientData *c_data = (Tm_ClientData *) client_data;
- Tcl_Interp *interp;
- char *command;
- char *msg;
-
- interp = c_data->widget_info->interp;
- # ifdef DEBUG
- fprintf(stderr, "%s\n", (char *) c_data->callback_func);
- # endif
- command = Tm_ExpandPercents(c_data->widget_info->pathName,
- c_data->widget_info->widget,
- ((XmAnyCallbackStruct *) call_data)->event, call_data,
- (char *) c_data->callback_func);
- # ifdef DEBUG
- fprintf(stderr, "%% expanded command: %s\n", command);
- # endif
-
- if (Tcl_GlobalEval(interp, command) != TCL_OK) {
- msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if (msg == NULL) {
- msg = interp->result;
- }
- XtAppWarningMsg(XtWidgetToApplicationContext(w),
- "TclError", "TclError", "TclError", msg, NULL, 0);
- }
-
- if (Tm_SaveResult(interp))
- Tm_AppendResult(interp, interp->result);
-
- XtFree(command);
- }
-
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_DestroyWidgetHandler --
- *
- * nearly all callbacks are vectored through here.
- * It calls the appropriate callback with right
- * Tcl command
- *
- * Results:
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-
- void
- Tm_DestroyWidgetHandler(w, client_data, call_data)
- Widget w;
- XtPointer client_data;
- XtPointer call_data;
- {
- Tm_Widget *c_data = (Tm_Widget *) client_data;
- Tcl_Interp *interp;
- char *path;
- char *parent;
-
- interp = c_data->interp;
- path = c_data->pathName;
- parent = c_data->parent;
-
- Tcl_DeleteCommand(interp, path);
-
- XtFree(parent);
- XtFree(path);
- XtFree((char *) c_data);
-
- }
-
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_DestroyReclaimHandler --
- *
- * reclaim space in callback client data when widget
- * is destroyed
- *
- * Results:
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-
- void
- Tm_DestroyReclaimHandler(w, client_data, call_data)
- Widget w;
- XtPointer client_data;
- XtPointer call_data;
- {
- Tm_ClientData *c_data = (Tm_ClientData *) client_data;
-
- XtFree(c_data->callback_func);
- XtFree((char *) c_data);
- }
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_TextVerifyCallbackHandler --
- *
- * special case callback handler for Text Verify callbacks.
- * It calls the appropriate callback with right
- * Tcl command, then sets fields as needed by Text
- * (or will do)
- *
- * Results:
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-
- void
- Tm_TextVerifyCallbackHandler(w, client_data, call_data)
- Widget w;
- XtPointer client_data;
- XtPointer call_data;
- {
- Tm_ClientData *c_data = (Tm_ClientData *) client_data;
- XmTextVerifyCallbackStruct *verify_data =
- (XmTextVerifyCallbackStruct *) call_data;
- Tcl_Interp *interp;
- char *path;
- char *msg;
- char *command;
- int doit;
- XmTextPosition startPos, endPos;
- char *ptr;
- int length;
- char buf_startPos[128];
- char buf_endPos[128];
- char buf_length[128];
- char buf[128];
- char *buf_ptr;
-
- interp = c_data->widget_info->interp;
- path = c_data->widget_info->pathName;
-
- /* in here we have to set tcl vbls to the values of the callback fields
- and afterwards get their values and set them in the callback data
- */
- if (verify_data->doit)
- Tcl_SetVar(interp, TM_TEXT_DOIT, "true", TCL_GLOBAL_ONLY);
- else
- Tcl_SetVar(interp, TM_TEXT_DOIT, "false", TCL_GLOBAL_ONLY);
-
- sprintf(buf_startPos, "%ld", verify_data->startPos);
- Tcl_SetVar(interp, TM_TEXT_STARTPOS, buf_startPos, TCL_GLOBAL_ONLY);
-
- sprintf(buf_endPos, "%ld", verify_data->endPos);
- Tcl_SetVar(interp, TM_TEXT_ENDPOS, buf_endPos, TCL_GLOBAL_ONLY);
-
- if (verify_data->reason == XmCR_MODIFYING_TEXT_VALUE) {
- length = verify_data->text->length;
- buf_ptr = XtMalloc(length + 1);
- strncpy(buf_ptr, verify_data->text->ptr, length);
- buf_ptr[length] = '\0';
- Tcl_SetVar(interp, TM_TEXT_PTR, buf_ptr, TCL_GLOBAL_ONLY);
-
- sprintf(buf_length, "%d", length);
- Tcl_SetVar(interp, TM_TEXT_LENGTH, buf_length, TCL_GLOBAL_ONLY);
- } else {
- Tcl_SetVar(interp, TM_TEXT_PTR, "", TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, TM_TEXT_LENGTH, "0", TCL_GLOBAL_ONLY);
- buf_ptr = NULL;
- }
-
-
- command = Tm_ExpandPercents(c_data->widget_info->pathName,
- c_data->widget_info->widget,
- ((XmAnyCallbackStruct *) call_data)->event, call_data,
- (char *) c_data->callback_func);
- if (Tcl_GlobalEval(interp, command) != TCL_OK) {
- msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if (msg == NULL) {
- msg = interp->result;
- }
- XtAppWarningMsg(XtWidgetToApplicationContext(w),
- "TclError", "TclError", "TclError", msg, NULL, 0);
- XtFree(command);
- XtFree(buf_ptr);
- return;
- }
- XtFree(command);
-
- if (Tm_SaveResult(interp))
- Tm_AppendResult(interp, interp->result);
-
- /* now set results back into callback struct for Text */
- msg = Tcl_GetVar(interp, TM_TEXT_DOIT, TCL_GLOBAL_ONLY);
- if (Tcl_GetBoolean(interp, msg, &doit) == TCL_ERROR) {
- XtAppWarningMsg(XtWidgetToApplicationContext(w),
- "TclError", "TclError", "TclError", msg, NULL, 0);
- XtFree(buf_ptr);
- return;
- }
- verify_data->doit = doit;
-
- if (verify_data->reason != XmCR_MODIFYING_TEXT_VALUE) {
- return;
- }
-
- msg = Tcl_GetVar(interp, TM_TEXT_STARTPOS, TCL_GLOBAL_ONLY);
- if (strcmp(msg, buf_startPos) != 0) {
- /* no error checks here - need Tcl_GetLong */
- startPos = strtol(msg, NULL, 0);
- verify_data->startPos = startPos;
- }
-
- msg = Tcl_GetVar(interp, TM_TEXT_ENDPOS, TCL_GLOBAL_ONLY);
- if (strcmp(msg, buf_endPos) != 0) {
- /* no error checks here - need Tcl_GetLong */
- endPos = strtol(msg, NULL, 0);
- verify_data->endPos = endPos;
- }
- msg = Tcl_GetVar(interp, TM_TEXT_PTR, TCL_GLOBAL_ONLY);
- if (strcmp(msg, buf_ptr) != 0) {
- XtFree(verify_data->text->ptr);
- verify_data->text->ptr = XtNewString(msg);
- }
- msg = Tcl_GetVar(interp, TM_TEXT_LENGTH, TCL_GLOBAL_ONLY);
- if (strcmp(msg, buf_length) != 0) {
- if (Tcl_GetInt(interp, msg, &length) == TCL_ERROR) {
- XtAppWarningMsg(XtWidgetToApplicationContext(w),
- "TclError", "TclError", "TclError", msg, NULL, 0);
- XtFree(buf_ptr);
- return;
- }
- verify_data->text->length = length;
- }
- XtFree(buf_ptr);
- }
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_InputHandler --
- *
- * Results:
- * none
- *
- * Side effects:
- * could be any - this handles any Xt input
- *
- *--------------------------------------------------------------
- */
-
- /* ARGSUSED */
- void
- Tm_InputHandler(clientData, source, id)
- XtPointer clientData;
- int *source;
- XtInputId *id;
- {
- Tm_InputData *i_data = (Tm_InputData *) clientData;
- Tcl_Interp *interp = i_data->interp;
- char *command = i_data->command;
- char *message;
-
- /* should "expand percents" first */
- if (Tcl_Eval(interp, command) != TCL_OK) {
- message = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if (message == NULL) {
- message = interp->result;
- }
- /* we don't have an AppContext for an XtAppWarningMessage! */
- fprintf(stderr, "%s\n", message);
- }
- }
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_TimerHandler --
- *
- * Results:
- * none
- *
- * Side effects:
- * could be any - this handles any Xt timer
- *
- *--------------------------------------------------------------
- */
-
- void
- Tm_TimerHandler(clientData, id)
- XtPointer clientData;
- XtIntervalId *id;
- {
- Tm_TimerData *t_data = (Tm_TimerData *) clientData;
- Tcl_Interp *interp = t_data->interp;
- char *command = t_data->command;
- char *message;
-
- /* should "expand percents" first */
- if (Tcl_Eval(interp, command) != TCL_OK) {
- message = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if (message == NULL) {
- message = interp->result;
- }
- /* we don't have an AppContext for an XtAppWarningMessage! */
- fprintf(stderr, "%s\n", message);
- }
- XtFree(command);
- XtFree((char *) clientData);
- }
-
-
- /*
- *--------------------------------------------------------------
- *
- * Tm_GetGC --
- *
- * get a graphics context attached to a widget
- *
- * Results:
- *
- * Side effects:
- *
- *--------------------------------------------------------------
- */
-
- char *
- Tm_GetGC(pathName, interp, w, class, argv, argc)
- char *pathName;
- Tcl_Interp *interp;
- Widget w;
- WidgetClass class;
- char **argv;
- int argc;
- {
- XrmValue from, converted;
- char *new_value;
- char *resource;
- XGCValues gc_value;
- XtGCMask mask = 0;
- GC gc;
- char *buf;
-
- while (argc >= 2) {
- if (argv[0][0] != '-') {
- fprintf(stderr, "Skipping argument %s\n", argv[0]);
- argc -= 2; argv += 2;
- continue;
- }
- resource = argv[0]+1;
-
- if (strcmp(resource, XmNforeground) == 0) {
- if (Tm_ConvertValue(w, XmRString, argv[1], strlen(argv[1]),
- XmRPixel, &gc_value.foreground, sizeof(unsigned long))) {
- mask |= GCForeground;
- }
- } else
-
- if (strcmp(resource, XmNbackground) == 0) {
- if (Tm_ConvertValue(w, XmRString, argv[1], strlen(argv[1]),
- XmRPixel, &gc_value.background, sizeof(unsigned long))) {
- mask |= GCBackground;
- }
- } else
-
- if (strcmp(resource, XmNfont) == 0) {
- if (Tm_ConvertValue(w, XmRString, argv[1], strlen(argv[1]),
- XmRFont, &gc_value.font, sizeof(unsigned long))) {
- mask |= GCFont;
- }
- }
- argc -= 2;
- argv += 2;
- }
-
- buf = XtMalloc(16);
- gc = XtGetGC(w, mask, &gc_value);
- /* %p may be broken on the Sun, so fit into an XtArgVal
- sprintf(buf, "%p", (void *) gc);
- */
- /* allow simple type checking: prefix value with "gc-" */
- sprintf(buf, "gc-%lu", (long) gc);
- return buf;
- }
-