diff options
Diffstat (limited to 'libXaw/src')
48 files changed, 46796 insertions, 46796 deletions
diff --git a/libXaw/src/Actions.c b/libXaw/src/Actions.c index b927e6ac5..996db3180 100644 --- a/libXaw/src/Actions.c +++ b/libXaw/src/Actions.c @@ -1,1137 +1,1137 @@ -/*
- * Copyright (c) 1998 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the XFree86 Project shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from the
- * XFree86 Project.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <X11/Xmd.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/CoreP.h>
-#include <X11/Constraint.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xfuncs.h>
-#include "Private.h"
-
-#ifdef __UNIXOS2__
-static char dummy;
-#endif
-
-#ifndef OLDXAW
-
-/*
- * Definitions
- */
-#define ERROR -2
-#define END -1
-#define BOOLEAN 0
-#define AND '&'
-#define OR '|'
-#define XOR '^'
-#define NOT '~'
-#define LP '('
-#define RP ')'
-
-/*
- * Types
- */
-/* boolean expressions */
-typedef struct _XawEvalInfo {
- Widget widget;
- XawActionResList *rlist;
- XawActionVarList *vlist;
- XawParseBooleanProc parse_proc;
- XEvent *event;
- char *cp, *lp;
- int token;
- Bool value;
-} XawEvalInfo;
-
-/* resources */
-typedef struct _XawActionRes {
- XrmQuark qname;
- XrmQuark qtype;
- Cardinal size;
-} XawActionRes;
-
-struct _XawActionResList {
- WidgetClass widget_class;
- XawActionRes **resources;
- Cardinal num_common_resources;
- Cardinal num_constraint_resources;
-};
-
-/* variables */
-typedef struct _XawActionVar {
- XrmQuark qname;
- XrmQuark qvalue;
-} XawActionVar;
-
-struct _XawActionVarList {
- Widget widget;
- Cardinal num_variables;
- XawActionVar **variables;
-};
-
-/*
- * Private methods
- */
-/* expressions */
-static int get_token(XawEvalInfo*);
-static Bool expr(XawEvalInfo*);
-static Bool and(XawEvalInfo*);
-static Bool prim(XawEvalInfo*);
-
-/* resources */
-static String XawConvertActionRes(XawActionResList*, Widget w, String);
-
-static String _XawEscapeActionVarValue(String);
-static String _XawUnescapeActionVarValue(String);
-static XawActionResList *_XawCreateActionResList(WidgetClass);
-static XawActionResList *_XawFindActionResList(WidgetClass);
-static void _XawBindActionResList(XawActionResList*);
-static XawActionRes *_XawFindActionRes(XawActionResList*, Widget, String);
-static int qcmp_action_resource_list(_Xconst void*, _Xconst void*);
-static int bcmp_action_resource_list(_Xconst void*, _Xconst void*);
-static int qcmp_action_resource(_Xconst void*, _Xconst void*);
-static int bcmp_action_resource(_Xconst void*, _Xconst void*);
-
-/* variables */
-static String XawConvertActionVar(XawActionVarList*, String);
-static void XawDeclareActionVar(XawActionVarList*, String, String);
-
-static XawActionVarList *_XawCreateActionVarList(Widget);
-static XawActionVarList *_XawFindActionVarList(Widget);
-static XawActionVar *_XawCreateActionVar(XawActionVarList*, String);
-static XawActionVar *_XawFindActionVar(XawActionVarList*, String);
-static void _XawDestroyActionVarList(Widget, XtPointer, XtPointer);
-
-/*
- * Initialization
- */
-/* resources */
-static XawActionResList **resource_list;
-static Cardinal num_resource_list;
-
-/* variables */
-static XawActionVarList **variable_list;
-static Cardinal num_variable_list;
-
-/*
- * Implementation
- */
-/*
- * Start of Boolean Expression Evaluation Implementation Code
- */
-Bool
-XawParseBoolean(Widget w, String param, XEvent *event, Bool *succed)
-{
- char *tmp = param;
- int value;
-
- if (!param)
- return (False);
-
- value = (int)strtod(param, &tmp);
- if (*tmp == '\0')
- return (value);
-
- if (XmuCompareISOLatin1(param, "true") == 0
- || XmuCompareISOLatin1(param, "yes") == 0
- || XmuCompareISOLatin1(param, "on") == 0
- || XmuCompareISOLatin1(param, "in") == 0
- || XmuCompareISOLatin1(param, "up") == 0)
- return (True);
- else if (XmuCompareISOLatin1(param, "false") == 0
- || XmuCompareISOLatin1(param, "no") == 0
- || XmuCompareISOLatin1(param, "off") == 0
- || XmuCompareISOLatin1(param, "out") == 0
- || XmuCompareISOLatin1(param, "down") == 0)
- ;
- else if (XmuCompareISOLatin1(param, "my") == 0
- || XmuCompareISOLatin1(param, "mine") == 0)
- return (event->xany.window == XtWindow(w));
- else if (XmuCompareISOLatin1(param, "faked") == 0)
- return (event->xany.send_event != 0);
- else
- *succed = False;
-
- return (False);
-}
-
-Bool
-XawBooleanExpression(Widget w, String param, XEvent *event)
-{
- XawEvalInfo info;
- Bool retval;
-
- if (!param)
- return (False);
-
- info.widget = w;
-
- info.rlist = XawGetActionResList(XtClass(w));
- info.vlist = XawGetActionVarList(w);
-
- /*
- * Verify widget class, in case we will allow the parse proc procedure
- * as a widget class element, or if we allow overriding the default
- * parse boolean proc.
- */
- info.parse_proc = XawParseBoolean;
-
- info.event = event;
- info.cp = info.lp = param;
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "(*) Parsing expression \"%s\"\n", param);
-#endif
-
- (void)get_token(&info);
- if (info.token == ERROR)
- return (False);
- retval = expr(&info);
-
- return (info.token != ERROR ? retval : False);
-}
-
-static int
-get_token(XawEvalInfo *info)
-{
- int ch;
- char *p, name[256];
-
- info->lp = info->cp;
-
- /*COSTCOND*/
- while (1) /* eat white spaces */
- {
- ch = *info->cp++;
- if (isspace(ch))
- continue;
- break;
- }
-
- switch (ch)
- {
- case AND: case OR: case XOR: case NOT: case LP: case RP:
- return (info->token = ch);
- }
-
- /* It's a symbol name, resolve it. */
- if (ch == XAW_PRIV_VAR_PREFIX || isalnum(ch) || ch == '_' || ch == '\\')
- {
- Bool succed = True;
-
- p = info->cp - 1;
-
- while ((ch = *info->cp) && (isalnum(ch) || ch == '_'))
- ++info->cp;
-
- strncpy(name, p, XawMin((int)sizeof(name) - 1,
- (unsigned)(info->cp - p)));
- name[XawMin((int)sizeof(name) -1, info->cp - p)] = '\0';
-
- if (name[0] == XAW_PRIV_VAR_PREFIX)
- {
- String value = XawConvertActionVar(info->vlist, name);
-
- info->value = info->parse_proc(info->widget, value, info->event,
- &succed) & 1;
- }
- else
- {
- info->value = info->parse_proc(info->widget, name, info->event,
- &succed) & 1;
- if (!succed)
- {
- String value =
- XawConvertActionRes(info->rlist, info->widget,
- name[0] == '\\' ? &name[1] : name);
- /* '\\' may have been used to escape a resource name.
- */
-
- succed = True;
- info->value = info->parse_proc(info->widget, value, info->event,
- &succed) & 1;
- if (!succed)
- {
- /* not a numeric value or boolean string */
- info->value = True;
- succed = True;
- }
- }
- }
- if (succed)
- return (info->token = BOOLEAN);
- }
- else if (ch == '\0')
- return (info->token = END);
-
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "evaluate(): bad token \"%c\" at \"%s\"", ch, info->cp - 1);
-
- XtAppWarning(XtWidgetToApplicationContext(info->widget), msg);
- }
-
- return (info->token = ERROR);
-}
-
-static Bool
-expr(XawEvalInfo *info)
-{
- Bool left = and(info);
-
- for (;;)
- switch (info->token)
- {
- case OR:
- (void)get_token(info);
- left |= and(info);
- break;
- case XOR:
- (void)get_token(info);
- left ^= and(info);
- break;
- default:
- return (left);
- }
- /* NOTREACHED */
-}
-
-static Bool
-and(XawEvalInfo *info)
-{
- Bool left = prim(info);
-
- for (;;)
- switch (info->token)
- {
- case AND:
- (void)get_token(info);
- left &= prim(info);
- break;
- default:
- return (left);
- }
- /* NOTREACHED */
-}
-
-static Bool
-prim(XawEvalInfo *info)
-{
- Bool e;
-
- switch (info->token)
- {
- case BOOLEAN:
- e = info->value;
- (void)get_token(info);
- return (e);
- case NOT:
- (void)get_token(info);
- return (!prim(info));
- case LP:
- (void)get_token(info);
- e = expr(info);
- if (info->token != RP)
- {
- char msg[256];
-
- info->token = ERROR;
- XmuSnprintf(msg, sizeof(msg),
- "evaluate(): expecting ), at \"%s\"", info->lp);
- XtAppWarning(XtWidgetToApplicationContext(info->widget), msg);
- return (False);
- }
- (void)get_token(info);
- return (e);
- case END:
- return (True);
- default:
- {
- char msg[256];
-
- info->token = ERROR;
- XmuSnprintf(msg, sizeof(msg),
- "evaluate(): sintax error, at \"%s\"", info->lp);
- XtAppWarning(XtWidgetToApplicationContext(info->widget), msg);
- } return (False);
- }
- /* NOTREACHED */
-}
-
-/*
- * Start of Resources Implementation Code
- */
-void
-XawSetValuesAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- Arg *arglist;
- Cardinal num_args, count;
- XawActionResList *rlist;
- XawActionVarList *vlist;
- XawActionRes *resource;
- XrmValue from, to;
- String value;
- char c_1;
- short c_2;
- int c_4;
-#ifdef LONG64
- long c_8;
-#endif
-
- if (!(*num_params & 1))
- {
- XawPrintActionErrorMsg("set-values", w, params, num_params);
- return;
- }
-
- if (!XawBooleanExpression(w, params[0], event))
- return;
-
- rlist = XawGetActionResList(XtClass(w));
- vlist = XawGetActionVarList(w);
-
- num_args = 0;
- arglist = (Arg *)XtMalloc(sizeof(Arg) * ((*num_params) >> 1));
-
- for (count = 1; count < *num_params; count += 2)
- {
- if ((resource = _XawFindActionRes(rlist, w, params[count])) == NULL)
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "set-values(): bad resource name \"%s\"",
- params[count]);
- XtAppWarning(XtWidgetToApplicationContext(w), msg);
- continue;
- }
- value = XawConvertActionVar(vlist, params[count + 1]);
- from.size = strlen(value) + 1;
- from.addr = value;
- to.size = resource->size;
- switch (to.size)
- {
- case 1: to.addr = (XPointer)&c_1; break;
- case 2: to.addr = (XPointer)&c_2; break;
- case 4: to.addr = (XPointer)&c_4; break;
-#ifdef LONG64
- case 8: to.addr = (XPointer)&c_8; break;
-#endif
- default:
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "set-values(): bad resource size for \"%s\"",
- params[count]);
- XtAppWarning(XtWidgetToApplicationContext(w), msg);
- } continue;
- }
-
- if (strcmp(XtRString, XrmQuarkToString(resource->qtype)) == 0)
-#ifdef LONG64
- c_8 = (long)from.addr;
-#else
- c_4 = (int)from.addr;
-#endif
- else if (!XtConvertAndStore(w, XtRString, &from,
- XrmQuarkToString(resource->qtype), &to))
- continue;
-
- switch (to.size)
- {
- case 1:
- XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_1);
- break;
- case 2:
- XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_2);
- break;
- case 4:
- XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_4);
- break;
-#ifdef LONG64
- case 8:
- XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_8);
- break;
-#endif
- }
- ++num_args;
- }
-
- XtSetValues(w, arglist, num_args);
- XtFree((char *)arglist);
-}
-
-void
-XawGetValuesAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- XawActionResList *rlist;
- XawActionVarList *vlist;
- String value;
- Cardinal count;
-
- if (!(*num_params & 1))
- {
- XawPrintActionErrorMsg("get-values", w, params, num_params);
- return;
- }
- if (!XawBooleanExpression(w, params[0], event))
- return;
-
- rlist = XawGetActionResList(XtClass(w));
- vlist = XawGetActionVarList(w);
-
- for (count = 1; count < *num_params; count += 2)
- {
- if ((value = XawConvertActionRes(rlist, w, params[count + 1])) == NULL)
- continue;
- XawDeclareActionVar(vlist, params[count], value);
- }
-}
-
-void
-XawDeclareAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- XawActionVarList *vlist;
- Cardinal count;
-
- if (!(*num_params & 1))
- {
- XawPrintActionErrorMsg("declare", w, params, num_params);
- return;
- }
- if (!XawBooleanExpression(w, params[0], event))
- return;
-
- vlist = XawGetActionVarList(w);
-
- for (count = 1; count < *num_params; count += 2)
- XawDeclareActionVar(vlist, params[count], params[count + 1]);
-}
-
-void
-XawCallProcAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- String *args;
- Cardinal num_args;
-
- if (*num_params < 2)
- {
- XawPrintActionErrorMsg("call-proc", w, params, num_params);
- return;
- }
-
- if (*num_params && !XawBooleanExpression(w, params[0], event))
- return;
-
- if (*num_params > 2)
- {
- args = ¶ms[2];
- num_args = *num_params - 2;
- }
- else
- {
- args = NULL;
- num_args = 0;
- }
-
- XtCallActionProc(w, params[1], event, args, num_args);
-}
-
-static String
-XawConvertActionRes(XawActionResList *list, Widget w, String name)
-{
- XawActionRes *resource;
- XrmValue from, to;
- Arg arg;
- char c_1;
- short c_2;
- int c_4;
-#ifdef LONG64
- long c_8;
-#endif
-
- if ((resource = _XawFindActionRes(list, w, name)) == NULL)
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "convert(): bad resource name \"%s\"", name);
- XtAppWarning(XtWidgetToApplicationContext(w), msg);
- return (NULL);
- }
-
- from.size = resource->size;
- switch (from.size)
- {
- case 1:
- XtSetArg(arg, XrmQuarkToString(resource->qname),
- from.addr = (XPointer)&c_1);
- break;
- case 2:
- XtSetArg(arg, XrmQuarkToString(resource->qname),
- from.addr = (XPointer)&c_2);
- break;
- case 4:
- XtSetArg(arg, XrmQuarkToString(resource->qname),
- from.addr = (XPointer)&c_4);
- break;
-#ifdef LONG64
- case 8:
- XtSetArg(arg, XrmQuarkToString(resource->qname),
- from.addr = (XPointer)&c_8);
- break;
-#endif
- default:
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "convert(): bad resource size for \"%s\"", name);
- XtAppWarning(XtWidgetToApplicationContext(w), name);
- } return (NULL);
- }
-
- XtGetValues(w, &arg, 1);
- to.size = sizeof(String);
- to.addr = NULL;
-
- if (strcmp(XtRString, XrmQuarkToString(resource->qtype)) == 0)
- to.addr = *(char **)from.addr;
- else if (!XtConvertAndStore(w, XrmQuarkToString(resource->qtype),
- &from, XtRString, &to))
- return (NULL);
-
- return ((String)to.addr);
-}
-
-void
-XawPrintActionErrorMsg(String action_name, Widget w,
- String *params, Cardinal *num_params)
-{
- char msg[1024];
- unsigned int size, idx;
-
- size = XmuSnprintf(msg, sizeof(msg), "%s(): bad number of parameters.\n\t(",
- action_name);
-
- idx = 0;
- while (idx < *num_params - 1 && size < sizeof(msg))
- size += XmuSnprintf(&msg[size], sizeof(msg) - size, "%s, ",
- params[idx++]);
- if (*num_params)
- XmuSnprintf(&msg[size], sizeof(msg) - size, "%s)", params[idx]);
- else
- XmuSnprintf(&msg[size], sizeof(msg) - size, ")");
- XtAppWarning(XtWidgetToApplicationContext(w), msg);
-}
-
-XawActionResList *
-XawGetActionResList(WidgetClass wc)
-{
- XawActionResList *list;
-
- list = _XawFindActionResList(wc);
-
- if (!list)
- list = _XawCreateActionResList(wc);
-
- return (list);
-}
-
-static int
-qcmp_action_resource_list(register _Xconst void *left,
- register _Xconst void *right)
-{
- return ((char *)((*(XawActionResList **)left)->widget_class) -
- (char *)((*(XawActionResList **)right)->widget_class));
-}
-
-static XawActionResList *
-_XawCreateActionResList(WidgetClass wc)
-{
- XawActionResList *list;
-
- list = (XawActionResList *)XtMalloc(sizeof(XawActionResList));
- list->widget_class = wc;
- list->num_common_resources = list->num_constraint_resources = 0;
- list->resources = NULL;
-
- if (!resource_list)
- {
- num_resource_list = 1;
- resource_list = (XawActionResList **)XtMalloc(sizeof(XawActionResList*));
- resource_list[0] = list;
- }
- else
- {
- ++num_resource_list;
- resource_list = (XawActionResList **)XtRealloc((char *)resource_list,
- sizeof(XawActionResList*)
- * num_resource_list);
- resource_list[num_resource_list - 1] = list;
- qsort(resource_list, num_resource_list, sizeof(XawActionResList*),
- qcmp_action_resource_list);
- }
-
- _XawBindActionResList(list);
-
- return (list);
-}
-
-static int
-bcmp_action_resource_list(register _Xconst void *wc,
- register _Xconst void *list)
-{
- return ((char *)wc - (char *)((*(XawActionResList **)list)->widget_class));
-}
-
-static XawActionResList *
-_XawFindActionResList(WidgetClass wc)
-{
- XawActionResList **list;
-
- if (!resource_list)
- return (NULL);
-
- list = (XawActionResList **)bsearch(wc, resource_list,
- num_resource_list,
- sizeof(XawActionResList*),
- bcmp_action_resource_list);
-
- return (list ? *list : NULL);
-}
-
-static int
-qcmp_action_resource(register _Xconst void *left,
- register _Xconst void *right)
-{
- return (strcmp(XrmQuarkToString((*(XawActionRes **)left)->qname),
- XrmQuarkToString((*(XawActionRes **)right)->qname)));
-}
-
-static void
-_XawBindActionResList(XawActionResList *list)
-{
- XtResourceList xt_list, cons_list;
- Cardinal i, num_xt, num_cons;
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "(*) Creating resource list for class \'%s\'\n---------\n",
- list->widget_class->core_class.class_name);
-#endif
-
- XtGetResourceList(list->widget_class, &xt_list, &num_xt);
- XtGetConstraintResourceList(list->widget_class, &cons_list, &num_cons);
- list->num_common_resources = num_xt;
- list->num_constraint_resources = num_cons;
-
- list->resources = (XawActionRes **)
- XtMalloc(sizeof(XawActionRes*) * (num_xt + num_cons));
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "Common resources\n---\n");
-#endif
-
- for (i = 0; i < num_xt; i++)
- {
- list->resources[i] = (XawActionRes *)XtMalloc(sizeof(XawActionRes));
- list->resources[i]->qname =
- XrmPermStringToQuark(xt_list[i].resource_name);
- list->resources[i]->qtype =
- XrmPermStringToQuark(xt_list[i].resource_type);
- list->resources[i]->size = xt_list[i].resource_size;
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "%-20s\t%-20s\t(%d)\n",
- xt_list[i].resource_name,
- xt_list[i].resource_type,
- xt_list[i].resource_size);
-#endif
- }
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "---\nContraint resources\n---");
-#endif
-
- for (; i < num_xt + num_cons; i++)
- {
- list->resources[i] = (XawActionRes *)XtMalloc(sizeof(XawActionRes));
- list->resources[i]->qname =
- XrmPermStringToQuark(cons_list[i - num_xt].resource_name);
- list->resources[i]->qtype =
- XrmPermStringToQuark(cons_list[i - num_xt].resource_type);
- list->resources[i]->size = cons_list[i - num_xt].resource_size;
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "%-20s\t%-20s\t(%d)\n",
- cons_list[i - num_xt].resource_name,
- cons_list[i - num_xt].resource_type,
- cons_list[i - num_xt].resource_size);
-#endif
- }
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "---\n");
-#endif
-
- XtFree((char *)xt_list);
- if (cons_list)
- XtFree((char *)cons_list);
-
- qsort(list->resources, list->num_common_resources, sizeof(XawActionRes*),
- qcmp_action_resource);
- if (num_cons)
- qsort(&list->resources[num_xt], list->num_constraint_resources,
- sizeof(XawActionRes*), qcmp_action_resource);
-}
-
-static int
-bcmp_action_resource(register _Xconst void *string,
- register _Xconst void *resource)
-{
- return (strcmp((String)string,
- XrmQuarkToString((*(XawActionRes **)resource)->qname)));
-}
-
-static XawActionRes *
-_XawFindActionRes(XawActionResList *list, Widget detail, String name)
-{
- XawActionRes **res;
-
- if (!list->resources)
- return (NULL);
-
- res = (XawActionRes **)bsearch(name, list->resources,
- list->num_common_resources,
- sizeof(XawActionRes*), bcmp_action_resource);
-
- if (!res && XtParent(detail)
- && XtIsSubclass(XtParent(detail), constraintWidgetClass))
- {
- XawActionResList *cons = XawGetActionResList(XtClass(XtParent(detail)));
-
- if (cons)
- res = (XawActionRes **)
- bsearch(name, &cons->resources[cons->num_common_resources],
- cons->num_constraint_resources,
- sizeof(XawActionRes*), bcmp_action_resource);
- }
-
- return (res ? *res : NULL);
-}
-
-/*
- * Start of Variables Implementation Code
- */
-/* For speed, only does memory allocation when really required */
-static String
-_XawEscapeActionVarValue(String value)
-{
- String escape;
-
- if (value[0] == '$' || value[0] == '\\')
- {
- escape = XtMalloc(strlen(value) + 2);
- escape[0] = '\\';
- strcpy(escape + 1, value);
- return (escape);
- }
- return (NULL);
-}
-
-/* For speed, only does memory allocation when really required */
-static String
-_XawUnescapeActionVarValue(String value)
-{
- String unescape;
-
- if (value[0] == '\\')
- {
- unescape = XtMalloc(strlen(value));
- strcpy(unescape, value + 1);
- return (unescape);
- }
- return (NULL);
-}
-
-static void
-XawDeclareActionVar(XawActionVarList *list, String name, String value)
-{
- XawActionVar *variable;
- String escape = NULL;
-
- if (name[0] != XAW_PRIV_VAR_PREFIX)
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg), "declare(): variable name must begin with "
- "\'%c\', at %s = %s", XAW_PRIV_VAR_PREFIX, name, value);
- XtAppWarning(XtWidgetToApplicationContext(list->widget), msg);
- return;
- }
- variable = _XawFindActionVar(list, name);
- if (!variable)
- variable = _XawCreateActionVar(list, name);
- if (value)
- escape = _XawEscapeActionVarValue(value);
-
- if (variable->qvalue)
- {
- String val = escape ? escape : value;
-
- if (strcmp(XrmQuarkToString(variable->qvalue), val) == 0)
- {
- if (escape)
- XtFree(escape);
- return;
- }
- }
- variable->qvalue = (escape ? XrmStringToQuark(escape) :
- (value ? XrmStringToQuark(value) : NULLQUARK));
- if (escape)
- XtFree(escape);
-}
-
-static String
-XawConvertActionVar(XawActionVarList *list, String name)
-{
- XawActionVar *variable;
- String unescape;
- XrmQuark quark;
-
- if (name[0] != XAW_PRIV_VAR_PREFIX)
- return (name);
-
- variable = _XawFindActionVar(list, name);
- if (!variable || variable->qvalue == NULLQUARK)
- return (name);
- unescape = _XawUnescapeActionVarValue(XrmQuarkToString(variable->qvalue));
- if (unescape)
- {
- quark = XrmStringToQuark(unescape);
- XtFree(unescape);
- }
- else
- quark = variable->qvalue;
-
- return (XrmQuarkToString(quark));
-}
-
-XawActionVarList *
-XawGetActionVarList(Widget w)
-{
- XawActionVarList *list;
-
- list = _XawFindActionVarList(w);
- if (!list)
- list = _XawCreateActionVarList(w);
-
- return (list);
-}
-
-static int
-qcmp_action_variable_list(register _Xconst void *left,
- register _Xconst void *right)
-{
- return ((char *)((*(XawActionVarList **)left)->widget) -
- (char *)((*(XawActionVarList **)right)->widget));
-}
-
-static XawActionVarList *
-_XawCreateActionVarList(Widget w)
-{
- XawActionVarList *list;
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "(*) Creating action variable list for widget %s (%p)\n",
- XtName(w), w);
-#endif
-
- list = (XawActionVarList *)XtMalloc(sizeof(XawActionVarList));
- list->widget = w;
- list->num_variables = 0;
- list->variables = NULL;
-
- if (!variable_list)
- {
- num_variable_list = 1;
- variable_list = (XawActionVarList **)XtMalloc(sizeof(XawActionVarList*));
- variable_list[0] = list;
- }
- else
- {
- ++num_variable_list;
- variable_list = (XawActionVarList **)
- XtRealloc((char *)variable_list,
- sizeof(XawActionVarList *) * num_variable_list);
- variable_list[num_variable_list - 1] = list;
- qsort(variable_list, num_variable_list, sizeof(XawActionVarList*),
- qcmp_action_variable_list);
- }
-
- XtAddCallback(w, XtNdestroyCallback, _XawDestroyActionVarList,
- (XtPointer)list);
-
- return (list);
-}
-
-static int
-bcmp_action_variable_list(register _Xconst void *widget,
- register _Xconst void *list)
-{
- return ((char *)widget - (char *)((*(XawActionVarList **)list)->widget));
-}
-
-static XawActionVarList *
-_XawFindActionVarList(Widget w)
-{
- XawActionVarList **list;
-
- if (!num_variable_list)
- return (NULL);
-
- list = (XawActionVarList **)bsearch(w, variable_list, num_variable_list,
- sizeof(XawActionVarList*),
- bcmp_action_variable_list);
-
- return (list ? *list : NULL);
-}
-
-static int
-qcmp_action_variable(register _Xconst void *left,
- register _Xconst void *right)
-{
- return (strcmp(XrmQuarkToString((*(XawActionVar **)left)->qname),
- XrmQuarkToString((*(XawActionVar **)right)->qname)));
-}
-
-static XawActionVar *
-_XawCreateActionVar(XawActionVarList *list, String name)
-{
- XawActionVar *variable;
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "(*) Creating action variable '%s' for widget %s (%p)\n",
- name, XtName(list->widget), list->widget);
-#endif
-
- variable = (XawActionVar *)XtMalloc(sizeof(XawActionVar));
- variable->qname = XrmStringToQuark(name);
- variable->qvalue = NULLQUARK;
-
- if (!list->variables)
- {
- list->num_variables = 1;
- list->variables = (XawActionVar **)XtMalloc(sizeof(XawActionVar*));
- list->variables[0] = variable;
- }
- else
- {
- ++list->num_variables;
- list->variables = (XawActionVar **)XtRealloc((char *)list->variables,
- sizeof(XawActionVar *) *
- list->num_variables);
- list->variables[list->num_variables - 1] = variable;
- qsort(list->variables, list->num_variables, sizeof(XawActionVar*),
- qcmp_action_variable);
- }
- return (variable);
-}
-
-static int
-bcmp_action_variable(register _Xconst void *string,
- register _Xconst void *variable)
-{
- return (strcmp((String)string,
- XrmQuarkToString((*(XawActionVar **)variable)->qname)));
-}
-
-static XawActionVar *
-_XawFindActionVar(XawActionVarList *list, String name)
-{
- XawActionVar **var;
-
- if (!list->variables)
- return (NULL);
-
- var = (XawActionVar **)bsearch(name, list->variables, list->num_variables,
- sizeof(XawActionVar*), bcmp_action_variable);
-
- return (var ? *var : NULL);
-}
-
-/*ARGSUSED*/
-static void
-_XawDestroyActionVarList(Widget w, XtPointer client_data, XtPointer call_data)
-{
- XawActionVarList *list = (XawActionVarList *)client_data;
- Cardinal i;
-
- for (i = 0; i < num_variable_list; i++)
- if (variable_list[i] == list)
- break;
- if (i >= num_variable_list || list->widget != w
- || variable_list[i]->widget != w)
- {
- XtWarning("destroy-variable-list(): Bad widget argument.");
- return;
- }
- if (--num_variable_list > 0)
- {
- memmove(&variable_list[i], &variable_list[i + 1],
- (num_variable_list - i) * sizeof(XawActionVarList *));
- variable_list = (XawActionVarList **)
- XtRealloc((char *)variable_list, sizeof(XawActionVarList *) *
- num_variable_list);
- }
- else
- {
- XtFree((char *)variable_list);
- variable_list = NULL;
- }
-
- XtFree((char *)list->variables);
- XtFree((char *)list);
-}
-
-#endif /* OLDXAW */
+/* + * Copyright (c) 1998 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/Xmd.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/CoreP.h> +#include <X11/Constraint.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xfuncs.h> +#include "Private.h" + +#ifdef __UNIXOS2__ +static char dummy; +#endif + +#ifndef OLDXAW + +/* + * Definitions + */ +#define ERROR -2 +#define END -1 +#define BOOLEAN 0 +#define AND '&' +#define OR '|' +#define XOR '^' +#define NOT '~' +#define LP '(' +#define RP ')' + +/* + * Types + */ +/* boolean expressions */ +typedef struct _XawEvalInfo { + Widget widget; + XawActionResList *rlist; + XawActionVarList *vlist; + XawParseBooleanProc parse_proc; + XEvent *event; + char *cp, *lp; + int token; + Bool value; +} XawEvalInfo; + +/* resources */ +typedef struct _XawActionRes { + XrmQuark qname; + XrmQuark qtype; + Cardinal size; +} XawActionRes; + +struct _XawActionResList { + WidgetClass widget_class; + XawActionRes **resources; + Cardinal num_common_resources; + Cardinal num_constraint_resources; +}; + +/* variables */ +typedef struct _XawActionVar { + XrmQuark qname; + XrmQuark qvalue; +} XawActionVar; + +struct _XawActionVarList { + Widget widget; + Cardinal num_variables; + XawActionVar **variables; +}; + +/* + * Private methods + */ +/* expressions */ +static int get_token(XawEvalInfo*); +static Bool expr(XawEvalInfo*); +static Bool and(XawEvalInfo*); +static Bool prim(XawEvalInfo*); + +/* resources */ +static String XawConvertActionRes(XawActionResList*, Widget w, String); + +static String _XawEscapeActionVarValue(String); +static String _XawUnescapeActionVarValue(String); +static XawActionResList *_XawCreateActionResList(WidgetClass); +static XawActionResList *_XawFindActionResList(WidgetClass); +static void _XawBindActionResList(XawActionResList*); +static XawActionRes *_XawFindActionRes(XawActionResList*, Widget, String); +static int qcmp_action_resource_list(_Xconst void*, _Xconst void*); +static int bcmp_action_resource_list(_Xconst void*, _Xconst void*); +static int qcmp_action_resource(_Xconst void*, _Xconst void*); +static int bcmp_action_resource(_Xconst void*, _Xconst void*); + +/* variables */ +static String XawConvertActionVar(XawActionVarList*, String); +static void XawDeclareActionVar(XawActionVarList*, String, String); + +static XawActionVarList *_XawCreateActionVarList(Widget); +static XawActionVarList *_XawFindActionVarList(Widget); +static XawActionVar *_XawCreateActionVar(XawActionVarList*, String); +static XawActionVar *_XawFindActionVar(XawActionVarList*, String); +static void _XawDestroyActionVarList(Widget, XtPointer, XtPointer); + +/* + * Initialization + */ +/* resources */ +static XawActionResList **resource_list; +static Cardinal num_resource_list; + +/* variables */ +static XawActionVarList **variable_list; +static Cardinal num_variable_list; + +/* + * Implementation + */ +/* + * Start of Boolean Expression Evaluation Implementation Code + */ +Bool +XawParseBoolean(Widget w, String param, XEvent *event, Bool *succed) +{ + char *tmp = param; + int value; + + if (!param) + return (False); + + value = (int)strtod(param, &tmp); + if (*tmp == '\0') + return (value); + + if (XmuCompareISOLatin1(param, "true") == 0 + || XmuCompareISOLatin1(param, "yes") == 0 + || XmuCompareISOLatin1(param, "on") == 0 + || XmuCompareISOLatin1(param, "in") == 0 + || XmuCompareISOLatin1(param, "up") == 0) + return (True); + else if (XmuCompareISOLatin1(param, "false") == 0 + || XmuCompareISOLatin1(param, "no") == 0 + || XmuCompareISOLatin1(param, "off") == 0 + || XmuCompareISOLatin1(param, "out") == 0 + || XmuCompareISOLatin1(param, "down") == 0) + ; + else if (XmuCompareISOLatin1(param, "my") == 0 + || XmuCompareISOLatin1(param, "mine") == 0) + return (event->xany.window == XtWindow(w)); + else if (XmuCompareISOLatin1(param, "faked") == 0) + return (event->xany.send_event != 0); + else + *succed = False; + + return (False); +} + +Bool +XawBooleanExpression(Widget w, String param, XEvent *event) +{ + XawEvalInfo info; + Bool retval; + + if (!param) + return (False); + + info.widget = w; + + info.rlist = XawGetActionResList(XtClass(w)); + info.vlist = XawGetActionVarList(w); + + /* + * Verify widget class, in case we will allow the parse proc procedure + * as a widget class element, or if we allow overriding the default + * parse boolean proc. + */ + info.parse_proc = XawParseBoolean; + + info.event = event; + info.cp = info.lp = param; + +#ifdef DIAGNOSTIC + fprintf(stderr, "(*) Parsing expression \"%s\"\n", param); +#endif + + (void)get_token(&info); + if (info.token == ERROR) + return (False); + retval = expr(&info); + + return (info.token != ERROR ? retval : False); +} + +static int +get_token(XawEvalInfo *info) +{ + int ch; + char *p, name[256]; + + info->lp = info->cp; + + /*COSTCOND*/ + while (1) /* eat white spaces */ + { + ch = *info->cp++; + if (isspace(ch)) + continue; + break; + } + + switch (ch) + { + case AND: case OR: case XOR: case NOT: case LP: case RP: + return (info->token = ch); + } + + /* It's a symbol name, resolve it. */ + if (ch == XAW_PRIV_VAR_PREFIX || isalnum(ch) || ch == '_' || ch == '\\') + { + Bool succed = True; + + p = info->cp - 1; + + while ((ch = *info->cp) && (isalnum(ch) || ch == '_')) + ++info->cp; + + strncpy(name, p, XawMin((int)sizeof(name) - 1, + (unsigned)(info->cp - p))); + name[XawMin((int)sizeof(name) -1, info->cp - p)] = '\0'; + + if (name[0] == XAW_PRIV_VAR_PREFIX) + { + String value = XawConvertActionVar(info->vlist, name); + + info->value = info->parse_proc(info->widget, value, info->event, + &succed) & 1; + } + else + { + info->value = info->parse_proc(info->widget, name, info->event, + &succed) & 1; + if (!succed) + { + String value = + XawConvertActionRes(info->rlist, info->widget, + name[0] == '\\' ? &name[1] : name); + /* '\\' may have been used to escape a resource name. + */ + + succed = True; + info->value = info->parse_proc(info->widget, value, info->event, + &succed) & 1; + if (!succed) + { + /* not a numeric value or boolean string */ + info->value = True; + succed = True; + } + } + } + if (succed) + return (info->token = BOOLEAN); + } + else if (ch == '\0') + return (info->token = END); + + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "evaluate(): bad token \"%c\" at \"%s\"", ch, info->cp - 1); + + XtAppWarning(XtWidgetToApplicationContext(info->widget), msg); + } + + return (info->token = ERROR); +} + +static Bool +expr(XawEvalInfo *info) +{ + Bool left = and(info); + + for (;;) + switch (info->token) + { + case OR: + (void)get_token(info); + left |= and(info); + break; + case XOR: + (void)get_token(info); + left ^= and(info); + break; + default: + return (left); + } + /* NOTREACHED */ +} + +static Bool +and(XawEvalInfo *info) +{ + Bool left = prim(info); + + for (;;) + switch (info->token) + { + case AND: + (void)get_token(info); + left &= prim(info); + break; + default: + return (left); + } + /* NOTREACHED */ +} + +static Bool +prim(XawEvalInfo *info) +{ + Bool e; + + switch (info->token) + { + case BOOLEAN: + e = info->value; + (void)get_token(info); + return (e); + case NOT: + (void)get_token(info); + return (!prim(info)); + case LP: + (void)get_token(info); + e = expr(info); + if (info->token != RP) + { + char msg[256]; + + info->token = ERROR; + XmuSnprintf(msg, sizeof(msg), + "evaluate(): expecting ), at \"%s\"", info->lp); + XtAppWarning(XtWidgetToApplicationContext(info->widget), msg); + return (False); + } + (void)get_token(info); + return (e); + case END: + return (True); + default: + { + char msg[256]; + + info->token = ERROR; + XmuSnprintf(msg, sizeof(msg), + "evaluate(): sintax error, at \"%s\"", info->lp); + XtAppWarning(XtWidgetToApplicationContext(info->widget), msg); + } return (False); + } + /* NOTREACHED */ +} + +/* + * Start of Resources Implementation Code + */ +void +XawSetValuesAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + Arg *arglist; + Cardinal num_args, count; + XawActionResList *rlist; + XawActionVarList *vlist; + XawActionRes *resource; + XrmValue from, to; + String value; + char c_1; + short c_2; + int c_4; +#ifdef LONG64 + long c_8; +#endif + + if (!(*num_params & 1)) + { + XawPrintActionErrorMsg("set-values", w, params, num_params); + return; + } + + if (!XawBooleanExpression(w, params[0], event)) + return; + + rlist = XawGetActionResList(XtClass(w)); + vlist = XawGetActionVarList(w); + + num_args = 0; + arglist = (Arg *)XtMalloc(sizeof(Arg) * ((*num_params) >> 1)); + + for (count = 1; count < *num_params; count += 2) + { + if ((resource = _XawFindActionRes(rlist, w, params[count])) == NULL) + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "set-values(): bad resource name \"%s\"", + params[count]); + XtAppWarning(XtWidgetToApplicationContext(w), msg); + continue; + } + value = XawConvertActionVar(vlist, params[count + 1]); + from.size = strlen(value) + 1; + from.addr = value; + to.size = resource->size; + switch (to.size) + { + case 1: to.addr = (XPointer)&c_1; break; + case 2: to.addr = (XPointer)&c_2; break; + case 4: to.addr = (XPointer)&c_4; break; +#ifdef LONG64 + case 8: to.addr = (XPointer)&c_8; break; +#endif + default: + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "set-values(): bad resource size for \"%s\"", + params[count]); + XtAppWarning(XtWidgetToApplicationContext(w), msg); + } continue; + } + + if (strcmp(XtRString, XrmQuarkToString(resource->qtype)) == 0) +#ifdef LONG64 + c_8 = (long)from.addr; +#else + c_4 = (int)from.addr; +#endif + else if (!XtConvertAndStore(w, XtRString, &from, + XrmQuarkToString(resource->qtype), &to)) + continue; + + switch (to.size) + { + case 1: + XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_1); + break; + case 2: + XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_2); + break; + case 4: + XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_4); + break; +#ifdef LONG64 + case 8: + XtSetArg(arglist[num_args], XrmQuarkToString(resource->qname), c_8); + break; +#endif + } + ++num_args; + } + + XtSetValues(w, arglist, num_args); + XtFree((char *)arglist); +} + +void +XawGetValuesAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + XawActionResList *rlist; + XawActionVarList *vlist; + String value; + Cardinal count; + + if (!(*num_params & 1)) + { + XawPrintActionErrorMsg("get-values", w, params, num_params); + return; + } + if (!XawBooleanExpression(w, params[0], event)) + return; + + rlist = XawGetActionResList(XtClass(w)); + vlist = XawGetActionVarList(w); + + for (count = 1; count < *num_params; count += 2) + { + if ((value = XawConvertActionRes(rlist, w, params[count + 1])) == NULL) + continue; + XawDeclareActionVar(vlist, params[count], value); + } +} + +void +XawDeclareAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + XawActionVarList *vlist; + Cardinal count; + + if (!(*num_params & 1)) + { + XawPrintActionErrorMsg("declare", w, params, num_params); + return; + } + if (!XawBooleanExpression(w, params[0], event)) + return; + + vlist = XawGetActionVarList(w); + + for (count = 1; count < *num_params; count += 2) + XawDeclareActionVar(vlist, params[count], params[count + 1]); +} + +void +XawCallProcAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + String *args; + Cardinal num_args; + + if (*num_params < 2) + { + XawPrintActionErrorMsg("call-proc", w, params, num_params); + return; + } + + if (*num_params && !XawBooleanExpression(w, params[0], event)) + return; + + if (*num_params > 2) + { + args = ¶ms[2]; + num_args = *num_params - 2; + } + else + { + args = NULL; + num_args = 0; + } + + XtCallActionProc(w, params[1], event, args, num_args); +} + +static String +XawConvertActionRes(XawActionResList *list, Widget w, String name) +{ + XawActionRes *resource; + XrmValue from, to; + Arg arg; + char c_1; + short c_2; + int c_4; +#ifdef LONG64 + long c_8; +#endif + + if ((resource = _XawFindActionRes(list, w, name)) == NULL) + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "convert(): bad resource name \"%s\"", name); + XtAppWarning(XtWidgetToApplicationContext(w), msg); + return (NULL); + } + + from.size = resource->size; + switch (from.size) + { + case 1: + XtSetArg(arg, XrmQuarkToString(resource->qname), + from.addr = (XPointer)&c_1); + break; + case 2: + XtSetArg(arg, XrmQuarkToString(resource->qname), + from.addr = (XPointer)&c_2); + break; + case 4: + XtSetArg(arg, XrmQuarkToString(resource->qname), + from.addr = (XPointer)&c_4); + break; +#ifdef LONG64 + case 8: + XtSetArg(arg, XrmQuarkToString(resource->qname), + from.addr = (XPointer)&c_8); + break; +#endif + default: + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "convert(): bad resource size for \"%s\"", name); + XtAppWarning(XtWidgetToApplicationContext(w), name); + } return (NULL); + } + + XtGetValues(w, &arg, 1); + to.size = sizeof(String); + to.addr = NULL; + + if (strcmp(XtRString, XrmQuarkToString(resource->qtype)) == 0) + to.addr = *(char **)from.addr; + else if (!XtConvertAndStore(w, XrmQuarkToString(resource->qtype), + &from, XtRString, &to)) + return (NULL); + + return ((String)to.addr); +} + +void +XawPrintActionErrorMsg(String action_name, Widget w, + String *params, Cardinal *num_params) +{ + char msg[1024]; + unsigned int size, idx; + + size = XmuSnprintf(msg, sizeof(msg), "%s(): bad number of parameters.\n\t(", + action_name); + + idx = 0; + while (idx < *num_params - 1 && size < sizeof(msg)) + size += XmuSnprintf(&msg[size], sizeof(msg) - size, "%s, ", + params[idx++]); + if (*num_params) + XmuSnprintf(&msg[size], sizeof(msg) - size, "%s)", params[idx]); + else + XmuSnprintf(&msg[size], sizeof(msg) - size, ")"); + XtAppWarning(XtWidgetToApplicationContext(w), msg); +} + +XawActionResList * +XawGetActionResList(WidgetClass wc) +{ + XawActionResList *list; + + list = _XawFindActionResList(wc); + + if (!list) + list = _XawCreateActionResList(wc); + + return (list); +} + +static int +qcmp_action_resource_list(register _Xconst void *left, + register _Xconst void *right) +{ + return ((char *)((*(XawActionResList **)left)->widget_class) - + (char *)((*(XawActionResList **)right)->widget_class)); +} + +static XawActionResList * +_XawCreateActionResList(WidgetClass wc) +{ + XawActionResList *list; + + list = (XawActionResList *)XtMalloc(sizeof(XawActionResList)); + list->widget_class = wc; + list->num_common_resources = list->num_constraint_resources = 0; + list->resources = NULL; + + if (!resource_list) + { + num_resource_list = 1; + resource_list = (XawActionResList **)XtMalloc(sizeof(XawActionResList*)); + resource_list[0] = list; + } + else + { + ++num_resource_list; + resource_list = (XawActionResList **)XtRealloc((char *)resource_list, + sizeof(XawActionResList*) + * num_resource_list); + resource_list[num_resource_list - 1] = list; + qsort(resource_list, num_resource_list, sizeof(XawActionResList*), + qcmp_action_resource_list); + } + + _XawBindActionResList(list); + + return (list); +} + +static int +bcmp_action_resource_list(register _Xconst void *wc, + register _Xconst void *list) +{ + return ((char *)wc - (char *)((*(XawActionResList **)list)->widget_class)); +} + +static XawActionResList * +_XawFindActionResList(WidgetClass wc) +{ + XawActionResList **list; + + if (!resource_list) + return (NULL); + + list = (XawActionResList **)bsearch(wc, resource_list, + num_resource_list, + sizeof(XawActionResList*), + bcmp_action_resource_list); + + return (list ? *list : NULL); +} + +static int +qcmp_action_resource(register _Xconst void *left, + register _Xconst void *right) +{ + return (strcmp(XrmQuarkToString((*(XawActionRes **)left)->qname), + XrmQuarkToString((*(XawActionRes **)right)->qname))); +} + +static void +_XawBindActionResList(XawActionResList *list) +{ + XtResourceList xt_list, cons_list; + Cardinal i, num_xt, num_cons; + +#ifdef DIAGNOSTIC + fprintf(stderr, "(*) Creating resource list for class \'%s\'\n---------\n", + list->widget_class->core_class.class_name); +#endif + + XtGetResourceList(list->widget_class, &xt_list, &num_xt); + XtGetConstraintResourceList(list->widget_class, &cons_list, &num_cons); + list->num_common_resources = num_xt; + list->num_constraint_resources = num_cons; + + list->resources = (XawActionRes **) + XtMalloc(sizeof(XawActionRes*) * (num_xt + num_cons)); + +#ifdef DIAGNOSTIC + fprintf(stderr, "Common resources\n---\n"); +#endif + + for (i = 0; i < num_xt; i++) + { + list->resources[i] = (XawActionRes *)XtMalloc(sizeof(XawActionRes)); + list->resources[i]->qname = + XrmPermStringToQuark(xt_list[i].resource_name); + list->resources[i]->qtype = + XrmPermStringToQuark(xt_list[i].resource_type); + list->resources[i]->size = xt_list[i].resource_size; + +#ifdef DIAGNOSTIC + fprintf(stderr, "%-20s\t%-20s\t(%d)\n", + xt_list[i].resource_name, + xt_list[i].resource_type, + xt_list[i].resource_size); +#endif + } + +#ifdef DIAGNOSTIC + fprintf(stderr, "---\nContraint resources\n---"); +#endif + + for (; i < num_xt + num_cons; i++) + { + list->resources[i] = (XawActionRes *)XtMalloc(sizeof(XawActionRes)); + list->resources[i]->qname = + XrmPermStringToQuark(cons_list[i - num_xt].resource_name); + list->resources[i]->qtype = + XrmPermStringToQuark(cons_list[i - num_xt].resource_type); + list->resources[i]->size = cons_list[i - num_xt].resource_size; + +#ifdef DIAGNOSTIC + fprintf(stderr, "%-20s\t%-20s\t(%d)\n", + cons_list[i - num_xt].resource_name, + cons_list[i - num_xt].resource_type, + cons_list[i - num_xt].resource_size); +#endif + } + +#ifdef DIAGNOSTIC + fprintf(stderr, "---\n"); +#endif + + XtFree((char *)xt_list); + if (cons_list) + XtFree((char *)cons_list); + + qsort(list->resources, list->num_common_resources, sizeof(XawActionRes*), + qcmp_action_resource); + if (num_cons) + qsort(&list->resources[num_xt], list->num_constraint_resources, + sizeof(XawActionRes*), qcmp_action_resource); +} + +static int +bcmp_action_resource(register _Xconst void *string, + register _Xconst void *resource) +{ + return (strcmp((String)string, + XrmQuarkToString((*(XawActionRes **)resource)->qname))); +} + +static XawActionRes * +_XawFindActionRes(XawActionResList *list, Widget detail, String name) +{ + XawActionRes **res; + + if (!list->resources) + return (NULL); + + res = (XawActionRes **)bsearch(name, list->resources, + list->num_common_resources, + sizeof(XawActionRes*), bcmp_action_resource); + + if (!res && XtParent(detail) + && XtIsSubclass(XtParent(detail), constraintWidgetClass)) + { + XawActionResList *cons = XawGetActionResList(XtClass(XtParent(detail))); + + if (cons) + res = (XawActionRes **) + bsearch(name, &cons->resources[cons->num_common_resources], + cons->num_constraint_resources, + sizeof(XawActionRes*), bcmp_action_resource); + } + + return (res ? *res : NULL); +} + +/* + * Start of Variables Implementation Code + */ +/* For speed, only does memory allocation when really required */ +static String +_XawEscapeActionVarValue(String value) +{ + String escape; + + if (value[0] == '$' || value[0] == '\\') + { + escape = XtMalloc(strlen(value) + 2); + escape[0] = '\\'; + strcpy(escape + 1, value); + return (escape); + } + return (NULL); +} + +/* For speed, only does memory allocation when really required */ +static String +_XawUnescapeActionVarValue(String value) +{ + String unescape; + + if (value[0] == '\\') + { + unescape = XtMalloc(strlen(value)); + strcpy(unescape, value + 1); + return (unescape); + } + return (NULL); +} + +static void +XawDeclareActionVar(XawActionVarList *list, String name, String value) +{ + XawActionVar *variable; + String escape = NULL; + + if (name[0] != XAW_PRIV_VAR_PREFIX) + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), "declare(): variable name must begin with " + "\'%c\', at %s = %s", XAW_PRIV_VAR_PREFIX, name, value); + XtAppWarning(XtWidgetToApplicationContext(list->widget), msg); + return; + } + variable = _XawFindActionVar(list, name); + if (!variable) + variable = _XawCreateActionVar(list, name); + if (value) + escape = _XawEscapeActionVarValue(value); + + if (variable->qvalue) + { + String val = escape ? escape : value; + + if (strcmp(XrmQuarkToString(variable->qvalue), val) == 0) + { + if (escape) + XtFree(escape); + return; + } + } + variable->qvalue = (escape ? XrmStringToQuark(escape) : + (value ? XrmStringToQuark(value) : NULLQUARK)); + if (escape) + XtFree(escape); +} + +static String +XawConvertActionVar(XawActionVarList *list, String name) +{ + XawActionVar *variable; + String unescape; + XrmQuark quark; + + if (name[0] != XAW_PRIV_VAR_PREFIX) + return (name); + + variable = _XawFindActionVar(list, name); + if (!variable || variable->qvalue == NULLQUARK) + return (name); + unescape = _XawUnescapeActionVarValue(XrmQuarkToString(variable->qvalue)); + if (unescape) + { + quark = XrmStringToQuark(unescape); + XtFree(unescape); + } + else + quark = variable->qvalue; + + return (XrmQuarkToString(quark)); +} + +XawActionVarList * +XawGetActionVarList(Widget w) +{ + XawActionVarList *list; + + list = _XawFindActionVarList(w); + if (!list) + list = _XawCreateActionVarList(w); + + return (list); +} + +static int +qcmp_action_variable_list(register _Xconst void *left, + register _Xconst void *right) +{ + return ((char *)((*(XawActionVarList **)left)->widget) - + (char *)((*(XawActionVarList **)right)->widget)); +} + +static XawActionVarList * +_XawCreateActionVarList(Widget w) +{ + XawActionVarList *list; + +#ifdef DIAGNOSTIC + fprintf(stderr, "(*) Creating action variable list for widget %s (%p)\n", + XtName(w), w); +#endif + + list = (XawActionVarList *)XtMalloc(sizeof(XawActionVarList)); + list->widget = w; + list->num_variables = 0; + list->variables = NULL; + + if (!variable_list) + { + num_variable_list = 1; + variable_list = (XawActionVarList **)XtMalloc(sizeof(XawActionVarList*)); + variable_list[0] = list; + } + else + { + ++num_variable_list; + variable_list = (XawActionVarList **) + XtRealloc((char *)variable_list, + sizeof(XawActionVarList *) * num_variable_list); + variable_list[num_variable_list - 1] = list; + qsort(variable_list, num_variable_list, sizeof(XawActionVarList*), + qcmp_action_variable_list); + } + + XtAddCallback(w, XtNdestroyCallback, _XawDestroyActionVarList, + (XtPointer)list); + + return (list); +} + +static int +bcmp_action_variable_list(register _Xconst void *widget, + register _Xconst void *list) +{ + return ((char *)widget - (char *)((*(XawActionVarList **)list)->widget)); +} + +static XawActionVarList * +_XawFindActionVarList(Widget w) +{ + XawActionVarList **list; + + if (!num_variable_list) + return (NULL); + + list = (XawActionVarList **)bsearch(w, variable_list, num_variable_list, + sizeof(XawActionVarList*), + bcmp_action_variable_list); + + return (list ? *list : NULL); +} + +static int +qcmp_action_variable(register _Xconst void *left, + register _Xconst void *right) +{ + return (strcmp(XrmQuarkToString((*(XawActionVar **)left)->qname), + XrmQuarkToString((*(XawActionVar **)right)->qname))); +} + +static XawActionVar * +_XawCreateActionVar(XawActionVarList *list, String name) +{ + XawActionVar *variable; + +#ifdef DIAGNOSTIC + fprintf(stderr, "(*) Creating action variable '%s' for widget %s (%p)\n", + name, XtName(list->widget), list->widget); +#endif + + variable = (XawActionVar *)XtMalloc(sizeof(XawActionVar)); + variable->qname = XrmStringToQuark(name); + variable->qvalue = NULLQUARK; + + if (!list->variables) + { + list->num_variables = 1; + list->variables = (XawActionVar **)XtMalloc(sizeof(XawActionVar*)); + list->variables[0] = variable; + } + else + { + ++list->num_variables; + list->variables = (XawActionVar **)XtRealloc((char *)list->variables, + sizeof(XawActionVar *) * + list->num_variables); + list->variables[list->num_variables - 1] = variable; + qsort(list->variables, list->num_variables, sizeof(XawActionVar*), + qcmp_action_variable); + } + return (variable); +} + +static int +bcmp_action_variable(register _Xconst void *string, + register _Xconst void *variable) +{ + return (strcmp((String)string, + XrmQuarkToString((*(XawActionVar **)variable)->qname))); +} + +static XawActionVar * +_XawFindActionVar(XawActionVarList *list, String name) +{ + XawActionVar **var; + + if (!list->variables) + return (NULL); + + var = (XawActionVar **)bsearch(name, list->variables, list->num_variables, + sizeof(XawActionVar*), bcmp_action_variable); + + return (var ? *var : NULL); +} + +/*ARGSUSED*/ +static void +_XawDestroyActionVarList(Widget w, XtPointer client_data, XtPointer call_data) +{ + XawActionVarList *list = (XawActionVarList *)client_data; + Cardinal i; + + for (i = 0; i < num_variable_list; i++) + if (variable_list[i] == list) + break; + if (i >= num_variable_list || list->widget != w + || variable_list[i]->widget != w) + { + XtWarning("destroy-variable-list(): Bad widget argument."); + return; + } + if (--num_variable_list > 0) + { + memmove(&variable_list[i], &variable_list[i + 1], + (num_variable_list - i) * sizeof(XawActionVarList *)); + variable_list = (XawActionVarList **) + XtRealloc((char *)variable_list, sizeof(XawActionVarList *) * + num_variable_list); + } + else + { + XtFree((char *)variable_list); + variable_list = NULL; + } + + XtFree((char *)list->variables); + XtFree((char *)list); +} + +#endif /* OLDXAW */ diff --git a/libXaw/src/AllWidgets.c b/libXaw/src/AllWidgets.c index 5d24e896b..27be437e5 100644 --- a/libXaw/src/AllWidgets.c +++ b/libXaw/src/AllWidgets.c @@ -1,118 +1,118 @@ -/*
-
-Copyright (c) 1991, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/Xmu/WidgetNode.h>
-#include <X11/Xaw/AllWidgets.h>
-
-extern WidgetClass applicationShellWidgetClass;
-extern WidgetClass asciiSinkObjectClass;
-extern WidgetClass asciiSrcObjectClass;
-extern WidgetClass asciiTextWidgetClass;
-extern WidgetClass boxWidgetClass;
-extern WidgetClass commandWidgetClass;
-extern WidgetClass dialogWidgetClass;
-extern WidgetClass formWidgetClass;
-extern WidgetClass gripWidgetClass;
-extern WidgetClass labelWidgetClass;
-extern WidgetClass listWidgetClass;
-extern WidgetClass menuButtonWidgetClass;
-extern WidgetClass multiSinkObjectClass;
-extern WidgetClass multiSrcObjectClass;
-extern WidgetClass overrideShellWidgetClass;
-extern WidgetClass panedWidgetClass;
-extern WidgetClass pannerWidgetClass;
-extern WidgetClass portholeWidgetClass;
-extern WidgetClass repeaterWidgetClass;
-extern WidgetClass scrollbarWidgetClass;
-extern WidgetClass shellWidgetClass;
-extern WidgetClass simpleMenuWidgetClass;
-extern WidgetClass simpleWidgetClass;
-extern WidgetClass smeBSBObjectClass;
-extern WidgetClass smeLineObjectClass;
-extern WidgetClass smeObjectClass;
-extern WidgetClass stripChartWidgetClass;
-extern WidgetClass textSinkObjectClass;
-extern WidgetClass textSrcObjectClass;
-extern WidgetClass textWidgetClass;
-extern WidgetClass toggleWidgetClass;
-extern WidgetClass topLevelShellWidgetClass;
-extern WidgetClass transientShellWidgetClass;
-extern WidgetClass treeWidgetClass;
-extern WidgetClass vendorShellWidgetClass;
-extern WidgetClass viewportWidgetClass;
-extern WidgetClass wmShellWidgetClass;
-
-XmuWidgetNode XawWidgetArray[] = {
-{ "applicationShell", &applicationShellWidgetClass },
-{ "asciiSink", &asciiSinkObjectClass },
-{ "asciiSrc", &asciiSrcObjectClass },
-{ "asciiText", &asciiTextWidgetClass },
-{ "box", &boxWidgetClass },
-{ "command", &commandWidgetClass },
-{ "composite", &compositeWidgetClass },
-{ "constraint", &constraintWidgetClass },
-{ "core", &coreWidgetClass },
-{ "dialog", &dialogWidgetClass },
-{ "form", &formWidgetClass },
-{ "grip", &gripWidgetClass },
-{ "label", &labelWidgetClass },
-{ "list", &listWidgetClass },
-{ "menuButton", &menuButtonWidgetClass },
-{ "multiSink", &multiSinkObjectClass },
-{ "multiSrc", &multiSrcObjectClass },
-{ "object", &objectClass },
-{ "overrideShell", &overrideShellWidgetClass },
-{ "paned", &panedWidgetClass },
-{ "panner", &pannerWidgetClass },
-{ "porthole", &portholeWidgetClass },
-{ "rect", &rectObjClass },
-{ "repeater", &repeaterWidgetClass },
-{ "scrollbar", &scrollbarWidgetClass },
-{ "shell", &shellWidgetClass },
-{ "simpleMenu", &simpleMenuWidgetClass },
-{ "simple", &simpleWidgetClass },
-{ "smeBSB", &smeBSBObjectClass },
-{ "smeLine", &smeLineObjectClass },
-{ "sme", &smeObjectClass },
-{ "stripChart", &stripChartWidgetClass },
-{ "textSink", &textSinkObjectClass },
-{ "textSrc", &textSrcObjectClass },
-{ "text", &textWidgetClass },
-{ "toggle", &toggleWidgetClass },
-{ "topLevelShell", &topLevelShellWidgetClass },
-{ "transientShell", &transientShellWidgetClass },
-{ "tree", &treeWidgetClass },
-{ "vendorShell", &vendorShellWidgetClass },
-{ "viewport", &viewportWidgetClass },
-{ "wmShell", &wmShellWidgetClass },
-};
-
-int XawWidgetCount = XtNumber(XawWidgetArray);
-
+/* + +Copyright (c) 1991, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/Xmu/WidgetNode.h> +#include <X11/Xaw/AllWidgets.h> + +extern WidgetClass applicationShellWidgetClass; +extern WidgetClass asciiSinkObjectClass; +extern WidgetClass asciiSrcObjectClass; +extern WidgetClass asciiTextWidgetClass; +extern WidgetClass boxWidgetClass; +extern WidgetClass commandWidgetClass; +extern WidgetClass dialogWidgetClass; +extern WidgetClass formWidgetClass; +extern WidgetClass gripWidgetClass; +extern WidgetClass labelWidgetClass; +extern WidgetClass listWidgetClass; +extern WidgetClass menuButtonWidgetClass; +extern WidgetClass multiSinkObjectClass; +extern WidgetClass multiSrcObjectClass; +extern WidgetClass overrideShellWidgetClass; +extern WidgetClass panedWidgetClass; +extern WidgetClass pannerWidgetClass; +extern WidgetClass portholeWidgetClass; +extern WidgetClass repeaterWidgetClass; +extern WidgetClass scrollbarWidgetClass; +extern WidgetClass shellWidgetClass; +extern WidgetClass simpleMenuWidgetClass; +extern WidgetClass simpleWidgetClass; +extern WidgetClass smeBSBObjectClass; +extern WidgetClass smeLineObjectClass; +extern WidgetClass smeObjectClass; +extern WidgetClass stripChartWidgetClass; +extern WidgetClass textSinkObjectClass; +extern WidgetClass textSrcObjectClass; +extern WidgetClass textWidgetClass; +extern WidgetClass toggleWidgetClass; +extern WidgetClass topLevelShellWidgetClass; +extern WidgetClass transientShellWidgetClass; +extern WidgetClass treeWidgetClass; +extern WidgetClass vendorShellWidgetClass; +extern WidgetClass viewportWidgetClass; +extern WidgetClass wmShellWidgetClass; + +XmuWidgetNode XawWidgetArray[] = { +{ "applicationShell", &applicationShellWidgetClass }, +{ "asciiSink", &asciiSinkObjectClass }, +{ "asciiSrc", &asciiSrcObjectClass }, +{ "asciiText", &asciiTextWidgetClass }, +{ "box", &boxWidgetClass }, +{ "command", &commandWidgetClass }, +{ "composite", &compositeWidgetClass }, +{ "constraint", &constraintWidgetClass }, +{ "core", &coreWidgetClass }, +{ "dialog", &dialogWidgetClass }, +{ "form", &formWidgetClass }, +{ "grip", &gripWidgetClass }, +{ "label", &labelWidgetClass }, +{ "list", &listWidgetClass }, +{ "menuButton", &menuButtonWidgetClass }, +{ "multiSink", &multiSinkObjectClass }, +{ "multiSrc", &multiSrcObjectClass }, +{ "object", &objectClass }, +{ "overrideShell", &overrideShellWidgetClass }, +{ "paned", &panedWidgetClass }, +{ "panner", &pannerWidgetClass }, +{ "porthole", &portholeWidgetClass }, +{ "rect", &rectObjClass }, +{ "repeater", &repeaterWidgetClass }, +{ "scrollbar", &scrollbarWidgetClass }, +{ "shell", &shellWidgetClass }, +{ "simpleMenu", &simpleMenuWidgetClass }, +{ "simple", &simpleWidgetClass }, +{ "smeBSB", &smeBSBObjectClass }, +{ "smeLine", &smeLineObjectClass }, +{ "sme", &smeObjectClass }, +{ "stripChart", &stripChartWidgetClass }, +{ "textSink", &textSinkObjectClass }, +{ "textSrc", &textSrcObjectClass }, +{ "text", &textWidgetClass }, +{ "toggle", &toggleWidgetClass }, +{ "topLevelShell", &topLevelShellWidgetClass }, +{ "transientShell", &transientShellWidgetClass }, +{ "tree", &treeWidgetClass }, +{ "vendorShell", &vendorShellWidgetClass }, +{ "viewport", &viewportWidgetClass }, +{ "wmShell", &wmShellWidgetClass }, +}; + +int XawWidgetCount = XtNumber(XawWidgetArray); + diff --git a/libXaw/src/AsciiSink.c b/libXaw/src/AsciiSink.c index a20cf63d3..56f899c09 100644 --- a/libXaw/src/AsciiSink.c +++ b/libXaw/src/AsciiSink.c @@ -1,1948 +1,1948 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xatom.h>
-#include <X11/Xaw/XawInit.h>
-#include <X11/Xaw/AsciiSinkP.h>
-#include <X11/Xaw/AsciiSrcP.h>
-#include <X11/Xaw/TextP.h>
-#include "Private.h"
-
-#ifdef GETLASTPOS
-#undef GETLASTPOS /* We will use our own GETLASTPOS */
-#endif
-
-#define GETLASTPOS \
- XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, True)
-
-/*
- * Class Methods
- */
-static void XawAsciiSinkClassPartInitialize(WidgetClass);
-static void XawAsciiSinkInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawAsciiSinkDestroy(Widget);
-static void XawAsciiSinkResize(Widget);
-static Boolean XawAsciiSinkSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static int MaxLines(Widget, unsigned int);
-static int MaxHeight(Widget, int);
-static void SetTabs(Widget, int, short*);
-static void DisplayText(Widget, int, int,
- XawTextPosition, XawTextPosition, Bool);
-static void InsertCursor(Widget, int, int, XawTextInsertState);
-static void FindPosition(Widget, XawTextPosition, int, int, Bool,
- XawTextPosition*, int*, int*);
-static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*,
- XawTextPosition*, int*);
-static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*);
-static void GetCursorBounds(Widget, XRectangle*);
-#ifndef OLDXAW
-static void AsciiPreparePaint(Widget, int, int,
- XawTextPosition, XawTextPosition, Bool);
-static void AsciiDoPaint(Widget);
-#endif
-
-/*
- * Prototypes
- */
-static void GetGC(AsciiSinkObject);
-static int CharWidth(AsciiSinkObject, XFontStruct*, int, unsigned int);
-static unsigned int PaintText(Widget w, GC gc, int x, int y,
- char *buf, int len, Bool);
-
-/*
- * Defined in TextSink.c
- */
-void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(AsciiSinkRec, ascii_sink.field)
-static XtResource resources[] = {
- {
- XtNfont,
- XtCFont,
- XtRFontStruct,
- sizeof(XFontStruct*),
- offset(font),
- XtRString,
- XtDefaultFont
- },
- {
- XtNecho,
- XtCOutput,
- XtRBoolean,
- sizeof(Boolean),
- offset(echo),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNdisplayNonprinting,
- XtCOutput,
- XtRBoolean,
- sizeof(Boolean),
- offset(display_nonprinting),
- XtRImmediate,
- (XtPointer)
- True
- },
-};
-#undef offset
-
-#define Superclass (&textSinkClassRec)
-AsciiSinkClassRec asciiSinkClassRec = {
- /* object */
- {
- (WidgetClass)Superclass, /* superclass */
- "AsciiSink", /* class_name */
- sizeof(AsciiSinkRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- XawAsciiSinkClassPartInitialize, /* class_part_initialize */
- False, /* class_inited */
- XawAsciiSinkInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* obj1 */
- NULL, /* obj2 */
- 0, /* obj3 */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* obj4 */
- False, /* obj5 */
- False, /* obj6 */
- False, /* obj7 */
- XawAsciiSinkDestroy, /* destroy */
- (XtProc)XawAsciiSinkResize, /* obj8 */
- NULL, /* obj9 */
- XawAsciiSinkSetValues, /* set_values */
- NULL, /* set_values_hook */
- NULL, /* obj10 */
- NULL, /* get_values_hook */
- NULL, /* obj11 */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* obj12 */
- NULL, /* obj13 */
- NULL, /* obj14 */
- NULL, /* extension */
- },
- /* text_sink */
- {
- DisplayText, /* DisplayText */
- InsertCursor, /* InsertCursor */
- XtInheritClearToBackground, /* ClearToBackground */
- FindPosition, /* FindPosition */
- FindDistance, /* FindDistance */
- Resolve, /* Resolve */
- MaxLines, /* MaxLines */
- MaxHeight, /* MaxHeight */
- SetTabs, /* SetTabs */
- GetCursorBounds, /* GetCursorBounds */
-#ifndef OLDXAW
- NULL /* extension */
-#endif
- },
- /* ascii_sink */
- {
- NULL, /* extension */
- }
-};
-
-WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec;
-
-/*
- * Implementation
- */
-static void
-XawAsciiSinkClassPartInitialize(WidgetClass wc)
-{
-#ifndef OLDXAW
- AsciiSinkObjectClass cclass = (AsciiSinkObjectClass)wc;
- XrmQuark record_type = XrmPermStringToQuark("TextSink");
- TextSinkExt ext = cclass->text_sink_class.extension;
-
- while (ext) {
- if (ext->record_type == record_type &&
- ext->version == 1) {
- ext->PreparePaint = AsciiPreparePaint;
- ext->DoPaint = AsciiDoPaint;
- break;
- }
- ext = (TextSinkExt)ext->next_extension;
- }
- if (ext == NULL)
- XtError("TextSinkClass: cannot resolve extension.\n");
-#endif
-}
-
-static int
-CharWidth(AsciiSinkObject sink, XFontStruct *font, int x, unsigned int c)
-{
- int width = 0;
-
- if (c == XawLF)
- return (0);
-
- if (c == XawTAB) {
- int i;
- Position *tab;
-
- width = x;
- /* Adjust for Left Margin */
- x -= ((TextWidget)XtParent((Widget)sink))->text.left_margin;
-
- i = 0;
- tab = sink->text_sink.tabs;
- /*CONSTCOND*/
- while (1) {
- if (x >= 0 && x < *tab)
- return (*tab - x);
- /* Start again */
- if (++i >= sink->text_sink.tab_count) {
- x -= *tab;
- i = 0;
- tab = sink->text_sink.tabs;
- if (width == x)
- return (0);
- }
- else
- ++tab;
- }
- /*NOTREACHED*/
- }
-
- if ((c & 0177) < XawSP || c == 0177) {
- if (sink->ascii_sink.display_nonprinting) {
- if (c > 0177) {
- width = CharWidth(sink, font, x, '\\');
- width += CharWidth(sink, font, x, ((c >> 6) & 7) + '0');
- width += CharWidth(sink, font, x, ((c >> 3) & 7) + '0');
- c = (c & 7) + '0';
- }
- else {
- width = CharWidth(sink, font, x, '^');
- if ((c |= 0100) == 0177)
- c = '?';
- }
- }
- else
- c = XawSP;
- }
-
- if (font->per_char
- && (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
- width += font->per_char[c - font->min_char_or_byte2].width;
- else
- width += font->min_bounds.width;
-
- return (width);
-}
-
-#ifndef OLDXAW
-static int
-GetTextWidth(TextWidget ctx, int current_width, XFontStruct *font,
- XawTextPosition from, int length)
-{
- int i, width = 0;
- XawTextBlock block;
- XawTextPosition pos = from;
-
- while (length > 0) {
- pos = XawTextSourceRead(ctx->text.source, from, &block, length);
- length -= pos - from;
- from = pos;
- for (i = 0; i < block.length; i++)
- width += CharWidth((AsciiSinkObject)ctx->text.sink, font,
- current_width + width,
- (unsigned char)block.ptr[i]);
- }
-
- return (width);
-}
-
-static
-void CalculateBearing(TextWidget ctx, XawTextPosition position, int x, int y,
- int ascent, int descent, Bool highlight, Bool right)
-{
-/*
- * Sample case:
- *
- * lbearing| width |rbearing
- * | |
- * | ####
- * | ### |
- * | #### |
- * | #### |
- * | ########## |
- * | #### |
- * | #### |
- * | #### |
- * | #### |
- * |### |
- * #### |
- * | |
- *
- */
- AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextProperty *property;
- XawTextPaintStruct *paint;
- XawTextBlock block;
- XFontStruct *font;
-
- property = NULL;
- if (XawTextSourceAnchorAndEntity(ctx->text.source, position,
- &anchor, &entity) &&
- (property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- font = property->font;
- else
- font = sink->ascii_sink.font;
- if (right) {
- if (font->max_bounds.rbearing > 0) {
- int rbearing = font->max_bounds.rbearing - font->max_bounds.width;
- unsigned char c;
-
- (void)XawTextSourceRead(ctx->text.source, position, &block, 1);
- c = *(unsigned char*)block.ptr;
- if (c == '\t' || c == '\n')
- c = ' ';
- else if ((c & 0177) < XawSP || c == 0177) {
- if (sink->ascii_sink.display_nonprinting)
- c = c > 0177 ? (c & 7) + '0' : c + '@';
- else
- c = ' ';
- }
- if (font->per_char &&
- (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
- rbearing = font->per_char[c - font->min_char_or_byte2].rbearing -
- font->per_char[c - font->min_char_or_byte2].width;
- if (rbearing > 0) {
- paint = XtNew(XawTextPaintStruct);
- paint->next = sink->text_sink.paint->bearings;
- sink->text_sink.paint->bearings = paint;
- paint->x = x - (paint->width = CharWidth(sink, font, 0, c));
- paint->y = y + ascent;
- paint->property = property;
- paint->max_ascent = ascent;
- paint->max_descent = descent;
- paint->backtabs = NULL;
- paint->highlight = highlight;
- paint->length = 1;
- paint->text = XtMalloc(1);
- paint->text[0] = c;
- }
- }
- }
- else {
- if (font->min_bounds.lbearing < 0) {
- int lbearing = font->min_bounds.lbearing;
- unsigned char c;
-
- (void)XawTextSourceRead(ctx->text.source, position, &block, 1);
- c = *(unsigned char*)block.ptr;
- if (c == '\t' || c == '\n')
- c = ' ';
- else if ((c & 0177) < XawSP || c == 0177) {
- if (sink->ascii_sink.display_nonprinting)
- c = c > 0177 ? '\\' : c + '^';
- else
- c = ' ';
- }
- if (font->per_char &&
- (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
- lbearing = font->per_char[c - font->min_char_or_byte2].lbearing;
- if (lbearing < 0) {
- paint = XtNew(XawTextPaintStruct);
- paint->next = sink->text_sink.paint->bearings;
- sink->text_sink.paint->bearings = paint;
- paint->x = x;
- paint->width = -CharWidth(sink, font, 0, c);
- paint->y = y + ascent;
- paint->property = property;
- paint->max_ascent = ascent;
- paint->max_descent = descent;
- paint->backtabs = NULL;
- paint->highlight = highlight;
- paint->length = 1;
- paint->text = XtMalloc(1);
- paint->text[0] = c;
- }
- }
- }
-}
-
-static void
-AsciiPreparePaint(Widget w, int y, int line,
- XawTextPosition from, XawTextPosition to, Bool highlight)
-{
- static XmuSegment segment;
- static XmuScanline next;
- static XmuScanline scanline = {0, &segment, &next};
- static XmuArea area = {&scanline};
-
- TextWidget ctx = (TextWidget)XtParent(w);
- AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
- XawTextPosition left, right, pos, pos2, tmp, length;
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextProperty *property;
- int i, ascent = 0, descent = 0, xl, xr, x = ctx->text.left_margin, bufsiz;
- XawTextBlock block;
- XFontStruct *font;
- XawTextPaintStruct *paint;
-
- if (!sink->ascii_sink.echo)
- return;
-
- /* pass 1: calculate ascent/descent values and x coordinate */
- /* XXX the MAX ascent/descent value should be in the line table XXX */
- /* XXX the x coordinate can be a parameter, but since it is required
- to calculate the ascent/descent, do it here to avoid an extra
- search in the entities */
- pos = tmp = left = ctx->text.lt.info[line].position;
- right = ctx->text.lt.info[line + 1].position;
- right = XawMin(right, ctx->text.lastPos + 1);
- while (pos < right) {
- if (XawTextSourceAnchorAndEntity(ctx->text.source, pos,
- &anchor, &entity)) {
- if ((property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- font = property->font;
- else
- font = sink->ascii_sink.font;
- tmp = pos;
- pos = anchor->position + entity->offset + entity->length;
- if ((length = XawMin(from, pos) - tmp) > 0)
- x += GetTextWidth(ctx, x, font, tmp, length);
- ascent = XawMax(font->ascent, ascent);
- descent = XawMax(font->descent, descent);
- }
- else if (anchor) {
- ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
- descent = XawMax(sink->ascii_sink.font->descent, descent);
- while (entity && pos < right) {
- tmp = pos;
- if ((pos = anchor->position + entity->offset) < tmp)
- pos = tmp;
- else {
- if ((length = XawMin(from, pos) - tmp) > 0) {
- x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp,
- length);
- tmp += length;
- }
- if (pos < right) {
- pos += entity->length;
- if ((property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- font = property->font;
- else
- font = sink->ascii_sink.font;
- if ((length = XawMin(from, pos) - tmp) > 0)
- x += GetTextWidth(ctx, x, font, tmp, length);
- ascent = XawMax(font->ascent, ascent);
- descent = XawMax(font->descent, descent);
- }
- }
- entity = entity->next;
- }
-
- if (anchor->entities == NULL) {
- tmp = XawMin(pos, from);
- if ((length = from - tmp) > 0)
- x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, length);
- break;
- }
- }
- else {
- tmp = XawMin(pos, from);
- if ((length = from - tmp) > 0)
- x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, length);
- ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
- descent = XawMax(sink->ascii_sink.font->descent, descent);
- break;
- }
- }
- if (!ascent)
- ascent = sink->ascii_sink.font->ascent;
- if (!descent)
- descent = sink->ascii_sink.font->descent;
-
- xl = x;
-
- /* pass 2: feed the XawTextPaintStruct lists */
- pos = from;
- while (pos < to) {
- paint = XtNew(XawTextPaintStruct);
- paint->next = sink->text_sink.paint->paint;
- sink->text_sink.paint->paint = paint;
- paint->x = x;
- paint->y = y + ascent;
- paint->property = NULL;
- paint->max_ascent = ascent;
- paint->max_descent = descent;
- paint->backtabs = NULL;
- paint->highlight = highlight;
-
- tmp = pos;
- if (XawTextSourceAnchorAndEntity(ctx->text.source, pos,
- &anchor, &entity)) {
- pos = anchor->position + entity->offset + entity->length;
- if ((paint->property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (paint->property->mask & XAW_TPROP_FONT))
- font = paint->property->font;
- else
- font = sink->ascii_sink.font;
- }
- else {
- if (anchor) {
- while (entity && anchor->position + entity->offset < pos)
- entity = entity->next;
- if (entity)
- pos = anchor->position + entity->offset;
- else
- pos = to;
- }
- else
- pos = to;
- font = sink->ascii_sink.font;
- }
- pos = XawMin(pos, to);
- length = pos - tmp;
-
- paint->text = XtMalloc(bufsiz = pos - tmp + 4);
- paint->length = 0;
- segment.x1 = x;
-
- pos2 = tmp;
- while (length > 0) {
- pos2 = XawTextSourceRead(ctx->text.source, tmp, &block, length);
- length = pos - pos2;
- tmp = pos2;
- for (i = 0; i < block.length; i++) {
- unsigned char c = (unsigned char)block.ptr[i];
-
- if (paint->length + 4 > bufsiz)
- paint->text = XtRealloc(paint->text, bufsiz += 32);
- paint->text[paint->length] = c;
- if (c == '\n') {
- x += CharWidth(sink, font, 0, ' ');
- continue;
- }
- if (c == '\t') {
- x += XTextWidth(font, paint->text, paint->length);
- segment.x2 = x + CharWidth(sink, font, x, '\t');
-
- if (XmuValidSegment(&segment)) {
- if (!highlight && (paint->property &&
- (paint->property->mask & XAW_TPROP_BACKGROUND))) {
- if (ascent > font->ascent) {
- scanline.y = y;
- next.y = y + ascent - font->ascent;
- XmuAreaOr(sink->text_sink.paint->clip, &area);
- }
- if (descent >= font->descent) {
- scanline.y = y + ascent + font->descent;
- next.y = scanline.y + descent - font->descent + 1;
- XmuAreaOr(sink->text_sink.paint->clip, &area);
- }
- if (paint->backtabs == NULL)
- paint->backtabs = XmuCreateArea();
- scanline.y = y + ascent - font->ascent;
- next.y = y + ascent + font->descent;
- XmuAreaOr(paint->backtabs, &area);
- }
- else {
- scanline.y = y;
- next.y = ctx->text.lt.info[line + 1].y;
- if (highlight) {
- if (!sink->text_sink.paint->hightabs)
- sink->text_sink.paint->hightabs =
- XmuCreateArea();
- XmuAreaOr(sink->text_sink.paint->hightabs, &area);
- }
- else
- XmuAreaOr(sink->text_sink.paint->clip, &area);
- }
- }
-
- paint->width = segment.x2 - segment.x1;
- x = segment.x1 = segment.x2;
-
- if (paint->length == 0) {
- paint->x = x;
- continue;
- }
- paint->text = XtRealloc(paint->text, paint->length);
- property = paint->property;
- paint = XtNew(XawTextPaintStruct);
- paint->next = sink->text_sink.paint->paint;
- sink->text_sink.paint->paint = paint;
- paint->x = x;
- paint->y = y + ascent;
- paint->property = property;
- paint->max_ascent = ascent;
- paint->max_descent = descent;
- paint->backtabs = NULL;
- paint->highlight = highlight;
- paint->text = XtMalloc(bufsiz = pos - tmp - length +
- block.length - i + 4);
- paint->length = 0;
- continue;
- }
- if ((c & 0177) < XawSP || c == 0177) {
- if (sink->ascii_sink.display_nonprinting) {
- if (c > 0177) {
- paint->text[paint->length++] = '\\';
- paint->text[paint->length++] = ((c >> 6) & 7) + '0';
- paint->text[paint->length++] = ((c >> 3) & 7) + '0';
- paint->text[paint->length] = (c & 7) + '0';
- }
- else {
- c |= 0100;
- paint->text[paint->length++] = '^';
- paint->text[paint->length] = c == 0177 ? '?' : c;
- }
- }
- else
- paint->text[paint->length] = ' ';
- }
- paint->length++;
- }
- }
-
- x += XTextWidth(font, paint->text, paint->length);
- segment.x2 = x;
- if (XmuValidSegment(&segment)) {
- /* erase only what really is needed */
- /*if (!highlight || (paint->property &&
- (paint->property->mask & XAW_TPROP_BACKGROUND))) {
- if (ascent > font->ascent) {
- scanline.y = y;
- next.y = y + ascent - font->ascent;
- XmuAreaOr(sink->text_sink.paint->clip, &area);
- }
- if (descent > font->descent) {
- scanline.y = y + ascent + font->descent;
- next.y = scanline.y + descent - font->descent;
- XmuAreaOr(sink->text_sink.paint->clip, &area);
- }
- }
- else*/ {
- scanline.y = y;
- next.y = ctx->text.lt.info[line + 1].y;
- XmuAreaOr(sink->text_sink.paint->clip, &area);
- }
- }
-
- paint->width = x - segment.x1;
- }
-
- xr = x;
-
- /* pass 3: bearing clipping */
- if (left < from) {
- CalculateBearing(ctx, from - 1, xl, y, ascent, descent, highlight, True);
- if (ctx->text.s.left < ctx->text.s.right) {
- if (ctx->text.s.right == from)
- CalculateBearing(ctx, from, xl, y, ascent, descent, True, False);
- else if (ctx->text.s.left == from)
- CalculateBearing(ctx, from, xl, y, ascent, descent, False, False);
- }
- }
- right = XawMin(right, ctx->text.lastPos);
- if (right >= to && to > from) {
- if (to < right)
- CalculateBearing(ctx, to, xr, y, ascent, descent, highlight, False);
- if (ctx->text.s.left < ctx->text.s.right) {
- if (ctx->text.s.right == to)
- CalculateBearing(ctx, to - 1, xr, y, ascent, descent, False, True);
- else if (ctx->text.s.left == to)
- CalculateBearing(ctx, to - 1, xr, y, ascent, descent, True, True);
- }
- }
-}
-
-static int
-qcmp_paint_struct(_Xconst void *left, _Xconst void *right)
-{
- return ((*(XawTextPaintStruct**)left)->property -
- (*(XawTextPaintStruct**)right)->property);
-}
-
-static void
-AsciiDoPaint(Widget w)
-{
- TextWidget ctx = (TextWidget)XtParent(w);
- AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
- XmuScanline *scan;
- XmuSegment *seg;
- XawTextPaintList *list = sink->text_sink.paint;
-#if 0
- XawTextPaintStruct *base, *head;
-#endif
- XawTextPaintStruct *paint = list->paint;
- XawTextProperty *property;
- XFontStruct *font = NULL;
- XRectangle *rects;
- int n_rects, i_rects;
- GC gc;
- Bool highlight;
- XRectangle rect;
- int width, height, line_width = -1;
- XGCValues values;
-
- /* pass 1: clear clipping areas */
- /* XXX Don't use XDrawImageString because the font may be italic, and
- will get incorrectly drawn. Probably, it could be a good idea to
- check if this is the case, and do special processing. But this
- will need to be checked if required. */
- for (scan = list->clip->scanline; scan && scan->next; scan = scan->next)
- for (seg = scan->segment; seg; seg = seg->next)
- _XawTextSinkClearToBackground(ctx->text.sink,
- seg->x1, scan->y,
- seg->x2 - seg->x1,
- scan->next->y - scan->y);
-
- /* pass 2: optimize drawing list to avoid too much GC change requests */
- /* XXX this assumes there will not exist entities drawn over other
- entities. */
-#if 0
- while (paint) {
- base = paint;
- head = paint->next;
- while (head) {
- if (head->property == paint->property) {
- base->next = head->next;
- head->next = paint->next;
- paint->next = head;
- paint = head;
- }
- base = head;
- head = head->next;
- }
- paint = paint->next;
- }
-#endif
- if (paint && paint->next) {
- XawTextPaintStruct **paints;
- int i = 0, n_paints = 0;
-
- while (paint) {
- paint = paint->next;
- ++n_paints;
- }
- paints = (XawTextPaintStruct**)
- XtMalloc(n_paints * sizeof(XawTextPaintStruct));
- paint = list->paint;
- while (paint) {
- paints[i++] = paint;
- paint = paint->next;
- }
- qsort((void*)paints, n_paints, sizeof(XawTextPaintStruct*),
- qcmp_paint_struct);
- list->paint = paints[0];
- for (i = 0; i < n_paints - 1; i++)
- paints[i]->next = paints[i + 1];
- paints[i]->next = NULL;
- XtFree((XtPointer)paints);
- }
-
- /* pass 3: clip gc */
- gc = sink->ascii_sink.normgc;
-
- rect.x = ctx->text.r_margin.left;
- rect.y = ctx->text.r_margin.top;
- width = (int)XtWidth(ctx) - RHMargins(ctx);
- height = (int)XtHeight(ctx) - RVMargins(ctx);
- rect.width = width;
- rect.height = height;
- if (width >= 0 && height >= 0)
- XSetClipRectangles(XtDisplay((Widget)ctx), gc,
- 0, 0, &rect, 1, Unsorted);
- else
- XSetClipMask(XtDisplay((Widget)ctx), gc, None);
-
- /* pass 4: draw backgrounds */
- paint = list->paint;
- property = NULL;
- rects = NULL;
- i_rects = n_rects = 0;
- while (paint) {
- if (paint->property && (paint->property->mask & XAW_TPROP_BACKGROUND)) {
- if (property != paint->property) {
- if (i_rects)
- XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc,
- rects, i_rects);
- i_rects = 0;
- property = paint->property;
- if (property->mask & XAW_TPROP_FONT)
- font = property->font;
- else
- font = sink->ascii_sink.font;
- XSetForeground(XtDisplay(ctx), gc, property->background);
- }
- if (i_rects <= n_rects)
- rects = (XRectangle*)
- XtRealloc((XtPointer)rects, sizeof(XRectangle) *
- ++n_rects);
- rects[i_rects].x = paint->x;
- rects[i_rects].y = paint->y - font->ascent;
- rects[i_rects].width = paint->width;
- rects[i_rects++].height = font->ascent + font->descent;
-
- if (paint->backtabs) {
- for (scan = paint->backtabs->scanline; scan && scan->next;
- scan = scan->next)
- for (seg = scan->segment; seg; seg = seg->next) {
- if (i_rects <= n_rects)
- rects = (XRectangle*)
- XtRealloc((XtPointer)rects, sizeof(XRectangle) *
- ++n_rects);
- rects[i_rects].x = seg->x1;
- rects[i_rects].y = scan->y;
- rects[i_rects].width = seg->x2 - seg->x1;
- rects[i_rects++].height = scan->next->y - scan->y;
- }
- }
-
-
- }
- paint = paint->next;
- }
- if (i_rects)
- XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, rects, i_rects);
-
- paint = list->paint;
- i_rects = 0;
- while (paint) {
- if (paint->highlight) {
- if (i_rects == 0)
- XSetForeground(XtDisplay(ctx), gc, sink->text_sink.cursor_color);
- if (i_rects <= n_rects)
- rects = (XRectangle*)
- XtRealloc((XtPointer)rects, sizeof(XRectangle) *
- ++n_rects);
- rects[i_rects].x = paint->x;
- rects[i_rects].y = paint->y - paint->max_ascent;
- rects[i_rects].width = paint->width;
- rects[i_rects++].height = paint->max_ascent + paint->max_descent + 1;
- }
- paint = paint->next;
- }
- if (list->hightabs) {
- for (scan = list->hightabs->scanline; scan && scan->next;
- scan = scan->next)
- for (seg = scan->segment; seg; seg = seg->next) {
- if (i_rects == 0)
- XSetForeground(XtDisplay(ctx), gc,
- sink->text_sink.cursor_color);
- if (i_rects <= n_rects)
- rects = (XRectangle*)
- XtRealloc((XtPointer)rects, sizeof(XRectangle) *
- ++n_rects);
- rects[i_rects].x = seg->x1;
- rects[i_rects].y = scan->y;
- rects[i_rects].width = seg->x2 - seg->x1;
- rects[i_rects++].height = scan->next->y - scan->y;
- }
- }
-
- if (i_rects)
- XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, rects, i_rects);
- if (rects)
- XtFree((XtPointer)rects);
-
- /* pass 5: draw text! */
- paint = list->paint;
- if (paint && (property = paint->property) == NULL) {
- font = sink->ascii_sink.font;
- XSetFont(XtDisplay(ctx), gc, font->fid);
- if (!paint->highlight)
- XSetForeground(XtDisplay(ctx), gc, sink->text_sink.foreground);
- }
- else
- property = NULL;
- highlight = False;
- while (paint) {
- if (!highlight && paint->highlight)
- XSetForeground(XtDisplay(ctx), gc, sink->text_sink.background);
- if (highlight || paint->highlight || paint->property != property) {
- if (!paint->property || !(paint->property->mask & XAW_TPROP_FONT))
- font = sink->ascii_sink.font;
- else
- font = paint->property->font;
- XSetFont(XtDisplay(ctx), gc, font->fid);
- if (!paint->highlight) {
- if (!paint->property ||
- !(paint->property->mask & XAW_TPROP_FOREGROUND))
- XSetForeground(XtDisplay(ctx), gc,
- sink->text_sink.foreground);
- else
- XSetForeground(XtDisplay(ctx), gc,
- paint->property->foreground);
- }
- highlight = paint->highlight;
- property = paint->property;
- }
-
- if (paint->x < XtWidth(ctx) && paint->x + paint->width > 0) {
- XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, paint->y,
- paint->text, paint->length);
- if (property) {
- if (property->mask & XAW_TPROP_UNDERLINE) {
- if (line_width != property->underline_thickness) {
- values.line_width = line_width =
- property->underline_thickness;
- XChangeGC(XtDisplay(ctx), gc, GCLineWidth, &values);
- }
-
- XDrawLine(XtDisplay(ctx), XtWindow(ctx), gc, paint->x,
- paint->y + property->underline_position,
- paint->x + paint->width,
- paint->y + property->underline_position);
- }
- if (property->mask & XAW_TPROP_OVERSTRIKE) {
- if (line_width != property->underline_thickness) {
- values.line_width = line_width =
- property->underline_thickness;
- XChangeGC(XtDisplay(ctx), gc, GCLineWidth, &values);
- }
-
- XDrawLine(XtDisplay(ctx), XtWindow(ctx), gc, paint->x,
- paint->y - (font->ascent>>1) + (font->descent>>1),
- paint->x + paint->width,
- paint->y - (font->ascent>>1) + (font->descent>>1));
- }
- }
- }
-
- paint = paint->next;
- }
-
- /* pass 6: bearing clipping */
- /* dont care on order of drawing or caching of state (by now) */
- paint = list->bearings;
- while (paint) {
- XRectangle rect;
-
- if (paint->highlight)
- XSetForeground(XtDisplay(ctx), gc, sink->text_sink.background);
- if (!paint->property || !(paint->property->mask & XAW_TPROP_FONT))
- font = sink->ascii_sink.font;
- else
- font = paint->property->font;
- XSetFont(XtDisplay(ctx), gc, font->fid);
- if (!paint->highlight) {
- if (!paint->property ||
- !(paint->property->mask & XAW_TPROP_FOREGROUND))
- XSetForeground(XtDisplay(ctx), gc, sink->text_sink.foreground);
- else
- XSetForeground(XtDisplay(ctx), gc, paint->property->foreground);
- }
- if (paint->x < XtWidth(ctx) && paint->x + paint->width > 0) {
- rect.x = paint->x + paint->width;
- rect.width = XawAbs(paint->width); /* more than enough */
- rect.y = paint->y - font->ascent;
- rect.height = rect.y + font->ascent + font->descent;
- XSetClipRectangles(XtDisplay((Widget)ctx), gc,
- 0, 0, &rect, 1, Unsorted);
- XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, paint->y,
- paint->text, paint->length);
- }
- paint = paint->next;
- }
-}
-#endif
-
-/*
- * Function:
- * PaintText
- *
- * Parameters:
- * w - text sink object
- * gc - gc to paint text with
- * x - location to paint the text
- * y - ""
- * buf - buffer and length of text to paint.
- * len - ""
- * clear_bg - clear background before drawing ?
- *
- * Description:
- * Actually paints the text into the window.
- *
- * Returns:
- * the width of the text painted
- */
-static unsigned int
-PaintText(Widget w, GC gc, int x, int y, char *buf, int len, Bool clear_bg)
-{
- AsciiSinkObject sink = (AsciiSinkObject)w;
- TextWidget ctx = (TextWidget)XtParent(w);
- int width = XTextWidth(sink->ascii_sink.font, buf, len);
-
- if ((x > XtWidth(ctx)) || width <= -x) /* Don't draw if we can't see it */
- return (width);
-
- if (clear_bg) {
- _XawTextSinkClearToBackground(w, x, y - sink->ascii_sink.font->ascent,
- width, sink->ascii_sink.font->ascent
- + sink->ascii_sink.font->descent);
- XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, x, y, buf, len);
- }
- else
- XDrawImageString(XtDisplay(ctx), XtWindow(ctx), gc, x, y, buf, len);
-
- return (width);
-}
-
-static void
-DisplayText(Widget w, int x, int y,
- XawTextPosition pos1, XawTextPosition pos2, Bool highlight)
-{
- TextWidget ctx = (TextWidget)XtParent(w);
- AsciiSinkObject sink = (AsciiSinkObject)w;
- XFontStruct *font = sink->ascii_sink.font;
- Widget source = XawTextGetSource(XtParent(w));
- unsigned char buf[260];
- int j, k;
- XawTextBlock blk;
- GC gc, invgc, tabgc;
- int max_x;
- Bool clear_bg;
-
- if (!sink->ascii_sink.echo || !ctx->text.lt.lines)
- return;
-
- max_x = (int)XtWidth(ctx) - ctx->text.r_margin.right;
- clear_bg = !highlight && ctx->core.background_pixmap != XtUnspecifiedPixmap;
-
- gc = highlight ? sink->ascii_sink.invgc : sink->ascii_sink.normgc;
- invgc = highlight ? sink->ascii_sink.normgc : sink->ascii_sink.invgc;
-
- if (highlight && sink->ascii_sink.xorgc)
- tabgc = sink->ascii_sink.xorgc;
- else
- tabgc = invgc;
-
- y += sink->ascii_sink.font->ascent;
- for (j = 0; pos1 < pos2;) {
- pos1 = XawTextSourceRead(source, pos1, &blk, pos2 - pos1);
- for (k = 0; k < blk.length; k++) {
- if (j >= sizeof(buf) - 4) { /* buffer full, dump the text */
- if ((x += PaintText(w, gc, x, y, (char*)buf, j, clear_bg))
- >= max_x)
- return;
- j = 0;
- }
- buf[j] = blk.ptr[k];
- if (buf[j] == XawLF) /* line feeds ('\n') are not printed */
- continue;
-
- else if (buf[j] == '\t') {
- int width;
-
- if (j != 0
- && (x += PaintText(w, gc, x, y, (char*)buf, j, clear_bg))
- >= max_x)
- return;
-
- if ((width = CharWidth(sink, font, x, '\t')) > -x) {
- if (clear_bg)
- _XawTextSinkClearToBackground(w, x, y-font->ascent, width,
- font->ascent+font->descent);
- else
- XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
- tabgc, x, y - font->ascent, width,
- font->ascent + font->descent);
- }
-
- if ((x += width) >= max_x)
- return;
-
- j = -1;
- }
- else if ((buf[j] & 0177) < XawSP || buf[j] == 0177) {
- if (sink->ascii_sink.display_nonprinting) {
- unsigned char c = buf[j];
-
- if (c > 0177) {
- buf[j++] = '\\';
- buf[j++] = ((c >> 6) & 7) + '0';
- buf[j++] = ((c >> 3) & 7) + '0';
- buf[j] = (c & 7) + '0';
- }
- else {
- c |= 0100;
- buf[j++] = '^';
- buf[j] = c == 0177 ? '?' : c;
- }
- }
- else
- buf[j] = ' ';
- }
- j++;
- }
- }
-
- if (j > 0)
- (void)PaintText(w, gc, x, y, (char*)buf, j, clear_bg);
-}
-
-/*
- * Function:
- * GetCursorBounds
- *
- * Parameters:
- * w - text sink object
- * rect - X rectangle to return the cursor bounds
- *
- * Description:
- * Returns the size and location of the cursor.
- */
-static void
-GetCursorBounds(Widget w, XRectangle *rect)
-{
- AsciiSinkObject sink = (AsciiSinkObject)w;
- XFontStruct *font = sink->ascii_sink.font;
- unsigned char ch;
-#ifndef OLDXAW
- TextWidget ctx = (TextWidget)XtParent(w);
- XawTextBlock block;
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextProperty *property;
-
- if (XawTextSourceAnchorAndEntity(XawTextGetSource(XtParent(w)),
- sink->ascii_sink.cursor_position,
- &anchor, &entity)) {
- if ((property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- font = property->font;
- }
- (void)XawTextSourceRead(XawTextGetSource((Widget)ctx),
- ctx->text.insertPos, &block, 1);
- if (!block.length || block.ptr[0] == '\n' || block.ptr[0] == '\t')
- ch = ' ';
- else if ((*((unsigned char*)block.ptr) & 0177) < XawSP ||
- *(unsigned char*)block.ptr == 0177) {
- if (sink->ascii_sink.display_nonprinting)
- ch = *((unsigned char*)block.ptr) > 0177 ? '\\' : '^';
- else
- ch = ' ';
- }
- else
- ch = *(unsigned char*)block.ptr;
-#else
- ch = ' ';
-#endif
-
- rect->width = CharWidth(sink, font, 0, ch);
- rect->height = font->descent + font->ascent + 1;
-
- rect->x = sink->ascii_sink.cursor_x;
- rect->y = sink->ascii_sink.cursor_y - font->ascent;
-}
-
-/* this function is required to support diferent fonts and correctly place
- * the cursor. There are better ways to calculate the base line, but there is
- * no place/code (yet) to store this information.
- */
-static int
-FindCursorY(TextWidget ctx, XawTextPosition position)
-{
- int y, line, ascent;
- AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
-#ifndef OLDXAW
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextProperty *property;
- XawTextPosition left, right;
-#endif
-
- for (line = 0; line < ctx->text.lt.lines; line++)
- if (position < ctx->text.lt.info[line + 1].position)
- break;
-
- y = ctx->text.lt.info[line].y;
-#ifndef OLDXAW
- ascent = 0;
- left = ctx->text.lt.info[line].position;
- right = ctx->text.lt.info[line + 1].position;
- right = XawMin(right, ctx->text.lastPos + 1);
- while (left < right) {
- if (XawTextSourceAnchorAndEntity(ctx->text.source, left,
- &anchor, &entity)) {
- if ((property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- ascent = XawMax(property->font->ascent, ascent);
- else
- ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
- left = anchor->position + entity->offset + entity->length;
- }
- else if (anchor) {
- ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
- while (entity) {
- XawTextPosition tmp = anchor->position + entity->offset + entity->length;
-
- if (tmp > left && tmp < right) {
- left = tmp;
- if ((property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- ascent = XawMax(property->font->ascent, ascent);
- else
- ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
- }
- entity = entity->next;
- }
- if (entity == NULL)
- break;
- }
- else {
- ascent = XawMax(sink->ascii_sink.font->ascent, ascent);
- break;
- }
- }
- if (!ascent)
- ascent = sink->ascii_sink.font->ascent;
-#else
- ascent = sink->ascii_sink.font->ascent;
-#endif
-
- return (y + ascent);
-}
-
-static void
-InsertCursor(Widget w, int x, int y, XawTextInsertState state)
-{
- AsciiSinkObject sink = (AsciiSinkObject)w;
- XFontStruct *font = sink->ascii_sink.font;
- TextWidget ctx = (TextWidget)XtParent(w);
- XawTextPosition position = XawTextGetInsertionPoint((Widget)ctx);
- Boolean overflow = (x & 0xffff8000) != 0;
-#ifndef OLDXAW
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextProperty *property;
-#endif
-
- if (XtIsRealized((Widget)ctx)) {
- int fheight;
- XawTextBlock block;
- XawTextPosition selection_start, selection_end;
- Boolean has_selection;
-
- if (!sink->ascii_sink.echo) {
- if (sink->ascii_sink.laststate != state) {
- int width = CharWidth(sink, font, 0, ' ') - 1;
-
- x = ctx->text.margin.left;
- y = ctx->text.margin.top;
- font = sink->ascii_sink.font;
- fheight = font->ascent + font->descent;
- if (state == XawisOn) {
- if (ctx->text.hasfocus)
- XFillRectangle(XtDisplay(ctx), XtWindow(ctx),
- sink->ascii_sink.xorgc, x, y,
- width + 1, fheight + 1);
- else
- XDrawRectangle(XtDisplay(ctx), XtWindow(ctx),
- sink->ascii_sink.xorgc, x, y,
- width, fheight);
-
- }
- else
- _XawTextSinkClearToBackground(w, x, y,
- width + 1, fheight + 1);
- }
- sink->ascii_sink.cursor_x = x;
- sink->ascii_sink.cursor_y = y;
- sink->ascii_sink.laststate = state;
- return;
- }
-
-
- XawTextGetSelectionPos((Widget)ctx, &selection_start, &selection_end);
- has_selection = selection_start != selection_end;
-
- if (sink->ascii_sink.laststate != state) {
- unsigned char ch;
-
-#ifndef OLDXAW
- if (XawTextSourceAnchorAndEntity(ctx->text.source,
- position, &anchor, &entity) &&
- (property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- font = property->font;
- else
- font = sink->ascii_sink.font;
-#endif
-
- fheight = font->ascent + font->descent;
- (void)XawTextSourceRead(XawTextGetSource((Widget)ctx),
- position, &block, 1);
- if (!block.length || block.ptr[0] == '\n' || block.ptr[0] == '\t')
- ch = ' ';
- else if ((*((unsigned char*)block.ptr) & 0177) < XawSP
- || *(unsigned char*)block.ptr == 0177) {
- if (sink->ascii_sink.display_nonprinting)
- ch = *((unsigned char*)block.ptr) > 0177 ? '\\' : '^';
- else
- ch = ' ';
- }
- else
- ch = *(unsigned char*)block.ptr;
-
- y = FindCursorY(ctx, position);
- if (ctx->text.hasfocus && !has_selection)
- XFillRectangle(XtDisplay(ctx), XtWindow(ctx),
- sink->ascii_sink.xorgc, x, y - font->ascent,
- CharWidth(sink, font, 0, ch), fheight + 1);
- else
- XDrawRectangle(XtDisplay(ctx), XtWindow(ctx),
- sink->ascii_sink.xorgc, x, y - font->ascent,
- CharWidth(sink, font, 0, ch) - 1, fheight);
- }
- }
-
- sink->ascii_sink.cursor_x = overflow ? -16384 : x;
- sink->ascii_sink.cursor_y = y;
- sink->ascii_sink.laststate = state;
- sink->ascii_sink.cursor_position = position;
-}
-
-/*
- * Given two positions, find the distance between them
- */
-static void
-FindDistance(Widget w, XawTextPosition fromPos, int fromx,
- XawTextPosition toPos, int *resWidth,
- XawTextPosition *resPos, int *resHeight)
-{
-#ifndef OLDXAW
- AsciiSinkObject sink = (AsciiSinkObject)w;
- TextWidget ctx = (TextWidget)XtParent(w);
- XFontStruct *font = sink->ascii_sink.font;
- Widget source = ctx->text.source;
- XawTextPosition idx, pos;
- unsigned char c;
- XawTextBlock blk;
- int i, rWidth, ascent = 0, descent = 0;
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextProperty *property;
- Cardinal length;
- Bool done = False;
-
- pos = idx = fromPos;
- rWidth = 0;
- c = 0;
-
- while (!done) {
- if (XawTextSourceAnchorAndEntity(source, pos, &anchor, &entity)) {
- length = anchor->position + entity->offset + entity->length;
- length = XawMin(toPos, length) - pos;
- if ((property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- font = property->font;
- else
- font = sink->ascii_sink.font;
- }
- else {
- if (anchor) {
- while (entity && anchor->position + entity->offset < pos)
- entity = entity->next;
- if (entity) {
- length = anchor->position + entity->offset;
- length = XawMin(toPos, length) - pos;
- }
- else
- length = XawMin(toPos - pos, 4096);
- }
- else
- length = XawMin(toPos - pos, 4096);
- font = sink->ascii_sink.font;
- }
-
- ascent = XawMax(font->ascent, ascent);
- descent = XawMax(font->descent, descent);
-
- pos = XawTextSourceRead(source, pos, &blk, length);
- if (blk.length == 0 && pos == idx) /* eof reached */
- break;
-
- idx = blk.firstPos;
- for (i = 0; idx < toPos; i++, idx++) {
- if (i >= blk.length)
- break;
- c = blk.ptr[i];
- rWidth += CharWidth(sink, font, fromx + rWidth, c);
- if (c == XawLF) {
- idx++;
- done = True;
- break;
- }
- }
- if (idx >= toPos)
- break;
- }
-
- *resPos = idx;
- *resWidth = rWidth;
- *resHeight = ascent + descent + 1;
-#else
- AsciiSinkObject sink = (AsciiSinkObject)w;
- TextWidget ctx = (TextWidget)XtParent(w);
- XFontStruct *font = sink->ascii_sink.font;
- Widget source = ctx->text.source;
- XawTextPosition idx, pos;
- unsigned char c;
- XawTextBlock blk;
- int i, rWidth;
-
- pos = XawTextSourceRead(source, fromPos, &blk, toPos - fromPos);
- rWidth = 0;
- for (i = 0, idx = fromPos; idx < toPos; i++, idx++) {
- if (i >= blk.length) {
- i = 0;
- pos = XawTextSourceRead(source, pos, &blk, toPos - pos);
- if (blk.length == 0)
- break;
- }
- c = blk.ptr[i];
- rWidth += CharWidth(sink, font, fromx + rWidth, c);
- if (c == XawLF) {
- idx++;
- break;
- }
- }
-
- *resPos = idx;
- *resWidth = rWidth;
- *resHeight = font->ascent + font->descent + 1;
-#endif
-}
-
-static void
-FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
- Bool stopAtWordBreak, XawTextPosition *resPos,
- int *resWidth, int *resHeight)
-{
-#ifndef OLDXAW
- AsciiSinkObject sink = (AsciiSinkObject)w;
- TextWidget ctx = (TextWidget)XtParent(w);
- Widget source = ctx->text.source;
- XFontStruct *font = sink->ascii_sink.font;
- XawTextPosition idx, pos, whiteSpacePosition = 0;
- int i, lastWidth, whiteSpaceWidth, rWidth, ascent = 0, descent = 0;
- Boolean whiteSpaceSeen;
- unsigned char c;
- XawTextBlock blk;
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextProperty *property;
- Cardinal length;
- Bool done = False;
-
- pos = idx = fromPos;
- rWidth = lastWidth = whiteSpaceWidth = 0;
- whiteSpaceSeen = False;
- c = 0;
-
- while (!done) {
- font = sink->ascii_sink.font;
- if (XawTextSourceAnchorAndEntity(source, pos, &anchor, &entity)) {
- length = anchor->position + entity->offset + entity->length - pos;
- if ((property = XawTextSinkGetProperty((Widget)sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- font = property->font;
- }
- else {
- if (anchor) {
- while (entity && anchor->position + entity->offset < pos)
- entity = entity->next;
- if (entity)
- length = anchor->position + entity->offset - pos;
- else
- length = 4096;
- }
- else
- length = 4096;
- }
-
- ascent = XawMax(font->ascent, ascent);
- descent = XawMax(font->descent, descent);
-
- pos = XawTextSourceRead(source, pos, &blk, length);
- if (blk.length == 0 && pos == idx) /* eof reached */
- break;
-
- idx = blk.firstPos;
- for (i = 0; rWidth <= width && i < blk.length; i++, idx++) {
- c = blk.ptr[i];
- lastWidth = rWidth;
- rWidth += CharWidth(sink, font, fromx + rWidth, c);
-
- if (c == XawLF) {
- idx++;
- done = True;
- break;
- }
- else if ((c == XawSP || c == XawTAB) && rWidth <= width) {
- whiteSpaceSeen = True;
- whiteSpacePosition = idx;
- whiteSpaceWidth = rWidth;
- }
- }
- if (rWidth > width)
- break;
- }
-
- if (rWidth > width && idx > fromPos) {
- idx--;
- rWidth = lastWidth;
- if (stopAtWordBreak && whiteSpaceSeen) {
- idx = whiteSpacePosition + 1;
- rWidth = whiteSpaceWidth;
- }
- }
-
- if (idx >= ctx->text.lastPos && c != XawLF)
- idx = ctx->text.lastPos + 1;
-
- *resPos = idx;
- *resWidth = rWidth;
- *resHeight = ascent + descent + 1;
-#else
- AsciiSinkObject sink = (AsciiSinkObject)w;
- TextWidget ctx = (TextWidget)XtParent(w);
- Widget source = ctx->text.source;
- XFontStruct *font = sink->ascii_sink.font;
- XawTextPosition idx, pos, whiteSpacePosition = 0;
- int i, lastWidth, whiteSpaceWidth, rWidth;
- Boolean whiteSpaceSeen;
- unsigned char c;
- XawTextBlock blk;
-
- pos = XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
- rWidth = lastWidth = whiteSpaceWidth = 0;
- whiteSpaceSeen = False;
- c = 0;
-
- for (i = 0, idx = fromPos; rWidth <= width; i++, idx++) {
- if (i >= blk.length) {
- i = 0;
- pos = XawTextSourceRead(source, pos, &blk, BUFSIZ);
- if (blk.length == 0)
- break;
- }
- c = blk.ptr[i];
- lastWidth = rWidth;
- rWidth += CharWidth(sink, font, fromx + rWidth, c);
-
- if (c == XawLF) {
- idx++;
- break;
- }
- else if ((c == XawSP || c == XawTAB) && rWidth <= width) {
- whiteSpaceSeen = True;
- whiteSpacePosition = idx;
- whiteSpaceWidth = rWidth;
- }
- }
-
- if (rWidth > width && idx > fromPos) {
- idx--;
- rWidth = lastWidth;
- if (stopAtWordBreak && whiteSpaceSeen) {
- idx = whiteSpacePosition + 1;
- rWidth = whiteSpaceWidth;
- }
- }
-
- if (idx >= ctx->text.lastPos && c != XawLF)
- idx = ctx->text.lastPos + 1;
-
- *resPos = idx;
- *resWidth = rWidth;
- *resHeight = font->ascent + font->descent + 1;
-#endif
-}
-
-static void
-Resolve(Widget w, XawTextPosition pos, int fromx, int width,
- XawTextPosition *pos_return)
-{
- int resWidth, resHeight;
- Widget source = XawTextGetSource(XtParent(w));
-
- FindPosition(w, pos, fromx, width, False, pos_return, &resWidth, &resHeight);
- if (*pos_return > GETLASTPOS)
- *pos_return = GETLASTPOS;
-}
-
-static void
-GetGC(AsciiSinkObject sink)
-{
- XtGCMask valuemask = (GCFont | GCGraphicsExposures | GCClipXOrigin |
- GCForeground | GCBackground);
- XGCValues values;
-
- /* XXX We dont want do share a gc that will change the clip-mask */
- values.clip_x_origin = (long)sink;
- values.clip_mask = None;
- values.font = sink->ascii_sink.font->fid;
- values.graphics_exposures = False;
-
- values.foreground = sink->text_sink.foreground;
- values.background = sink->text_sink.background;
- sink->ascii_sink.normgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
- GCClipMask | GCFont | GCForeground |
- GCBackground, 0);
-
- values.foreground = sink->text_sink.background;
-#ifndef OLDXAW
- values.background = sink->text_sink.cursor_color;
-#else
- values.background = sink->text_sink.foreground;
-#endif
- sink->ascii_sink.invgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
- GCClipMask | GCFont, 0);
-
- valuemask |= GCFunction;
- values.function = GXxor;
-#ifndef OLDXAW
- values.foreground = sink->text_sink.background ^ sink->text_sink.cursor_color;
-#else
- values.foreground = sink->text_sink.background ^ sink->text_sink.foreground;
-#endif
- values.background = 0L;
- sink->ascii_sink.xorgc = XtAllocateGC((Widget)sink, 0, valuemask,
- &values, GCClipMask | GCFont, 0);
-
- XawAsciiSinkResize((Widget)sink);
-}
-
-/* Function:
- * XawAsciiSinkInitialize
- *
- * Parameters:
- * request - the requested and new values for the object instance
- * cnew - ""
- *
- * Description:
- * Initializes the TextSink Object.
- */
-/*ARGSUSED*/
-static void
-XawAsciiSinkInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- AsciiSinkObject sink = (AsciiSinkObject)cnew;
-
- GetGC(sink);
-
- if (!sink->ascii_sink.font) XtError("Aborting: no font found\n");
-
- sink->ascii_sink.cursor_position = 0;
- sink->ascii_sink.laststate = XawisOff;
- sink->ascii_sink.cursor_x = sink->ascii_sink.cursor_y = 0;
-}
-
-/*
- * Function:
- * XawAsciiSinkDestroy
- *
- * Parameters:
- * w - AsciiSink Object
- *
- * Description:
- * This function cleans up when the object is destroyed.
- */
-static void
-XawAsciiSinkDestroy(Widget w)
-{
- AsciiSinkObject sink = (AsciiSinkObject)w;
-
- XtReleaseGC(w, sink->ascii_sink.normgc);
- XtReleaseGC(w, sink->ascii_sink.invgc);
- XtReleaseGC(w, sink->ascii_sink.xorgc);
-
- sink->ascii_sink.normgc =
- sink->ascii_sink.invgc =
- sink->ascii_sink.xorgc = NULL;
-}
-
-static void
-XawAsciiSinkResize(Widget w)
-{
- TextWidget ctx = (TextWidget)XtParent(w);
- AsciiSinkObject sink = (AsciiSinkObject)w;
- XRectangle rect;
- int width, height;
-
- if (w->core.widget_class != asciiSinkObjectClass)
- return;
-
- rect.x = ctx->text.r_margin.left;
- rect.y = ctx->text.r_margin.top;
- width = (int)XtWidth(ctx) - RHMargins(ctx);
- height = (int)XtHeight(ctx) - RVMargins(ctx);
- rect.width = width;
- rect.height = height;
-
- if (sink->ascii_sink.normgc) {
- if (width >= 0 && height >= 0)
- XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.normgc,
- 0, 0, &rect, 1, Unsorted);
- else
- XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.normgc, None);
- }
- if (sink->ascii_sink.invgc) {
- if (width >= 0 && height >= 0)
- XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.invgc,
- 0, 0, &rect, 1, Unsorted);
- else
- XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.invgc, None);
- }
- if (sink->ascii_sink.xorgc) {
- if (width >= 0 && height >= 0)
- XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.xorgc,
- 0, 0, &rect, 1, Unsorted);
- else
- XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.xorgc, None);
- }
-}
-
-/*
- * Function:
- * XawAsciiSinkSetValues
- *
- * Parameters:
- * current - current state of the object
- * request - what was requested
- * cnew - what the object will become
- *
- * Description:
- * Sets the values for the AsciiSink.
- *
- * Returns:
- * True if redisplay is needed
- */
-/*ARGSUSED*/
-static Boolean
-XawAsciiSinkSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- AsciiSinkObject w = (AsciiSinkObject)cnew;
- AsciiSinkObject old_w = (AsciiSinkObject)current;
-
- if (w->ascii_sink.font != old_w->ascii_sink.font
- || w->text_sink.background != old_w->text_sink.background
- || w->text_sink.foreground != old_w->text_sink.foreground
-#ifndef OLDXAW
- || w->text_sink.cursor_color != old_w->text_sink.cursor_color
- || w->text_sink.properties != old_w->text_sink.properties
-#endif
- ) {
-#ifdef OLDXAW
- XtReleaseGC(cnew, w->ascii_sink.normgc);
- XtReleaseGC(cnew, w->ascii_sink.invgc);
- XtReleaseGC(cnew, w->ascii_sink.xorgc);
- GetGC(w);
-#endif
- ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
- }
- else if (w->ascii_sink.echo != old_w->ascii_sink.echo
- || w->ascii_sink.display_nonprinting
- != old_w->ascii_sink.display_nonprinting)
- ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
-#ifndef OLDXAW
- if (w->text_sink.properties != old_w->text_sink.properties) {
- XawTextProperty *property =
- XawTextSinkGetProperty(cnew, XrmStringToQuark("default"));
-
- if (property) {
- if (property->mask & XAW_TPROP_FONT)
- w->ascii_sink.font = property->font;
- if (property->mask & XAW_TPROP_FOREGROUND)
- w->text_sink.foreground = property->foreground;
- if (property->mask & XAW_TPROP_BACKGROUND)
- w->text_sink.background = property->background;
- }
- }
-#endif
-
- return (False);
-}
-
-/*
- * Function:
- * MaxLines
- *
- * Parameters:
- * w - AsciiSink Object
- * height - height to fit lines into
- *
- * Description:
- * Finds the Maximum number of lines that will fit in a given height.
- *
- * Returns:
- * The number of lines that will fit
- */
-/*ARGSUSED*/
-static int
-MaxLines(Widget w, unsigned int height)
-{
- AsciiSinkObject sink = (AsciiSinkObject)w;
- int font_height;
-
- font_height = sink->ascii_sink.font->ascent + sink->ascii_sink.font->descent + 1;
-
- return ((int)height / font_height);
-}
-
-/*
- * Function:
- * MaxHeight
- *
- * Parameters:
- * w - AsciiSink Object
- * lines - number of lines
- *
- * Description:
- * Finds the Minium height that will contain a given number lines.
- *
- * Returns:
- * the height
- */
-static int
-MaxHeight(Widget w, int lines)
-{
- AsciiSinkObject sink = (AsciiSinkObject)w;
-
- return (lines * (sink->ascii_sink.font->ascent +
- sink->ascii_sink.font->descent + 1));
-}
-
-/*
- * Function:
- * SetTabs
- *
- * Parameters:
- * w - AsciiSink Object
- * tab_count - number of tabs in the list
- * tabs - text positions of the tabs
- *
- * Description:
- * Sets the Tab stops.
- */
-static void
-SetTabs(Widget w, int tab_count, short *tabs)
-{
- AsciiSinkObject sink = (AsciiSinkObject)w;
- int i;
- Atom XA_FIGURE_WIDTH;
- unsigned long figure_width = 0;
- XFontStruct *font = sink->ascii_sink.font;
-
- /*
- * Find the figure width of the current font
- */
- XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", False);
- if (XA_FIGURE_WIDTH != None
- && (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)
- || figure_width == 0)) {
- if (font->per_char && font->min_char_or_byte2 <= '$'
- && font->max_char_or_byte2 >= '$')
- figure_width = font->per_char['$' - font->min_char_or_byte2].width;
- else
- figure_width = font->max_bounds.width;
- }
-
- if (tab_count > sink->text_sink.tab_count) {
- sink->text_sink.tabs = (Position *)
- XtRealloc((char*)sink->text_sink.tabs, tab_count * sizeof(Position));
- sink->text_sink.char_tabs = (short *)
- XtRealloc((char*)sink->text_sink.char_tabs, tab_count * sizeof(short));
- }
-
- for (i = 0 ; i < tab_count ; i++) {
- sink->text_sink.tabs[i] = tabs[i] * figure_width;
- sink->text_sink.char_tabs[i] = tabs[i];
- }
-
- sink->text_sink.tab_count = tab_count;
-
-#ifndef NO_TAB_FIX
- {
- TextWidget ctx = (TextWidget)XtParent(w);
- ctx->text.redisplay_needed = True;
- _XawTextBuildLineTable(ctx, ctx->text.lt.top, True);
- }
-#endif
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xatom.h> +#include <X11/Xaw/XawInit.h> +#include <X11/Xaw/AsciiSinkP.h> +#include <X11/Xaw/AsciiSrcP.h> +#include <X11/Xaw/TextP.h> +#include "Private.h" + +#ifdef GETLASTPOS +#undef GETLASTPOS /* We will use our own GETLASTPOS */ +#endif + +#define GETLASTPOS \ + XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, True) + +/* + * Class Methods + */ +static void XawAsciiSinkClassPartInitialize(WidgetClass); +static void XawAsciiSinkInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawAsciiSinkDestroy(Widget); +static void XawAsciiSinkResize(Widget); +static Boolean XawAsciiSinkSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static int MaxLines(Widget, unsigned int); +static int MaxHeight(Widget, int); +static void SetTabs(Widget, int, short*); +static void DisplayText(Widget, int, int, + XawTextPosition, XawTextPosition, Bool); +static void InsertCursor(Widget, int, int, XawTextInsertState); +static void FindPosition(Widget, XawTextPosition, int, int, Bool, + XawTextPosition*, int*, int*); +static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*, + XawTextPosition*, int*); +static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*); +static void GetCursorBounds(Widget, XRectangle*); +#ifndef OLDXAW +static void AsciiPreparePaint(Widget, int, int, + XawTextPosition, XawTextPosition, Bool); +static void AsciiDoPaint(Widget); +#endif + +/* + * Prototypes + */ +static void GetGC(AsciiSinkObject); +static int CharWidth(AsciiSinkObject, XFontStruct*, int, unsigned int); +static unsigned int PaintText(Widget w, GC gc, int x, int y, + char *buf, int len, Bool); + +/* + * Defined in TextSink.c + */ +void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(AsciiSinkRec, ascii_sink.field) +static XtResource resources[] = { + { + XtNfont, + XtCFont, + XtRFontStruct, + sizeof(XFontStruct*), + offset(font), + XtRString, + XtDefaultFont + }, + { + XtNecho, + XtCOutput, + XtRBoolean, + sizeof(Boolean), + offset(echo), + XtRImmediate, + (XtPointer)True + }, + { + XtNdisplayNonprinting, + XtCOutput, + XtRBoolean, + sizeof(Boolean), + offset(display_nonprinting), + XtRImmediate, + (XtPointer) + True + }, +}; +#undef offset + +#define Superclass (&textSinkClassRec) +AsciiSinkClassRec asciiSinkClassRec = { + /* object */ + { + (WidgetClass)Superclass, /* superclass */ + "AsciiSink", /* class_name */ + sizeof(AsciiSinkRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + XawAsciiSinkClassPartInitialize, /* class_part_initialize */ + False, /* class_inited */ + XawAsciiSinkInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* obj1 */ + NULL, /* obj2 */ + 0, /* obj3 */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* obj4 */ + False, /* obj5 */ + False, /* obj6 */ + False, /* obj7 */ + XawAsciiSinkDestroy, /* destroy */ + (XtProc)XawAsciiSinkResize, /* obj8 */ + NULL, /* obj9 */ + XawAsciiSinkSetValues, /* set_values */ + NULL, /* set_values_hook */ + NULL, /* obj10 */ + NULL, /* get_values_hook */ + NULL, /* obj11 */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* obj12 */ + NULL, /* obj13 */ + NULL, /* obj14 */ + NULL, /* extension */ + }, + /* text_sink */ + { + DisplayText, /* DisplayText */ + InsertCursor, /* InsertCursor */ + XtInheritClearToBackground, /* ClearToBackground */ + FindPosition, /* FindPosition */ + FindDistance, /* FindDistance */ + Resolve, /* Resolve */ + MaxLines, /* MaxLines */ + MaxHeight, /* MaxHeight */ + SetTabs, /* SetTabs */ + GetCursorBounds, /* GetCursorBounds */ +#ifndef OLDXAW + NULL /* extension */ +#endif + }, + /* ascii_sink */ + { + NULL, /* extension */ + } +}; + +WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec; + +/* + * Implementation + */ +static void +XawAsciiSinkClassPartInitialize(WidgetClass wc) +{ +#ifndef OLDXAW + AsciiSinkObjectClass cclass = (AsciiSinkObjectClass)wc; + XrmQuark record_type = XrmPermStringToQuark("TextSink"); + TextSinkExt ext = cclass->text_sink_class.extension; + + while (ext) { + if (ext->record_type == record_type && + ext->version == 1) { + ext->PreparePaint = AsciiPreparePaint; + ext->DoPaint = AsciiDoPaint; + break; + } + ext = (TextSinkExt)ext->next_extension; + } + if (ext == NULL) + XtError("TextSinkClass: cannot resolve extension.\n"); +#endif +} + +static int +CharWidth(AsciiSinkObject sink, XFontStruct *font, int x, unsigned int c) +{ + int width = 0; + + if (c == XawLF) + return (0); + + if (c == XawTAB) { + int i; + Position *tab; + + width = x; + /* Adjust for Left Margin */ + x -= ((TextWidget)XtParent((Widget)sink))->text.left_margin; + + i = 0; + tab = sink->text_sink.tabs; + /*CONSTCOND*/ + while (1) { + if (x >= 0 && x < *tab) + return (*tab - x); + /* Start again */ + if (++i >= sink->text_sink.tab_count) { + x -= *tab; + i = 0; + tab = sink->text_sink.tabs; + if (width == x) + return (0); + } + else + ++tab; + } + /*NOTREACHED*/ + } + + if ((c & 0177) < XawSP || c == 0177) { + if (sink->ascii_sink.display_nonprinting) { + if (c > 0177) { + width = CharWidth(sink, font, x, '\\'); + width += CharWidth(sink, font, x, ((c >> 6) & 7) + '0'); + width += CharWidth(sink, font, x, ((c >> 3) & 7) + '0'); + c = (c & 7) + '0'; + } + else { + width = CharWidth(sink, font, x, '^'); + if ((c |= 0100) == 0177) + c = '?'; + } + } + else + c = XawSP; + } + + if (font->per_char + && (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)) + width += font->per_char[c - font->min_char_or_byte2].width; + else + width += font->min_bounds.width; + + return (width); +} + +#ifndef OLDXAW +static int +GetTextWidth(TextWidget ctx, int current_width, XFontStruct *font, + XawTextPosition from, int length) +{ + int i, width = 0; + XawTextBlock block; + XawTextPosition pos = from; + + while (length > 0) { + pos = XawTextSourceRead(ctx->text.source, from, &block, length); + length -= pos - from; + from = pos; + for (i = 0; i < block.length; i++) + width += CharWidth((AsciiSinkObject)ctx->text.sink, font, + current_width + width, + (unsigned char)block.ptr[i]); + } + + return (width); +} + +static +void CalculateBearing(TextWidget ctx, XawTextPosition position, int x, int y, + int ascent, int descent, Bool highlight, Bool right) +{ +/* + * Sample case: + * + * lbearing| width |rbearing + * | | + * | #### + * | ### | + * | #### | + * | #### | + * | ########## | + * | #### | + * | #### | + * | #### | + * | #### | + * |### | + * #### | + * | | + * + */ + AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink; + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextProperty *property; + XawTextPaintStruct *paint; + XawTextBlock block; + XFontStruct *font; + + property = NULL; + if (XawTextSourceAnchorAndEntity(ctx->text.source, position, + &anchor, &entity) && + (property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + font = property->font; + else + font = sink->ascii_sink.font; + if (right) { + if (font->max_bounds.rbearing > 0) { + int rbearing = font->max_bounds.rbearing - font->max_bounds.width; + unsigned char c; + + (void)XawTextSourceRead(ctx->text.source, position, &block, 1); + c = *(unsigned char*)block.ptr; + if (c == '\t' || c == '\n') + c = ' '; + else if ((c & 0177) < XawSP || c == 0177) { + if (sink->ascii_sink.display_nonprinting) + c = c > 0177 ? (c & 7) + '0' : c + '@'; + else + c = ' '; + } + if (font->per_char && + (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)) + rbearing = font->per_char[c - font->min_char_or_byte2].rbearing - + font->per_char[c - font->min_char_or_byte2].width; + if (rbearing > 0) { + paint = XtNew(XawTextPaintStruct); + paint->next = sink->text_sink.paint->bearings; + sink->text_sink.paint->bearings = paint; + paint->x = x - (paint->width = CharWidth(sink, font, 0, c)); + paint->y = y + ascent; + paint->property = property; + paint->max_ascent = ascent; + paint->max_descent = descent; + paint->backtabs = NULL; + paint->highlight = highlight; + paint->length = 1; + paint->text = XtMalloc(1); + paint->text[0] = c; + } + } + } + else { + if (font->min_bounds.lbearing < 0) { + int lbearing = font->min_bounds.lbearing; + unsigned char c; + + (void)XawTextSourceRead(ctx->text.source, position, &block, 1); + c = *(unsigned char*)block.ptr; + if (c == '\t' || c == '\n') + c = ' '; + else if ((c & 0177) < XawSP || c == 0177) { + if (sink->ascii_sink.display_nonprinting) + c = c > 0177 ? '\\' : c + '^'; + else + c = ' '; + } + if (font->per_char && + (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)) + lbearing = font->per_char[c - font->min_char_or_byte2].lbearing; + if (lbearing < 0) { + paint = XtNew(XawTextPaintStruct); + paint->next = sink->text_sink.paint->bearings; + sink->text_sink.paint->bearings = paint; + paint->x = x; + paint->width = -CharWidth(sink, font, 0, c); + paint->y = y + ascent; + paint->property = property; + paint->max_ascent = ascent; + paint->max_descent = descent; + paint->backtabs = NULL; + paint->highlight = highlight; + paint->length = 1; + paint->text = XtMalloc(1); + paint->text[0] = c; + } + } + } +} + +static void +AsciiPreparePaint(Widget w, int y, int line, + XawTextPosition from, XawTextPosition to, Bool highlight) +{ + static XmuSegment segment; + static XmuScanline next; + static XmuScanline scanline = {0, &segment, &next}; + static XmuArea area = {&scanline}; + + TextWidget ctx = (TextWidget)XtParent(w); + AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink; + XawTextPosition left, right, pos, pos2, tmp, length; + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextProperty *property; + int i, ascent = 0, descent = 0, xl, xr, x = ctx->text.left_margin, bufsiz; + XawTextBlock block; + XFontStruct *font; + XawTextPaintStruct *paint; + + if (!sink->ascii_sink.echo) + return; + + /* pass 1: calculate ascent/descent values and x coordinate */ + /* XXX the MAX ascent/descent value should be in the line table XXX */ + /* XXX the x coordinate can be a parameter, but since it is required + to calculate the ascent/descent, do it here to avoid an extra + search in the entities */ + pos = tmp = left = ctx->text.lt.info[line].position; + right = ctx->text.lt.info[line + 1].position; + right = XawMin(right, ctx->text.lastPos + 1); + while (pos < right) { + if (XawTextSourceAnchorAndEntity(ctx->text.source, pos, + &anchor, &entity)) { + if ((property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + font = property->font; + else + font = sink->ascii_sink.font; + tmp = pos; + pos = anchor->position + entity->offset + entity->length; + if ((length = XawMin(from, pos) - tmp) > 0) + x += GetTextWidth(ctx, x, font, tmp, length); + ascent = XawMax(font->ascent, ascent); + descent = XawMax(font->descent, descent); + } + else if (anchor) { + ascent = XawMax(sink->ascii_sink.font->ascent, ascent); + descent = XawMax(sink->ascii_sink.font->descent, descent); + while (entity && pos < right) { + tmp = pos; + if ((pos = anchor->position + entity->offset) < tmp) + pos = tmp; + else { + if ((length = XawMin(from, pos) - tmp) > 0) { + x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, + length); + tmp += length; + } + if (pos < right) { + pos += entity->length; + if ((property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + font = property->font; + else + font = sink->ascii_sink.font; + if ((length = XawMin(from, pos) - tmp) > 0) + x += GetTextWidth(ctx, x, font, tmp, length); + ascent = XawMax(font->ascent, ascent); + descent = XawMax(font->descent, descent); + } + } + entity = entity->next; + } + + if (anchor->entities == NULL) { + tmp = XawMin(pos, from); + if ((length = from - tmp) > 0) + x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, length); + break; + } + } + else { + tmp = XawMin(pos, from); + if ((length = from - tmp) > 0) + x += GetTextWidth(ctx, x, sink->ascii_sink.font, tmp, length); + ascent = XawMax(sink->ascii_sink.font->ascent, ascent); + descent = XawMax(sink->ascii_sink.font->descent, descent); + break; + } + } + if (!ascent) + ascent = sink->ascii_sink.font->ascent; + if (!descent) + descent = sink->ascii_sink.font->descent; + + xl = x; + + /* pass 2: feed the XawTextPaintStruct lists */ + pos = from; + while (pos < to) { + paint = XtNew(XawTextPaintStruct); + paint->next = sink->text_sink.paint->paint; + sink->text_sink.paint->paint = paint; + paint->x = x; + paint->y = y + ascent; + paint->property = NULL; + paint->max_ascent = ascent; + paint->max_descent = descent; + paint->backtabs = NULL; + paint->highlight = highlight; + + tmp = pos; + if (XawTextSourceAnchorAndEntity(ctx->text.source, pos, + &anchor, &entity)) { + pos = anchor->position + entity->offset + entity->length; + if ((paint->property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (paint->property->mask & XAW_TPROP_FONT)) + font = paint->property->font; + else + font = sink->ascii_sink.font; + } + else { + if (anchor) { + while (entity && anchor->position + entity->offset < pos) + entity = entity->next; + if (entity) + pos = anchor->position + entity->offset; + else + pos = to; + } + else + pos = to; + font = sink->ascii_sink.font; + } + pos = XawMin(pos, to); + length = pos - tmp; + + paint->text = XtMalloc(bufsiz = pos - tmp + 4); + paint->length = 0; + segment.x1 = x; + + pos2 = tmp; + while (length > 0) { + pos2 = XawTextSourceRead(ctx->text.source, tmp, &block, length); + length = pos - pos2; + tmp = pos2; + for (i = 0; i < block.length; i++) { + unsigned char c = (unsigned char)block.ptr[i]; + + if (paint->length + 4 > bufsiz) + paint->text = XtRealloc(paint->text, bufsiz += 32); + paint->text[paint->length] = c; + if (c == '\n') { + x += CharWidth(sink, font, 0, ' '); + continue; + } + if (c == '\t') { + x += XTextWidth(font, paint->text, paint->length); + segment.x2 = x + CharWidth(sink, font, x, '\t'); + + if (XmuValidSegment(&segment)) { + if (!highlight && (paint->property && + (paint->property->mask & XAW_TPROP_BACKGROUND))) { + if (ascent > font->ascent) { + scanline.y = y; + next.y = y + ascent - font->ascent; + XmuAreaOr(sink->text_sink.paint->clip, &area); + } + if (descent >= font->descent) { + scanline.y = y + ascent + font->descent; + next.y = scanline.y + descent - font->descent + 1; + XmuAreaOr(sink->text_sink.paint->clip, &area); + } + if (paint->backtabs == NULL) + paint->backtabs = XmuCreateArea(); + scanline.y = y + ascent - font->ascent; + next.y = y + ascent + font->descent; + XmuAreaOr(paint->backtabs, &area); + } + else { + scanline.y = y; + next.y = ctx->text.lt.info[line + 1].y; + if (highlight) { + if (!sink->text_sink.paint->hightabs) + sink->text_sink.paint->hightabs = + XmuCreateArea(); + XmuAreaOr(sink->text_sink.paint->hightabs, &area); + } + else + XmuAreaOr(sink->text_sink.paint->clip, &area); + } + } + + paint->width = segment.x2 - segment.x1; + x = segment.x1 = segment.x2; + + if (paint->length == 0) { + paint->x = x; + continue; + } + paint->text = XtRealloc(paint->text, paint->length); + property = paint->property; + paint = XtNew(XawTextPaintStruct); + paint->next = sink->text_sink.paint->paint; + sink->text_sink.paint->paint = paint; + paint->x = x; + paint->y = y + ascent; + paint->property = property; + paint->max_ascent = ascent; + paint->max_descent = descent; + paint->backtabs = NULL; + paint->highlight = highlight; + paint->text = XtMalloc(bufsiz = pos - tmp - length + + block.length - i + 4); + paint->length = 0; + continue; + } + if ((c & 0177) < XawSP || c == 0177) { + if (sink->ascii_sink.display_nonprinting) { + if (c > 0177) { + paint->text[paint->length++] = '\\'; + paint->text[paint->length++] = ((c >> 6) & 7) + '0'; + paint->text[paint->length++] = ((c >> 3) & 7) + '0'; + paint->text[paint->length] = (c & 7) + '0'; + } + else { + c |= 0100; + paint->text[paint->length++] = '^'; + paint->text[paint->length] = c == 0177 ? '?' : c; + } + } + else + paint->text[paint->length] = ' '; + } + paint->length++; + } + } + + x += XTextWidth(font, paint->text, paint->length); + segment.x2 = x; + if (XmuValidSegment(&segment)) { + /* erase only what really is needed */ + /*if (!highlight || (paint->property && + (paint->property->mask & XAW_TPROP_BACKGROUND))) { + if (ascent > font->ascent) { + scanline.y = y; + next.y = y + ascent - font->ascent; + XmuAreaOr(sink->text_sink.paint->clip, &area); + } + if (descent > font->descent) { + scanline.y = y + ascent + font->descent; + next.y = scanline.y + descent - font->descent; + XmuAreaOr(sink->text_sink.paint->clip, &area); + } + } + else*/ { + scanline.y = y; + next.y = ctx->text.lt.info[line + 1].y; + XmuAreaOr(sink->text_sink.paint->clip, &area); + } + } + + paint->width = x - segment.x1; + } + + xr = x; + + /* pass 3: bearing clipping */ + if (left < from) { + CalculateBearing(ctx, from - 1, xl, y, ascent, descent, highlight, True); + if (ctx->text.s.left < ctx->text.s.right) { + if (ctx->text.s.right == from) + CalculateBearing(ctx, from, xl, y, ascent, descent, True, False); + else if (ctx->text.s.left == from) + CalculateBearing(ctx, from, xl, y, ascent, descent, False, False); + } + } + right = XawMin(right, ctx->text.lastPos); + if (right >= to && to > from) { + if (to < right) + CalculateBearing(ctx, to, xr, y, ascent, descent, highlight, False); + if (ctx->text.s.left < ctx->text.s.right) { + if (ctx->text.s.right == to) + CalculateBearing(ctx, to - 1, xr, y, ascent, descent, False, True); + else if (ctx->text.s.left == to) + CalculateBearing(ctx, to - 1, xr, y, ascent, descent, True, True); + } + } +} + +static int +qcmp_paint_struct(_Xconst void *left, _Xconst void *right) +{ + return ((*(XawTextPaintStruct**)left)->property - + (*(XawTextPaintStruct**)right)->property); +} + +static void +AsciiDoPaint(Widget w) +{ + TextWidget ctx = (TextWidget)XtParent(w); + AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink; + XmuScanline *scan; + XmuSegment *seg; + XawTextPaintList *list = sink->text_sink.paint; +#if 0 + XawTextPaintStruct *base, *head; +#endif + XawTextPaintStruct *paint = list->paint; + XawTextProperty *property; + XFontStruct *font = NULL; + XRectangle *rects; + int n_rects, i_rects; + GC gc; + Bool highlight; + XRectangle rect; + int width, height, line_width = -1; + XGCValues values; + + /* pass 1: clear clipping areas */ + /* XXX Don't use XDrawImageString because the font may be italic, and + will get incorrectly drawn. Probably, it could be a good idea to + check if this is the case, and do special processing. But this + will need to be checked if required. */ + for (scan = list->clip->scanline; scan && scan->next; scan = scan->next) + for (seg = scan->segment; seg; seg = seg->next) + _XawTextSinkClearToBackground(ctx->text.sink, + seg->x1, scan->y, + seg->x2 - seg->x1, + scan->next->y - scan->y); + + /* pass 2: optimize drawing list to avoid too much GC change requests */ + /* XXX this assumes there will not exist entities drawn over other + entities. */ +#if 0 + while (paint) { + base = paint; + head = paint->next; + while (head) { + if (head->property == paint->property) { + base->next = head->next; + head->next = paint->next; + paint->next = head; + paint = head; + } + base = head; + head = head->next; + } + paint = paint->next; + } +#endif + if (paint && paint->next) { + XawTextPaintStruct **paints; + int i = 0, n_paints = 0; + + while (paint) { + paint = paint->next; + ++n_paints; + } + paints = (XawTextPaintStruct**) + XtMalloc(n_paints * sizeof(XawTextPaintStruct)); + paint = list->paint; + while (paint) { + paints[i++] = paint; + paint = paint->next; + } + qsort((void*)paints, n_paints, sizeof(XawTextPaintStruct*), + qcmp_paint_struct); + list->paint = paints[0]; + for (i = 0; i < n_paints - 1; i++) + paints[i]->next = paints[i + 1]; + paints[i]->next = NULL; + XtFree((XtPointer)paints); + } + + /* pass 3: clip gc */ + gc = sink->ascii_sink.normgc; + + rect.x = ctx->text.r_margin.left; + rect.y = ctx->text.r_margin.top; + width = (int)XtWidth(ctx) - RHMargins(ctx); + height = (int)XtHeight(ctx) - RVMargins(ctx); + rect.width = width; + rect.height = height; + if (width >= 0 && height >= 0) + XSetClipRectangles(XtDisplay((Widget)ctx), gc, + 0, 0, &rect, 1, Unsorted); + else + XSetClipMask(XtDisplay((Widget)ctx), gc, None); + + /* pass 4: draw backgrounds */ + paint = list->paint; + property = NULL; + rects = NULL; + i_rects = n_rects = 0; + while (paint) { + if (paint->property && (paint->property->mask & XAW_TPROP_BACKGROUND)) { + if (property != paint->property) { + if (i_rects) + XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, + rects, i_rects); + i_rects = 0; + property = paint->property; + if (property->mask & XAW_TPROP_FONT) + font = property->font; + else + font = sink->ascii_sink.font; + XSetForeground(XtDisplay(ctx), gc, property->background); + } + if (i_rects <= n_rects) + rects = (XRectangle*) + XtRealloc((XtPointer)rects, sizeof(XRectangle) * + ++n_rects); + rects[i_rects].x = paint->x; + rects[i_rects].y = paint->y - font->ascent; + rects[i_rects].width = paint->width; + rects[i_rects++].height = font->ascent + font->descent; + + if (paint->backtabs) { + for (scan = paint->backtabs->scanline; scan && scan->next; + scan = scan->next) + for (seg = scan->segment; seg; seg = seg->next) { + if (i_rects <= n_rects) + rects = (XRectangle*) + XtRealloc((XtPointer)rects, sizeof(XRectangle) * + ++n_rects); + rects[i_rects].x = seg->x1; + rects[i_rects].y = scan->y; + rects[i_rects].width = seg->x2 - seg->x1; + rects[i_rects++].height = scan->next->y - scan->y; + } + } + + + } + paint = paint->next; + } + if (i_rects) + XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, rects, i_rects); + + paint = list->paint; + i_rects = 0; + while (paint) { + if (paint->highlight) { + if (i_rects == 0) + XSetForeground(XtDisplay(ctx), gc, sink->text_sink.cursor_color); + if (i_rects <= n_rects) + rects = (XRectangle*) + XtRealloc((XtPointer)rects, sizeof(XRectangle) * + ++n_rects); + rects[i_rects].x = paint->x; + rects[i_rects].y = paint->y - paint->max_ascent; + rects[i_rects].width = paint->width; + rects[i_rects++].height = paint->max_ascent + paint->max_descent + 1; + } + paint = paint->next; + } + if (list->hightabs) { + for (scan = list->hightabs->scanline; scan && scan->next; + scan = scan->next) + for (seg = scan->segment; seg; seg = seg->next) { + if (i_rects == 0) + XSetForeground(XtDisplay(ctx), gc, + sink->text_sink.cursor_color); + if (i_rects <= n_rects) + rects = (XRectangle*) + XtRealloc((XtPointer)rects, sizeof(XRectangle) * + ++n_rects); + rects[i_rects].x = seg->x1; + rects[i_rects].y = scan->y; + rects[i_rects].width = seg->x2 - seg->x1; + rects[i_rects++].height = scan->next->y - scan->y; + } + } + + if (i_rects) + XFillRectangles(XtDisplay(ctx), XtWindow(ctx), gc, rects, i_rects); + if (rects) + XtFree((XtPointer)rects); + + /* pass 5: draw text! */ + paint = list->paint; + if (paint && (property = paint->property) == NULL) { + font = sink->ascii_sink.font; + XSetFont(XtDisplay(ctx), gc, font->fid); + if (!paint->highlight) + XSetForeground(XtDisplay(ctx), gc, sink->text_sink.foreground); + } + else + property = NULL; + highlight = False; + while (paint) { + if (!highlight && paint->highlight) + XSetForeground(XtDisplay(ctx), gc, sink->text_sink.background); + if (highlight || paint->highlight || paint->property != property) { + if (!paint->property || !(paint->property->mask & XAW_TPROP_FONT)) + font = sink->ascii_sink.font; + else + font = paint->property->font; + XSetFont(XtDisplay(ctx), gc, font->fid); + if (!paint->highlight) { + if (!paint->property || + !(paint->property->mask & XAW_TPROP_FOREGROUND)) + XSetForeground(XtDisplay(ctx), gc, + sink->text_sink.foreground); + else + XSetForeground(XtDisplay(ctx), gc, + paint->property->foreground); + } + highlight = paint->highlight; + property = paint->property; + } + + if (paint->x < XtWidth(ctx) && paint->x + paint->width > 0) { + XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, paint->y, + paint->text, paint->length); + if (property) { + if (property->mask & XAW_TPROP_UNDERLINE) { + if (line_width != property->underline_thickness) { + values.line_width = line_width = + property->underline_thickness; + XChangeGC(XtDisplay(ctx), gc, GCLineWidth, &values); + } + + XDrawLine(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, + paint->y + property->underline_position, + paint->x + paint->width, + paint->y + property->underline_position); + } + if (property->mask & XAW_TPROP_OVERSTRIKE) { + if (line_width != property->underline_thickness) { + values.line_width = line_width = + property->underline_thickness; + XChangeGC(XtDisplay(ctx), gc, GCLineWidth, &values); + } + + XDrawLine(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, + paint->y - (font->ascent>>1) + (font->descent>>1), + paint->x + paint->width, + paint->y - (font->ascent>>1) + (font->descent>>1)); + } + } + } + + paint = paint->next; + } + + /* pass 6: bearing clipping */ + /* dont care on order of drawing or caching of state (by now) */ + paint = list->bearings; + while (paint) { + XRectangle rect; + + if (paint->highlight) + XSetForeground(XtDisplay(ctx), gc, sink->text_sink.background); + if (!paint->property || !(paint->property->mask & XAW_TPROP_FONT)) + font = sink->ascii_sink.font; + else + font = paint->property->font; + XSetFont(XtDisplay(ctx), gc, font->fid); + if (!paint->highlight) { + if (!paint->property || + !(paint->property->mask & XAW_TPROP_FOREGROUND)) + XSetForeground(XtDisplay(ctx), gc, sink->text_sink.foreground); + else + XSetForeground(XtDisplay(ctx), gc, paint->property->foreground); + } + if (paint->x < XtWidth(ctx) && paint->x + paint->width > 0) { + rect.x = paint->x + paint->width; + rect.width = XawAbs(paint->width); /* more than enough */ + rect.y = paint->y - font->ascent; + rect.height = rect.y + font->ascent + font->descent; + XSetClipRectangles(XtDisplay((Widget)ctx), gc, + 0, 0, &rect, 1, Unsorted); + XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, paint->x, paint->y, + paint->text, paint->length); + } + paint = paint->next; + } +} +#endif + +/* + * Function: + * PaintText + * + * Parameters: + * w - text sink object + * gc - gc to paint text with + * x - location to paint the text + * y - "" + * buf - buffer and length of text to paint. + * len - "" + * clear_bg - clear background before drawing ? + * + * Description: + * Actually paints the text into the window. + * + * Returns: + * the width of the text painted + */ +static unsigned int +PaintText(Widget w, GC gc, int x, int y, char *buf, int len, Bool clear_bg) +{ + AsciiSinkObject sink = (AsciiSinkObject)w; + TextWidget ctx = (TextWidget)XtParent(w); + int width = XTextWidth(sink->ascii_sink.font, buf, len); + + if ((x > XtWidth(ctx)) || width <= -x) /* Don't draw if we can't see it */ + return (width); + + if (clear_bg) { + _XawTextSinkClearToBackground(w, x, y - sink->ascii_sink.font->ascent, + width, sink->ascii_sink.font->ascent + + sink->ascii_sink.font->descent); + XDrawString(XtDisplay(ctx), XtWindow(ctx), gc, x, y, buf, len); + } + else + XDrawImageString(XtDisplay(ctx), XtWindow(ctx), gc, x, y, buf, len); + + return (width); +} + +static void +DisplayText(Widget w, int x, int y, + XawTextPosition pos1, XawTextPosition pos2, Bool highlight) +{ + TextWidget ctx = (TextWidget)XtParent(w); + AsciiSinkObject sink = (AsciiSinkObject)w; + XFontStruct *font = sink->ascii_sink.font; + Widget source = XawTextGetSource(XtParent(w)); + unsigned char buf[260]; + int j, k; + XawTextBlock blk; + GC gc, invgc, tabgc; + int max_x; + Bool clear_bg; + + if (!sink->ascii_sink.echo || !ctx->text.lt.lines) + return; + + max_x = (int)XtWidth(ctx) - ctx->text.r_margin.right; + clear_bg = !highlight && ctx->core.background_pixmap != XtUnspecifiedPixmap; + + gc = highlight ? sink->ascii_sink.invgc : sink->ascii_sink.normgc; + invgc = highlight ? sink->ascii_sink.normgc : sink->ascii_sink.invgc; + + if (highlight && sink->ascii_sink.xorgc) + tabgc = sink->ascii_sink.xorgc; + else + tabgc = invgc; + + y += sink->ascii_sink.font->ascent; + for (j = 0; pos1 < pos2;) { + pos1 = XawTextSourceRead(source, pos1, &blk, pos2 - pos1); + for (k = 0; k < blk.length; k++) { + if (j >= sizeof(buf) - 4) { /* buffer full, dump the text */ + if ((x += PaintText(w, gc, x, y, (char*)buf, j, clear_bg)) + >= max_x) + return; + j = 0; + } + buf[j] = blk.ptr[k]; + if (buf[j] == XawLF) /* line feeds ('\n') are not printed */ + continue; + + else if (buf[j] == '\t') { + int width; + + if (j != 0 + && (x += PaintText(w, gc, x, y, (char*)buf, j, clear_bg)) + >= max_x) + return; + + if ((width = CharWidth(sink, font, x, '\t')) > -x) { + if (clear_bg) + _XawTextSinkClearToBackground(w, x, y-font->ascent, width, + font->ascent+font->descent); + else + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + tabgc, x, y - font->ascent, width, + font->ascent + font->descent); + } + + if ((x += width) >= max_x) + return; + + j = -1; + } + else if ((buf[j] & 0177) < XawSP || buf[j] == 0177) { + if (sink->ascii_sink.display_nonprinting) { + unsigned char c = buf[j]; + + if (c > 0177) { + buf[j++] = '\\'; + buf[j++] = ((c >> 6) & 7) + '0'; + buf[j++] = ((c >> 3) & 7) + '0'; + buf[j] = (c & 7) + '0'; + } + else { + c |= 0100; + buf[j++] = '^'; + buf[j] = c == 0177 ? '?' : c; + } + } + else + buf[j] = ' '; + } + j++; + } + } + + if (j > 0) + (void)PaintText(w, gc, x, y, (char*)buf, j, clear_bg); +} + +/* + * Function: + * GetCursorBounds + * + * Parameters: + * w - text sink object + * rect - X rectangle to return the cursor bounds + * + * Description: + * Returns the size and location of the cursor. + */ +static void +GetCursorBounds(Widget w, XRectangle *rect) +{ + AsciiSinkObject sink = (AsciiSinkObject)w; + XFontStruct *font = sink->ascii_sink.font; + unsigned char ch; +#ifndef OLDXAW + TextWidget ctx = (TextWidget)XtParent(w); + XawTextBlock block; + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextProperty *property; + + if (XawTextSourceAnchorAndEntity(XawTextGetSource(XtParent(w)), + sink->ascii_sink.cursor_position, + &anchor, &entity)) { + if ((property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + font = property->font; + } + (void)XawTextSourceRead(XawTextGetSource((Widget)ctx), + ctx->text.insertPos, &block, 1); + if (!block.length || block.ptr[0] == '\n' || block.ptr[0] == '\t') + ch = ' '; + else if ((*((unsigned char*)block.ptr) & 0177) < XawSP || + *(unsigned char*)block.ptr == 0177) { + if (sink->ascii_sink.display_nonprinting) + ch = *((unsigned char*)block.ptr) > 0177 ? '\\' : '^'; + else + ch = ' '; + } + else + ch = *(unsigned char*)block.ptr; +#else + ch = ' '; +#endif + + rect->width = CharWidth(sink, font, 0, ch); + rect->height = font->descent + font->ascent + 1; + + rect->x = sink->ascii_sink.cursor_x; + rect->y = sink->ascii_sink.cursor_y - font->ascent; +} + +/* this function is required to support diferent fonts and correctly place + * the cursor. There are better ways to calculate the base line, but there is + * no place/code (yet) to store this information. + */ +static int +FindCursorY(TextWidget ctx, XawTextPosition position) +{ + int y, line, ascent; + AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink; +#ifndef OLDXAW + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextProperty *property; + XawTextPosition left, right; +#endif + + for (line = 0; line < ctx->text.lt.lines; line++) + if (position < ctx->text.lt.info[line + 1].position) + break; + + y = ctx->text.lt.info[line].y; +#ifndef OLDXAW + ascent = 0; + left = ctx->text.lt.info[line].position; + right = ctx->text.lt.info[line + 1].position; + right = XawMin(right, ctx->text.lastPos + 1); + while (left < right) { + if (XawTextSourceAnchorAndEntity(ctx->text.source, left, + &anchor, &entity)) { + if ((property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + ascent = XawMax(property->font->ascent, ascent); + else + ascent = XawMax(sink->ascii_sink.font->ascent, ascent); + left = anchor->position + entity->offset + entity->length; + } + else if (anchor) { + ascent = XawMax(sink->ascii_sink.font->ascent, ascent); + while (entity) { + XawTextPosition tmp = anchor->position + entity->offset + entity->length; + + if (tmp > left && tmp < right) { + left = tmp; + if ((property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + ascent = XawMax(property->font->ascent, ascent); + else + ascent = XawMax(sink->ascii_sink.font->ascent, ascent); + } + entity = entity->next; + } + if (entity == NULL) + break; + } + else { + ascent = XawMax(sink->ascii_sink.font->ascent, ascent); + break; + } + } + if (!ascent) + ascent = sink->ascii_sink.font->ascent; +#else + ascent = sink->ascii_sink.font->ascent; +#endif + + return (y + ascent); +} + +static void +InsertCursor(Widget w, int x, int y, XawTextInsertState state) +{ + AsciiSinkObject sink = (AsciiSinkObject)w; + XFontStruct *font = sink->ascii_sink.font; + TextWidget ctx = (TextWidget)XtParent(w); + XawTextPosition position = XawTextGetInsertionPoint((Widget)ctx); + Boolean overflow = (x & 0xffff8000) != 0; +#ifndef OLDXAW + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextProperty *property; +#endif + + if (XtIsRealized((Widget)ctx)) { + int fheight; + XawTextBlock block; + XawTextPosition selection_start, selection_end; + Boolean has_selection; + + if (!sink->ascii_sink.echo) { + if (sink->ascii_sink.laststate != state) { + int width = CharWidth(sink, font, 0, ' ') - 1; + + x = ctx->text.margin.left; + y = ctx->text.margin.top; + font = sink->ascii_sink.font; + fheight = font->ascent + font->descent; + if (state == XawisOn) { + if (ctx->text.hasfocus) + XFillRectangle(XtDisplay(ctx), XtWindow(ctx), + sink->ascii_sink.xorgc, x, y, + width + 1, fheight + 1); + else + XDrawRectangle(XtDisplay(ctx), XtWindow(ctx), + sink->ascii_sink.xorgc, x, y, + width, fheight); + + } + else + _XawTextSinkClearToBackground(w, x, y, + width + 1, fheight + 1); + } + sink->ascii_sink.cursor_x = x; + sink->ascii_sink.cursor_y = y; + sink->ascii_sink.laststate = state; + return; + } + + + XawTextGetSelectionPos((Widget)ctx, &selection_start, &selection_end); + has_selection = selection_start != selection_end; + + if (sink->ascii_sink.laststate != state) { + unsigned char ch; + +#ifndef OLDXAW + if (XawTextSourceAnchorAndEntity(ctx->text.source, + position, &anchor, &entity) && + (property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + font = property->font; + else + font = sink->ascii_sink.font; +#endif + + fheight = font->ascent + font->descent; + (void)XawTextSourceRead(XawTextGetSource((Widget)ctx), + position, &block, 1); + if (!block.length || block.ptr[0] == '\n' || block.ptr[0] == '\t') + ch = ' '; + else if ((*((unsigned char*)block.ptr) & 0177) < XawSP + || *(unsigned char*)block.ptr == 0177) { + if (sink->ascii_sink.display_nonprinting) + ch = *((unsigned char*)block.ptr) > 0177 ? '\\' : '^'; + else + ch = ' '; + } + else + ch = *(unsigned char*)block.ptr; + + y = FindCursorY(ctx, position); + if (ctx->text.hasfocus && !has_selection) + XFillRectangle(XtDisplay(ctx), XtWindow(ctx), + sink->ascii_sink.xorgc, x, y - font->ascent, + CharWidth(sink, font, 0, ch), fheight + 1); + else + XDrawRectangle(XtDisplay(ctx), XtWindow(ctx), + sink->ascii_sink.xorgc, x, y - font->ascent, + CharWidth(sink, font, 0, ch) - 1, fheight); + } + } + + sink->ascii_sink.cursor_x = overflow ? -16384 : x; + sink->ascii_sink.cursor_y = y; + sink->ascii_sink.laststate = state; + sink->ascii_sink.cursor_position = position; +} + +/* + * Given two positions, find the distance between them + */ +static void +FindDistance(Widget w, XawTextPosition fromPos, int fromx, + XawTextPosition toPos, int *resWidth, + XawTextPosition *resPos, int *resHeight) +{ +#ifndef OLDXAW + AsciiSinkObject sink = (AsciiSinkObject)w; + TextWidget ctx = (TextWidget)XtParent(w); + XFontStruct *font = sink->ascii_sink.font; + Widget source = ctx->text.source; + XawTextPosition idx, pos; + unsigned char c; + XawTextBlock blk; + int i, rWidth, ascent = 0, descent = 0; + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextProperty *property; + Cardinal length; + Bool done = False; + + pos = idx = fromPos; + rWidth = 0; + c = 0; + + while (!done) { + if (XawTextSourceAnchorAndEntity(source, pos, &anchor, &entity)) { + length = anchor->position + entity->offset + entity->length; + length = XawMin(toPos, length) - pos; + if ((property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + font = property->font; + else + font = sink->ascii_sink.font; + } + else { + if (anchor) { + while (entity && anchor->position + entity->offset < pos) + entity = entity->next; + if (entity) { + length = anchor->position + entity->offset; + length = XawMin(toPos, length) - pos; + } + else + length = XawMin(toPos - pos, 4096); + } + else + length = XawMin(toPos - pos, 4096); + font = sink->ascii_sink.font; + } + + ascent = XawMax(font->ascent, ascent); + descent = XawMax(font->descent, descent); + + pos = XawTextSourceRead(source, pos, &blk, length); + if (blk.length == 0 && pos == idx) /* eof reached */ + break; + + idx = blk.firstPos; + for (i = 0; idx < toPos; i++, idx++) { + if (i >= blk.length) + break; + c = blk.ptr[i]; + rWidth += CharWidth(sink, font, fromx + rWidth, c); + if (c == XawLF) { + idx++; + done = True; + break; + } + } + if (idx >= toPos) + break; + } + + *resPos = idx; + *resWidth = rWidth; + *resHeight = ascent + descent + 1; +#else + AsciiSinkObject sink = (AsciiSinkObject)w; + TextWidget ctx = (TextWidget)XtParent(w); + XFontStruct *font = sink->ascii_sink.font; + Widget source = ctx->text.source; + XawTextPosition idx, pos; + unsigned char c; + XawTextBlock blk; + int i, rWidth; + + pos = XawTextSourceRead(source, fromPos, &blk, toPos - fromPos); + rWidth = 0; + for (i = 0, idx = fromPos; idx < toPos; i++, idx++) { + if (i >= blk.length) { + i = 0; + pos = XawTextSourceRead(source, pos, &blk, toPos - pos); + if (blk.length == 0) + break; + } + c = blk.ptr[i]; + rWidth += CharWidth(sink, font, fromx + rWidth, c); + if (c == XawLF) { + idx++; + break; + } + } + + *resPos = idx; + *resWidth = rWidth; + *resHeight = font->ascent + font->descent + 1; +#endif +} + +static void +FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width, + Bool stopAtWordBreak, XawTextPosition *resPos, + int *resWidth, int *resHeight) +{ +#ifndef OLDXAW + AsciiSinkObject sink = (AsciiSinkObject)w; + TextWidget ctx = (TextWidget)XtParent(w); + Widget source = ctx->text.source; + XFontStruct *font = sink->ascii_sink.font; + XawTextPosition idx, pos, whiteSpacePosition = 0; + int i, lastWidth, whiteSpaceWidth, rWidth, ascent = 0, descent = 0; + Boolean whiteSpaceSeen; + unsigned char c; + XawTextBlock blk; + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextProperty *property; + Cardinal length; + Bool done = False; + + pos = idx = fromPos; + rWidth = lastWidth = whiteSpaceWidth = 0; + whiteSpaceSeen = False; + c = 0; + + while (!done) { + font = sink->ascii_sink.font; + if (XawTextSourceAnchorAndEntity(source, pos, &anchor, &entity)) { + length = anchor->position + entity->offset + entity->length - pos; + if ((property = XawTextSinkGetProperty((Widget)sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + font = property->font; + } + else { + if (anchor) { + while (entity && anchor->position + entity->offset < pos) + entity = entity->next; + if (entity) + length = anchor->position + entity->offset - pos; + else + length = 4096; + } + else + length = 4096; + } + + ascent = XawMax(font->ascent, ascent); + descent = XawMax(font->descent, descent); + + pos = XawTextSourceRead(source, pos, &blk, length); + if (blk.length == 0 && pos == idx) /* eof reached */ + break; + + idx = blk.firstPos; + for (i = 0; rWidth <= width && i < blk.length; i++, idx++) { + c = blk.ptr[i]; + lastWidth = rWidth; + rWidth += CharWidth(sink, font, fromx + rWidth, c); + + if (c == XawLF) { + idx++; + done = True; + break; + } + else if ((c == XawSP || c == XawTAB) && rWidth <= width) { + whiteSpaceSeen = True; + whiteSpacePosition = idx; + whiteSpaceWidth = rWidth; + } + } + if (rWidth > width) + break; + } + + if (rWidth > width && idx > fromPos) { + idx--; + rWidth = lastWidth; + if (stopAtWordBreak && whiteSpaceSeen) { + idx = whiteSpacePosition + 1; + rWidth = whiteSpaceWidth; + } + } + + if (idx >= ctx->text.lastPos && c != XawLF) + idx = ctx->text.lastPos + 1; + + *resPos = idx; + *resWidth = rWidth; + *resHeight = ascent + descent + 1; +#else + AsciiSinkObject sink = (AsciiSinkObject)w; + TextWidget ctx = (TextWidget)XtParent(w); + Widget source = ctx->text.source; + XFontStruct *font = sink->ascii_sink.font; + XawTextPosition idx, pos, whiteSpacePosition = 0; + int i, lastWidth, whiteSpaceWidth, rWidth; + Boolean whiteSpaceSeen; + unsigned char c; + XawTextBlock blk; + + pos = XawTextSourceRead(source, fromPos, &blk, BUFSIZ); + rWidth = lastWidth = whiteSpaceWidth = 0; + whiteSpaceSeen = False; + c = 0; + + for (i = 0, idx = fromPos; rWidth <= width; i++, idx++) { + if (i >= blk.length) { + i = 0; + pos = XawTextSourceRead(source, pos, &blk, BUFSIZ); + if (blk.length == 0) + break; + } + c = blk.ptr[i]; + lastWidth = rWidth; + rWidth += CharWidth(sink, font, fromx + rWidth, c); + + if (c == XawLF) { + idx++; + break; + } + else if ((c == XawSP || c == XawTAB) && rWidth <= width) { + whiteSpaceSeen = True; + whiteSpacePosition = idx; + whiteSpaceWidth = rWidth; + } + } + + if (rWidth > width && idx > fromPos) { + idx--; + rWidth = lastWidth; + if (stopAtWordBreak && whiteSpaceSeen) { + idx = whiteSpacePosition + 1; + rWidth = whiteSpaceWidth; + } + } + + if (idx >= ctx->text.lastPos && c != XawLF) + idx = ctx->text.lastPos + 1; + + *resPos = idx; + *resWidth = rWidth; + *resHeight = font->ascent + font->descent + 1; +#endif +} + +static void +Resolve(Widget w, XawTextPosition pos, int fromx, int width, + XawTextPosition *pos_return) +{ + int resWidth, resHeight; + Widget source = XawTextGetSource(XtParent(w)); + + FindPosition(w, pos, fromx, width, False, pos_return, &resWidth, &resHeight); + if (*pos_return > GETLASTPOS) + *pos_return = GETLASTPOS; +} + +static void +GetGC(AsciiSinkObject sink) +{ + XtGCMask valuemask = (GCFont | GCGraphicsExposures | GCClipXOrigin | + GCForeground | GCBackground); + XGCValues values; + + /* XXX We dont want do share a gc that will change the clip-mask */ + values.clip_x_origin = (long)sink; + values.clip_mask = None; + values.font = sink->ascii_sink.font->fid; + values.graphics_exposures = False; + + values.foreground = sink->text_sink.foreground; + values.background = sink->text_sink.background; + sink->ascii_sink.normgc = XtAllocateGC((Widget)sink, 0, valuemask, &values, + GCClipMask | GCFont | GCForeground | + GCBackground, 0); + + values.foreground = sink->text_sink.background; +#ifndef OLDXAW + values.background = sink->text_sink.cursor_color; +#else + values.background = sink->text_sink.foreground; +#endif + sink->ascii_sink.invgc = XtAllocateGC((Widget)sink, 0, valuemask, &values, + GCClipMask | GCFont, 0); + + valuemask |= GCFunction; + values.function = GXxor; +#ifndef OLDXAW + values.foreground = sink->text_sink.background ^ sink->text_sink.cursor_color; +#else + values.foreground = sink->text_sink.background ^ sink->text_sink.foreground; +#endif + values.background = 0L; + sink->ascii_sink.xorgc = XtAllocateGC((Widget)sink, 0, valuemask, + &values, GCClipMask | GCFont, 0); + + XawAsciiSinkResize((Widget)sink); +} + +/* Function: + * XawAsciiSinkInitialize + * + * Parameters: + * request - the requested and new values for the object instance + * cnew - "" + * + * Description: + * Initializes the TextSink Object. + */ +/*ARGSUSED*/ +static void +XawAsciiSinkInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + AsciiSinkObject sink = (AsciiSinkObject)cnew; + + GetGC(sink); + + if (!sink->ascii_sink.font) XtError("Aborting: no font found\n"); + + sink->ascii_sink.cursor_position = 0; + sink->ascii_sink.laststate = XawisOff; + sink->ascii_sink.cursor_x = sink->ascii_sink.cursor_y = 0; +} + +/* + * Function: + * XawAsciiSinkDestroy + * + * Parameters: + * w - AsciiSink Object + * + * Description: + * This function cleans up when the object is destroyed. + */ +static void +XawAsciiSinkDestroy(Widget w) +{ + AsciiSinkObject sink = (AsciiSinkObject)w; + + XtReleaseGC(w, sink->ascii_sink.normgc); + XtReleaseGC(w, sink->ascii_sink.invgc); + XtReleaseGC(w, sink->ascii_sink.xorgc); + + sink->ascii_sink.normgc = + sink->ascii_sink.invgc = + sink->ascii_sink.xorgc = NULL; +} + +static void +XawAsciiSinkResize(Widget w) +{ + TextWidget ctx = (TextWidget)XtParent(w); + AsciiSinkObject sink = (AsciiSinkObject)w; + XRectangle rect; + int width, height; + + if (w->core.widget_class != asciiSinkObjectClass) + return; + + rect.x = ctx->text.r_margin.left; + rect.y = ctx->text.r_margin.top; + width = (int)XtWidth(ctx) - RHMargins(ctx); + height = (int)XtHeight(ctx) - RVMargins(ctx); + rect.width = width; + rect.height = height; + + if (sink->ascii_sink.normgc) { + if (width >= 0 && height >= 0) + XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.normgc, + 0, 0, &rect, 1, Unsorted); + else + XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.normgc, None); + } + if (sink->ascii_sink.invgc) { + if (width >= 0 && height >= 0) + XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.invgc, + 0, 0, &rect, 1, Unsorted); + else + XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.invgc, None); + } + if (sink->ascii_sink.xorgc) { + if (width >= 0 && height >= 0) + XSetClipRectangles(XtDisplay((Widget)ctx), sink->ascii_sink.xorgc, + 0, 0, &rect, 1, Unsorted); + else + XSetClipMask(XtDisplay((Widget)ctx), sink->ascii_sink.xorgc, None); + } +} + +/* + * Function: + * XawAsciiSinkSetValues + * + * Parameters: + * current - current state of the object + * request - what was requested + * cnew - what the object will become + * + * Description: + * Sets the values for the AsciiSink. + * + * Returns: + * True if redisplay is needed + */ +/*ARGSUSED*/ +static Boolean +XawAsciiSinkSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + AsciiSinkObject w = (AsciiSinkObject)cnew; + AsciiSinkObject old_w = (AsciiSinkObject)current; + + if (w->ascii_sink.font != old_w->ascii_sink.font + || w->text_sink.background != old_w->text_sink.background + || w->text_sink.foreground != old_w->text_sink.foreground +#ifndef OLDXAW + || w->text_sink.cursor_color != old_w->text_sink.cursor_color + || w->text_sink.properties != old_w->text_sink.properties +#endif + ) { +#ifdef OLDXAW + XtReleaseGC(cnew, w->ascii_sink.normgc); + XtReleaseGC(cnew, w->ascii_sink.invgc); + XtReleaseGC(cnew, w->ascii_sink.xorgc); + GetGC(w); +#endif + ((TextWidget)XtParent(cnew))->text.redisplay_needed = True; + } + else if (w->ascii_sink.echo != old_w->ascii_sink.echo + || w->ascii_sink.display_nonprinting + != old_w->ascii_sink.display_nonprinting) + ((TextWidget)XtParent(cnew))->text.redisplay_needed = True; +#ifndef OLDXAW + if (w->text_sink.properties != old_w->text_sink.properties) { + XawTextProperty *property = + XawTextSinkGetProperty(cnew, XrmStringToQuark("default")); + + if (property) { + if (property->mask & XAW_TPROP_FONT) + w->ascii_sink.font = property->font; + if (property->mask & XAW_TPROP_FOREGROUND) + w->text_sink.foreground = property->foreground; + if (property->mask & XAW_TPROP_BACKGROUND) + w->text_sink.background = property->background; + } + } +#endif + + return (False); +} + +/* + * Function: + * MaxLines + * + * Parameters: + * w - AsciiSink Object + * height - height to fit lines into + * + * Description: + * Finds the Maximum number of lines that will fit in a given height. + * + * Returns: + * The number of lines that will fit + */ +/*ARGSUSED*/ +static int +MaxLines(Widget w, unsigned int height) +{ + AsciiSinkObject sink = (AsciiSinkObject)w; + int font_height; + + font_height = sink->ascii_sink.font->ascent + sink->ascii_sink.font->descent + 1; + + return ((int)height / font_height); +} + +/* + * Function: + * MaxHeight + * + * Parameters: + * w - AsciiSink Object + * lines - number of lines + * + * Description: + * Finds the Minium height that will contain a given number lines. + * + * Returns: + * the height + */ +static int +MaxHeight(Widget w, int lines) +{ + AsciiSinkObject sink = (AsciiSinkObject)w; + + return (lines * (sink->ascii_sink.font->ascent + + sink->ascii_sink.font->descent + 1)); +} + +/* + * Function: + * SetTabs + * + * Parameters: + * w - AsciiSink Object + * tab_count - number of tabs in the list + * tabs - text positions of the tabs + * + * Description: + * Sets the Tab stops. + */ +static void +SetTabs(Widget w, int tab_count, short *tabs) +{ + AsciiSinkObject sink = (AsciiSinkObject)w; + int i; + Atom XA_FIGURE_WIDTH; + unsigned long figure_width = 0; + XFontStruct *font = sink->ascii_sink.font; + + /* + * Find the figure width of the current font + */ + XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", False); + if (XA_FIGURE_WIDTH != None + && (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width) + || figure_width == 0)) { + if (font->per_char && font->min_char_or_byte2 <= '$' + && font->max_char_or_byte2 >= '$') + figure_width = font->per_char['$' - font->min_char_or_byte2].width; + else + figure_width = font->max_bounds.width; + } + + if (tab_count > sink->text_sink.tab_count) { + sink->text_sink.tabs = (Position *) + XtRealloc((char*)sink->text_sink.tabs, tab_count * sizeof(Position)); + sink->text_sink.char_tabs = (short *) + XtRealloc((char*)sink->text_sink.char_tabs, tab_count * sizeof(short)); + } + + for (i = 0 ; i < tab_count ; i++) { + sink->text_sink.tabs[i] = tabs[i] * figure_width; + sink->text_sink.char_tabs[i] = tabs[i]; + } + + sink->text_sink.tab_count = tab_count; + +#ifndef NO_TAB_FIX + { + TextWidget ctx = (TextWidget)XtParent(w); + ctx->text.redisplay_needed = True; + _XawTextBuildLineTable(ctx, ctx->text.lt.top, True); + } +#endif +} diff --git a/libXaw/src/AsciiSrc.c b/libXaw/src/AsciiSrc.c index 2a07e6220..245a65464 100644 --- a/libXaw/src/AsciiSrc.c +++ b/libXaw/src/AsciiSrc.c @@ -1,1888 +1,1888 @@ -/*
-
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-/*
- * AsciiSrc.c - AsciiSrc object. (For use with the text widget).
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xos.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xaw/XawInit.h>
-#include <X11/Xaw/AsciiSrcP.h>
-#include <X11/Xaw/MultiSrcP.h>
-#ifndef OLDXAW
-#include <X11/Xaw/TextSinkP.h>
-#include <X11/Xaw/AsciiSinkP.h>
-#endif
-#include "Private.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#if (defined(ASCII_STRING) || defined(ASCII_DISK))
-#include <X11/Xaw/AsciiText.h> /* for Widget Classes */
-#endif
-
-#ifdef X_NOT_POSIX
-#define Off_t long
-#define Size_t unsigned int
-#else
-#define Off_t off_t
-#define Size_t size_t
-#endif
-
-#define MAGIC_VALUE ((XawTextPosition)-1)
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
-/*
- * Class Methods
- */
-static void XawAsciiSrcClassInitialize(void);
-static void XawAsciiSrcDestroy(Widget);
-static void XawAsciiSrcGetValuesHook(Widget, ArgList, Cardinal*);
-static void XawAsciiSrcInitialize(Widget, Widget, ArgList, Cardinal*);
-static Boolean XawAsciiSrcSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int);
-static int ReplaceText(Widget, XawTextPosition, XawTextPosition,
- XawTextBlock*);
-static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType,
- XawTextScanDirection, int, Bool);
-static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection,
- XawTextBlock*);
-
-/*
- * Prototypes
- */
-static Piece *AllocNewPiece(AsciiSrcObject, Piece*);
-static void BreakPiece(AsciiSrcObject, Piece*);
-static Boolean CvtAsciiTypeToString(Display*, XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr, XtPointer*);
-static void CvtStringToAsciiType(XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr);
-static Piece *FindPiece(AsciiSrcObject, XawTextPosition, XawTextPosition*);
-static void FreeAllPieces(AsciiSrcObject);
-static FILE *InitStringOrFile(AsciiSrcObject, Bool);
-static void LoadPieces(AsciiSrcObject, FILE*, char*);
-static void RemoveOldStringOrFile(AsciiSrcObject, Bool);
-static void RemovePiece(AsciiSrcObject, Piece*);
-static String StorePiecesInString(AsciiSrcObject);
-static Bool WriteToFile(String, String, unsigned);
-static Bool WritePiecesToFile(AsciiSrcObject, String);
-static void GetDefaultPieceSize(Widget, int, XrmValue*);
-
-/*
- * More Prototypes
- */
-#ifdef ASCII_DISK
-Widget XawAsciiDiskSourceCreate(Widget, ArgList, Cardinal);
-#endif
-#ifdef ASCII_STRING
-Widget XawStringSourceCreate(Widget, ArgList, Cardinal);
-void XawTextSetLastPos(Widget, XawTextPosition);
-#endif
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(AsciiSrcRec, ascii_src.field)
-static XtResource resources[] = {
- {
- XtNstring,
- XtCString,
- XtRString,
- sizeof(char*),
- offset(string),
- XtRString,
- NULL
- },
- {
- XtNtype,
- XtCType,
- XtRAsciiType,
- sizeof(XawAsciiType),
- offset(type),
- XtRImmediate,
- (XtPointer)XawAsciiString
- },
- {
- XtNdataCompression,
- XtCDataCompression,
- XtRBoolean,
- sizeof(Boolean),
- offset(data_compression),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNpieceSize,
- XtCPieceSize,
- XtRInt,
- sizeof(XawTextPosition),
- offset(piece_size),
- XtRCallProc,
- (XtPointer)GetDefaultPieceSize
- },
-#ifdef OLDXAW
- {
- XtNcallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(callback),
- XtRCallback,
- (XtPointer)NULL
- },
-#endif
- {
- XtNuseStringInPlace,
- XtCUseStringInPlace,
- XtRBoolean,
- sizeof(Boolean),
- offset(use_string_in_place),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNlength,
- XtCLength,
- XtRInt,
- sizeof(int),
- offset(ascii_length),
- XtRImmediate,
- (XtPointer)MAGIC_VALUE
- },
-#ifdef ASCII_DISK
- {
- XtNfile,
- XtCFile,
- XtRString,
- sizeof(String),
- offset(filename),
- XtRString,
- NULL
- },
-#endif /* ASCII_DISK */
-};
-#undef offset
-
-
-#define Superclass (&textSrcClassRec)
-AsciiSrcClassRec asciiSrcClassRec = {
- /* object */
- {
- (WidgetClass)Superclass, /* superclass */
- "AsciiSrc", /* class_name */
- sizeof(AsciiSrcRec), /* widget_size */
- XawAsciiSrcClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawAsciiSrcInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* compress_motion */
- False, /* compress_exposure */
- False, /* compress_enterleave */
- False, /* visible_interest */
- XawAsciiSrcDestroy, /* destroy */
- NULL, /* resize */
- NULL, /* expose */
- XawAsciiSrcSetValues, /* set_values */
- NULL, /* set_values_hook */
- NULL, /* set_values_almost */
- XawAsciiSrcGetValuesHook, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- NULL, /* query_geometry */
- NULL, /* display_accelerator */
- NULL, /* extension */
- },
- /* text_src */
- {
- ReadText, /* Read */
- ReplaceText, /* Replace */
- Scan, /* Scan */
- Search, /* Search */
- XtInheritSetSelection, /* SetSelection */
- XtInheritConvertSelection, /* ConvertSelection */
- },
- /* ascii_src */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec;
-
-static XrmQuark Qstring, Qfile;
-
-/*
- * Implementation
- */
-/*
- * Function:
- * XawAsciiSrcClassInitialize()
- *
- * Description:
- * Initializes the asciiSrcObjectClass and install the converters for
- * AsciiType <-> String.
- */
-static void
-XawAsciiSrcClassInitialize(void)
-{
- XawInitializeWidgetSet();
- Qstring = XrmPermStringToQuark(XtEstring);
- Qfile = XrmPermStringToQuark(XtEfile);
- XtAddConverter(XtRString, XtRAsciiType, CvtStringToAsciiType, NULL, 0);
- XtSetTypeConverter(XtRAsciiType, XtRString, CvtAsciiTypeToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-/*
- * Function:
- * XawAsciiSrcInitialize
- *
- * Parameters:
- * request - widget requested by the argument list
- * cnew - new widget with both resource and non resource values
- * args - (unused)
- * num_args - (unused)
- *
- * Description:
- * Initializes the ascii src object.
- */
-/*ARGSUSED*/
-static void
-XawAsciiSrcInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- AsciiSrcObject src = (AsciiSrcObject)cnew;
- FILE *file;
-
- /*
- * Set correct flags (override resources) depending upon widget class
- */
- src->text_src.text_format = XawFmt8Bit;
-
-#ifdef ASCII_DISK
- if (XtIsSubclass(XtParent(cnew), asciiDiskWidgetClass)) {
- src->ascii_src.type = XawAsciiFile;
- src->ascii_src.string = src->ascii_src.filename;
- }
-#endif
-
-#ifdef ASCII_STRING
- if (XtIsSubclass(XtParent(cnew), asciiStringWidgetClass)) {
- src->ascii_src.use_string_in_place = True;
- src->ascii_src.type = XawAsciiString;
- }
-#endif
-
-#ifdef OLDXAW
- src->ascii_src.changes = False;
-#else
- src->text_src.changed = False;
-#endif
- src->ascii_src.allocated_string = False;
-
- if (src->ascii_src.use_string_in_place && src->ascii_src.string == NULL)
- src->ascii_src.use_string_in_place = False;
-
- file = InitStringOrFile(src, src->ascii_src.type == XawAsciiFile);
- LoadPieces(src, file, NULL);
-
- if (file != NULL)
- fclose(file);
-}
-
-/*
- * Function:
- * ReadText
- *
- * Parameters:
- * w - AsciiSource widget
- * pos - position of the text to retreive.
- * text - text block that will contain returned text
- * length - maximum number of characters to read
- *
- * Description:
- * This function reads the source.
- *
- * Returns:
- * The character position following the retrieved text.
- */
-static XawTextPosition
-ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length)
-{
- AsciiSrcObject src = (AsciiSrcObject)w;
- XawTextPosition count, start;
- Piece *piece;
-#ifndef OLDXAW
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextPosition offset, end = pos + length;
- Bool state;
-
- end = XawMin(end, src->ascii_src.length);
- while ((state = XawTextSourceAnchorAndEntity(w, pos, &anchor, &entity)) &&
- (entity->flags & XAW_TENTF_HIDE))
- pos = anchor->position + entity->offset + entity->length;
- if (state == False ||
- !(entity->flags & XAW_TENTF_REPLACE)) {
- while (entity) {
- offset = anchor->position + entity->offset;
- if (offset >= end)
- break;
- if (offset > pos &&
- (entity->flags & (XAW_TENTF_HIDE | XAW_TENTF_REPLACE))) {
- end = XawMin(end, offset);
- break;
- }
- if ((entity = entity->next) == NULL &&
- (anchor = XawTextSourceNextAnchor(w, anchor)) != NULL)
- entity = anchor->entities;
- }
- }
- else if (state && (entity->flags & XAW_TENTF_REPLACE) && pos < end) {
- XawTextBlock *block = (XawTextBlock*)entity->data;
-
- offset = anchor->position + entity->offset;
- end = XawMin(end, offset + block->length);
- if ((length = end - pos) < 0)
- length = 0;
- text->length = length;
- text->format = XawFmt8Bit;
- if (length == 0) {
- text->firstPos = end = offset + entity->length;
- text->ptr = "";
- }
- else {
- text->firstPos = pos;
- text->ptr = block->ptr + (pos - offset);
- if (pos + length < offset + block->length)
- end = pos + length; /* there is data left to be read */
- else
- end = offset + entity->length;
- }
-
- return (end);
- }
-
- if ((length = end - pos) < 0)
- length = 0;
-#endif
-
- piece = FindPiece(src, pos, &start);
- text->firstPos = pos;
- text->ptr = piece->text + (pos - start);
- count = piece->used - (pos - start);
- text->length = Max(0, (length > count) ? count : length);
- text->format = XawFmt8Bit;
-
- return (pos + text->length);
-}
-
-/*
- * Function:
- * ReplaceText
- *
- * Parameters:
- * w - AsciiSource object
- * startPos - ends of text that will be replaced
- * endPos - ""
- * text - new text to be inserted into buffer at startPos
- *
- * Description:
- * Replaces a block of text with new text.
- *
- * Returns:
- * XawEditDone on success, XawEditError otherwise
- */
-/*ARGSUSED*/
-static int
-ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos,
- XawTextBlock *text)
-{
- AsciiSrcObject src = (AsciiSrcObject)w;
- Piece *start_piece, *end_piece, *temp_piece;
- XawTextPosition start_first, end_first;
- int length, firstPos;
-
- /*
- * Editing a read only source is not allowed
- */
- if (src->text_src.edit_mode == XawtextRead)
- return (XawEditError);
-
- start_piece = FindPiece(src, startPos, &start_first);
- end_piece = FindPiece(src, endPos, &end_first);
-
-#ifndef OLDXAW
- /*
- * This is a big hack, but I can't think about a clever way to know
- * if the character being moved forward has a negative lbearing.
- *
- */
- if (start_piece->used) {
- int i;
-
- for (i = 0; i < src->text_src.num_text; i++) {
- int line;
- TextWidget ctx = (TextWidget)src->text_src.text[i];
-
- for (line = 0; line < ctx->text.lt.lines; line++)
- if (startPos < ctx->text.lt.info[line + 1].position)
- break;
- if (i < ctx->text.lt.lines &&
- startPos > ctx->text.lt.info[i].position) {
- AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
- XawTextAnchor *anchor;
- XawTextEntity *entity;
- XawTextProperty *property;
- XFontStruct *font;
-
- if (XawTextSourceAnchorAndEntity(w, startPos, &anchor, &entity) &&
- (property = XawTextSinkGetProperty(ctx->text.sink,
- entity->property)) != NULL &&
- (property->mask & XAW_TPROP_FONT))
- font = property->font;
- else
- font = sink->ascii_sink.font;
-
- if (font->min_bounds.lbearing < 0) {
- int lbearing = font->min_bounds.lbearing;
- unsigned char c = *(unsigned char*)
- (start_piece->text + (startPos - start_first));
-
- if (c == '\t' || c == '\n')
- c = ' ';
- else if ((c & 0177) < XawSP || c == 0177) {
- if (sink->ascii_sink.display_nonprinting)
- c = c > 0177 ? '\\' : c + '^';
- else
- c = ' ';
- }
- if (font->per_char &&
- (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
- lbearing = font->per_char[c - font->min_char_or_byte2].lbearing;
- if (lbearing < 0)
- _XawTextNeedsUpdating(ctx, startPos - 1, startPos);
- }
- }
- }
- }
-
-
-#endif
-
- /*
- * Remove Old Stuff
- */
- if (start_piece != end_piece) {
- temp_piece = start_piece->next;
-
- /*
- * If empty and not the only piece then remove it.
- */
- if (((start_piece->used = startPos - start_first) == 0)
- && !(start_piece->next == NULL && start_piece->prev == NULL))
- RemovePiece(src, start_piece);
-
- while (temp_piece != end_piece) {
- temp_piece = temp_piece->next;
- RemovePiece(src, temp_piece->prev);
- }
-
- end_piece->used -= endPos - end_first;
- if (end_piece->used != 0)
- memmove(end_piece->text, end_piece->text + endPos - end_first,
- (unsigned)end_piece->used);
- }
- else { /* We are fully in one piece */
- if ((start_piece->used -= endPos - startPos) == 0) {
- if (!(start_piece->next == NULL && start_piece->prev == NULL))
- RemovePiece(src, start_piece);
- }
- else {
- memmove(start_piece->text + (startPos - start_first),
- start_piece->text + (endPos - start_first),
- (unsigned)(start_piece->used - (startPos - start_first)));
- if (src->ascii_src.use_string_in_place
- && src->ascii_src.length - (endPos - startPos)
- < src->ascii_src.piece_size - 1)
- start_piece->text[src->ascii_src.length - (endPos - startPos)] =
- '\0';
- }
- }
-
- src->ascii_src.length += -(endPos - startPos) + text->length;
-
- if ( text->length != 0) {
- /*
- * Put in the New Stuff
- */
- start_piece = FindPiece(src, startPos, &start_first);
-
- length = text->length;
- firstPos = text->firstPos;
-
- while (length > 0) {
- char *ptr;
- int fill;
-
- if (src->ascii_src.use_string_in_place) {
- if (start_piece->used == src->ascii_src.piece_size - 1) {
- /*
- * If we are in ascii string emulation mode. Then the
- * string is not allowed to grow
- */
- start_piece->used = src->ascii_src.length =
- src->ascii_src.piece_size - 1;
- start_piece->text[src->ascii_src.length] = '\0';
- return (XawEditError);
- }
- }
-
- if (start_piece->used == src->ascii_src.piece_size) {
- BreakPiece(src, start_piece);
- start_piece = FindPiece(src, startPos, &start_first);
- }
-
- fill = Min((int)(src->ascii_src.piece_size - start_piece->used),
- length);
-
- ptr = start_piece->text + (startPos - start_first);
- memmove(ptr + fill, ptr,
- (unsigned)(start_piece->used - (startPos - start_first)));
- memcpy(ptr, text->ptr + firstPos, (unsigned)fill);
-
- startPos += fill;
- firstPos += fill;
- start_piece->used += fill;
- length -= fill;
- }
- }
-
- if (src->ascii_src.use_string_in_place)
- start_piece->text[start_piece->used] = '\0';
-
-#ifdef OLDXAW
- src->ascii_src.changes = True;
- XtCallCallbacks(w, XtNcallback, NULL);
-#endif
-
- return (XawEditDone);
-}
-
-/*
- * Function:
- * Scan
- *
- * Parameters:
- * w - AsciiSource object
- * position - position to start scanning
- * type - type of thing to scan for
- * dir - direction to scan
- * count - which occurance if this thing to search for.
- * include - whether or not to include the character found in
- * the position that is returned
- *
- * Description:
- * Scans the text source for the number and type of item specified.
- *
- * Returns:
- * The position of the item found
- *
- * Note:
- * While there are only 'n' characters in the file there are n+1
- * possible cursor positions (one before the first character and
- * one after the last character
- */
-static XawTextPosition
-Scan(Widget w, register XawTextPosition position, XawTextScanType type,
- XawTextScanDirection dir, int count, Bool include)
-{
- AsciiSrcObject src = (AsciiSrcObject)w;
- Piece *piece;
- XawTextPosition first, first_eol_position = 0;
- register char *ptr, *lim;
- register int cnt = count;
- register unsigned char c;
-
- if (dir == XawsdLeft) {
- if (position <= 0)
- return (0);
- --position;
- }
- else if (position >= src->ascii_src.length)
- return (src->ascii_src.length);
-
- piece = FindPiece(src, position, &first);
- if (piece->used == 0)
- return (0);
-
- ptr = (position - first) + piece->text;
-
- if (dir == XawsdRight) {
- lim = piece->text + piece->used;
- switch (type) {
- case XawstEOL:
- case XawstParagraph:
- case XawstWhiteSpace:
- case XawstAlphaNumeric:
- for (; cnt > 0; cnt--) {
- Bool non_space = False, first_eol = True;
-
- /*CONSTCOND*/
- while (True) {
- if (ptr >= lim) {
- piece = piece->next;
- if (piece == NULL) /* End of text */
- return (src->ascii_src.length);
- ptr = piece->text;
- lim = piece->text + piece->used;
- }
-
- c = *ptr++;
- ++position;
-
- if (type == XawstEOL) {
- if (c == '\n')
- break;
- }
- else if (type == XawstAlphaNumeric) {
- if (!isalnum(c)) {
- if (non_space)
- break;
- }
- else
- non_space = True;
- }
- else if (type == XawstWhiteSpace) {
- if (isspace(c)) {
- if (non_space)
- break;
- }
- else
- non_space = True;
- }
- else { /* XawstParagraph */
- if (first_eol) {
- if (c == '\n') {
- first_eol_position = position;
- first_eol = False;
- }
- }
- else if (c == '\n')
- break;
- else if (!isspace(c))
- first_eol = True;
- }
- }
- }
- break;
- case XawstPositions:
- position += count;
- return (position < src->ascii_src.length ?
- position : src->ascii_src.length);
- case XawstAll:
- return (src->ascii_src.length);
- default:
- break;
- }
- if (!include) {
- if (type == XawstParagraph)
- position = first_eol_position;
- if (count)
- --position;
- }
- }
- else {
- lim = piece->text;
- switch (type) {
- case XawstEOL:
- case XawstParagraph:
- case XawstWhiteSpace:
- case XawstAlphaNumeric:
- for (; cnt > 0; cnt--) {
- Bool non_space = False, first_eol = True;
-
- /*CONSTCOND*/
- while (True) {
- if (ptr < lim) {
- piece = piece->prev;
- if (piece == NULL) /* Begining of text */
- return (0);
- ptr = piece->text + piece->used - 1;
- lim = piece->text;
- }
-
- c = *ptr--;
- --position;
-
- if (type == XawstEOL) {
- if (c == '\n')
- break;
- }
- else if (type == XawstAlphaNumeric) {
- if (!isalnum(c)) {
- if (non_space)
- break;
- }
- else
- non_space = True;
- }
- else if (type == XawstWhiteSpace) {
- if (isspace(c)) {
- if (non_space)
- break;
- }
- else
- non_space = True;
- }
- else { /* XawstParagraph */
- if (first_eol) {
- if (c == '\n') {
- first_eol_position = position;
- first_eol = False;
- }
- }
- else if (c == '\n')
- break;
- else if (!isspace(c))
- first_eol = True;
- }
- }
- }
- break;
- case XawstPositions:
- position -= count - 1;
- return (position > 0 ? position : 0);
- case XawstAll:
- return (0);
- default:
- break;
- }
- if (!include) {
- if (type == XawstParagraph)
- position = first_eol_position;
- if (count)
- ++position;
- }
- position++;
- }
-
- return (position);
-}
-
-/*
- * Function:
- * Search
- *
- * Parameters:
- * w - AsciiSource object
- * position - the position to start scanning
- * dir - direction to scan
- * text - text block to search for
- *
- * Description:
- * Searchs the text source for the text block passed.
- *
- * Returns:
- * The position of the item found
- */
-static XawTextPosition
-Search(Widget w, register XawTextPosition position, XawTextScanDirection dir,
- XawTextBlock *text)
-{
- AsciiSrcObject src = (AsciiSrcObject)w;
- register int count = 0;
- register char *ptr, c;
- char *str;
- Piece *piece;
- char *buf;
- XawTextPosition first;
- int cnt, case_sensitive;
-
- if (dir == XawsdLeft) {
- if (position == 0)
- return (XawTextSearchError);
- position--;
- }
-
- buf = XtMalloc((unsigned)sizeof(unsigned char) * text->length);
- memcpy(buf, text->ptr, (unsigned)text->length);
- piece = FindPiece(src, position, &first);
- ptr = (position - first) + piece->text;
- case_sensitive = text->firstPos;
-
- if (dir == XawsdRight) {
- str = buf;
- c = *str;
- /*CONSTCOND*/
- while (1) {
- if (*ptr++ == c
- || (case_sensitive && isalpha(c) && isalpha(ptr[-1])
- && toupper(c) == toupper(ptr[-1]))) {
- if (++count == text->length)
- break;
- c = *++str;
- }
- else if (count) {
- ptr -= count;
- str -= count;
- position -= count;
- count = 0;
- c = *str;
-
- if (ptr < piece->text) {
- do {
- cnt = piece->text - ptr;
- piece = piece->prev;
- if (piece == NULL) {
- XtFree(buf);
- return (XawTextSearchError);
- }
- ptr = piece->text + piece->used - cnt;
- } while (ptr < piece->text);
- }
- }
- position++;
- if (ptr >= (piece->text + piece->used)) {
- do {
- cnt = ptr - (piece->text + piece->used);
- piece = piece->next;
- if (piece == NULL) {
- XtFree(buf);
- return (XawTextSearchError);
- }
- ptr = piece->text + cnt;
- } while (ptr >= (piece->text + piece->used));
- }
- }
-
- position -= text->length - 1;
- }
- else {
- str = buf + text->length - 1;
- c = *str;
- /*CONSTCOND*/
- while (1) {
- if (*ptr-- == c
- || (case_sensitive && isalpha(c) && isalpha(ptr[1])
- && toupper(c) == toupper(ptr[1]))) {
- if (++count == text->length)
- break;
- c = *--str;
- }
- else if (count) {
- ptr += count;
- str += count;
- position += count;
- count = 0;
- c = *str;
-
- if (ptr >= (piece->text + piece->used)) {
- do {
- cnt = ptr - (piece->text + piece->used);
- piece = piece->next;
- if (piece == NULL) {
- XtFree(buf);
- return (XawTextSearchError);
- }
- ptr = piece->text + cnt;
- } while (ptr >= (piece->text + piece->used));
- }
- }
- position--;
- if (ptr < piece->text) {
- do {
- cnt = piece->text - ptr;
- piece = piece->prev;
- if (piece == NULL) {
- XtFree(buf);
- return (XawTextSearchError);
- }
- ptr = piece->text + piece->used - cnt;
- } while (ptr < piece->text);
- }
- }
- }
-
- XtFree(buf);
-
- return (position);
-}
-
-/*
- * Function:
- * XawAsciiSrcSetValues
- *
- * Parameters:
- * current - current state of the widget
- * request - what was requested
- * cnew - what the widget will become
- * args - representation of changed resources
- * num_args - number of resources that have changed
- *
- * Description:
- * Sets the values for the AsciiSource.
- *
- * Returns:
- * True if redisplay is needed
- */
-static Boolean
-XawAsciiSrcSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- AsciiSrcObject src = (AsciiSrcObject)cnew;
- AsciiSrcObject old_src = (AsciiSrcObject)current;
- Bool total_reset = False, string_set = False;
- FILE *file;
- unsigned int i;
-
- if (old_src->ascii_src.use_string_in_place
- != src->ascii_src.use_string_in_place) {
- XtAppWarning(XtWidgetToApplicationContext(cnew),
- "AsciiSrc: The XtNuseStringInPlace resource may "
- "not be changed.");
- src->ascii_src.use_string_in_place =
- old_src->ascii_src.use_string_in_place;
- }
-
- for (i = 0; i < *num_args ; i++)
- if (streq(args[i].name, XtNstring)) {
- string_set = True;
- break;
- }
-
- if (string_set || (old_src->ascii_src.type != src->ascii_src.type)) {
- RemoveOldStringOrFile(old_src, string_set); /* remove old info */
- file = InitStringOrFile(src, string_set); /* Init new info */
- LoadPieces(src, file, NULL); /* load new info into internal buffers */
- if (file != NULL)
- fclose(file);
-#ifndef OLDXAW
- for (i = 0; i < src->text_src.num_text; i++)
- /* Tell text widget what happened */
- XawTextSetSource(src->text_src.text[i], cnew, 0);
-#else
- XawTextSetSource(XtParent(cnew), cnew, 0);
-#endif
- total_reset = True;
- }
-
- if (old_src->ascii_src.ascii_length != src->ascii_src.ascii_length)
- src->ascii_src.piece_size = src->ascii_src.ascii_length + 1;
-
- if (!total_reset &&
- old_src->ascii_src.piece_size != src->ascii_src.piece_size) {
- String string = StorePiecesInString(old_src);
-
- FreeAllPieces(old_src);
- LoadPieces(src, NULL, string);
- XtFree(string);
- }
-
- return (False);
-}
-
-/*
- * Function:
- * XawAsciiSrcGetValuesHook
- *
- * Parameters:
- * w - AsciiSource Widget
- * args - argument list
- * num_args - number of args
- *
- * Description:
- * This is a get values hook routine that sets the
- * values specific to the ascii source.
- */
-static void
-XawAsciiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
-{
- AsciiSrcObject src = (AsciiSrcObject)w;
- unsigned int i;
-
- if (src->ascii_src.type == XawAsciiString) {
- for (i = 0; i < *num_args ; i++)
- if (streq(args[i].name, XtNstring)) {
- if (src->ascii_src.use_string_in_place)
- *((char **)args[i].value) = src->ascii_src.first_piece->text;
- else if (XawAsciiSave(w)) /* If save sucessful */
- *((char **)args[i].value) = src->ascii_src.string;
- break;
- }
- }
- }
-
-/*
- * Function:
- * XawAsciiSrcDestroy
- *
- * Parameters:
- * src - Ascii source object to free
- *
- * Description:
- * Destroys an ascii source (frees all data)
- */
-static void
-XawAsciiSrcDestroy(Widget w)
-{
- RemoveOldStringOrFile((AsciiSrcObject) w, True);
-}
-
-/*
- * Public routines
- */
-/*
- * Function:
- * XawAsciiSourceFreeString
- *
- * Parameters:
- * w - AsciiSrc widget
- *
- * Description:
- * Frees the string returned by a get values call
- * on the string when the source is of type string.
- */
-void
-XawAsciiSourceFreeString(Widget w)
-{
- AsciiSrcObject src = (AsciiSrcObject)w;
-
- /* If the src is really a multi, call the multi routine */
- if (XtIsSubclass(w, multiSrcObjectClass)) {
- _XawMultiSourceFreeString(w);
- return;
- }
- else if (!XtIsSubclass(w, asciiSrcObjectClass)) {
- XtErrorMsg("bad argument", "asciiSource", "XawError",
- "XawAsciiSourceFreeString's parameter must be "
- "an asciiSrc or multiSrc.",
- NULL, NULL);
- }
-
- if (src->ascii_src.allocated_string && src->ascii_src.type != XawAsciiFile) {
- src->ascii_src.allocated_string = False;
- XtFree(src->ascii_src.string);
- src->ascii_src.string = NULL;
- }
-}
-
-/*
- * Function:
- * XawAsciiSave
- *
- * Parameters:
- * w - asciiSrc Widget
- *
- * Description:
- * Saves all the pieces into a file or string as required.
- *
- * Returns:
- * True if the save was successful
- */
-Bool
-XawAsciiSave(Widget w)
-{
- AsciiSrcObject src = (AsciiSrcObject)w;
-
- /* If the src is really a multi, call the multi save */
- if (XtIsSubclass(w, multiSrcObjectClass ))
- return (_XawMultiSave(w));
-
- else if (!XtIsSubclass(w, asciiSrcObjectClass))
- XtErrorMsg("bad argument", "asciiSource", "XawError",
- "XawAsciiSave's parameter must be an asciiSrc or multiSrc.",
- NULL, NULL);
-
- /*
- * If using the string in place then there is no need to play games
- * to get the internal info into a readable string.
- */
- if (src->ascii_src.use_string_in_place)
- return (True);
-
- if (src->ascii_src.type == XawAsciiFile) {
-#ifdef OLDXAW
- if (!src->ascii_src.changes)
-#else
- if (!src->text_src.changed) /* No changes to save */
-#endif
- return (True);
-
- if (WritePiecesToFile(src, src->ascii_src.string) == False)
- return (False);
- }
- else {
- if (src->ascii_src.allocated_string == True)
- XtFree(src->ascii_src.string);
- else
- src->ascii_src.allocated_string = True;
-
- src->ascii_src.string = StorePiecesInString(src);
- }
-#ifdef OLDXAW
- src->ascii_src.changes = False;
-#else
- src->text_src.changed = False;
-#endif
-
- return (True);
-}
-
-/*
- * Function:
- * XawAsciiSaveAsFile
- *
- * Arguments:
- * w - AsciiSrc widget
- * name - name of the file to save this file into
- *
- * Description:
- * Save the current buffer as a file.
- *
- * Returns:
- * True if the save was sucessful
- */
-Bool
-XawAsciiSaveAsFile(Widget w, _Xconst char *name)
-{
- AsciiSrcObject src = (AsciiSrcObject)w;
- Bool ret;
-
- /* If the src is really a multi, call the multi save */
-
- if (XtIsSubclass( w, multiSrcObjectClass))
- return (_XawMultiSaveAsFile(w, name));
-
- else if (!XtIsSubclass(w, asciiSrcObjectClass))
- XtErrorMsg("bad argument", "asciiSource", "XawError",
- "XawAsciiSaveAsFile's 1st parameter must be an "
- "asciiSrc or multiSrc.",
- NULL, NULL);
-
- if (src->ascii_src.type == XawAsciiFile)
- ret = WritePiecesToFile(src, (String)name);
- else {
- String string = StorePiecesInString(src);
-
- ret = WriteToFile(string, (String)name, src->ascii_src.length);
- XtFree(string);
- }
-
- return (ret);
-}
-
-/*
- * Function:
- * XawAsciiSourceChanged
- *
- * Parameters:
- * w - ascii source widget
- *
- * Description:
- * Returns true if the source has changed since last saved.
- *
- * Returns:
- * A Boolean (see description).
- */
-Bool
-XawAsciiSourceChanged(Widget w)
-{
-#ifdef OLDXAW
- if (XtIsSubclass(w, multiSrcObjectClass))
- return (((MultiSrcObject)w)->multi_src.changes);
-
- if (XtIsSubclass(w, asciiSrcObjectClass))
- return (((AsciiSrcObject)w)->ascii_src.changes);
-#else
- if (XtIsSubclass(w, textSrcObjectClass))
- return (((TextSrcObject)w)->textSrc.changed);
-#endif
- XtErrorMsg("bad argument", "asciiSource", "XawError",
- "XawAsciiSourceChanged parameter must be an "
- "asciiSrc or multiSrc.",
- NULL, NULL);
-
- return (True);
-}
-
-/*
- * Private Functions
- */
-static void
-RemoveOldStringOrFile(AsciiSrcObject src, Bool checkString)
-{
- FreeAllPieces(src);
-
- if (checkString && src->ascii_src.allocated_string) {
- XtFree(src->ascii_src.string);
- src->ascii_src.allocated_string = False;
- src->ascii_src.string = NULL;
- }
-}
-
-/*
- * Function:
- * WriteToFile
- *
- * Parameters:
- * string - string to write
- * name - the name of the file
- *
- * Description:
- * Write the string specified to the begining of the file specified.
- *
- * Returns:
- * returns True if sucessful, False otherwise
- */
-static Bool
-WriteToFile(String string, String name, unsigned length)
-{
- int fd;
-
- if ((fd = creat(name, 0666)) == -1)
- return (False);
-
- if (write(fd, string, length) == -1) {
- close(fd);
- return (False);
- }
-
- if (close(fd) == -1)
- return (False);
-
- return (True);
-}
-
-/*
- * Function:
- * WritePiecesToFile
- *
- * Parameters:
- * src - ascii source object
- * name - name of the file
- *
- * Description:
- * Almost identical to WriteToFile, but only works for ascii src objects
- * of type XawAsciiFile. This function avoids allocating temporary memory,
- * what can be useful when editing very large files.
- *
- * Returns:
- * returns True if sucessful, False otherwise
- */
-static Bool
-WritePiecesToFile(AsciiSrcObject src, String name)
-{
- Piece *piece;
- int fd;
-
- if (src->ascii_src.data_compression) {
- Piece *tmp;
-
- piece = src->ascii_src.first_piece;
- while (piece) {
- int bytes = src->ascii_src.piece_size - piece->used;
-
- if (bytes > 0 && (tmp = piece->next) != NULL) {
- bytes = XawMin(bytes, tmp->used);
- memcpy(piece->text + piece->used, tmp->text, bytes);
- memmove(tmp->text, tmp->text + bytes, tmp->used - bytes);
- piece->used += bytes;
- if ((tmp->used -= bytes) == 0) {
- RemovePiece(src, tmp);
- continue;
- }
- }
- piece = piece->next;
- }
- }
-
- if ((fd = creat(name, 0666)) == -1)
- return (False);
-
- for (piece = src->ascii_src.first_piece; piece; piece = piece->next)
- if (write(fd, piece->text, piece->used) == -1) {
- close(fd);
- return (False);
- }
-
- if (close(fd) == -1)
- return (False);
-
- return (True);
-}
-
-/*
- * Function:
- * StorePiecesInString
- *
- * Parameters:
- * data - ascii pointer data
- *
- * Description:
- * Store the pieces in memory into a standard ascii string.
- */
-static String
-StorePiecesInString(AsciiSrcObject src)
-{
- String string;
- XawTextPosition first;
- Piece *piece;
-
- string = XtMalloc((unsigned)(src->ascii_src.length + 1));
-
- for (first = 0, piece = src->ascii_src.first_piece ; piece != NULL;
- first += piece->used, piece = piece->next)
- memcpy(string + first, piece->text, (unsigned)piece->used);
-
- string[src->ascii_src.length] = '\0';
-
- /*
- * This will refill all pieces to capacity
- */
- if (src->ascii_src.data_compression) {
- FreeAllPieces(src);
- LoadPieces(src, NULL, string);
- }
-
- return (string);
-}
-
-/*
- * Function:
- * InitStringOrFile
- *
- * Parameters:
- * src - AsciiSource
- *
- * Description:
- * Initializes the string or file.
- */
-static FILE *
-InitStringOrFile(AsciiSrcObject src, Bool newString)
-{
- mode_t open_mode = 0;
- const char *fdopen_mode = NULL;
- int fd;
- FILE *file;
-
- if (src->ascii_src.type == XawAsciiString) {
- if (src->ascii_src.string == NULL)
- src->ascii_src.length = 0;
-
- else if (!src->ascii_src.use_string_in_place) {
- src->ascii_src.string = XtNewString(src->ascii_src.string);
- src->ascii_src.allocated_string = True;
- src->ascii_src.length = strlen(src->ascii_src.string);
- }
-
- if (src->ascii_src.use_string_in_place) {
- if (src->ascii_src.string != NULL)
- src->ascii_src.length = strlen(src->ascii_src.string);
- /* In case the length resource is incorrectly set */
- if (src->ascii_src.length > src->ascii_src.ascii_length)
- src->ascii_src.ascii_length = src->ascii_src.length;
-
- if (src->ascii_src.ascii_length == MAGIC_VALUE)
- src->ascii_src.piece_size = src->ascii_src.length;
- else
- src->ascii_src.piece_size = src->ascii_src.ascii_length + 1;
- }
-
- return (NULL);
- }
-
- /*
- * type is XawAsciiFile
- */
- src->ascii_src.is_tempfile = False;
-
- switch (src->text_src.edit_mode) {
- case XawtextRead:
- if (src->ascii_src.string == NULL)
- XtErrorMsg("NoFile", "asciiSourceCreate", "XawError",
- "Creating a read only disk widget and no file specified.",
- NULL, NULL);
- open_mode = O_RDONLY;
- fdopen_mode = "r";
- break;
- case XawtextAppend:
- case XawtextEdit:
- if (src->ascii_src.string == NULL) {
- src->ascii_src.string = "*ascii-src*";
- src->ascii_src.is_tempfile = True;
- }
- else {
-/* O_NOFOLLOW is a FreeBSD & Linux extension */
-#ifdef O_NOFOLLOW
- open_mode = O_RDWR | O_NOFOLLOW;
-#else
- open_mode = O_RDWR; /* unsafe; subject to race conditions */
-#endif /* O_NOFOLLOW */
- fdopen_mode = "r+";
- }
- break;
- default:
- XtErrorMsg("badMode", "asciiSourceCreate", "XawError",
- "Bad editMode for ascii source; must be Read, "
- "Append or Edit.",
- NULL, NULL);
- }
-
- /* If is_tempfile, allocate a private copy of the text
- * Unlikely to be changed, just to set allocated_string */
- if (newString || src->ascii_src.is_tempfile) {
- src->ascii_src.string = XtNewString(src->ascii_src.string);
- src->ascii_src.allocated_string = True;
- }
-
- if (!src->ascii_src.is_tempfile) {
- if ((fd = open(src->ascii_src.string, open_mode, 0666)) != -1) {
- if ((file = fdopen(fd, fdopen_mode))) {
- (void)fseek(file, 0, SEEK_END);
- src->ascii_src.length = (XawTextPosition)ftell(file);
- return (file);
- }
- }
- {
- String params[2];
- Cardinal num_params = 2;
-
- params[0] = src->ascii_src.string;
- params[1] = strerror(errno);
- XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
- "openError", "asciiSourceCreate", "XawWarning",
- "Cannot open file %s; %s", params, &num_params);
- }
- }
- src->ascii_src.length = 0;
- return (NULL);
-}
-
-static void
-LoadPieces(AsciiSrcObject src, FILE *file, char *string)
-{
- char *ptr;
- Piece *piece = NULL;
- XawTextPosition left;
-
- if (string == NULL) {
- if (src->ascii_src.type == XawAsciiFile) {
- if (src->ascii_src.length != 0) {
- int len;
-
- left = 0;
- fseek(file, 0, 0);
- while (left < src->ascii_src.length) {
- ptr = XtMalloc((unsigned)src->ascii_src.piece_size);
- if ((len = fread(ptr, (Size_t)sizeof(unsigned char),
- (Size_t)src->ascii_src.piece_size, file)) < 0)
- XtErrorMsg("readError", "asciiSourceCreate", "XawError",
- "fread returned error.", NULL, NULL);
- piece = AllocNewPiece(src, piece);
- piece->text = ptr;
- piece->used = XawMin(len, src->ascii_src.piece_size);
- left += piece->used;
- }
- }
- else {
- piece = AllocNewPiece(src, NULL);
- piece->text = XtMalloc((unsigned)src->ascii_src.piece_size);
- piece->used = 0;
- }
- return;
- }
- else
- string = src->ascii_src.string;
- }
-
- if (src->ascii_src.use_string_in_place) {
- piece = AllocNewPiece(src, piece);
- piece->used = XawMin(src->ascii_src.length, src->ascii_src.piece_size);
- piece->text = src->ascii_src.string;
- return;
- }
-
- ptr = string;
- left = src->ascii_src.length;
- do {
- piece = AllocNewPiece(src, piece);
-
- piece->text = XtMalloc((unsigned)src->ascii_src.piece_size);
- piece->used = XawMin(left, src->ascii_src.piece_size);
- if (piece->used != 0)
- memcpy(piece->text, ptr, (unsigned)piece->used);
-
- left -= piece->used;
- ptr += piece->used;
- } while (left > 0);
-}
-
-/*
- * Function:
- * AllocNewPiece
- *
- * Parameters:
- * src - AsciiSrc Widget
- * prev - piece just before this one, or NULL
- *
- * Description:
- * Allocates a new piece of memory.
- *
- * Returns:
- * The allocated piece
- */
-static Piece *
-AllocNewPiece(AsciiSrcObject src, Piece *prev)
-{
- Piece *piece = XtNew(Piece);
-
- if (prev == NULL) {
- src->ascii_src.first_piece = piece;
- piece->next = NULL;
- }
- else {
- if (prev->next != NULL)
- (prev->next)->prev = piece;
- piece->next = prev->next;
- prev->next = piece;
- }
-
- piece->prev = prev;
-
- return (piece);
-}
-
-/*
- * Function:
- * FreeAllPieces
- *
- * Parameters:
- * src - AsciiSrc Widget
- *
- * Description:
- * Frees all the pieces.
- */
-static void
-FreeAllPieces(AsciiSrcObject src)
-{
- Piece *next, * first = src->ascii_src.first_piece;
-
-#ifdef DEBUG
- if (first->prev != NULL)
- printf("Xaw AsciiSrc Object: possible memory leak in FreeAllPieces().\n");
-#endif
-
- for (; first != NULL ; first = next) {
- next = first->next;
- RemovePiece(src, first);
- }
-}
-
-/*
- * Function:
- * RemovePiece
- *
- * Parameters:
- * piece - piece to remove
- *
- * Description:
- * Removes a piece from the list.
- */
-static void
-RemovePiece(AsciiSrcObject src, Piece *piece)
-{
- if (piece->prev == NULL)
- src->ascii_src.first_piece = piece->next;
- else
- piece->prev->next = piece->next;
-
- if (piece->next != NULL)
- piece->next->prev = piece->prev;
-
- if (!src->ascii_src.use_string_in_place)
- XtFree(piece->text);
-
- XtFree((char *)piece);
-}
-
-/*
- * Function:
- * FindPiece
- *
- * Parameters:
- * src - AsciiSrc Widget
- * position - position that we are searching for
- * first - position of the first character in this piece (return)
- *
- * Description:
- * Finds the piece containing the position indicated.
- *
- * Returns:
- * the piece that contains this position
- */
-static Piece *
-FindPiece(AsciiSrcObject src, XawTextPosition position, XawTextPosition *first)
-{
- Piece *old_piece, *piece;
- XawTextPosition temp;
-
- for (old_piece = NULL, piece = src->ascii_src.first_piece, temp = 0;
- piece; old_piece = piece, piece = piece->next)
- if ((temp += piece->used) > position) {
- *first = temp - piece->used;
- return (piece);
- }
-
- *first = temp - (old_piece ? old_piece->used : 0);
-
- return (old_piece); /* if we run off the end the return the last piece */
-}
-
-/*
- * Function:
- * BreakPiece
- *
- * Parameters:
- * src - AsciiSrc Widget
- * piece - piece to break
- *
- * Description:
- * Breaks a full piece into two new pieces.
- */
-#define HALF_PIECE (src->ascii_src.piece_size >> 1)
-static void
-BreakPiece(AsciiSrcObject src, Piece *piece)
-{
- Piece *cnew = AllocNewPiece(src, piece);
-
- cnew->text = XtMalloc((unsigned)src->ascii_src.piece_size);
- memcpy(cnew->text, piece->text + HALF_PIECE,
- (unsigned)(src->ascii_src.piece_size - HALF_PIECE));
- piece->used = HALF_PIECE;
- cnew->used = src->ascii_src.piece_size - HALF_PIECE;
-}
-
-/*ARGSUSED*/
-static void
-CvtStringToAsciiType(XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal)
-{
- static XawAsciiType type;
- XrmQuark q;
- char name[7];
-
- XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
- q = XrmStringToQuark(name);
-
- if (q == Qstring)
- type = XawAsciiString;
- else if (q == Qfile)
- type = XawAsciiFile;
- else {
- toVal->size = 0;
- toVal->addr = NULL;
- XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType);
- }
-
- toVal->size = sizeof(XawAsciiType);
- toVal->addr = (XPointer)&type;
-}
-
-/*ARGSUSED*/
-static Boolean
-CvtAsciiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal,
- XtPointer *data)
-{
- static String buffer;
- Cardinal size;
-
- switch (*(XawAsciiType *)fromVal->addr) {
- case XawAsciiFile:
- buffer = XtEfile;
- break;
- case XawAsciiString:
- buffer = XtEstring;
- break;
- default:
- XawTypeToStringWarning(dpy, XtRAsciiType);
- toVal->addr = NULL;
- toVal->size = 0;
- return (False);
- }
-
- size = strlen(buffer) + 1;
- if (toVal->addr != NULL) {
- if (toVal->size < size) {
- toVal->size = size;
- return (False);
- }
- strcpy((char *)toVal->addr, buffer);
- }
- else
- toVal->addr = (XPointer)buffer;
- toVal->size = sizeof(String);
-
- return (True);
-}
-
-/*ARGSUSED*/
-static void
-GetDefaultPieceSize(Widget w, int offset, XrmValue *value)
-{
- static XPointer pagesize;
-
- if (pagesize == NULL) {
- pagesize = (XPointer)((long)_XawGetPageSize());
- if (pagesize < (XPointer)BUFSIZ)
- pagesize = (XPointer)BUFSIZ;
- }
-
- value->addr = (XPointer)&pagesize;
-}
-
-#if (defined(ASCII_STRING) || defined(ASCII_DISK))
-# include <X11/Xaw/Cardinals.h>
-#endif
-
-#ifdef ASCII_STRING
-/*
- * Compatability functions.
- */
-/*
- * Function:
- * AsciiStringSourceCreate
- *
- * Parameters:
- * parent - widget that will own this source
- * args - the argument list
- * num_args - ""
- *
- * Description:
- * Creates a string source.
- *
- * Returns:
- * A pointer to the new text source.
- */
-Widget
-XawStringSourceCreate(Widget parent, ArgList args, Cardinal num_args)
-{
- XawTextSource src;
- ArgList ascii_args;
- Arg temp[2];
-
- XtSetArg(temp[0], XtNtype, XawAsciiString);
- XtSetArg(temp[1], XtNuseStringInPlace, True);
- ascii_args = XtMergeArgLists(temp, TWO, args, num_args);
-
- src = XtCreateWidget("genericAsciiString", asciiSrcObjectClass, parent,
- ascii_args, num_args + TWO);
- XtFree((char *)ascii_args);
-
- return (src);
-}
-
-/*
- * This is hacked up to try to emulate old functionality, it
- * may not work, as I have not old code to test it on.
- *
- * Chris D. Peterson 8/31/89.
- */
-void
-XawTextSetLastPos(Widget w, XawTextPosition lastPos)
-{
- AsciiSrcObject src = (AsciiSrcObject)XawTextGetSource(w);
-
- src->ascii_src.piece_size = lastPos;
-}
-#endif /* ASCII_STRING */
-
-#ifdef ASCII_DISK
-/*
- * Function:
- * AsciiDiskSourceCreate
- *
- * Parameters:
- * parent - widget that will own this source
- * args - argument list
- * num_args - ""
- *
- * Description:
- * Creates a disk source.
- *
- * Returns:
- * A pointer to the new text source
- */
-Widget
-XawDiskSourceCreate(Widget parent, ArgList args, Cardinal num_args)
-{
- XawTextSource src;
- ArgList ascii_args;
- Arg temp[1];
- int i;
-
- XtSetArg(temp[0], XtNtype, XawAsciiFile);
- ascii_args = XtMergeArgLists(temp, ONE, args, num_args);
- num_args++;
-
- for (i = 0; i < num_args; i++)
- if (streq(ascii_args[i].name, XtNfile)
- || streq(ascii_args[i].name, XtCFile))
- ascii_args[i].name = XtNstring;
-
- src = XtCreateWidget("genericAsciiDisk", asciiSrcObjectClass, parent,
- ascii_args, num_args);
- XtFree((char *)ascii_args);
-
- return (src);
-}
-#endif /* ASCII_DISK */
+/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * AsciiSrc.c - AsciiSrc object. (For use with the text widget). + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw/XawInit.h> +#include <X11/Xaw/AsciiSrcP.h> +#include <X11/Xaw/MultiSrcP.h> +#ifndef OLDXAW +#include <X11/Xaw/TextSinkP.h> +#include <X11/Xaw/AsciiSinkP.h> +#endif +#include "Private.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#if (defined(ASCII_STRING) || defined(ASCII_DISK)) +#include <X11/Xaw/AsciiText.h> /* for Widget Classes */ +#endif + +#ifdef X_NOT_POSIX +#define Off_t long +#define Size_t unsigned int +#else +#define Off_t off_t +#define Size_t size_t +#endif + +#define MAGIC_VALUE ((XawTextPosition)-1) +#define streq(a, b) (strcmp((a), (b)) == 0) + +/* + * Class Methods + */ +static void XawAsciiSrcClassInitialize(void); +static void XawAsciiSrcDestroy(Widget); +static void XawAsciiSrcGetValuesHook(Widget, ArgList, Cardinal*); +static void XawAsciiSrcInitialize(Widget, Widget, ArgList, Cardinal*); +static Boolean XawAsciiSrcSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int); +static int ReplaceText(Widget, XawTextPosition, XawTextPosition, + XawTextBlock*); +static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, + XawTextScanDirection, int, Bool); +static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, + XawTextBlock*); + +/* + * Prototypes + */ +static Piece *AllocNewPiece(AsciiSrcObject, Piece*); +static void BreakPiece(AsciiSrcObject, Piece*); +static Boolean CvtAsciiTypeToString(Display*, XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr, XtPointer*); +static void CvtStringToAsciiType(XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr); +static Piece *FindPiece(AsciiSrcObject, XawTextPosition, XawTextPosition*); +static void FreeAllPieces(AsciiSrcObject); +static FILE *InitStringOrFile(AsciiSrcObject, Bool); +static void LoadPieces(AsciiSrcObject, FILE*, char*); +static void RemoveOldStringOrFile(AsciiSrcObject, Bool); +static void RemovePiece(AsciiSrcObject, Piece*); +static String StorePiecesInString(AsciiSrcObject); +static Bool WriteToFile(String, String, unsigned); +static Bool WritePiecesToFile(AsciiSrcObject, String); +static void GetDefaultPieceSize(Widget, int, XrmValue*); + +/* + * More Prototypes + */ +#ifdef ASCII_DISK +Widget XawAsciiDiskSourceCreate(Widget, ArgList, Cardinal); +#endif +#ifdef ASCII_STRING +Widget XawStringSourceCreate(Widget, ArgList, Cardinal); +void XawTextSetLastPos(Widget, XawTextPosition); +#endif + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(AsciiSrcRec, ascii_src.field) +static XtResource resources[] = { + { + XtNstring, + XtCString, + XtRString, + sizeof(char*), + offset(string), + XtRString, + NULL + }, + { + XtNtype, + XtCType, + XtRAsciiType, + sizeof(XawAsciiType), + offset(type), + XtRImmediate, + (XtPointer)XawAsciiString + }, + { + XtNdataCompression, + XtCDataCompression, + XtRBoolean, + sizeof(Boolean), + offset(data_compression), + XtRImmediate, + (XtPointer)True + }, + { + XtNpieceSize, + XtCPieceSize, + XtRInt, + sizeof(XawTextPosition), + offset(piece_size), + XtRCallProc, + (XtPointer)GetDefaultPieceSize + }, +#ifdef OLDXAW + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(callback), + XtRCallback, + (XtPointer)NULL + }, +#endif + { + XtNuseStringInPlace, + XtCUseStringInPlace, + XtRBoolean, + sizeof(Boolean), + offset(use_string_in_place), + XtRImmediate, + (XtPointer)False + }, + { + XtNlength, + XtCLength, + XtRInt, + sizeof(int), + offset(ascii_length), + XtRImmediate, + (XtPointer)MAGIC_VALUE + }, +#ifdef ASCII_DISK + { + XtNfile, + XtCFile, + XtRString, + sizeof(String), + offset(filename), + XtRString, + NULL + }, +#endif /* ASCII_DISK */ +}; +#undef offset + + +#define Superclass (&textSrcClassRec) +AsciiSrcClassRec asciiSrcClassRec = { + /* object */ + { + (WidgetClass)Superclass, /* superclass */ + "AsciiSrc", /* class_name */ + sizeof(AsciiSrcRec), /* widget_size */ + XawAsciiSrcClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawAsciiSrcInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + False, /* compress_exposure */ + False, /* compress_enterleave */ + False, /* visible_interest */ + XawAsciiSrcDestroy, /* destroy */ + NULL, /* resize */ + NULL, /* expose */ + XawAsciiSrcSetValues, /* set_values */ + NULL, /* set_values_hook */ + NULL, /* set_values_almost */ + XawAsciiSrcGetValuesHook, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + NULL, /* query_geometry */ + NULL, /* display_accelerator */ + NULL, /* extension */ + }, + /* text_src */ + { + ReadText, /* Read */ + ReplaceText, /* Replace */ + Scan, /* Scan */ + Search, /* Search */ + XtInheritSetSelection, /* SetSelection */ + XtInheritConvertSelection, /* ConvertSelection */ + }, + /* ascii_src */ + { + NULL, /* extension */ + }, +}; + +WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec; + +static XrmQuark Qstring, Qfile; + +/* + * Implementation + */ +/* + * Function: + * XawAsciiSrcClassInitialize() + * + * Description: + * Initializes the asciiSrcObjectClass and install the converters for + * AsciiType <-> String. + */ +static void +XawAsciiSrcClassInitialize(void) +{ + XawInitializeWidgetSet(); + Qstring = XrmPermStringToQuark(XtEstring); + Qfile = XrmPermStringToQuark(XtEfile); + XtAddConverter(XtRString, XtRAsciiType, CvtStringToAsciiType, NULL, 0); + XtSetTypeConverter(XtRAsciiType, XtRString, CvtAsciiTypeToString, + NULL, 0, XtCacheNone, NULL); +} + +/* + * Function: + * XawAsciiSrcInitialize + * + * Parameters: + * request - widget requested by the argument list + * cnew - new widget with both resource and non resource values + * args - (unused) + * num_args - (unused) + * + * Description: + * Initializes the ascii src object. + */ +/*ARGSUSED*/ +static void +XawAsciiSrcInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + AsciiSrcObject src = (AsciiSrcObject)cnew; + FILE *file; + + /* + * Set correct flags (override resources) depending upon widget class + */ + src->text_src.text_format = XawFmt8Bit; + +#ifdef ASCII_DISK + if (XtIsSubclass(XtParent(cnew), asciiDiskWidgetClass)) { + src->ascii_src.type = XawAsciiFile; + src->ascii_src.string = src->ascii_src.filename; + } +#endif + +#ifdef ASCII_STRING + if (XtIsSubclass(XtParent(cnew), asciiStringWidgetClass)) { + src->ascii_src.use_string_in_place = True; + src->ascii_src.type = XawAsciiString; + } +#endif + +#ifdef OLDXAW + src->ascii_src.changes = False; +#else + src->text_src.changed = False; +#endif + src->ascii_src.allocated_string = False; + + if (src->ascii_src.use_string_in_place && src->ascii_src.string == NULL) + src->ascii_src.use_string_in_place = False; + + file = InitStringOrFile(src, src->ascii_src.type == XawAsciiFile); + LoadPieces(src, file, NULL); + + if (file != NULL) + fclose(file); +} + +/* + * Function: + * ReadText + * + * Parameters: + * w - AsciiSource widget + * pos - position of the text to retreive. + * text - text block that will contain returned text + * length - maximum number of characters to read + * + * Description: + * This function reads the source. + * + * Returns: + * The character position following the retrieved text. + */ +static XawTextPosition +ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length) +{ + AsciiSrcObject src = (AsciiSrcObject)w; + XawTextPosition count, start; + Piece *piece; +#ifndef OLDXAW + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextPosition offset, end = pos + length; + Bool state; + + end = XawMin(end, src->ascii_src.length); + while ((state = XawTextSourceAnchorAndEntity(w, pos, &anchor, &entity)) && + (entity->flags & XAW_TENTF_HIDE)) + pos = anchor->position + entity->offset + entity->length; + if (state == False || + !(entity->flags & XAW_TENTF_REPLACE)) { + while (entity) { + offset = anchor->position + entity->offset; + if (offset >= end) + break; + if (offset > pos && + (entity->flags & (XAW_TENTF_HIDE | XAW_TENTF_REPLACE))) { + end = XawMin(end, offset); + break; + } + if ((entity = entity->next) == NULL && + (anchor = XawTextSourceNextAnchor(w, anchor)) != NULL) + entity = anchor->entities; + } + } + else if (state && (entity->flags & XAW_TENTF_REPLACE) && pos < end) { + XawTextBlock *block = (XawTextBlock*)entity->data; + + offset = anchor->position + entity->offset; + end = XawMin(end, offset + block->length); + if ((length = end - pos) < 0) + length = 0; + text->length = length; + text->format = XawFmt8Bit; + if (length == 0) { + text->firstPos = end = offset + entity->length; + text->ptr = ""; + } + else { + text->firstPos = pos; + text->ptr = block->ptr + (pos - offset); + if (pos + length < offset + block->length) + end = pos + length; /* there is data left to be read */ + else + end = offset + entity->length; + } + + return (end); + } + + if ((length = end - pos) < 0) + length = 0; +#endif + + piece = FindPiece(src, pos, &start); + text->firstPos = pos; + text->ptr = piece->text + (pos - start); + count = piece->used - (pos - start); + text->length = Max(0, (length > count) ? count : length); + text->format = XawFmt8Bit; + + return (pos + text->length); +} + +/* + * Function: + * ReplaceText + * + * Parameters: + * w - AsciiSource object + * startPos - ends of text that will be replaced + * endPos - "" + * text - new text to be inserted into buffer at startPos + * + * Description: + * Replaces a block of text with new text. + * + * Returns: + * XawEditDone on success, XawEditError otherwise + */ +/*ARGSUSED*/ +static int +ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos, + XawTextBlock *text) +{ + AsciiSrcObject src = (AsciiSrcObject)w; + Piece *start_piece, *end_piece, *temp_piece; + XawTextPosition start_first, end_first; + int length, firstPos; + + /* + * Editing a read only source is not allowed + */ + if (src->text_src.edit_mode == XawtextRead) + return (XawEditError); + + start_piece = FindPiece(src, startPos, &start_first); + end_piece = FindPiece(src, endPos, &end_first); + +#ifndef OLDXAW + /* + * This is a big hack, but I can't think about a clever way to know + * if the character being moved forward has a negative lbearing. + * + */ + if (start_piece->used) { + int i; + + for (i = 0; i < src->text_src.num_text; i++) { + int line; + TextWidget ctx = (TextWidget)src->text_src.text[i]; + + for (line = 0; line < ctx->text.lt.lines; line++) + if (startPos < ctx->text.lt.info[line + 1].position) + break; + if (i < ctx->text.lt.lines && + startPos > ctx->text.lt.info[i].position) { + AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink; + XawTextAnchor *anchor; + XawTextEntity *entity; + XawTextProperty *property; + XFontStruct *font; + + if (XawTextSourceAnchorAndEntity(w, startPos, &anchor, &entity) && + (property = XawTextSinkGetProperty(ctx->text.sink, + entity->property)) != NULL && + (property->mask & XAW_TPROP_FONT)) + font = property->font; + else + font = sink->ascii_sink.font; + + if (font->min_bounds.lbearing < 0) { + int lbearing = font->min_bounds.lbearing; + unsigned char c = *(unsigned char*) + (start_piece->text + (startPos - start_first)); + + if (c == '\t' || c == '\n') + c = ' '; + else if ((c & 0177) < XawSP || c == 0177) { + if (sink->ascii_sink.display_nonprinting) + c = c > 0177 ? '\\' : c + '^'; + else + c = ' '; + } + if (font->per_char && + (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)) + lbearing = font->per_char[c - font->min_char_or_byte2].lbearing; + if (lbearing < 0) + _XawTextNeedsUpdating(ctx, startPos - 1, startPos); + } + } + } + } + + +#endif + + /* + * Remove Old Stuff + */ + if (start_piece != end_piece) { + temp_piece = start_piece->next; + + /* + * If empty and not the only piece then remove it. + */ + if (((start_piece->used = startPos - start_first) == 0) + && !(start_piece->next == NULL && start_piece->prev == NULL)) + RemovePiece(src, start_piece); + + while (temp_piece != end_piece) { + temp_piece = temp_piece->next; + RemovePiece(src, temp_piece->prev); + } + + end_piece->used -= endPos - end_first; + if (end_piece->used != 0) + memmove(end_piece->text, end_piece->text + endPos - end_first, + (unsigned)end_piece->used); + } + else { /* We are fully in one piece */ + if ((start_piece->used -= endPos - startPos) == 0) { + if (!(start_piece->next == NULL && start_piece->prev == NULL)) + RemovePiece(src, start_piece); + } + else { + memmove(start_piece->text + (startPos - start_first), + start_piece->text + (endPos - start_first), + (unsigned)(start_piece->used - (startPos - start_first))); + if (src->ascii_src.use_string_in_place + && src->ascii_src.length - (endPos - startPos) + < src->ascii_src.piece_size - 1) + start_piece->text[src->ascii_src.length - (endPos - startPos)] = + '\0'; + } + } + + src->ascii_src.length += -(endPos - startPos) + text->length; + + if ( text->length != 0) { + /* + * Put in the New Stuff + */ + start_piece = FindPiece(src, startPos, &start_first); + + length = text->length; + firstPos = text->firstPos; + + while (length > 0) { + char *ptr; + int fill; + + if (src->ascii_src.use_string_in_place) { + if (start_piece->used == src->ascii_src.piece_size - 1) { + /* + * If we are in ascii string emulation mode. Then the + * string is not allowed to grow + */ + start_piece->used = src->ascii_src.length = + src->ascii_src.piece_size - 1; + start_piece->text[src->ascii_src.length] = '\0'; + return (XawEditError); + } + } + + if (start_piece->used == src->ascii_src.piece_size) { + BreakPiece(src, start_piece); + start_piece = FindPiece(src, startPos, &start_first); + } + + fill = Min((int)(src->ascii_src.piece_size - start_piece->used), + length); + + ptr = start_piece->text + (startPos - start_first); + memmove(ptr + fill, ptr, + (unsigned)(start_piece->used - (startPos - start_first))); + memcpy(ptr, text->ptr + firstPos, (unsigned)fill); + + startPos += fill; + firstPos += fill; + start_piece->used += fill; + length -= fill; + } + } + + if (src->ascii_src.use_string_in_place) + start_piece->text[start_piece->used] = '\0'; + +#ifdef OLDXAW + src->ascii_src.changes = True; + XtCallCallbacks(w, XtNcallback, NULL); +#endif + + return (XawEditDone); +} + +/* + * Function: + * Scan + * + * Parameters: + * w - AsciiSource object + * position - position to start scanning + * type - type of thing to scan for + * dir - direction to scan + * count - which occurance if this thing to search for. + * include - whether or not to include the character found in + * the position that is returned + * + * Description: + * Scans the text source for the number and type of item specified. + * + * Returns: + * The position of the item found + * + * Note: + * While there are only 'n' characters in the file there are n+1 + * possible cursor positions (one before the first character and + * one after the last character + */ +static XawTextPosition +Scan(Widget w, register XawTextPosition position, XawTextScanType type, + XawTextScanDirection dir, int count, Bool include) +{ + AsciiSrcObject src = (AsciiSrcObject)w; + Piece *piece; + XawTextPosition first, first_eol_position = 0; + register char *ptr, *lim; + register int cnt = count; + register unsigned char c; + + if (dir == XawsdLeft) { + if (position <= 0) + return (0); + --position; + } + else if (position >= src->ascii_src.length) + return (src->ascii_src.length); + + piece = FindPiece(src, position, &first); + if (piece->used == 0) + return (0); + + ptr = (position - first) + piece->text; + + if (dir == XawsdRight) { + lim = piece->text + piece->used; + switch (type) { + case XawstEOL: + case XawstParagraph: + case XawstWhiteSpace: + case XawstAlphaNumeric: + for (; cnt > 0; cnt--) { + Bool non_space = False, first_eol = True; + + /*CONSTCOND*/ + while (True) { + if (ptr >= lim) { + piece = piece->next; + if (piece == NULL) /* End of text */ + return (src->ascii_src.length); + ptr = piece->text; + lim = piece->text + piece->used; + } + + c = *ptr++; + ++position; + + if (type == XawstEOL) { + if (c == '\n') + break; + } + else if (type == XawstAlphaNumeric) { + if (!isalnum(c)) { + if (non_space) + break; + } + else + non_space = True; + } + else if (type == XawstWhiteSpace) { + if (isspace(c)) { + if (non_space) + break; + } + else + non_space = True; + } + else { /* XawstParagraph */ + if (first_eol) { + if (c == '\n') { + first_eol_position = position; + first_eol = False; + } + } + else if (c == '\n') + break; + else if (!isspace(c)) + first_eol = True; + } + } + } + break; + case XawstPositions: + position += count; + return (position < src->ascii_src.length ? + position : src->ascii_src.length); + case XawstAll: + return (src->ascii_src.length); + default: + break; + } + if (!include) { + if (type == XawstParagraph) + position = first_eol_position; + if (count) + --position; + } + } + else { + lim = piece->text; + switch (type) { + case XawstEOL: + case XawstParagraph: + case XawstWhiteSpace: + case XawstAlphaNumeric: + for (; cnt > 0; cnt--) { + Bool non_space = False, first_eol = True; + + /*CONSTCOND*/ + while (True) { + if (ptr < lim) { + piece = piece->prev; + if (piece == NULL) /* Begining of text */ + return (0); + ptr = piece->text + piece->used - 1; + lim = piece->text; + } + + c = *ptr--; + --position; + + if (type == XawstEOL) { + if (c == '\n') + break; + } + else if (type == XawstAlphaNumeric) { + if (!isalnum(c)) { + if (non_space) + break; + } + else + non_space = True; + } + else if (type == XawstWhiteSpace) { + if (isspace(c)) { + if (non_space) + break; + } + else + non_space = True; + } + else { /* XawstParagraph */ + if (first_eol) { + if (c == '\n') { + first_eol_position = position; + first_eol = False; + } + } + else if (c == '\n') + break; + else if (!isspace(c)) + first_eol = True; + } + } + } + break; + case XawstPositions: + position -= count - 1; + return (position > 0 ? position : 0); + case XawstAll: + return (0); + default: + break; + } + if (!include) { + if (type == XawstParagraph) + position = first_eol_position; + if (count) + ++position; + } + position++; + } + + return (position); +} + +/* + * Function: + * Search + * + * Parameters: + * w - AsciiSource object + * position - the position to start scanning + * dir - direction to scan + * text - text block to search for + * + * Description: + * Searchs the text source for the text block passed. + * + * Returns: + * The position of the item found + */ +static XawTextPosition +Search(Widget w, register XawTextPosition position, XawTextScanDirection dir, + XawTextBlock *text) +{ + AsciiSrcObject src = (AsciiSrcObject)w; + register int count = 0; + register char *ptr, c; + char *str; + Piece *piece; + char *buf; + XawTextPosition first; + int cnt, case_sensitive; + + if (dir == XawsdLeft) { + if (position == 0) + return (XawTextSearchError); + position--; + } + + buf = XtMalloc((unsigned)sizeof(unsigned char) * text->length); + memcpy(buf, text->ptr, (unsigned)text->length); + piece = FindPiece(src, position, &first); + ptr = (position - first) + piece->text; + case_sensitive = text->firstPos; + + if (dir == XawsdRight) { + str = buf; + c = *str; + /*CONSTCOND*/ + while (1) { + if (*ptr++ == c + || (case_sensitive && isalpha(c) && isalpha(ptr[-1]) + && toupper(c) == toupper(ptr[-1]))) { + if (++count == text->length) + break; + c = *++str; + } + else if (count) { + ptr -= count; + str -= count; + position -= count; + count = 0; + c = *str; + + if (ptr < piece->text) { + do { + cnt = piece->text - ptr; + piece = piece->prev; + if (piece == NULL) { + XtFree(buf); + return (XawTextSearchError); + } + ptr = piece->text + piece->used - cnt; + } while (ptr < piece->text); + } + } + position++; + if (ptr >= (piece->text + piece->used)) { + do { + cnt = ptr - (piece->text + piece->used); + piece = piece->next; + if (piece == NULL) { + XtFree(buf); + return (XawTextSearchError); + } + ptr = piece->text + cnt; + } while (ptr >= (piece->text + piece->used)); + } + } + + position -= text->length - 1; + } + else { + str = buf + text->length - 1; + c = *str; + /*CONSTCOND*/ + while (1) { + if (*ptr-- == c + || (case_sensitive && isalpha(c) && isalpha(ptr[1]) + && toupper(c) == toupper(ptr[1]))) { + if (++count == text->length) + break; + c = *--str; + } + else if (count) { + ptr += count; + str += count; + position += count; + count = 0; + c = *str; + + if (ptr >= (piece->text + piece->used)) { + do { + cnt = ptr - (piece->text + piece->used); + piece = piece->next; + if (piece == NULL) { + XtFree(buf); + return (XawTextSearchError); + } + ptr = piece->text + cnt; + } while (ptr >= (piece->text + piece->used)); + } + } + position--; + if (ptr < piece->text) { + do { + cnt = piece->text - ptr; + piece = piece->prev; + if (piece == NULL) { + XtFree(buf); + return (XawTextSearchError); + } + ptr = piece->text + piece->used - cnt; + } while (ptr < piece->text); + } + } + } + + XtFree(buf); + + return (position); +} + +/* + * Function: + * XawAsciiSrcSetValues + * + * Parameters: + * current - current state of the widget + * request - what was requested + * cnew - what the widget will become + * args - representation of changed resources + * num_args - number of resources that have changed + * + * Description: + * Sets the values for the AsciiSource. + * + * Returns: + * True if redisplay is needed + */ +static Boolean +XawAsciiSrcSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + AsciiSrcObject src = (AsciiSrcObject)cnew; + AsciiSrcObject old_src = (AsciiSrcObject)current; + Bool total_reset = False, string_set = False; + FILE *file; + unsigned int i; + + if (old_src->ascii_src.use_string_in_place + != src->ascii_src.use_string_in_place) { + XtAppWarning(XtWidgetToApplicationContext(cnew), + "AsciiSrc: The XtNuseStringInPlace resource may " + "not be changed."); + src->ascii_src.use_string_in_place = + old_src->ascii_src.use_string_in_place; + } + + for (i = 0; i < *num_args ; i++) + if (streq(args[i].name, XtNstring)) { + string_set = True; + break; + } + + if (string_set || (old_src->ascii_src.type != src->ascii_src.type)) { + RemoveOldStringOrFile(old_src, string_set); /* remove old info */ + file = InitStringOrFile(src, string_set); /* Init new info */ + LoadPieces(src, file, NULL); /* load new info into internal buffers */ + if (file != NULL) + fclose(file); +#ifndef OLDXAW + for (i = 0; i < src->text_src.num_text; i++) + /* Tell text widget what happened */ + XawTextSetSource(src->text_src.text[i], cnew, 0); +#else + XawTextSetSource(XtParent(cnew), cnew, 0); +#endif + total_reset = True; + } + + if (old_src->ascii_src.ascii_length != src->ascii_src.ascii_length) + src->ascii_src.piece_size = src->ascii_src.ascii_length + 1; + + if (!total_reset && + old_src->ascii_src.piece_size != src->ascii_src.piece_size) { + String string = StorePiecesInString(old_src); + + FreeAllPieces(old_src); + LoadPieces(src, NULL, string); + XtFree(string); + } + + return (False); +} + +/* + * Function: + * XawAsciiSrcGetValuesHook + * + * Parameters: + * w - AsciiSource Widget + * args - argument list + * num_args - number of args + * + * Description: + * This is a get values hook routine that sets the + * values specific to the ascii source. + */ +static void +XawAsciiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args) +{ + AsciiSrcObject src = (AsciiSrcObject)w; + unsigned int i; + + if (src->ascii_src.type == XawAsciiString) { + for (i = 0; i < *num_args ; i++) + if (streq(args[i].name, XtNstring)) { + if (src->ascii_src.use_string_in_place) + *((char **)args[i].value) = src->ascii_src.first_piece->text; + else if (XawAsciiSave(w)) /* If save sucessful */ + *((char **)args[i].value) = src->ascii_src.string; + break; + } + } + } + +/* + * Function: + * XawAsciiSrcDestroy + * + * Parameters: + * src - Ascii source object to free + * + * Description: + * Destroys an ascii source (frees all data) + */ +static void +XawAsciiSrcDestroy(Widget w) +{ + RemoveOldStringOrFile((AsciiSrcObject) w, True); +} + +/* + * Public routines + */ +/* + * Function: + * XawAsciiSourceFreeString + * + * Parameters: + * w - AsciiSrc widget + * + * Description: + * Frees the string returned by a get values call + * on the string when the source is of type string. + */ +void +XawAsciiSourceFreeString(Widget w) +{ + AsciiSrcObject src = (AsciiSrcObject)w; + + /* If the src is really a multi, call the multi routine */ + if (XtIsSubclass(w, multiSrcObjectClass)) { + _XawMultiSourceFreeString(w); + return; + } + else if (!XtIsSubclass(w, asciiSrcObjectClass)) { + XtErrorMsg("bad argument", "asciiSource", "XawError", + "XawAsciiSourceFreeString's parameter must be " + "an asciiSrc or multiSrc.", + NULL, NULL); + } + + if (src->ascii_src.allocated_string && src->ascii_src.type != XawAsciiFile) { + src->ascii_src.allocated_string = False; + XtFree(src->ascii_src.string); + src->ascii_src.string = NULL; + } +} + +/* + * Function: + * XawAsciiSave + * + * Parameters: + * w - asciiSrc Widget + * + * Description: + * Saves all the pieces into a file or string as required. + * + * Returns: + * True if the save was successful + */ +Bool +XawAsciiSave(Widget w) +{ + AsciiSrcObject src = (AsciiSrcObject)w; + + /* If the src is really a multi, call the multi save */ + if (XtIsSubclass(w, multiSrcObjectClass )) + return (_XawMultiSave(w)); + + else if (!XtIsSubclass(w, asciiSrcObjectClass)) + XtErrorMsg("bad argument", "asciiSource", "XawError", + "XawAsciiSave's parameter must be an asciiSrc or multiSrc.", + NULL, NULL); + + /* + * If using the string in place then there is no need to play games + * to get the internal info into a readable string. + */ + if (src->ascii_src.use_string_in_place) + return (True); + + if (src->ascii_src.type == XawAsciiFile) { +#ifdef OLDXAW + if (!src->ascii_src.changes) +#else + if (!src->text_src.changed) /* No changes to save */ +#endif + return (True); + + if (WritePiecesToFile(src, src->ascii_src.string) == False) + return (False); + } + else { + if (src->ascii_src.allocated_string == True) + XtFree(src->ascii_src.string); + else + src->ascii_src.allocated_string = True; + + src->ascii_src.string = StorePiecesInString(src); + } +#ifdef OLDXAW + src->ascii_src.changes = False; +#else + src->text_src.changed = False; +#endif + + return (True); +} + +/* + * Function: + * XawAsciiSaveAsFile + * + * Arguments: + * w - AsciiSrc widget + * name - name of the file to save this file into + * + * Description: + * Save the current buffer as a file. + * + * Returns: + * True if the save was sucessful + */ +Bool +XawAsciiSaveAsFile(Widget w, _Xconst char *name) +{ + AsciiSrcObject src = (AsciiSrcObject)w; + Bool ret; + + /* If the src is really a multi, call the multi save */ + + if (XtIsSubclass( w, multiSrcObjectClass)) + return (_XawMultiSaveAsFile(w, name)); + + else if (!XtIsSubclass(w, asciiSrcObjectClass)) + XtErrorMsg("bad argument", "asciiSource", "XawError", + "XawAsciiSaveAsFile's 1st parameter must be an " + "asciiSrc or multiSrc.", + NULL, NULL); + + if (src->ascii_src.type == XawAsciiFile) + ret = WritePiecesToFile(src, (String)name); + else { + String string = StorePiecesInString(src); + + ret = WriteToFile(string, (String)name, src->ascii_src.length); + XtFree(string); + } + + return (ret); +} + +/* + * Function: + * XawAsciiSourceChanged + * + * Parameters: + * w - ascii source widget + * + * Description: + * Returns true if the source has changed since last saved. + * + * Returns: + * A Boolean (see description). + */ +Bool +XawAsciiSourceChanged(Widget w) +{ +#ifdef OLDXAW + if (XtIsSubclass(w, multiSrcObjectClass)) + return (((MultiSrcObject)w)->multi_src.changes); + + if (XtIsSubclass(w, asciiSrcObjectClass)) + return (((AsciiSrcObject)w)->ascii_src.changes); +#else + if (XtIsSubclass(w, textSrcObjectClass)) + return (((TextSrcObject)w)->textSrc.changed); +#endif + XtErrorMsg("bad argument", "asciiSource", "XawError", + "XawAsciiSourceChanged parameter must be an " + "asciiSrc or multiSrc.", + NULL, NULL); + + return (True); +} + +/* + * Private Functions + */ +static void +RemoveOldStringOrFile(AsciiSrcObject src, Bool checkString) +{ + FreeAllPieces(src); + + if (checkString && src->ascii_src.allocated_string) { + XtFree(src->ascii_src.string); + src->ascii_src.allocated_string = False; + src->ascii_src.string = NULL; + } +} + +/* + * Function: + * WriteToFile + * + * Parameters: + * string - string to write + * name - the name of the file + * + * Description: + * Write the string specified to the begining of the file specified. + * + * Returns: + * returns True if sucessful, False otherwise + */ +static Bool +WriteToFile(String string, String name, unsigned length) +{ + int fd; + + if ((fd = creat(name, 0666)) == -1) + return (False); + + if (write(fd, string, length) == -1) { + close(fd); + return (False); + } + + if (close(fd) == -1) + return (False); + + return (True); +} + +/* + * Function: + * WritePiecesToFile + * + * Parameters: + * src - ascii source object + * name - name of the file + * + * Description: + * Almost identical to WriteToFile, but only works for ascii src objects + * of type XawAsciiFile. This function avoids allocating temporary memory, + * what can be useful when editing very large files. + * + * Returns: + * returns True if sucessful, False otherwise + */ +static Bool +WritePiecesToFile(AsciiSrcObject src, String name) +{ + Piece *piece; + int fd; + + if (src->ascii_src.data_compression) { + Piece *tmp; + + piece = src->ascii_src.first_piece; + while (piece) { + int bytes = src->ascii_src.piece_size - piece->used; + + if (bytes > 0 && (tmp = piece->next) != NULL) { + bytes = XawMin(bytes, tmp->used); + memcpy(piece->text + piece->used, tmp->text, bytes); + memmove(tmp->text, tmp->text + bytes, tmp->used - bytes); + piece->used += bytes; + if ((tmp->used -= bytes) == 0) { + RemovePiece(src, tmp); + continue; + } + } + piece = piece->next; + } + } + + if ((fd = creat(name, 0666)) == -1) + return (False); + + for (piece = src->ascii_src.first_piece; piece; piece = piece->next) + if (write(fd, piece->text, piece->used) == -1) { + close(fd); + return (False); + } + + if (close(fd) == -1) + return (False); + + return (True); +} + +/* + * Function: + * StorePiecesInString + * + * Parameters: + * data - ascii pointer data + * + * Description: + * Store the pieces in memory into a standard ascii string. + */ +static String +StorePiecesInString(AsciiSrcObject src) +{ + String string; + XawTextPosition first; + Piece *piece; + + string = XtMalloc((unsigned)(src->ascii_src.length + 1)); + + for (first = 0, piece = src->ascii_src.first_piece ; piece != NULL; + first += piece->used, piece = piece->next) + memcpy(string + first, piece->text, (unsigned)piece->used); + + string[src->ascii_src.length] = '\0'; + + /* + * This will refill all pieces to capacity + */ + if (src->ascii_src.data_compression) { + FreeAllPieces(src); + LoadPieces(src, NULL, string); + } + + return (string); +} + +/* + * Function: + * InitStringOrFile + * + * Parameters: + * src - AsciiSource + * + * Description: + * Initializes the string or file. + */ +static FILE * +InitStringOrFile(AsciiSrcObject src, Bool newString) +{ + mode_t open_mode = 0; + const char *fdopen_mode = NULL; + int fd; + FILE *file; + + if (src->ascii_src.type == XawAsciiString) { + if (src->ascii_src.string == NULL) + src->ascii_src.length = 0; + + else if (!src->ascii_src.use_string_in_place) { + src->ascii_src.string = XtNewString(src->ascii_src.string); + src->ascii_src.allocated_string = True; + src->ascii_src.length = strlen(src->ascii_src.string); + } + + if (src->ascii_src.use_string_in_place) { + if (src->ascii_src.string != NULL) + src->ascii_src.length = strlen(src->ascii_src.string); + /* In case the length resource is incorrectly set */ + if (src->ascii_src.length > src->ascii_src.ascii_length) + src->ascii_src.ascii_length = src->ascii_src.length; + + if (src->ascii_src.ascii_length == MAGIC_VALUE) + src->ascii_src.piece_size = src->ascii_src.length; + else + src->ascii_src.piece_size = src->ascii_src.ascii_length + 1; + } + + return (NULL); + } + + /* + * type is XawAsciiFile + */ + src->ascii_src.is_tempfile = False; + + switch (src->text_src.edit_mode) { + case XawtextRead: + if (src->ascii_src.string == NULL) + XtErrorMsg("NoFile", "asciiSourceCreate", "XawError", + "Creating a read only disk widget and no file specified.", + NULL, NULL); + open_mode = O_RDONLY; + fdopen_mode = "r"; + break; + case XawtextAppend: + case XawtextEdit: + if (src->ascii_src.string == NULL) { + src->ascii_src.string = "*ascii-src*"; + src->ascii_src.is_tempfile = True; + } + else { +/* O_NOFOLLOW is a FreeBSD & Linux extension */ +#ifdef O_NOFOLLOW + open_mode = O_RDWR | O_NOFOLLOW; +#else + open_mode = O_RDWR; /* unsafe; subject to race conditions */ +#endif /* O_NOFOLLOW */ + fdopen_mode = "r+"; + } + break; + default: + XtErrorMsg("badMode", "asciiSourceCreate", "XawError", + "Bad editMode for ascii source; must be Read, " + "Append or Edit.", + NULL, NULL); + } + + /* If is_tempfile, allocate a private copy of the text + * Unlikely to be changed, just to set allocated_string */ + if (newString || src->ascii_src.is_tempfile) { + src->ascii_src.string = XtNewString(src->ascii_src.string); + src->ascii_src.allocated_string = True; + } + + if (!src->ascii_src.is_tempfile) { + if ((fd = open(src->ascii_src.string, open_mode, 0666)) != -1) { + if ((file = fdopen(fd, fdopen_mode))) { + (void)fseek(file, 0, SEEK_END); + src->ascii_src.length = (XawTextPosition)ftell(file); + return (file); + } + } + { + String params[2]; + Cardinal num_params = 2; + + params[0] = src->ascii_src.string; + params[1] = strerror(errno); + XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), + "openError", "asciiSourceCreate", "XawWarning", + "Cannot open file %s; %s", params, &num_params); + } + } + src->ascii_src.length = 0; + return (NULL); +} + +static void +LoadPieces(AsciiSrcObject src, FILE *file, char *string) +{ + char *ptr; + Piece *piece = NULL; + XawTextPosition left; + + if (string == NULL) { + if (src->ascii_src.type == XawAsciiFile) { + if (src->ascii_src.length != 0) { + int len; + + left = 0; + fseek(file, 0, 0); + while (left < src->ascii_src.length) { + ptr = XtMalloc((unsigned)src->ascii_src.piece_size); + if ((len = fread(ptr, (Size_t)sizeof(unsigned char), + (Size_t)src->ascii_src.piece_size, file)) < 0) + XtErrorMsg("readError", "asciiSourceCreate", "XawError", + "fread returned error.", NULL, NULL); + piece = AllocNewPiece(src, piece); + piece->text = ptr; + piece->used = XawMin(len, src->ascii_src.piece_size); + left += piece->used; + } + } + else { + piece = AllocNewPiece(src, NULL); + piece->text = XtMalloc((unsigned)src->ascii_src.piece_size); + piece->used = 0; + } + return; + } + else + string = src->ascii_src.string; + } + + if (src->ascii_src.use_string_in_place) { + piece = AllocNewPiece(src, piece); + piece->used = XawMin(src->ascii_src.length, src->ascii_src.piece_size); + piece->text = src->ascii_src.string; + return; + } + + ptr = string; + left = src->ascii_src.length; + do { + piece = AllocNewPiece(src, piece); + + piece->text = XtMalloc((unsigned)src->ascii_src.piece_size); + piece->used = XawMin(left, src->ascii_src.piece_size); + if (piece->used != 0) + memcpy(piece->text, ptr, (unsigned)piece->used); + + left -= piece->used; + ptr += piece->used; + } while (left > 0); +} + +/* + * Function: + * AllocNewPiece + * + * Parameters: + * src - AsciiSrc Widget + * prev - piece just before this one, or NULL + * + * Description: + * Allocates a new piece of memory. + * + * Returns: + * The allocated piece + */ +static Piece * +AllocNewPiece(AsciiSrcObject src, Piece *prev) +{ + Piece *piece = XtNew(Piece); + + if (prev == NULL) { + src->ascii_src.first_piece = piece; + piece->next = NULL; + } + else { + if (prev->next != NULL) + (prev->next)->prev = piece; + piece->next = prev->next; + prev->next = piece; + } + + piece->prev = prev; + + return (piece); +} + +/* + * Function: + * FreeAllPieces + * + * Parameters: + * src - AsciiSrc Widget + * + * Description: + * Frees all the pieces. + */ +static void +FreeAllPieces(AsciiSrcObject src) +{ + Piece *next, * first = src->ascii_src.first_piece; + +#ifdef DEBUG + if (first->prev != NULL) + printf("Xaw AsciiSrc Object: possible memory leak in FreeAllPieces().\n"); +#endif + + for (; first != NULL ; first = next) { + next = first->next; + RemovePiece(src, first); + } +} + +/* + * Function: + * RemovePiece + * + * Parameters: + * piece - piece to remove + * + * Description: + * Removes a piece from the list. + */ +static void +RemovePiece(AsciiSrcObject src, Piece *piece) +{ + if (piece->prev == NULL) + src->ascii_src.first_piece = piece->next; + else + piece->prev->next = piece->next; + + if (piece->next != NULL) + piece->next->prev = piece->prev; + + if (!src->ascii_src.use_string_in_place) + XtFree(piece->text); + + XtFree((char *)piece); +} + +/* + * Function: + * FindPiece + * + * Parameters: + * src - AsciiSrc Widget + * position - position that we are searching for + * first - position of the first character in this piece (return) + * + * Description: + * Finds the piece containing the position indicated. + * + * Returns: + * the piece that contains this position + */ +static Piece * +FindPiece(AsciiSrcObject src, XawTextPosition position, XawTextPosition *first) +{ + Piece *old_piece, *piece; + XawTextPosition temp; + + for (old_piece = NULL, piece = src->ascii_src.first_piece, temp = 0; + piece; old_piece = piece, piece = piece->next) + if ((temp += piece->used) > position) { + *first = temp - piece->used; + return (piece); + } + + *first = temp - (old_piece ? old_piece->used : 0); + + return (old_piece); /* if we run off the end the return the last piece */ +} + +/* + * Function: + * BreakPiece + * + * Parameters: + * src - AsciiSrc Widget + * piece - piece to break + * + * Description: + * Breaks a full piece into two new pieces. + */ +#define HALF_PIECE (src->ascii_src.piece_size >> 1) +static void +BreakPiece(AsciiSrcObject src, Piece *piece) +{ + Piece *cnew = AllocNewPiece(src, piece); + + cnew->text = XtMalloc((unsigned)src->ascii_src.piece_size); + memcpy(cnew->text, piece->text + HALF_PIECE, + (unsigned)(src->ascii_src.piece_size - HALF_PIECE)); + piece->used = HALF_PIECE; + cnew->used = src->ascii_src.piece_size - HALF_PIECE; +} + +/*ARGSUSED*/ +static void +CvtStringToAsciiType(XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal) +{ + static XawAsciiType type; + XrmQuark q; + char name[7]; + + XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); + q = XrmStringToQuark(name); + + if (q == Qstring) + type = XawAsciiString; + else if (q == Qfile) + type = XawAsciiFile; + else { + toVal->size = 0; + toVal->addr = NULL; + XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType); + } + + toVal->size = sizeof(XawAsciiType); + toVal->addr = (XPointer)&type; +} + +/*ARGSUSED*/ +static Boolean +CvtAsciiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal, + XtPointer *data) +{ + static String buffer; + Cardinal size; + + switch (*(XawAsciiType *)fromVal->addr) { + case XawAsciiFile: + buffer = XtEfile; + break; + case XawAsciiString: + buffer = XtEstring; + break; + default: + XawTypeToStringWarning(dpy, XtRAsciiType); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + + size = strlen(buffer) + 1; + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +/*ARGSUSED*/ +static void +GetDefaultPieceSize(Widget w, int offset, XrmValue *value) +{ + static XPointer pagesize; + + if (pagesize == NULL) { + pagesize = (XPointer)((long)_XawGetPageSize()); + if (pagesize < (XPointer)BUFSIZ) + pagesize = (XPointer)BUFSIZ; + } + + value->addr = (XPointer)&pagesize; +} + +#if (defined(ASCII_STRING) || defined(ASCII_DISK)) +# include <X11/Xaw/Cardinals.h> +#endif + +#ifdef ASCII_STRING +/* + * Compatability functions. + */ +/* + * Function: + * AsciiStringSourceCreate + * + * Parameters: + * parent - widget that will own this source + * args - the argument list + * num_args - "" + * + * Description: + * Creates a string source. + * + * Returns: + * A pointer to the new text source. + */ +Widget +XawStringSourceCreate(Widget parent, ArgList args, Cardinal num_args) +{ + XawTextSource src; + ArgList ascii_args; + Arg temp[2]; + + XtSetArg(temp[0], XtNtype, XawAsciiString); + XtSetArg(temp[1], XtNuseStringInPlace, True); + ascii_args = XtMergeArgLists(temp, TWO, args, num_args); + + src = XtCreateWidget("genericAsciiString", asciiSrcObjectClass, parent, + ascii_args, num_args + TWO); + XtFree((char *)ascii_args); + + return (src); +} + +/* + * This is hacked up to try to emulate old functionality, it + * may not work, as I have not old code to test it on. + * + * Chris D. Peterson 8/31/89. + */ +void +XawTextSetLastPos(Widget w, XawTextPosition lastPos) +{ + AsciiSrcObject src = (AsciiSrcObject)XawTextGetSource(w); + + src->ascii_src.piece_size = lastPos; +} +#endif /* ASCII_STRING */ + +#ifdef ASCII_DISK +/* + * Function: + * AsciiDiskSourceCreate + * + * Parameters: + * parent - widget that will own this source + * args - argument list + * num_args - "" + * + * Description: + * Creates a disk source. + * + * Returns: + * A pointer to the new text source + */ +Widget +XawDiskSourceCreate(Widget parent, ArgList args, Cardinal num_args) +{ + XawTextSource src; + ArgList ascii_args; + Arg temp[1]; + int i; + + XtSetArg(temp[0], XtNtype, XawAsciiFile); + ascii_args = XtMergeArgLists(temp, ONE, args, num_args); + num_args++; + + for (i = 0; i < num_args; i++) + if (streq(ascii_args[i].name, XtNfile) + || streq(ascii_args[i].name, XtCFile)) + ascii_args[i].name = XtNstring; + + src = XtCreateWidget("genericAsciiDisk", asciiSrcObjectClass, parent, + ascii_args, num_args); + XtFree((char *)ascii_args); + + return (src); +} +#endif /* ASCII_DISK */ diff --git a/libXaw/src/AsciiText.c b/libXaw/src/AsciiText.c index 6d76b154f..25cea9d18 100644 --- a/libXaw/src/AsciiText.c +++ b/libXaw/src/AsciiText.c @@ -1,357 +1,357 @@ -/*
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-*/
-
-/*
- * AsciiText.c - Source code for AsciiText Widget
- *
- * This Widget is intended to be used as a simple front end to the
- * text widget with an ascii source and ascii sink attached to it
- *
- * Date: June 29, 1989
- *
- * By: Chris D. Peterson
- * MIT X Consortium
- * kit@expo.lcs.mit.edu
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/AsciiTextP.h>
-#include <X11/Xaw/AsciiSrcP.h>
-#include <X11/Xaw/AsciiSink.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/MultiSinkP.h>
-#include <X11/Xaw/MultiSrc.h>
-#include <X11/Xaw/XawImP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#define TAB_COUNT 32
-
-/*
- * Class Methods
- */
-static void XawAsciiInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawAsciiDestroy(Widget);
-
-/*
- * From TextSrc.c
- */
-void _XawSourceAddText(Widget, Widget);
-void _XawSourceRemoveText(Widget, Widget, Bool);
-
-#define Superclass (&textClassRec)
-AsciiTextClassRec asciiTextClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "Text", /* class_name */
- sizeof(AsciiRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part_init */
- False, /* class_inited */
- XawAsciiInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- NULL, /* resources */
- 0, /* num_resource */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- XtExposeGraphicsExpose | /* compress_exposure */
- XtExposeNoExpose,
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawAsciiDestroy, /* destroy */
- XtInheritResize, /* resize */
- XtInheritExpose, /* expose */
- NULL, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- XtInheritAcceptFocus, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- XtInheritTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* text */
- {
- NULL, /* extension */
- },
- /* ascii */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass asciiTextWidgetClass = (WidgetClass)&asciiTextClassRec;
-
-#ifdef ASCII_STRING
-AsciiStringClassRec asciiStringClassRec = {
- /* core */
- {
- (WidgetClass)&asciiTextClassRec, /* superclass */
- "Text", /* class_name */
- sizeof(AsciiStringRec), /* widget_size */
- NULL, /* class_initialize */
- NULL, /* class_part_init */
- False, /* class_inited */
- NULL, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- NULL, /* resources */
- 0, /* num_resource */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- XtExposeGraphicsExpose | /* compress_exposure */
- XtExposeNoExpose,
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- XtInheritResize, /* resize */
- XtInheritExpose, /* expose */
- NULL, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- XtInheritAcceptFocus, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- XtInheritTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* text */
- {
- NULL, /* extension */
- },
- /* ascii */
- {
- NULL, /* extension */
- },
- /* string */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass asciiStringWidgetClass = (WidgetClass)&asciiStringClassRec;
-#endif /* ASCII_STRING */
-
-#ifdef ASCII_DISK
-AsciiDiskClassRec asciiDiskClassRec = {
- /* core */
- {
- (WidgetClass)&asciiTextClassRec, /* superclass */
- "Text", /* class_name */
- sizeof(AsciiDiskRec), /* widget_size */
- NULL, /* class_initialize */
- NULL, /* class_part_init */
- False, /* class_inited */
- NULL, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- NULL, /* resources */
- 0, /* num_resource */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- XtExposeGraphicsExpose | /* compress_enterleave */
- XtExposeNoExpose,
- False, /* visible_interest */
- NULL, /* destroy */
- XtInheritResize, /* resize */
- XtInheritExpose, /* expose */
- NULL, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- XtInheritAcceptFocus, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- XtInheritTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* text */
- {
- NULL, /* extension */
- },
- /* ascii */
- {
- NULL, /* extension */
- },
- /* disk */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass asciiDiskWidgetClass = (WidgetClass)&asciiDiskClassRec;
-#endif /* ASCII_DISK */
-
-/*
- * Implementation
- */
-static void
-XawAsciiInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- AsciiWidget w = (AsciiWidget)cnew;
- int i;
- int tabs[TAB_COUNT], tab;
-
- MultiSinkObject sink;
-
- /* superclass Initialize can't set the following,
- * as it didn't know the source or sink when it was called
- */
- if (XtHeight(request) == DEFAULT_TEXT_HEIGHT)
- XtHeight(cnew) = DEFAULT_TEXT_HEIGHT;
-
- /* This is the main change for internationalization */
- if (w->simple.international == True) { /* The multi* are international */
- if (w->text.sink == NULL)
- w->text.sink = XtCreateWidget("textSink", multiSinkObjectClass,
- cnew, args, *num_args);
- else if (!XtIsSubclass(w->text.sink, multiSinkObjectClass))
- XtError("Sink object is not a subclass of multiSink");
-
- if (w->text.source == NULL)
- w->text.source = XtCreateWidget("textSource", multiSrcObjectClass,
- cnew, args, *num_args);
- else if (!XtIsSubclass(w->text.source, multiSrcObjectClass))
- XtError("Source object is not a subclass of multiSrc");
-#ifndef OLDXAW
- else
- _XawSourceAddText(w->text.source, cnew);
-#endif
- }
- else {
- if (w->text.sink == NULL)
- w->text.sink = XtCreateWidget("textSink", asciiSinkObjectClass,
- cnew, args, *num_args);
- else if (!XtIsSubclass(w->text.source, asciiSinkObjectClass))
- XtError("Sink object is not a subclass of asciiSink");
-
- if (w->text.source == NULL)
- w->text.source = XtCreateWidget("textSource", asciiSrcObjectClass,
- cnew, args, *num_args);
- else if (!XtIsSubclass(w->text.source, asciiSrcObjectClass))
- XtError("Source object is not a subclass of asciiSrc");
-#ifndef OLDXAW
- else
- _XawSourceAddText(w->text.source, cnew);
-#endif
- }
-
- if (XtHeight(w) == DEFAULT_TEXT_HEIGHT)
- XtHeight(w) = VMargins(w) + XawTextSinkMaxHeight(w->text.sink, 1);
-
- for (i = 0, tab = 0; i < TAB_COUNT; i++)
- tabs[i] = (tab += 8);
-
- XawTextSinkSetTabs(w->text.sink, TAB_COUNT, tabs);
-
- XawTextDisableRedisplay(cnew);
- XawTextEnableRedisplay(cnew);
-
- _XawImRegister(cnew);
-
- /* If we are using a MultiSink we need to tell the input method stuff */
- if (w->simple.international == True) {
- Arg list[4];
- Cardinal ac = 0;
-
- sink = (MultiSinkObject)w->text.sink;
- XtSetArg(list[ac], XtNfontSet, sink->multi_sink.fontset); ac++;
- XtSetArg(list[ac], XtNinsertPosition, w->text.insertPos); ac++;
- XtSetArg(list[ac], XtNforeground, sink->text_sink.foreground); ac++;
- XtSetArg(list[ac], XtNbackground, sink->text_sink.background); ac++;
- _XawImSetValues(cnew, list, ac);
- }
-}
-
-static void
-XawAsciiDestroy(Widget w)
-{
- AsciiWidget ascii = (AsciiWidget)w;
-
- _XawImUnregister(w);
-
- if (w == XtParent(ascii->text.sink))
- XtDestroyWidget(ascii->text.sink);
-
-#ifdef OLDXAW
- if (w == XtParent(ascii->text.source))
- XtDestroyWidget(ascii->text.source);
-#else
- _XawSourceRemoveText(ascii->text.source, w,
- ascii->text.source &&
- w == XtParent(ascii->text.source));
-#endif
-}
+/* + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/* + * AsciiText.c - Source code for AsciiText Widget + * + * This Widget is intended to be used as a simple front end to the + * text widget with an ascii source and ascii sink attached to it + * + * Date: June 29, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/AsciiTextP.h> +#include <X11/Xaw/AsciiSrcP.h> +#include <X11/Xaw/AsciiSink.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/MultiSinkP.h> +#include <X11/Xaw/MultiSrc.h> +#include <X11/Xaw/XawImP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define TAB_COUNT 32 + +/* + * Class Methods + */ +static void XawAsciiInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawAsciiDestroy(Widget); + +/* + * From TextSrc.c + */ +void _XawSourceAddText(Widget, Widget); +void _XawSourceRemoveText(Widget, Widget, Bool); + +#define Superclass (&textClassRec) +AsciiTextClassRec asciiTextClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Text", /* class_name */ + sizeof(AsciiRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + XawAsciiInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + NULL, /* resources */ + 0, /* num_resource */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + XtExposeGraphicsExpose | /* compress_exposure */ + XtExposeNoExpose, + True, /* compress_enterleave */ + False, /* visible_interest */ + XawAsciiDestroy, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + NULL, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + XtInheritAcceptFocus, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + XtInheritTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* text */ + { + NULL, /* extension */ + }, + /* ascii */ + { + NULL, /* extension */ + }, +}; + +WidgetClass asciiTextWidgetClass = (WidgetClass)&asciiTextClassRec; + +#ifdef ASCII_STRING +AsciiStringClassRec asciiStringClassRec = { + /* core */ + { + (WidgetClass)&asciiTextClassRec, /* superclass */ + "Text", /* class_name */ + sizeof(AsciiStringRec), /* widget_size */ + NULL, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + NULL, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + NULL, /* resources */ + 0, /* num_resource */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + XtExposeGraphicsExpose | /* compress_exposure */ + XtExposeNoExpose, + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + NULL, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + XtInheritAcceptFocus, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + XtInheritTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* text */ + { + NULL, /* extension */ + }, + /* ascii */ + { + NULL, /* extension */ + }, + /* string */ + { + NULL, /* extension */ + }, +}; + +WidgetClass asciiStringWidgetClass = (WidgetClass)&asciiStringClassRec; +#endif /* ASCII_STRING */ + +#ifdef ASCII_DISK +AsciiDiskClassRec asciiDiskClassRec = { + /* core */ + { + (WidgetClass)&asciiTextClassRec, /* superclass */ + "Text", /* class_name */ + sizeof(AsciiDiskRec), /* widget_size */ + NULL, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + NULL, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + NULL, /* resources */ + 0, /* num_resource */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + XtExposeGraphicsExpose | /* compress_enterleave */ + XtExposeNoExpose, + False, /* visible_interest */ + NULL, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + NULL, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + XtInheritAcceptFocus, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + XtInheritTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* text */ + { + NULL, /* extension */ + }, + /* ascii */ + { + NULL, /* extension */ + }, + /* disk */ + { + NULL, /* extension */ + }, +}; + +WidgetClass asciiDiskWidgetClass = (WidgetClass)&asciiDiskClassRec; +#endif /* ASCII_DISK */ + +/* + * Implementation + */ +static void +XawAsciiInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + AsciiWidget w = (AsciiWidget)cnew; + int i; + int tabs[TAB_COUNT], tab; + + MultiSinkObject sink; + + /* superclass Initialize can't set the following, + * as it didn't know the source or sink when it was called + */ + if (XtHeight(request) == DEFAULT_TEXT_HEIGHT) + XtHeight(cnew) = DEFAULT_TEXT_HEIGHT; + + /* This is the main change for internationalization */ + if (w->simple.international == True) { /* The multi* are international */ + if (w->text.sink == NULL) + w->text.sink = XtCreateWidget("textSink", multiSinkObjectClass, + cnew, args, *num_args); + else if (!XtIsSubclass(w->text.sink, multiSinkObjectClass)) + XtError("Sink object is not a subclass of multiSink"); + + if (w->text.source == NULL) + w->text.source = XtCreateWidget("textSource", multiSrcObjectClass, + cnew, args, *num_args); + else if (!XtIsSubclass(w->text.source, multiSrcObjectClass)) + XtError("Source object is not a subclass of multiSrc"); +#ifndef OLDXAW + else + _XawSourceAddText(w->text.source, cnew); +#endif + } + else { + if (w->text.sink == NULL) + w->text.sink = XtCreateWidget("textSink", asciiSinkObjectClass, + cnew, args, *num_args); + else if (!XtIsSubclass(w->text.source, asciiSinkObjectClass)) + XtError("Sink object is not a subclass of asciiSink"); + + if (w->text.source == NULL) + w->text.source = XtCreateWidget("textSource", asciiSrcObjectClass, + cnew, args, *num_args); + else if (!XtIsSubclass(w->text.source, asciiSrcObjectClass)) + XtError("Source object is not a subclass of asciiSrc"); +#ifndef OLDXAW + else + _XawSourceAddText(w->text.source, cnew); +#endif + } + + if (XtHeight(w) == DEFAULT_TEXT_HEIGHT) + XtHeight(w) = VMargins(w) + XawTextSinkMaxHeight(w->text.sink, 1); + + for (i = 0, tab = 0; i < TAB_COUNT; i++) + tabs[i] = (tab += 8); + + XawTextSinkSetTabs(w->text.sink, TAB_COUNT, tabs); + + XawTextDisableRedisplay(cnew); + XawTextEnableRedisplay(cnew); + + _XawImRegister(cnew); + + /* If we are using a MultiSink we need to tell the input method stuff */ + if (w->simple.international == True) { + Arg list[4]; + Cardinal ac = 0; + + sink = (MultiSinkObject)w->text.sink; + XtSetArg(list[ac], XtNfontSet, sink->multi_sink.fontset); ac++; + XtSetArg(list[ac], XtNinsertPosition, w->text.insertPos); ac++; + XtSetArg(list[ac], XtNforeground, sink->text_sink.foreground); ac++; + XtSetArg(list[ac], XtNbackground, sink->text_sink.background); ac++; + _XawImSetValues(cnew, list, ac); + } +} + +static void +XawAsciiDestroy(Widget w) +{ + AsciiWidget ascii = (AsciiWidget)w; + + _XawImUnregister(w); + + if (w == XtParent(ascii->text.sink)) + XtDestroyWidget(ascii->text.sink); + +#ifdef OLDXAW + if (w == XtParent(ascii->text.source)) + XtDestroyWidget(ascii->text.source); +#else + _XawSourceRemoveText(ascii->text.source, w, + ascii->text.source && + w == XtParent(ascii->text.source)); +#endif +} diff --git a/libXaw/src/Box.c b/libXaw/src/Box.c index 5c6cfa2a2..7aa14a5e8 100644 --- a/libXaw/src/Box.c +++ b/libXaw/src/Box.c @@ -1,672 +1,672 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xaw/BoxP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * Class Methods
- */
-static void XawBoxChangeManaged(Widget);
-static void XawBoxClassInitialize(void);
-#ifndef OLDXAW
-static void XawBoxExpose(Widget, XEvent*, Region);
-#endif
-static XtGeometryResult XawBoxGeometryManager(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawBoxInitialize(Widget, Widget, ArgList, Cardinal*);
-static XtGeometryResult XawBoxQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawBoxRealize(Widget, Mask*, XSetWindowAttributes*);
-static void XawBoxResize(Widget);
-static Boolean XawBoxSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void DoLayout(BoxWidget, unsigned int, unsigned int,
- Dimension*, Dimension*, Bool);
-static Bool TryNewLayout(BoxWidget);
-
-/*
- * Initialization
- */
-#ifndef OLDXAW
-static XtActionsRec actions[] = {
- {"set-values", XawSetValuesAction},
- {"get-values", XawGetValuesAction},
- {"declare", XawDeclareAction},
- {"call-proc", XawCallProcAction},
-};
-#endif
-
-static XtResource resources[] = {
- {
- XtNhSpace,
- XtCHSpace,
- XtRDimension,
- sizeof(Dimension),
- XtOffsetOf(BoxRec, box.h_space),
- XtRImmediate,
- (XtPointer)4
- },
- {
- XtNvSpace,
- XtCVSpace,
- XtRDimension,
- sizeof(Dimension),
- XtOffsetOf(BoxRec, box.v_space),
- XtRImmediate,
- (XtPointer)4
- },
- {
- XtNorientation,
- XtCOrientation,
- XtROrientation,
- sizeof(XtOrientation),
- XtOffsetOf(BoxRec, box.orientation),
- XtRImmediate,
- (XtPointer)XtorientVertical
- },
-#ifndef OLDXAW
- {
- XawNdisplayList,
- XawCDisplayList,
- XawRDisplayList,
- sizeof(XawDisplayList*),
- XtOffsetOf(BoxRec, box.display_list),
- XtRImmediate,
- NULL
- },
-#endif
-};
-
-BoxClassRec boxClassRec = {
- /* core */
- {
- (WidgetClass)&compositeClassRec, /* superclass */
- "Box", /* class_name */
- sizeof(BoxRec), /* widget_size */
- XawBoxClassInitialize, /* class_initialize */
- NULL, /* class_part_init */
- False, /* class_inited */
- XawBoxInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawBoxRealize, /* realize */
-#ifndef OLDXAW
- actions, /* actions */
- XtNumber(actions), /* num_actions */
-#else
- NULL, /* actions */
- 0, /* num_actions */
-#endif
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- XawBoxResize, /* resize */
-#ifndef OLDXAW
- XawBoxExpose, /* expose */
-#else
- NULL, /* expose */
-#endif
- XawBoxSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XawBoxQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* composite */
- {
- XawBoxGeometryManager, /* geometry_manager */
- XawBoxChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- /* box */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass boxWidgetClass = (WidgetClass)&boxClassRec;
-
-/*
- * Do a layout, either actually assigning positions, or just calculating size.
- * Returns minimum width and height that will preserve the same layout.
- */
-static void
-DoLayout(BoxWidget bbw, unsigned int width, unsigned int height,
- Dimension *reply_width, Dimension *reply_height, Bool position)
-{
- Boolean vbox = (bbw->box.orientation == XtorientVertical);
- Cardinal i;
- Dimension w, h; /* Width and height needed for box */
- Dimension lw, lh; /* Width and height needed for current line */
- Dimension bw, bh; /* Width and height needed for current widget */
- Dimension h_space; /* Local copy of bbw->box.h_space */
- Widget widget; /* Current widget */
- unsigned int num_mapped_children = 0;
-
- /* Box width and height */
- h_space = bbw->box.h_space;
-
- w = 0;
- for (i = 0; i < bbw->composite.num_children; i++) {
- if (XtIsManaged(bbw->composite.children[i])
- && bbw->composite.children[i]->core.width > w)
- w = bbw->composite.children[i]->core.width;
- }
- w += h_space;
- if (w > width)
- width = w;
- h = bbw->box.v_space;
-
- /* Line width and height */
- lh = 0;
- lw = h_space;
-
- for (i = 0; i < bbw->composite.num_children; i++) {
- widget = bbw->composite.children[i];
- if (widget->core.managed) {
- if (widget->core.mapped_when_managed)
- num_mapped_children++;
- /* Compute widget width */
- bw = XtWidth(widget) + (XtBorderWidth(widget)<<1) + h_space;
- if ((Dimension)(lw + bw) > width) {
- if (lw > h_space) {
- /* At least one widget on this line, and
- * can't fit any more. Start new line if vbox
- */
- AssignMax(w, lw);
- if (vbox) {
- h += lh + bbw->box.v_space;
- lh = 0;
- lw = h_space;
- }
- }
- else if (!position) {
- /* too narrow for this widget; we'll assume we can grow */
- DoLayout(bbw, (unsigned)(lw + bw), height, reply_width,
- reply_height, position);
- return;
- }
- }
- if (position && (lw != XtX(widget) || h != XtY(widget))) {
- /* It would be nice to use window gravity, but there isn't
- * sufficient fine-grain control to nicely handle all
- * situations (e.g. when only the height changes --
- * a common case). Explicit unmapping is a cheap hack
- * to speed things up & avoid the visual jitter as
- * things slide around.
- *
- * %%% perhaps there should be a client resource to
- * control this. If so, we'll have to optimize to
- * perform the moves from the correct end so we don't
- * force extra exposures as children occlude each other.
- */
- if (XtIsRealized(widget) && widget->core.mapped_when_managed)
- XUnmapWindow( XtDisplay(widget), XtWindow(widget));
- XtMoveWidget(widget, (int)lw, (int)h);
- }
- lw += bw;
- bh = XtHeight(widget) + (XtBorderWidth(widget) << 1);
- AssignMax(lh, bh);
- }
- }
-
- if (!vbox && width && lw > width && lh < height) {
- /* reduce width if too wide and height not filled */
- Dimension sw = lw, sh = lh;
- Dimension width_needed = width;
- XtOrientation orientation = bbw->box.orientation;
-
- bbw->box.orientation = XtorientVertical;
- while (sh < height && sw > width) {
- width_needed = sw;
- DoLayout(bbw, (unsigned)(sw-1), height, &sw, &sh, False);
- }
- if (sh < height)
- width_needed = sw;
- if (width_needed != lw) {
- DoLayout(bbw, width_needed, height,
- reply_width, reply_height, position);
- bbw->box.orientation = orientation;
- return;
- }
- bbw->box.orientation = orientation;
- }
- if (vbox && (width < w || width < lw)) {
- AssignMax(w, lw);
- DoLayout(bbw, w, height, reply_width, reply_height, position);
- return;
- }
- if (position && XtIsRealized((Widget)bbw)) {
- if (bbw->composite.num_children == num_mapped_children)
- XMapSubwindows(XtDisplay((Widget)bbw), XtWindow((Widget)bbw));
- else {
- int ii = bbw->composite.num_children;
- Widget *childP = bbw->composite.children;
-
- for (; ii > 0; childP++, ii--)
- if (XtIsRealized(*childP) && XtIsManaged(*childP)
- && (*childP)->core.mapped_when_managed)
- XtMapWidget(*childP);
- }
- }
-
- /* Finish off last line */
- if (lw > h_space) {
- AssignMax(w, lw);
- h += lh + bbw->box.v_space;
- }
-
- *reply_width = Max(w, 1);
- *reply_height = Max(h, 1);
-}
-
-/*
- * Calculate preferred size, given constraining box, caching it in the widget
- */
-static XtGeometryResult
-XawBoxQueryGeometry(Widget widget, XtWidgetGeometry *constraint,
- XtWidgetGeometry *preferred)
-{
- BoxWidget w = (BoxWidget)widget;
- Dimension width;
- Dimension preferred_width = w->box.preferred_width;
- Dimension preferred_height = w->box.preferred_height;
-
- constraint->request_mode &= CWWidth | CWHeight;
-
- if (constraint->request_mode == 0)
- /* parent isn't going to change w or h, so nothing to re-compute */
- return (XtGeometryYes);
-
- if (constraint->request_mode == w->box.last_query_mode
- && (!(constraint->request_mode & CWWidth)
- || constraint->width == w->box.last_query_width)
- && (!(constraint->request_mode & CWHeight)
- || constraint->height == w->box.last_query_height)) {
- /* same query; current preferences are still valid */
- preferred->request_mode = CWWidth | CWHeight;
- preferred->width = preferred_width;
- preferred->height = preferred_height;
- if (constraint->request_mode == (CWWidth | CWHeight)
- && constraint->width == preferred_width
- && constraint->height == preferred_height)
- return (XtGeometryYes);
- else
- return (XtGeometryAlmost);
- }
-
- /* else gotta do it the long way...
- I have a preference for tall and narrow, so if my width is
- constrained, I'll accept it; otherwise, I'll compute the minimum
- width that will fit me within the height constraint */
-
- w->box.last_query_mode = constraint->request_mode;
- w->box.last_query_width = constraint->width;
- w->box.last_query_height= constraint->height;
-
- if (constraint->request_mode & CWWidth)
- width = constraint->width;
- else { /* if (constraint->request_mode & CWHeight) */
- /* let's see if I can become any narrower */
- width = 0;
- constraint->width = 65535;
- }
-
- /* height is currently ignored by DoLayout.
- height = (constraint->request_mode & CWHeight) ? constraint->height
- : *preferred_height;
- */
- DoLayout(w, width, 0, &preferred_width, &preferred_height, False);
-
- if (constraint->request_mode & CWHeight
- && preferred_height > constraint->height) {
- /* find minimum width for this height */
- if (preferred_width <= constraint->width) {
- width = preferred_width;
- do { /* find some width big enough to stay within this height */
- width <<= 1;
- if (width > constraint->width)
- width = constraint->width;
- DoLayout(w, width, 0, &preferred_width, &preferred_height, False);
- } while (preferred_height > constraint->height
- && width < constraint->width);
- if (width != constraint->width) {
- do { /* find minimum width */
- width = preferred_width;
- DoLayout(w, (unsigned)(preferred_width - 1), 0,
- &preferred_width, &preferred_height, False);
- } while (preferred_height < constraint->height);
- /* one last time */
- DoLayout(w, width, 0, &preferred_width, &preferred_height, False);
- }
- }
- }
-
- preferred->request_mode = CWWidth | CWHeight;
- preferred->width = w->box.preferred_width = preferred_width;
- preferred->height = w->box.preferred_height = preferred_height;
-
- if (constraint->request_mode == (CWWidth|CWHeight)
- && constraint->width == preferred_width
- && constraint->height == preferred_height)
- return (XtGeometryYes);
-
- return (XtGeometryAlmost);
-}
-
-/*
- * Actually layout the box
- */
-static void
-XawBoxResize(Widget w)
-{
- Dimension tmp;
-
- DoLayout((BoxWidget)w, XtWidth(w), XtHeight(w), &tmp, &tmp, True);
-}
-
-/*
- * Try to do a new layout within the current width and height;
- * if that fails try to resize and do it within the box returne
- * by XawBoxQueryGeometry
- *
- * TryNewLayout just says if it's possible, and doesn't actually move the kids
- */
-static Bool
-TryNewLayout(BoxWidget bbw)
-{
- Dimension preferred_width, preferred_height;
- Dimension proposed_width, proposed_height;
- int iterations;
-
- DoLayout(bbw, bbw->core.width, bbw->core.height,
- &preferred_width, &preferred_height, False);
-
- /* at this point, preferred_width is guaranteed to not be greater
- than bbw->core.width unless some child is larger, so there's no
- point in re-computing another layout */
-
- if (XtWidth(bbw) == preferred_width && XtHeight(bbw) == preferred_height)
- return (True);
-
- /* let's see if our parent will go for a new size */
- iterations = 0;
- proposed_width = preferred_width;
- proposed_height = preferred_height;
- do {
- switch (XtMakeResizeRequest((Widget)bbw,proposed_width,proposed_height,
- &proposed_width, &proposed_height)) {
- case XtGeometryYes:
- return (True);
- case XtGeometryNo:
- if (iterations > 0)
- /* protect from malicious parents who change their minds */
- DoLayout(bbw, bbw->core.width, bbw->core.height,
- &preferred_width, &preferred_height, False);
- if (preferred_width <= XtWidth(bbw)
- && preferred_height <= XtHeight(bbw))
- return (True);
- else
- return (False);
- case XtGeometryAlmost:
- if (proposed_height >= preferred_height &&
- proposed_width >= preferred_width) {
- /*
- * Take it, and assume the parent knows what it is doing.
- *
- * The parent must accept this since it was returned in
- * almost.
- */
- (void)XtMakeResizeRequest((Widget)bbw,
- proposed_width, proposed_height,
- &proposed_width, &proposed_height);
- return (True);
- }
- else if (proposed_width != preferred_width) {
- /* recalc bounding box; height might change */
- DoLayout(bbw, proposed_width, 0,
- &preferred_width, &preferred_height, False);
- proposed_height = preferred_height;
- }
- else { /* proposed_height != preferred_height */
- XtWidgetGeometry constraints, reply;
-
- constraints.request_mode = CWHeight;
- constraints.height = proposed_height;
- (void)XawBoxQueryGeometry((Widget)bbw, &constraints, &reply);
- proposed_width = preferred_width;
- }
- /*FALLTHROUGH*/
- default:
- break;
- }
- iterations++;
- } while (iterations < 10);
-
- return (False);
-}
-
-/*
- * Geometry Manager
- *
- * 'reply' is unused; we say only yeay or nay, never almost.
- */
-/*ARGSUSED*/
-static XtGeometryResult
-XawBoxGeometryManager(Widget w, XtWidgetGeometry *request,
- XtWidgetGeometry *reply)
-{
- Dimension width, height, borderWidth;
- BoxWidget bbw;
-
- /* Position request always denied */
- if (((request->request_mode & CWX) && request->x != XtX(w))
- || ((request->request_mode & CWY) && request->y != XtY(w)))
- return (XtGeometryNo);
-
- /* Size changes must see if the new size can be accomodated */
- if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) {
- /* Make all three fields in the request valid */
- if ((request->request_mode & CWWidth) == 0)
- request->width = XtWidth(w);
- if ((request->request_mode & CWHeight) == 0)
- request->height = XtHeight(w);
- if ((request->request_mode & CWBorderWidth) == 0)
- request->border_width = XtBorderWidth(w);
-
- /* Save current size and set to new size */
- width = XtWidth(w);
- height = XtHeight(w);
- borderWidth = XtBorderWidth(w);
- XtWidth(w) = request->width;
- XtHeight(w) = request->height;
- XtBorderWidth(w) = request->border_width;
-
- /* Decide if new layout works:
- (1) new widget is smaller,
- (2) new widget fits in existing Box,
- (3) Box can be expanded to allow new widget to fit
- */
-
- bbw = (BoxWidget) w->core.parent;
-
- if (TryNewLayout(bbw)) {
- /* Fits in existing or new space, relayout */
- (*XtClass((Widget)bbw)->core_class.resize)((Widget)bbw);
- return (XtGeometryYes);
- }
- else {
- /* Cannot satisfy request, change back to original geometry */
- XtWidth(w) = width;
- XtHeight(w) = height;
- XtBorderWidth(w) = borderWidth;
- return (XtGeometryNo);
- }
- }
-
- /* Any stacking changes don't make a difference, so allow if that's all */
- return (XtGeometryYes);
-}
-
-static void
-XawBoxChangeManaged(Widget w)
-{
- /* Reconfigure the box */
- (void)TryNewLayout((BoxWidget)w);
- XawBoxResize(w);
-}
-
-static void
-XawBoxClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation,
- NULL, 0);
- XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-/*ARGSUSED*/
-static void
-XawBoxInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- BoxWidget newbbw = (BoxWidget)cnew;
-
- newbbw->box.last_query_mode = CWWidth | CWHeight;
- newbbw->box.last_query_width = newbbw->box.last_query_height = 0;
- newbbw->box.preferred_width = Max(newbbw->box.h_space, 1);
- newbbw->box.preferred_height = Max(newbbw->box.v_space, 1);
-
- if (XtWidth(newbbw) == 0)
- XtWidth(newbbw) = newbbw->box.preferred_width;
-
- if (XtHeight(newbbw) == 0)
- XtHeight(newbbw) = newbbw->box.preferred_height;
-}
-
-static void
-XawBoxRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
-{
-#ifndef OLDXAW
- XawPixmap *pixmap;
-#endif
-
- XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent,
- *valueMask, attributes);
-
-#ifndef OLDXAW
- if (w->core.background_pixmap > XtUnspecifiedPixmap) {
- pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
- w->core.colormap, w->core.depth);
- if (pixmap && pixmap->mask)
- XawReshapeWidget(w, pixmap);
- }
-#endif
-}
-
-/*ARGSUSED*/
-static Boolean
-XawBoxSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- /* need to relayout if h_space or v_space change */
-#ifndef OLDXAW
- BoxWidget b_old = (BoxWidget)current;
- BoxWidget b_new = (BoxWidget)cnew;
-
- if (b_old->core.background_pixmap != b_new->core.background_pixmap) {
- XawPixmap *opix, *npix;
-
- opix = XawPixmapFromXPixmap(b_old->core.background_pixmap,
- XtScreen(b_old), b_old->core.colormap,
- b_old->core.depth);
- npix = XawPixmapFromXPixmap(b_new->core.background_pixmap,
- XtScreen(b_new), b_new->core.colormap,
- b_new->core.depth);
- if ((npix && npix->mask) || (opix && opix->mask))
- XawReshapeWidget(cnew, npix);
- }
-#endif /* OLDXAW */
-
- return (False);
-}
-
-#ifndef OLDXAW
-static void
-XawBoxExpose(Widget w, XEvent *event, Region region)
-{
- BoxWidget xaw = (BoxWidget)w;
-
- if (xaw->box.display_list)
- XawRunDisplayList(w, xaw->box.display_list, event, region);
-}
-#endif /* OLDXAW */
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw/BoxP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * Class Methods + */ +static void XawBoxChangeManaged(Widget); +static void XawBoxClassInitialize(void); +#ifndef OLDXAW +static void XawBoxExpose(Widget, XEvent*, Region); +#endif +static XtGeometryResult XawBoxGeometryManager(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawBoxInitialize(Widget, Widget, ArgList, Cardinal*); +static XtGeometryResult XawBoxQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawBoxRealize(Widget, Mask*, XSetWindowAttributes*); +static void XawBoxResize(Widget); +static Boolean XawBoxSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void DoLayout(BoxWidget, unsigned int, unsigned int, + Dimension*, Dimension*, Bool); +static Bool TryNewLayout(BoxWidget); + +/* + * Initialization + */ +#ifndef OLDXAW +static XtActionsRec actions[] = { + {"set-values", XawSetValuesAction}, + {"get-values", XawGetValuesAction}, + {"declare", XawDeclareAction}, + {"call-proc", XawCallProcAction}, +}; +#endif + +static XtResource resources[] = { + { + XtNhSpace, + XtCHSpace, + XtRDimension, + sizeof(Dimension), + XtOffsetOf(BoxRec, box.h_space), + XtRImmediate, + (XtPointer)4 + }, + { + XtNvSpace, + XtCVSpace, + XtRDimension, + sizeof(Dimension), + XtOffsetOf(BoxRec, box.v_space), + XtRImmediate, + (XtPointer)4 + }, + { + XtNorientation, + XtCOrientation, + XtROrientation, + sizeof(XtOrientation), + XtOffsetOf(BoxRec, box.orientation), + XtRImmediate, + (XtPointer)XtorientVertical + }, +#ifndef OLDXAW + { + XawNdisplayList, + XawCDisplayList, + XawRDisplayList, + sizeof(XawDisplayList*), + XtOffsetOf(BoxRec, box.display_list), + XtRImmediate, + NULL + }, +#endif +}; + +BoxClassRec boxClassRec = { + /* core */ + { + (WidgetClass)&compositeClassRec, /* superclass */ + "Box", /* class_name */ + sizeof(BoxRec), /* widget_size */ + XawBoxClassInitialize, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + XawBoxInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawBoxRealize, /* realize */ +#ifndef OLDXAW + actions, /* actions */ + XtNumber(actions), /* num_actions */ +#else + NULL, /* actions */ + 0, /* num_actions */ +#endif + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XawBoxResize, /* resize */ +#ifndef OLDXAW + XawBoxExpose, /* expose */ +#else + NULL, /* expose */ +#endif + XawBoxSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XawBoxQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* composite */ + { + XawBoxGeometryManager, /* geometry_manager */ + XawBoxChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + /* box */ + { + NULL, /* extension */ + }, +}; + +WidgetClass boxWidgetClass = (WidgetClass)&boxClassRec; + +/* + * Do a layout, either actually assigning positions, or just calculating size. + * Returns minimum width and height that will preserve the same layout. + */ +static void +DoLayout(BoxWidget bbw, unsigned int width, unsigned int height, + Dimension *reply_width, Dimension *reply_height, Bool position) +{ + Boolean vbox = (bbw->box.orientation == XtorientVertical); + Cardinal i; + Dimension w, h; /* Width and height needed for box */ + Dimension lw, lh; /* Width and height needed for current line */ + Dimension bw, bh; /* Width and height needed for current widget */ + Dimension h_space; /* Local copy of bbw->box.h_space */ + Widget widget; /* Current widget */ + unsigned int num_mapped_children = 0; + + /* Box width and height */ + h_space = bbw->box.h_space; + + w = 0; + for (i = 0; i < bbw->composite.num_children; i++) { + if (XtIsManaged(bbw->composite.children[i]) + && bbw->composite.children[i]->core.width > w) + w = bbw->composite.children[i]->core.width; + } + w += h_space; + if (w > width) + width = w; + h = bbw->box.v_space; + + /* Line width and height */ + lh = 0; + lw = h_space; + + for (i = 0; i < bbw->composite.num_children; i++) { + widget = bbw->composite.children[i]; + if (widget->core.managed) { + if (widget->core.mapped_when_managed) + num_mapped_children++; + /* Compute widget width */ + bw = XtWidth(widget) + (XtBorderWidth(widget)<<1) + h_space; + if ((Dimension)(lw + bw) > width) { + if (lw > h_space) { + /* At least one widget on this line, and + * can't fit any more. Start new line if vbox + */ + AssignMax(w, lw); + if (vbox) { + h += lh + bbw->box.v_space; + lh = 0; + lw = h_space; + } + } + else if (!position) { + /* too narrow for this widget; we'll assume we can grow */ + DoLayout(bbw, (unsigned)(lw + bw), height, reply_width, + reply_height, position); + return; + } + } + if (position && (lw != XtX(widget) || h != XtY(widget))) { + /* It would be nice to use window gravity, but there isn't + * sufficient fine-grain control to nicely handle all + * situations (e.g. when only the height changes -- + * a common case). Explicit unmapping is a cheap hack + * to speed things up & avoid the visual jitter as + * things slide around. + * + * %%% perhaps there should be a client resource to + * control this. If so, we'll have to optimize to + * perform the moves from the correct end so we don't + * force extra exposures as children occlude each other. + */ + if (XtIsRealized(widget) && widget->core.mapped_when_managed) + XUnmapWindow( XtDisplay(widget), XtWindow(widget)); + XtMoveWidget(widget, (int)lw, (int)h); + } + lw += bw; + bh = XtHeight(widget) + (XtBorderWidth(widget) << 1); + AssignMax(lh, bh); + } + } + + if (!vbox && width && lw > width && lh < height) { + /* reduce width if too wide and height not filled */ + Dimension sw = lw, sh = lh; + Dimension width_needed = width; + XtOrientation orientation = bbw->box.orientation; + + bbw->box.orientation = XtorientVertical; + while (sh < height && sw > width) { + width_needed = sw; + DoLayout(bbw, (unsigned)(sw-1), height, &sw, &sh, False); + } + if (sh < height) + width_needed = sw; + if (width_needed != lw) { + DoLayout(bbw, width_needed, height, + reply_width, reply_height, position); + bbw->box.orientation = orientation; + return; + } + bbw->box.orientation = orientation; + } + if (vbox && (width < w || width < lw)) { + AssignMax(w, lw); + DoLayout(bbw, w, height, reply_width, reply_height, position); + return; + } + if (position && XtIsRealized((Widget)bbw)) { + if (bbw->composite.num_children == num_mapped_children) + XMapSubwindows(XtDisplay((Widget)bbw), XtWindow((Widget)bbw)); + else { + int ii = bbw->composite.num_children; + Widget *childP = bbw->composite.children; + + for (; ii > 0; childP++, ii--) + if (XtIsRealized(*childP) && XtIsManaged(*childP) + && (*childP)->core.mapped_when_managed) + XtMapWidget(*childP); + } + } + + /* Finish off last line */ + if (lw > h_space) { + AssignMax(w, lw); + h += lh + bbw->box.v_space; + } + + *reply_width = Max(w, 1); + *reply_height = Max(h, 1); +} + +/* + * Calculate preferred size, given constraining box, caching it in the widget + */ +static XtGeometryResult +XawBoxQueryGeometry(Widget widget, XtWidgetGeometry *constraint, + XtWidgetGeometry *preferred) +{ + BoxWidget w = (BoxWidget)widget; + Dimension width; + Dimension preferred_width = w->box.preferred_width; + Dimension preferred_height = w->box.preferred_height; + + constraint->request_mode &= CWWidth | CWHeight; + + if (constraint->request_mode == 0) + /* parent isn't going to change w or h, so nothing to re-compute */ + return (XtGeometryYes); + + if (constraint->request_mode == w->box.last_query_mode + && (!(constraint->request_mode & CWWidth) + || constraint->width == w->box.last_query_width) + && (!(constraint->request_mode & CWHeight) + || constraint->height == w->box.last_query_height)) { + /* same query; current preferences are still valid */ + preferred->request_mode = CWWidth | CWHeight; + preferred->width = preferred_width; + preferred->height = preferred_height; + if (constraint->request_mode == (CWWidth | CWHeight) + && constraint->width == preferred_width + && constraint->height == preferred_height) + return (XtGeometryYes); + else + return (XtGeometryAlmost); + } + + /* else gotta do it the long way... + I have a preference for tall and narrow, so if my width is + constrained, I'll accept it; otherwise, I'll compute the minimum + width that will fit me within the height constraint */ + + w->box.last_query_mode = constraint->request_mode; + w->box.last_query_width = constraint->width; + w->box.last_query_height= constraint->height; + + if (constraint->request_mode & CWWidth) + width = constraint->width; + else { /* if (constraint->request_mode & CWHeight) */ + /* let's see if I can become any narrower */ + width = 0; + constraint->width = 65535; + } + + /* height is currently ignored by DoLayout. + height = (constraint->request_mode & CWHeight) ? constraint->height + : *preferred_height; + */ + DoLayout(w, width, 0, &preferred_width, &preferred_height, False); + + if (constraint->request_mode & CWHeight + && preferred_height > constraint->height) { + /* find minimum width for this height */ + if (preferred_width <= constraint->width) { + width = preferred_width; + do { /* find some width big enough to stay within this height */ + width <<= 1; + if (width > constraint->width) + width = constraint->width; + DoLayout(w, width, 0, &preferred_width, &preferred_height, False); + } while (preferred_height > constraint->height + && width < constraint->width); + if (width != constraint->width) { + do { /* find minimum width */ + width = preferred_width; + DoLayout(w, (unsigned)(preferred_width - 1), 0, + &preferred_width, &preferred_height, False); + } while (preferred_height < constraint->height); + /* one last time */ + DoLayout(w, width, 0, &preferred_width, &preferred_height, False); + } + } + } + + preferred->request_mode = CWWidth | CWHeight; + preferred->width = w->box.preferred_width = preferred_width; + preferred->height = w->box.preferred_height = preferred_height; + + if (constraint->request_mode == (CWWidth|CWHeight) + && constraint->width == preferred_width + && constraint->height == preferred_height) + return (XtGeometryYes); + + return (XtGeometryAlmost); +} + +/* + * Actually layout the box + */ +static void +XawBoxResize(Widget w) +{ + Dimension tmp; + + DoLayout((BoxWidget)w, XtWidth(w), XtHeight(w), &tmp, &tmp, True); +} + +/* + * Try to do a new layout within the current width and height; + * if that fails try to resize and do it within the box returne + * by XawBoxQueryGeometry + * + * TryNewLayout just says if it's possible, and doesn't actually move the kids + */ +static Bool +TryNewLayout(BoxWidget bbw) +{ + Dimension preferred_width, preferred_height; + Dimension proposed_width, proposed_height; + int iterations; + + DoLayout(bbw, bbw->core.width, bbw->core.height, + &preferred_width, &preferred_height, False); + + /* at this point, preferred_width is guaranteed to not be greater + than bbw->core.width unless some child is larger, so there's no + point in re-computing another layout */ + + if (XtWidth(bbw) == preferred_width && XtHeight(bbw) == preferred_height) + return (True); + + /* let's see if our parent will go for a new size */ + iterations = 0; + proposed_width = preferred_width; + proposed_height = preferred_height; + do { + switch (XtMakeResizeRequest((Widget)bbw,proposed_width,proposed_height, + &proposed_width, &proposed_height)) { + case XtGeometryYes: + return (True); + case XtGeometryNo: + if (iterations > 0) + /* protect from malicious parents who change their minds */ + DoLayout(bbw, bbw->core.width, bbw->core.height, + &preferred_width, &preferred_height, False); + if (preferred_width <= XtWidth(bbw) + && preferred_height <= XtHeight(bbw)) + return (True); + else + return (False); + case XtGeometryAlmost: + if (proposed_height >= preferred_height && + proposed_width >= preferred_width) { + /* + * Take it, and assume the parent knows what it is doing. + * + * The parent must accept this since it was returned in + * almost. + */ + (void)XtMakeResizeRequest((Widget)bbw, + proposed_width, proposed_height, + &proposed_width, &proposed_height); + return (True); + } + else if (proposed_width != preferred_width) { + /* recalc bounding box; height might change */ + DoLayout(bbw, proposed_width, 0, + &preferred_width, &preferred_height, False); + proposed_height = preferred_height; + } + else { /* proposed_height != preferred_height */ + XtWidgetGeometry constraints, reply; + + constraints.request_mode = CWHeight; + constraints.height = proposed_height; + (void)XawBoxQueryGeometry((Widget)bbw, &constraints, &reply); + proposed_width = preferred_width; + } + /*FALLTHROUGH*/ + default: + break; + } + iterations++; + } while (iterations < 10); + + return (False); +} + +/* + * Geometry Manager + * + * 'reply' is unused; we say only yeay or nay, never almost. + */ +/*ARGSUSED*/ +static XtGeometryResult +XawBoxGeometryManager(Widget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + Dimension width, height, borderWidth; + BoxWidget bbw; + + /* Position request always denied */ + if (((request->request_mode & CWX) && request->x != XtX(w)) + || ((request->request_mode & CWY) && request->y != XtY(w))) + return (XtGeometryNo); + + /* Size changes must see if the new size can be accomodated */ + if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) { + /* Make all three fields in the request valid */ + if ((request->request_mode & CWWidth) == 0) + request->width = XtWidth(w); + if ((request->request_mode & CWHeight) == 0) + request->height = XtHeight(w); + if ((request->request_mode & CWBorderWidth) == 0) + request->border_width = XtBorderWidth(w); + + /* Save current size and set to new size */ + width = XtWidth(w); + height = XtHeight(w); + borderWidth = XtBorderWidth(w); + XtWidth(w) = request->width; + XtHeight(w) = request->height; + XtBorderWidth(w) = request->border_width; + + /* Decide if new layout works: + (1) new widget is smaller, + (2) new widget fits in existing Box, + (3) Box can be expanded to allow new widget to fit + */ + + bbw = (BoxWidget) w->core.parent; + + if (TryNewLayout(bbw)) { + /* Fits in existing or new space, relayout */ + (*XtClass((Widget)bbw)->core_class.resize)((Widget)bbw); + return (XtGeometryYes); + } + else { + /* Cannot satisfy request, change back to original geometry */ + XtWidth(w) = width; + XtHeight(w) = height; + XtBorderWidth(w) = borderWidth; + return (XtGeometryNo); + } + } + + /* Any stacking changes don't make a difference, so allow if that's all */ + return (XtGeometryYes); +} + +static void +XawBoxChangeManaged(Widget w) +{ + /* Reconfigure the box */ + (void)TryNewLayout((BoxWidget)w); + XawBoxResize(w); +} + +static void +XawBoxClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation, + NULL, 0); + XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString, + NULL, 0, XtCacheNone, NULL); +} + +/*ARGSUSED*/ +static void +XawBoxInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + BoxWidget newbbw = (BoxWidget)cnew; + + newbbw->box.last_query_mode = CWWidth | CWHeight; + newbbw->box.last_query_width = newbbw->box.last_query_height = 0; + newbbw->box.preferred_width = Max(newbbw->box.h_space, 1); + newbbw->box.preferred_height = Max(newbbw->box.v_space, 1); + + if (XtWidth(newbbw) == 0) + XtWidth(newbbw) = newbbw->box.preferred_width; + + if (XtHeight(newbbw) == 0) + XtHeight(newbbw) = newbbw->box.preferred_height; +} + +static void +XawBoxRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) +{ +#ifndef OLDXAW + XawPixmap *pixmap; +#endif + + XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent, + *valueMask, attributes); + +#ifndef OLDXAW + if (w->core.background_pixmap > XtUnspecifiedPixmap) { + pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w), + w->core.colormap, w->core.depth); + if (pixmap && pixmap->mask) + XawReshapeWidget(w, pixmap); + } +#endif +} + +/*ARGSUSED*/ +static Boolean +XawBoxSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + /* need to relayout if h_space or v_space change */ +#ifndef OLDXAW + BoxWidget b_old = (BoxWidget)current; + BoxWidget b_new = (BoxWidget)cnew; + + if (b_old->core.background_pixmap != b_new->core.background_pixmap) { + XawPixmap *opix, *npix; + + opix = XawPixmapFromXPixmap(b_old->core.background_pixmap, + XtScreen(b_old), b_old->core.colormap, + b_old->core.depth); + npix = XawPixmapFromXPixmap(b_new->core.background_pixmap, + XtScreen(b_new), b_new->core.colormap, + b_new->core.depth); + if ((npix && npix->mask) || (opix && opix->mask)) + XawReshapeWidget(cnew, npix); + } +#endif /* OLDXAW */ + + return (False); +} + +#ifndef OLDXAW +static void +XawBoxExpose(Widget w, XEvent *event, Region region) +{ + BoxWidget xaw = (BoxWidget)w; + + if (xaw->box.display_list) + XawRunDisplayList(w, xaw->box.display_list, event, region); +} +#endif /* OLDXAW */ diff --git a/libXaw/src/Command.c b/libXaw/src/Command.c index 268fc19a7..9ad1f15fa 100644 --- a/libXaw/src/Command.c +++ b/libXaw/src/Command.c @@ -1,657 +1,657 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
- * Command.c - Command button widget
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/extensions/shape.h>
-#include <X11/Xmu/Converters.h>
-#include <X11/Xmu/Drawing.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xaw/CommandP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#define DEFAULT_HIGHLIGHT_THICKNESS 2
-#define DEFAULT_SHAPE_HIGHLIGHT 32767
-#define STR_EQUAL(str1, str2) (str1 == str2 || strcmp(str1, str2) == 0)
-
-/*
- * Class Methods
- */
-static void XawCommandClassInitialize(void);
-static void XawCommandDestroy(Widget);
-static void XawCommandInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawCommandRealize(Widget, Mask*, XSetWindowAttributes*);
-static void XawCommandResize(Widget);
-static void XawCommandRedisplay(Widget, XEvent*, Region);
-static Boolean XawCommandSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-static void XawCommandGetValuesHook(Widget, ArgList, Cardinal*);
-static Bool ChangeSensitive(Widget);
-
-/*
- * Prototypes
- */
-static GC Get_GC(CommandWidget, Pixel, Pixel);
-static void PaintCommandWidget(Widget, XEvent*, Region, Bool);
-static Region HighlightRegion(CommandWidget);
-static Bool ShapeButton(CommandWidget, Bool);
-static void XawCommandToggle(Widget);
-
-/*
- * Actions
- */
-static void Highlight(Widget, XEvent*, String*, Cardinal*);
-static void Notify(Widget, XEvent*, String*, Cardinal*);
-static void Reset(Widget, XEvent*, String*, Cardinal*);
-static void Set(Widget, XEvent*, String*, Cardinal*);
-static void Unhighlight(Widget, XEvent*, String*, Cardinal*);
-static void Unset(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * Initialization
- */
-static char defaultTranslations[] =
-"<Enter>:" "highlight()\n"
-"<Leave>:" "reset()\n"
-"<Btn1Down>:" "set()\n"
-"<Btn1Up>:" "notify() unset()\n"
-;
-
-#define offset(field) XtOffsetOf(CommandRec, field)
-static XtResource resources[] = {
- {
- XtNcallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(command.callbacks),
- XtRCallback,
- NULL
- },
- {
- XtNhighlightThickness,
- XtCThickness,
- XtRDimension,
- sizeof(Dimension),
- offset(command.highlight_thickness),
- XtRImmediate,
- (XtPointer)DEFAULT_SHAPE_HIGHLIGHT
- },
- {
- XtNshapeStyle,
- XtCShapeStyle,
- XtRShapeStyle,
- sizeof(int),
- offset(command.shape_style),
- XtRImmediate,
- (XtPointer)XawShapeRectangle
- },
- {
- XtNcornerRoundPercent,
- XtCCornerRoundPercent,
- XtRDimension,
- sizeof(Dimension),
- offset(command.corner_round),
- XtRImmediate,
- (XtPointer)25
- },
-};
-#undef offset
-
-static XtActionsRec actionsList[] = {
- {"set", Set},
- {"notify", Notify},
- {"highlight", Highlight},
- {"reset", Reset},
- {"unset", Unset},
- {"unhighlight", Unhighlight}
-};
-
-#define SuperClass ((LabelWidgetClass)&labelClassRec)
-
-CommandClassRec commandClassRec = {
- /* core */
- {
- (WidgetClass)SuperClass, /* superclass */
- "Command", /* class_name */
- sizeof(CommandRec), /* size */
- XawCommandClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawCommandInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawCommandRealize, /* realize */
- actionsList, /* actions */
- XtNumber(actionsList), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawCommandDestroy, /* destroy */
- XawCommandResize, /* resize */
- XawCommandRedisplay, /* expose */
- XawCommandSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- XawCommandGetValuesHook, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- defaultTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- ChangeSensitive, /* change_sensitive */
- },
- /* label */
- {
- NULL, /* not used */
- },
- /* command */
- {
- NULL, /* not used */
- },
-};
-
-WidgetClass commandWidgetClass = (WidgetClass)&commandClassRec;
-
-/*
- * Implementation
- */
-static GC
-Get_GC(CommandWidget cbw, Pixel fg, Pixel bg)
-{
- XGCValues values;
-
- values.foreground = fg;
- values.background = bg;
- values.font = cbw->label.font->fid;
- values.cap_style = CapProjecting;
-
- if (cbw->command.highlight_thickness > 1)
- values.line_width = cbw->command.highlight_thickness;
- else
- values.line_width = 0;
-
- if (cbw->simple.international == True)
- return (XtAllocateGC((Widget)cbw, 0,
- GCForeground | GCBackground | GCLineWidth |
- GCCapStyle, &values, GCFont, 0));
- else
- return (XtGetGC((Widget)cbw,
- GCForeground | GCBackground | GCFont | GCLineWidth |
- GCCapStyle, &values));
-}
-
-/*ARGSUSED*/
-static void
-XawCommandInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- CommandWidget cbw = (CommandWidget)cnew;
- int shape_event_base, shape_error_base;
-
- if (!cbw->label.font) XtError("Aborting: no font found\n");
-
- if (cbw->command.shape_style != XawShapeRectangle &&
- !XShapeQueryExtension(XtDisplay(cnew), &shape_event_base,
- &shape_error_base))
- cbw->command.shape_style = XawShapeRectangle;
-
- if (cbw->command.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) {
- if (cbw->command.shape_style != XawShapeRectangle)
- cbw->command.highlight_thickness = 0;
- else
- cbw->command.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS;
- }
-
- cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground,
- cbw->core.background_pixel);
- cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel,
- cbw->label.foreground);
- XtReleaseGC(cnew, cbw->label.normal_GC);
- cbw->label.normal_GC = cbw->command.normal_GC;
-
- cbw->command.set = False;
- cbw->command.highlighted = HighlightNone;
-}
-
-static Region
-HighlightRegion(CommandWidget cbw)
-{
- static Region outerRegion = NULL, innerRegion, emptyRegion;
- XRectangle rect;
-
- if (cbw->command.highlight_thickness == 0 ||
- cbw->command.highlight_thickness > Min(XtWidth(cbw), XtHeight(cbw)) / 2)
- return (NULL);
-
- if (outerRegion == NULL) {
- /* save time by allocating scratch regions only once. */
- outerRegion = XCreateRegion();
- innerRegion = XCreateRegion();
- emptyRegion = XCreateRegion();
- }
-
- rect.x = rect.y = 0;
- rect.width = XtWidth(cbw);
- rect.height = XtHeight(cbw);
- XUnionRectWithRegion(&rect, emptyRegion, outerRegion);
- rect.x = rect.y = cbw->command.highlight_thickness;
- rect.width -= cbw->command.highlight_thickness * 2;
- rect.height -= cbw->command.highlight_thickness * 2;
- XUnionRectWithRegion(&rect, emptyRegion, innerRegion);
- XSubtractRegion(outerRegion, innerRegion, outerRegion);
-
- return (outerRegion);
-}
-
-/***************************
-* Action Procedures
-***************************/
-static void
-XawCommandToggle(Widget w)
-{
- CommandWidget xaw = (CommandWidget)w;
- Arg args[2];
- Cardinal num_args;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNbackground,
- xaw->label.foreground); ++num_args;
- XtSetArg(args[num_args], XtNforeground,
- xaw->core.background_pixel); ++num_args;
- XtSetValues(w, args, num_args);
-}
-
-/*ARGSUSED*/
-static void
-Set(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CommandWidget cbw = (CommandWidget)w;
-
- if (cbw->command.set)
- return;
-
- XawCommandToggle(w);
- cbw->command.set= True;
-}
-
-/*ARGSUSED*/
-static void
-Unset(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CommandWidget cbw = (CommandWidget)w;
-
- if (!cbw->command.set)
- return;
-
- cbw->command.set = False;
- XawCommandToggle(w);
-}
-
-/*ARGSUSED*/
-static void
-Reset(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CommandWidget cbw = (CommandWidget)w;
-
- if (cbw->command.set) {
- cbw->command.highlighted = HighlightNone;
- Unset(w, event, params, num_params);
- }
- else
- Unhighlight(w, event, params, num_params);
-}
-
-/*ARGSUSED*/
-static void
-Highlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CommandWidget cbw = (CommandWidget)w;
-
- if (*num_params == (Cardinal)0)
- cbw->command.highlighted = HighlightWhenUnset;
- else {
- if (*num_params != (Cardinal)1)
- XtWarning("Too many parameters passed to highlight action table.");
- switch (params[0][0]) {
- case 'A':
- case 'a':
- cbw->command.highlighted = HighlightAlways;
- break;
- default:
- cbw->command.highlighted = HighlightWhenUnset;
- break;
- }
- }
-
- if (XtIsRealized(w))
- PaintCommandWidget(w, event, HighlightRegion(cbw), True);
-}
-
-/*ARGSUSED*/
-static void
-Unhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CommandWidget cbw = (CommandWidget)w;
-
- cbw->command.highlighted = HighlightNone;
- if (XtIsRealized(w))
- PaintCommandWidget(w, event, HighlightRegion(cbw), True);
-}
-
-/*ARGSUSED*/
-static void
-Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CommandWidget cbw = (CommandWidget)w;
-
- /* check to be sure state is still Set so that user can cancel
- the action (e.g. by moving outside the window, in the default
- bindings.
- */
- if (cbw->command.set)
- XtCallCallbackList(w, cbw->command.callbacks, (XtPointer) NULL);
-}
-
-static void
-XawCommandRedisplay(Widget w, XEvent *event, Region region)
-{
- PaintCommandWidget(w, event, region, False);
-}
-
-/*
- * Function:
- * PaintCommandWidget
- * Parameters:
- * w - command widget
- * region - region to paint (passed to the superclass)
- * change - did it change either set or highlight state?
- */
-static void
-PaintCommandWidget(Widget w, XEvent *event, Region region, Bool change)
-{
- CommandWidget cbw = (CommandWidget)w;
- Bool very_thick;
- GC rev_gc;
-
- very_thick = cbw->command.highlight_thickness
- > Min(XtWidth(cbw), XtHeight(cbw)) / 2;
-
- if (cbw->command.highlight_thickness == 0) {
- (*SuperClass->core_class.expose) (w, event, region);
- return;
- }
-
- /*
- * If we are set then use the same colors as if we are not highlighted
- */
-
- if (cbw->command.highlighted != HighlightNone) {
- rev_gc = cbw->command.normal_GC;
- }
- else {
- rev_gc = cbw->command.inverse_GC;
- }
-
- if (!((!change && cbw->command.highlighted == HighlightNone)
- || (cbw->command.highlighted == HighlightWhenUnset
- && cbw->command.set))) {
- if (very_thick)
- XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc,
- 0, 0, XtWidth(cbw), XtHeight(cbw));
- else {
- /* wide lines are centered on the path, so indent it */
- if (cbw->core.background_pixmap != XtUnspecifiedPixmap &&
- rev_gc == cbw->command.inverse_GC) {
- XClearArea(XtDisplay(w), XtWindow(w),
- 0, 0, XtWidth(cbw), cbw->command.highlight_thickness,
- False);
- XClearArea(XtDisplay(w), XtWindow(w),
- 0, cbw->command.highlight_thickness,
- cbw->command.highlight_thickness,
- XtHeight(cbw) - (cbw->command.highlight_thickness<<1),
- False);
- XClearArea(XtDisplay(w), XtWindow(w),
- XtWidth(cbw) - cbw->command.highlight_thickness,
- cbw->command.highlight_thickness,
- cbw->command.highlight_thickness,
- XtHeight(cbw) - (cbw->command.highlight_thickness<<1),
- False);
- XClearArea(XtDisplay(w), XtWindow(w),
- 0, XtHeight(cbw) - cbw->command.highlight_thickness,
- XtWidth(cbw), cbw->command.highlight_thickness,
- False);
- }
- else {
- int offset = cbw->command.highlight_thickness / 2;
-
- XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset,
- XtWidth(cbw) - cbw->command.highlight_thickness,
- XtHeight(cbw) - cbw->command.highlight_thickness);
- }
- }
- }
-
- (*SuperClass->core_class.expose)(w, event, region);
-}
-
-static void
-XawCommandDestroy(Widget w)
-{
- CommandWidget cbw = (CommandWidget)w;
-
- /* Label will release cbw->command.normal_GC */
- XtReleaseGC(w, cbw->command.inverse_GC);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawCommandSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- CommandWidget oldcbw = (CommandWidget)current;
- CommandWidget cbw = (CommandWidget)cnew;
- Boolean redisplay = False;
-
- if (oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) {
- cbw->command.highlighted = HighlightNone;
- redisplay = True;
- }
-
- if (cbw->command.set) {
- unsigned int i;
- Pixel foreground, background;
-
- foreground = oldcbw->label.foreground;
- background = oldcbw->core.background_pixel;
- for (i = 0; i < *num_args; i++) {
- if (STR_EQUAL(args[i].name, XtNforeground))
- background = cbw->label.foreground;
- else if (STR_EQUAL(args[i].name, XtNbackground))
- foreground = cbw->core.background_pixel;
- }
- cbw->label.foreground = foreground;
- cbw->core.background_pixel = background;
- }
-
- if (oldcbw->label.foreground != cbw->label.foreground
- || oldcbw->core.background_pixel != cbw->core.background_pixel
- || oldcbw->command.highlight_thickness
- != cbw->command.highlight_thickness
- || oldcbw->label.font != cbw->label.font) {
- XtReleaseGC(cnew, cbw->command.inverse_GC);
-
- cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground,
- cbw->core.background_pixel);
- cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel,
- cbw->label.foreground);
- XtReleaseGC(cnew, cbw->label.normal_GC);
- cbw->label.normal_GC = cbw->command.normal_GC;
-
- redisplay = True;
- }
-
- if (XtIsRealized(cnew)
- && oldcbw->command.shape_style != cbw->command.shape_style
- && !ShapeButton(cbw, True))
- cbw->command.shape_style = oldcbw->command.shape_style;
-
- return (redisplay);
-}
-
-static void
-XawCommandGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
-{
- CommandWidget cbw = (CommandWidget)w;
- unsigned int i;
-
- for (i = 0; i < *num_args; i++) {
- if (STR_EQUAL(args[i].name, XtNforeground))
- *((String*)args[i].value) = cbw->command.set ?
- (String)cbw->core.background_pixel : (String)cbw->label.foreground;
- else if (STR_EQUAL(args[i].name, XtNbackground))
- *((String*)args[i].value) = cbw->command.set ?
- (String)cbw->label.foreground : (String)cbw->core.background_pixel;
- }
-}
-
-static void
-XawCommandClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtSetTypeConverter(XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRShapeStyle, XtRString, XmuCvtShapeStyleToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-static Bool
-ShapeButton(CommandWidget cbw, Bool checkRectangular)
-{
- Dimension corner_size = 0;
-
- if (cbw->command.shape_style == XawShapeRoundedRectangle) {
- corner_size = XtWidth(cbw) < XtHeight(cbw) ?
- XtWidth(cbw) : XtHeight(cbw);
- corner_size = (corner_size * cbw->command.corner_round) / 100;
- }
-
- if (checkRectangular || cbw->command.shape_style != XawShapeRectangle) {
- if (!XmuReshapeWidget((Widget)cbw, cbw->command.shape_style,
- corner_size, corner_size)) {
- cbw->command.shape_style = XawShapeRectangle;
- return (False);
- }
- }
-
- return (True);
-}
-
-static void
-XawCommandRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
-{
- (*commandWidgetClass->core_class.superclass->core_class.realize)
- (w, valueMask, attributes);
-
- ShapeButton((CommandWidget)w, False);
-}
-
-static void
-XawCommandResize(Widget w)
-{
- if (XtIsRealized(w))
- ShapeButton((CommandWidget)w, False);
-
- (*commandWidgetClass->core_class.superclass->core_class.resize)(w);
-}
-
-static Bool
-ChangeSensitive(Widget w)
-{
- CommandWidget cbw = (CommandWidget)w;
-
- if (XtIsRealized(w)) {
- if (XtIsSensitive(w)) {
- if (w->core.border_pixmap != XtUnspecifiedPixmap)
- XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
- w->core.border_pixmap);
- else
- XSetWindowBorder(XtDisplay(w), XtWindow(w),
- w->core.border_pixel);
- }
- else {
- if (cbw->simple.insensitive_border == None)
- cbw->simple.insensitive_border =
- XmuCreateStippledPixmap(XtScreen(w),
- w->core.border_pixel,
- cbw->command.set ?
- cbw->label.foreground :
- w->core.background_pixel,
- w->core.depth);
- XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
- cbw->simple.insensitive_border);
- }
- }
-
- return (False);
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Command.c - Command button widget + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/extensions/shape.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw/CommandP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define DEFAULT_HIGHLIGHT_THICKNESS 2 +#define DEFAULT_SHAPE_HIGHLIGHT 32767 +#define STR_EQUAL(str1, str2) (str1 == str2 || strcmp(str1, str2) == 0) + +/* + * Class Methods + */ +static void XawCommandClassInitialize(void); +static void XawCommandDestroy(Widget); +static void XawCommandInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawCommandRealize(Widget, Mask*, XSetWindowAttributes*); +static void XawCommandResize(Widget); +static void XawCommandRedisplay(Widget, XEvent*, Region); +static Boolean XawCommandSetValues(Widget, Widget, Widget, ArgList, Cardinal*); +static void XawCommandGetValuesHook(Widget, ArgList, Cardinal*); +static Bool ChangeSensitive(Widget); + +/* + * Prototypes + */ +static GC Get_GC(CommandWidget, Pixel, Pixel); +static void PaintCommandWidget(Widget, XEvent*, Region, Bool); +static Region HighlightRegion(CommandWidget); +static Bool ShapeButton(CommandWidget, Bool); +static void XawCommandToggle(Widget); + +/* + * Actions + */ +static void Highlight(Widget, XEvent*, String*, Cardinal*); +static void Notify(Widget, XEvent*, String*, Cardinal*); +static void Reset(Widget, XEvent*, String*, Cardinal*); +static void Set(Widget, XEvent*, String*, Cardinal*); +static void Unhighlight(Widget, XEvent*, String*, Cardinal*); +static void Unset(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +static char defaultTranslations[] = +"<Enter>:" "highlight()\n" +"<Leave>:" "reset()\n" +"<Btn1Down>:" "set()\n" +"<Btn1Up>:" "notify() unset()\n" +; + +#define offset(field) XtOffsetOf(CommandRec, field) +static XtResource resources[] = { + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(command.callbacks), + XtRCallback, + NULL + }, + { + XtNhighlightThickness, + XtCThickness, + XtRDimension, + sizeof(Dimension), + offset(command.highlight_thickness), + XtRImmediate, + (XtPointer)DEFAULT_SHAPE_HIGHLIGHT + }, + { + XtNshapeStyle, + XtCShapeStyle, + XtRShapeStyle, + sizeof(int), + offset(command.shape_style), + XtRImmediate, + (XtPointer)XawShapeRectangle + }, + { + XtNcornerRoundPercent, + XtCCornerRoundPercent, + XtRDimension, + sizeof(Dimension), + offset(command.corner_round), + XtRImmediate, + (XtPointer)25 + }, +}; +#undef offset + +static XtActionsRec actionsList[] = { + {"set", Set}, + {"notify", Notify}, + {"highlight", Highlight}, + {"reset", Reset}, + {"unset", Unset}, + {"unhighlight", Unhighlight} +}; + +#define SuperClass ((LabelWidgetClass)&labelClassRec) + +CommandClassRec commandClassRec = { + /* core */ + { + (WidgetClass)SuperClass, /* superclass */ + "Command", /* class_name */ + sizeof(CommandRec), /* size */ + XawCommandClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawCommandInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawCommandRealize, /* realize */ + actionsList, /* actions */ + XtNumber(actionsList), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawCommandDestroy, /* destroy */ + XawCommandResize, /* resize */ + XawCommandRedisplay, /* expose */ + XawCommandSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + XawCommandGetValuesHook, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + ChangeSensitive, /* change_sensitive */ + }, + /* label */ + { + NULL, /* not used */ + }, + /* command */ + { + NULL, /* not used */ + }, +}; + +WidgetClass commandWidgetClass = (WidgetClass)&commandClassRec; + +/* + * Implementation + */ +static GC +Get_GC(CommandWidget cbw, Pixel fg, Pixel bg) +{ + XGCValues values; + + values.foreground = fg; + values.background = bg; + values.font = cbw->label.font->fid; + values.cap_style = CapProjecting; + + if (cbw->command.highlight_thickness > 1) + values.line_width = cbw->command.highlight_thickness; + else + values.line_width = 0; + + if (cbw->simple.international == True) + return (XtAllocateGC((Widget)cbw, 0, + GCForeground | GCBackground | GCLineWidth | + GCCapStyle, &values, GCFont, 0)); + else + return (XtGetGC((Widget)cbw, + GCForeground | GCBackground | GCFont | GCLineWidth | + GCCapStyle, &values)); +} + +/*ARGSUSED*/ +static void +XawCommandInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + CommandWidget cbw = (CommandWidget)cnew; + int shape_event_base, shape_error_base; + + if (!cbw->label.font) XtError("Aborting: no font found\n"); + + if (cbw->command.shape_style != XawShapeRectangle && + !XShapeQueryExtension(XtDisplay(cnew), &shape_event_base, + &shape_error_base)) + cbw->command.shape_style = XawShapeRectangle; + + if (cbw->command.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) { + if (cbw->command.shape_style != XawShapeRectangle) + cbw->command.highlight_thickness = 0; + else + cbw->command.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS; + } + + cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, + cbw->core.background_pixel); + cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, + cbw->label.foreground); + XtReleaseGC(cnew, cbw->label.normal_GC); + cbw->label.normal_GC = cbw->command.normal_GC; + + cbw->command.set = False; + cbw->command.highlighted = HighlightNone; +} + +static Region +HighlightRegion(CommandWidget cbw) +{ + static Region outerRegion = NULL, innerRegion, emptyRegion; + XRectangle rect; + + if (cbw->command.highlight_thickness == 0 || + cbw->command.highlight_thickness > Min(XtWidth(cbw), XtHeight(cbw)) / 2) + return (NULL); + + if (outerRegion == NULL) { + /* save time by allocating scratch regions only once. */ + outerRegion = XCreateRegion(); + innerRegion = XCreateRegion(); + emptyRegion = XCreateRegion(); + } + + rect.x = rect.y = 0; + rect.width = XtWidth(cbw); + rect.height = XtHeight(cbw); + XUnionRectWithRegion(&rect, emptyRegion, outerRegion); + rect.x = rect.y = cbw->command.highlight_thickness; + rect.width -= cbw->command.highlight_thickness * 2; + rect.height -= cbw->command.highlight_thickness * 2; + XUnionRectWithRegion(&rect, emptyRegion, innerRegion); + XSubtractRegion(outerRegion, innerRegion, outerRegion); + + return (outerRegion); +} + +/*************************** +* Action Procedures +***************************/ +static void +XawCommandToggle(Widget w) +{ + CommandWidget xaw = (CommandWidget)w; + Arg args[2]; + Cardinal num_args; + + num_args = 0; + XtSetArg(args[num_args], XtNbackground, + xaw->label.foreground); ++num_args; + XtSetArg(args[num_args], XtNforeground, + xaw->core.background_pixel); ++num_args; + XtSetValues(w, args, num_args); +} + +/*ARGSUSED*/ +static void +Set(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CommandWidget cbw = (CommandWidget)w; + + if (cbw->command.set) + return; + + XawCommandToggle(w); + cbw->command.set= True; +} + +/*ARGSUSED*/ +static void +Unset(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CommandWidget cbw = (CommandWidget)w; + + if (!cbw->command.set) + return; + + cbw->command.set = False; + XawCommandToggle(w); +} + +/*ARGSUSED*/ +static void +Reset(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CommandWidget cbw = (CommandWidget)w; + + if (cbw->command.set) { + cbw->command.highlighted = HighlightNone; + Unset(w, event, params, num_params); + } + else + Unhighlight(w, event, params, num_params); +} + +/*ARGSUSED*/ +static void +Highlight(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CommandWidget cbw = (CommandWidget)w; + + if (*num_params == (Cardinal)0) + cbw->command.highlighted = HighlightWhenUnset; + else { + if (*num_params != (Cardinal)1) + XtWarning("Too many parameters passed to highlight action table."); + switch (params[0][0]) { + case 'A': + case 'a': + cbw->command.highlighted = HighlightAlways; + break; + default: + cbw->command.highlighted = HighlightWhenUnset; + break; + } + } + + if (XtIsRealized(w)) + PaintCommandWidget(w, event, HighlightRegion(cbw), True); +} + +/*ARGSUSED*/ +static void +Unhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CommandWidget cbw = (CommandWidget)w; + + cbw->command.highlighted = HighlightNone; + if (XtIsRealized(w)) + PaintCommandWidget(w, event, HighlightRegion(cbw), True); +} + +/*ARGSUSED*/ +static void +Notify(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CommandWidget cbw = (CommandWidget)w; + + /* check to be sure state is still Set so that user can cancel + the action (e.g. by moving outside the window, in the default + bindings. + */ + if (cbw->command.set) + XtCallCallbackList(w, cbw->command.callbacks, (XtPointer) NULL); +} + +static void +XawCommandRedisplay(Widget w, XEvent *event, Region region) +{ + PaintCommandWidget(w, event, region, False); +} + +/* + * Function: + * PaintCommandWidget + * Parameters: + * w - command widget + * region - region to paint (passed to the superclass) + * change - did it change either set or highlight state? + */ +static void +PaintCommandWidget(Widget w, XEvent *event, Region region, Bool change) +{ + CommandWidget cbw = (CommandWidget)w; + Bool very_thick; + GC rev_gc; + + very_thick = cbw->command.highlight_thickness + > Min(XtWidth(cbw), XtHeight(cbw)) / 2; + + if (cbw->command.highlight_thickness == 0) { + (*SuperClass->core_class.expose) (w, event, region); + return; + } + + /* + * If we are set then use the same colors as if we are not highlighted + */ + + if (cbw->command.highlighted != HighlightNone) { + rev_gc = cbw->command.normal_GC; + } + else { + rev_gc = cbw->command.inverse_GC; + } + + if (!((!change && cbw->command.highlighted == HighlightNone) + || (cbw->command.highlighted == HighlightWhenUnset + && cbw->command.set))) { + if (very_thick) + XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc, + 0, 0, XtWidth(cbw), XtHeight(cbw)); + else { + /* wide lines are centered on the path, so indent it */ + if (cbw->core.background_pixmap != XtUnspecifiedPixmap && + rev_gc == cbw->command.inverse_GC) { + XClearArea(XtDisplay(w), XtWindow(w), + 0, 0, XtWidth(cbw), cbw->command.highlight_thickness, + False); + XClearArea(XtDisplay(w), XtWindow(w), + 0, cbw->command.highlight_thickness, + cbw->command.highlight_thickness, + XtHeight(cbw) - (cbw->command.highlight_thickness<<1), + False); + XClearArea(XtDisplay(w), XtWindow(w), + XtWidth(cbw) - cbw->command.highlight_thickness, + cbw->command.highlight_thickness, + cbw->command.highlight_thickness, + XtHeight(cbw) - (cbw->command.highlight_thickness<<1), + False); + XClearArea(XtDisplay(w), XtWindow(w), + 0, XtHeight(cbw) - cbw->command.highlight_thickness, + XtWidth(cbw), cbw->command.highlight_thickness, + False); + } + else { + int offset = cbw->command.highlight_thickness / 2; + + XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset, + XtWidth(cbw) - cbw->command.highlight_thickness, + XtHeight(cbw) - cbw->command.highlight_thickness); + } + } + } + + (*SuperClass->core_class.expose)(w, event, region); +} + +static void +XawCommandDestroy(Widget w) +{ + CommandWidget cbw = (CommandWidget)w; + + /* Label will release cbw->command.normal_GC */ + XtReleaseGC(w, cbw->command.inverse_GC); +} + +/*ARGSUSED*/ +static Boolean +XawCommandSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + CommandWidget oldcbw = (CommandWidget)current; + CommandWidget cbw = (CommandWidget)cnew; + Boolean redisplay = False; + + if (oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) { + cbw->command.highlighted = HighlightNone; + redisplay = True; + } + + if (cbw->command.set) { + unsigned int i; + Pixel foreground, background; + + foreground = oldcbw->label.foreground; + background = oldcbw->core.background_pixel; + for (i = 0; i < *num_args; i++) { + if (STR_EQUAL(args[i].name, XtNforeground)) + background = cbw->label.foreground; + else if (STR_EQUAL(args[i].name, XtNbackground)) + foreground = cbw->core.background_pixel; + } + cbw->label.foreground = foreground; + cbw->core.background_pixel = background; + } + + if (oldcbw->label.foreground != cbw->label.foreground + || oldcbw->core.background_pixel != cbw->core.background_pixel + || oldcbw->command.highlight_thickness + != cbw->command.highlight_thickness + || oldcbw->label.font != cbw->label.font) { + XtReleaseGC(cnew, cbw->command.inverse_GC); + + cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, + cbw->core.background_pixel); + cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, + cbw->label.foreground); + XtReleaseGC(cnew, cbw->label.normal_GC); + cbw->label.normal_GC = cbw->command.normal_GC; + + redisplay = True; + } + + if (XtIsRealized(cnew) + && oldcbw->command.shape_style != cbw->command.shape_style + && !ShapeButton(cbw, True)) + cbw->command.shape_style = oldcbw->command.shape_style; + + return (redisplay); +} + +static void +XawCommandGetValuesHook(Widget w, ArgList args, Cardinal *num_args) +{ + CommandWidget cbw = (CommandWidget)w; + unsigned int i; + + for (i = 0; i < *num_args; i++) { + if (STR_EQUAL(args[i].name, XtNforeground)) + *((String*)args[i].value) = cbw->command.set ? + (String)cbw->core.background_pixel : (String)cbw->label.foreground; + else if (STR_EQUAL(args[i].name, XtNbackground)) + *((String*)args[i].value) = cbw->command.set ? + (String)cbw->label.foreground : (String)cbw->core.background_pixel; + } +} + +static void +XawCommandClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtSetTypeConverter(XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRShapeStyle, XtRString, XmuCvtShapeStyleToString, + NULL, 0, XtCacheNone, NULL); +} + +static Bool +ShapeButton(CommandWidget cbw, Bool checkRectangular) +{ + Dimension corner_size = 0; + + if (cbw->command.shape_style == XawShapeRoundedRectangle) { + corner_size = XtWidth(cbw) < XtHeight(cbw) ? + XtWidth(cbw) : XtHeight(cbw); + corner_size = (corner_size * cbw->command.corner_round) / 100; + } + + if (checkRectangular || cbw->command.shape_style != XawShapeRectangle) { + if (!XmuReshapeWidget((Widget)cbw, cbw->command.shape_style, + corner_size, corner_size)) { + cbw->command.shape_style = XawShapeRectangle; + return (False); + } + } + + return (True); +} + +static void +XawCommandRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) +{ + (*commandWidgetClass->core_class.superclass->core_class.realize) + (w, valueMask, attributes); + + ShapeButton((CommandWidget)w, False); +} + +static void +XawCommandResize(Widget w) +{ + if (XtIsRealized(w)) + ShapeButton((CommandWidget)w, False); + + (*commandWidgetClass->core_class.superclass->core_class.resize)(w); +} + +static Bool +ChangeSensitive(Widget w) +{ + CommandWidget cbw = (CommandWidget)w; + + if (XtIsRealized(w)) { + if (XtIsSensitive(w)) { + if (w->core.border_pixmap != XtUnspecifiedPixmap) + XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w), + w->core.border_pixmap); + else + XSetWindowBorder(XtDisplay(w), XtWindow(w), + w->core.border_pixel); + } + else { + if (cbw->simple.insensitive_border == None) + cbw->simple.insensitive_border = + XmuCreateStippledPixmap(XtScreen(w), + w->core.border_pixel, + cbw->command.set ? + cbw->label.foreground : + w->core.background_pixel, + w->core.depth); + XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w), + cbw->simple.insensitive_border); + } + } + + return (False); +} diff --git a/libXaw/src/Converters.c b/libXaw/src/Converters.c index 5fcda7c3b..08b18c4da 100644 --- a/libXaw/src/Converters.c +++ b/libXaw/src/Converters.c @@ -1,699 +1,699 @@ -/*
- * Copyright (c) 1998 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the XFree86 Project shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from the
- * XFree86 Project.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/Simple.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#ifndef OLDXAW
-
-/*
- * Definitions
- */
-#define done(type, value) \
-{ \
- if (toVal->addr != NULL) \
- { \
- if (toVal->size < sizeof(type)) \
- { \
- toVal->size = sizeof(type); \
- return (False); \
- } \
- *(type *)(toVal->addr) = (value); \
- } \
- else \
- { \
- static type static_val; \
- \
- static_val = (value); \
- toVal->addr = (XPointer)&static_val; \
- } \
- toVal->size = sizeof(type); \
- return (True); \
-}
-
-#define string_done(value) \
-{ \
- if (toVal->addr != NULL) \
- { \
- if (toVal->size < size) \
- { \
- toVal->size = size; \
- return (False); \
- } \
- strcpy((char *)toVal->addr, (value)); \
- } \
- else \
- toVal->addr = (XPointer)(value); \
- toVal->size = size; \
- return (True); \
-}
-
-/*
- * Prototypes
- */
-static Boolean _XawCvtAtomToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtBooleanToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtBoolToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtCARD32ToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtCardinalToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtDimensionToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtDisplayListToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtFontStructToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtIntToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtPixelToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtPixmapToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtShortToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtPositionToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtStringToDisplayList(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtStringToPixmap(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean _XawCvtUnsignedCharToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static void TypeToStringNoArgsWarning(Display*, String);
-
-/*
- * Initialization
- */
-static XtConvertArgRec PixelArgs[] = {
- {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
- sizeof(Colormap)},
-};
-
-static XtConvertArgRec DLArgs[] = {
- {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
- sizeof(Screen *)},
- {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
- sizeof(Colormap)},
- {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.depth),
- sizeof(int)},
-};
-#endif /* OLDXAW */
-
-static String XtCToolkitError = "ToolkitError";
-static String XtNconversionError = "conversionError";
-
-#ifndef OLDXAW
-static String XtNwrongParameters = "wrongParameters";
-
-/*
- * Implementation
- */
-void
-XawInitializeDefaultConverters(void)
-{
- static Boolean first_time = True;
-
- if (first_time == False)
- return;
-
- first_time = False;
-
- /* Replace with more apropriate converters */
- XtSetTypeConverter(XtRCallback, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRColormap, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRFunction, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRPointer, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRScreen, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRStringArray, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRVisual, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRWidget, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRWidgetList, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRWindow, XtRString, _XawCvtCARD32ToString,
- NULL, 0, XtCacheNone, NULL);
-
- XtSetTypeConverter(XtRAtom, XtRString, _XawCvtAtomToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRBool, XtRString, _XawCvtBoolToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRBoolean, XtRString, _XawCvtBooleanToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRCardinal, XtRString, _XawCvtCardinalToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRDimension, XtRString, _XawCvtDimensionToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XawRDisplayList, XtRString, _XawCvtDisplayListToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRFontStruct, XtRString, _XawCvtFontStructToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRInt, XtRString, _XawCvtIntToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRPixel, XtRString, _XawCvtPixelToString,
- &PixelArgs[0], XtNumber(PixelArgs), XtCacheNone, NULL);
- XtSetTypeConverter(XtRPixmap, XtRString, _XawCvtPixmapToString,
- &DLArgs[0], XtNumber(DLArgs), XtCacheNone, NULL);
- XtSetTypeConverter(XtRPosition, XtRString, _XawCvtPositionToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRShort, XtRString, _XawCvtShortToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRString, XawRDisplayList, _XawCvtStringToDisplayList,
- &DLArgs[0], XtNumber(DLArgs), XtCacheAll, NULL);
- XtSetTypeConverter(XtRString, XtRPixmap, _XawCvtStringToPixmap,
- &DLArgs[0], XtNumber(DLArgs), XtCacheAll, NULL);
- XtSetTypeConverter(XtRUnsignedChar, XtRString, _XawCvtUnsignedCharToString,
- NULL, 0, XtCacheNone, NULL);
-}
-#endif /* OLDXAW */
-
-void
-XawTypeToStringWarning(Display *dpy, String type)
-{
- char fname[64];
- String params[1];
- Cardinal num_params;
-
- XmuSnprintf(fname, sizeof(fname), "cvt%sToString", type);
-
- params[0] = type;
- num_params = 1;
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- XtNconversionError, fname, XtCToolkitError,
- "Cannot convert %s to String",
- params, &num_params);
-}
-
-#ifndef OLDXAW
-static void
-TypeToStringNoArgsWarning(Display *dpy, String type)
-{
- char fname[64];
- String params[1];
- Cardinal num_params;
-
- XmuSnprintf(fname, sizeof(fname), "cvt%sToString", type);
-
- params[0] = type;
- num_params = 1;
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- XtNconversionError, fname,
- XtCToolkitError,
- "%s to String conversion needs no extra arguments",
- params, &num_params);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtBooleanToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[6];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRBoolean);
-
- XmuSnprintf(buffer, sizeof(buffer), "%s",
- *(Boolean *)fromVal->addr ? XtEtrue : XtEfalse);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtBoolToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[6];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRBool);
-
- XmuSnprintf(buffer, sizeof(buffer), "%s",
- *(Bool *)fromVal->addr ? XtEtrue : XtEfalse);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtPositionToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[7];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRPosition);
-
- XmuSnprintf(buffer, sizeof(buffer), "%d", *(Position *)fromVal->addr);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtShortToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[7];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRShort);
-
- XmuSnprintf(buffer, sizeof(buffer), "%d", *(short *)fromVal->addr);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtDimensionToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[6];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRDimension);
-
- XmuSnprintf(buffer, sizeof(buffer), "%u", *(Dimension *)fromVal->addr);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtCARD32ToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[11];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, "CARD32");
-
- XmuSnprintf(buffer, sizeof(buffer), "0x%08hx", *(int *)fromVal->addr);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtIntToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[12];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRInt);
-
- XmuSnprintf(buffer, sizeof(buffer), "%d", *(int *)fromVal->addr);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtCardinalToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[11];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRCardinal);
-
- XmuSnprintf(buffer, sizeof(buffer), "%u", *(Cardinal *)fromVal->addr);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtAtomToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char *buffer = NULL;
- static char *nullatom = "NULL";
- Cardinal size;
- Atom atom;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRAtom);
-
- if (buffer && buffer != nullatom)
- XFree(buffer);
-
- atom = *(Atom *)fromVal[0].addr;
- if (atom == 0)
- buffer = nullatom;
- else if ((buffer = XGetAtomName(dpy, *(Atom *)fromVal[0].addr)) == NULL)
- {
- XawTypeToStringWarning(dpy, XtRAtom);
- toVal->addr = NULL;
- toVal->size = sizeof(String);
- return (False);
- }
-
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtPixelToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[19];
- Cardinal size;
- Colormap colormap;
- XColor color;
-
- if (*num_args != 1)
- {
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- XtNwrongParameters, "cvtPixelToString",
- XtCToolkitError,
- "Pixel to String conversion needs colormap argument",
- NULL, NULL);
- return (False);
- }
-
- colormap = *(Colormap *)args[0].addr;
- color.pixel = *(Pixel *)fromVal->addr;
-
- /* Note:
- * If we know the visual type, we can calculate the xcolor
- * without asking Xlib.
- */
- XQueryColor(dpy, colormap, &color);
- XmuSnprintf(buffer, sizeof(buffer), "rgb:%04hx/%04hx/%04hx",
- color.red, color.green, color.blue);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtFontStructToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[128];
- Cardinal size;
- Atom atom;
- unsigned long value;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRFontStruct);
-
- if ((atom = XInternAtom(dpy, "FONT", True)) == None)
- return (False);
-
- size = 0;
-
- if (XGetFontProperty(*(XFontStruct **)fromVal->addr, atom, &value))
- {
- char *tmp = XGetAtomName(dpy, value);
-
- if (tmp)
- {
- XmuSnprintf(buffer, sizeof(buffer), "%s", tmp);
- size = strlen(tmp);
- XFree(tmp);
- }
- }
-
- if (size)
- {
- ++size;
- string_done(buffer);
- }
-
- XawTypeToStringWarning(dpy, XtRFontStruct);
-
- return (False);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtUnsignedCharToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char buffer[4];
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XtRUnsignedChar);
-
- XmuSnprintf(buffer, sizeof(buffer), "%u",
- *(unsigned char *)fromVal->addr);
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtStringToDisplayList(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- XawDisplayList *dlist;
- Screen *screen;
- Colormap colormap;
- int depth;
- String commands;
-
- if (*num_args != 3)
- {
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- XtNwrongParameters, "cvtStringToDisplayList",
- XtCToolkitError,
- "String to DisplayList conversion needs screen, "
- "colormap, and depth arguments",
- NULL, NULL);
- return (False);
- }
-
- screen = *(Screen **)args[0].addr;
- colormap = *(Colormap *)args[1].addr;
- depth = *(int *)args[2].addr;
-
- commands = (String)(fromVal[0].addr);
-
- dlist = XawCreateDisplayList(commands, screen, colormap, depth);
-
- if (!dlist)
- {
- XtDisplayStringConversionWarning(dpy, (String)fromVal->addr,
- XawRDisplayList);
- toVal->addr = NULL;
- toVal->size = sizeof(XawDisplayList*);
- return (False);
- }
-
- done(XawDisplayList*, dlist);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtDisplayListToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- String buffer;
- Cardinal size;
-
- if (*num_args != 0)
- TypeToStringNoArgsWarning(dpy, XawRDisplayList);
-
- buffer = XawDisplayListString(*(XawDisplayList **)(fromVal[0].addr));
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtStringToPixmap(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- XawPixmap *xaw_pixmap;
- Pixmap pixmap;
- Screen *screen;
- Colormap colormap;
- int depth;
- String name;
-
- if (*num_args != 3)
- {
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- XtNwrongParameters, "cvtStringToPixmap",
- XtCToolkitError,
- "String to Pixmap conversion needs screen, "
- "colormap, and depth arguments",
- NULL, NULL);
- return (False);
- }
-
- screen = *(Screen **)args[0].addr;
- colormap = *(Colormap *)args[1].addr;
- depth = *(int *)args[2].addr;
-
- name = (String)(fromVal[0].addr);
-
- if (XmuCompareISOLatin1(name, "None") == 0)
- pixmap = None;
- else if (XmuCompareISOLatin1(name, "ParentRelative") == 0)
- pixmap = ParentRelative;
- else if (XmuCompareISOLatin1(name, "XtUnspecifiedPixmap") == 0)
- pixmap = XtUnspecifiedPixmap;
- else
- {
- xaw_pixmap = XawLoadPixmap(name, screen, colormap, depth);
- if (!xaw_pixmap)
- {
- XtDisplayStringConversionWarning(dpy, (String)fromVal->addr,
- XtRPixmap);
- toVal->addr = (XtPointer)XtUnspecifiedPixmap;
- toVal->size = sizeof(Pixmap);
- return (False);
- }
- else
- pixmap = xaw_pixmap->pixmap;
- }
-
- done(Pixmap, pixmap);
-}
-
-/*ARGSUSED*/
-static Boolean
-_XawCvtPixmapToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- XawPixmap *xaw_pixmap;
- Pixmap pixmap;
- Screen *screen;
- Colormap colormap;
- int depth;
- String buffer = NULL;
- Cardinal size;
-
- if (*num_args != 3)
- {
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- XtNwrongParameters, "cvtPixmapToString",
- XtCToolkitError,
- "Pixmap to String conversion needs screen, "
- "colormap, and depth arguments",
- NULL, NULL);
- return (False);
- }
-
- screen = *(Screen **)args[0].addr;
- colormap = *(Colormap *)args[1].addr;
- depth = *(int *)args[2].addr;
-
- pixmap = *(Pixmap *)(fromVal[0].addr);
-
- switch (pixmap)
- {
- case None:
- buffer = "None";
- break;
- case ParentRelative:
- buffer = "ParentRelative";
- break;
- case XtUnspecifiedPixmap:
- buffer = "XtUnspecifiedPixmap";
- break;
- default:
- xaw_pixmap = XawPixmapFromXPixmap(pixmap, screen, colormap, depth);
- if (xaw_pixmap)
- buffer = xaw_pixmap->name;
- break;
- }
-
- if (!buffer)
- /* Bad Pixmap or Pixmap was not loaded by XawLoadPixmap() */
- return (_XawCvtCARD32ToString(dpy, args, num_args, fromVal, toVal,
- converter_data));
-
- size = strlen(buffer) + 1;
-
- string_done(buffer);
-}
-
-#endif /* OLDXAW */
+/* + * Copyright (c) 1998 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/Simple.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#ifndef OLDXAW + +/* + * Definitions + */ +#define done(type, value) \ +{ \ + if (toVal->addr != NULL) \ + { \ + if (toVal->size < sizeof(type)) \ + { \ + toVal->size = sizeof(type); \ + return (False); \ + } \ + *(type *)(toVal->addr) = (value); \ + } \ + else \ + { \ + static type static_val; \ + \ + static_val = (value); \ + toVal->addr = (XPointer)&static_val; \ + } \ + toVal->size = sizeof(type); \ + return (True); \ +} + +#define string_done(value) \ +{ \ + if (toVal->addr != NULL) \ + { \ + if (toVal->size < size) \ + { \ + toVal->size = size; \ + return (False); \ + } \ + strcpy((char *)toVal->addr, (value)); \ + } \ + else \ + toVal->addr = (XPointer)(value); \ + toVal->size = size; \ + return (True); \ +} + +/* + * Prototypes + */ +static Boolean _XawCvtAtomToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtBooleanToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtBoolToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtCARD32ToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtCardinalToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtDimensionToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtDisplayListToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtFontStructToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtIntToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtPixelToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtPixmapToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtShortToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtPositionToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtStringToDisplayList(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtStringToPixmap(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean _XawCvtUnsignedCharToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static void TypeToStringNoArgsWarning(Display*, String); + +/* + * Initialization + */ +static XtConvertArgRec PixelArgs[] = { + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), + sizeof(Colormap)}, +}; + +static XtConvertArgRec DLArgs[] = { + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)}, + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), + sizeof(Colormap)}, + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.depth), + sizeof(int)}, +}; +#endif /* OLDXAW */ + +static String XtCToolkitError = "ToolkitError"; +static String XtNconversionError = "conversionError"; + +#ifndef OLDXAW +static String XtNwrongParameters = "wrongParameters"; + +/* + * Implementation + */ +void +XawInitializeDefaultConverters(void) +{ + static Boolean first_time = True; + + if (first_time == False) + return; + + first_time = False; + + /* Replace with more apropriate converters */ + XtSetTypeConverter(XtRCallback, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRColormap, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRFunction, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRPointer, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRScreen, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRStringArray, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRVisual, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRWidget, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRWidgetList, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRWindow, XtRString, _XawCvtCARD32ToString, + NULL, 0, XtCacheNone, NULL); + + XtSetTypeConverter(XtRAtom, XtRString, _XawCvtAtomToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRBool, XtRString, _XawCvtBoolToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRBoolean, XtRString, _XawCvtBooleanToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRCardinal, XtRString, _XawCvtCardinalToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRDimension, XtRString, _XawCvtDimensionToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XawRDisplayList, XtRString, _XawCvtDisplayListToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRFontStruct, XtRString, _XawCvtFontStructToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRInt, XtRString, _XawCvtIntToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRPixel, XtRString, _XawCvtPixelToString, + &PixelArgs[0], XtNumber(PixelArgs), XtCacheNone, NULL); + XtSetTypeConverter(XtRPixmap, XtRString, _XawCvtPixmapToString, + &DLArgs[0], XtNumber(DLArgs), XtCacheNone, NULL); + XtSetTypeConverter(XtRPosition, XtRString, _XawCvtPositionToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRShort, XtRString, _XawCvtShortToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRString, XawRDisplayList, _XawCvtStringToDisplayList, + &DLArgs[0], XtNumber(DLArgs), XtCacheAll, NULL); + XtSetTypeConverter(XtRString, XtRPixmap, _XawCvtStringToPixmap, + &DLArgs[0], XtNumber(DLArgs), XtCacheAll, NULL); + XtSetTypeConverter(XtRUnsignedChar, XtRString, _XawCvtUnsignedCharToString, + NULL, 0, XtCacheNone, NULL); +} +#endif /* OLDXAW */ + +void +XawTypeToStringWarning(Display *dpy, String type) +{ + char fname[64]; + String params[1]; + Cardinal num_params; + + XmuSnprintf(fname, sizeof(fname), "cvt%sToString", type); + + params[0] = type; + num_params = 1; + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + XtNconversionError, fname, XtCToolkitError, + "Cannot convert %s to String", + params, &num_params); +} + +#ifndef OLDXAW +static void +TypeToStringNoArgsWarning(Display *dpy, String type) +{ + char fname[64]; + String params[1]; + Cardinal num_params; + + XmuSnprintf(fname, sizeof(fname), "cvt%sToString", type); + + params[0] = type; + num_params = 1; + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + XtNconversionError, fname, + XtCToolkitError, + "%s to String conversion needs no extra arguments", + params, &num_params); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtBooleanToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[6]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRBoolean); + + XmuSnprintf(buffer, sizeof(buffer), "%s", + *(Boolean *)fromVal->addr ? XtEtrue : XtEfalse); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtBoolToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[6]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRBool); + + XmuSnprintf(buffer, sizeof(buffer), "%s", + *(Bool *)fromVal->addr ? XtEtrue : XtEfalse); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtPositionToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[7]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRPosition); + + XmuSnprintf(buffer, sizeof(buffer), "%d", *(Position *)fromVal->addr); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtShortToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[7]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRShort); + + XmuSnprintf(buffer, sizeof(buffer), "%d", *(short *)fromVal->addr); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtDimensionToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[6]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRDimension); + + XmuSnprintf(buffer, sizeof(buffer), "%u", *(Dimension *)fromVal->addr); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtCARD32ToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[11]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, "CARD32"); + + XmuSnprintf(buffer, sizeof(buffer), "0x%08hx", *(int *)fromVal->addr); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtIntToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[12]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRInt); + + XmuSnprintf(buffer, sizeof(buffer), "%d", *(int *)fromVal->addr); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtCardinalToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[11]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRCardinal); + + XmuSnprintf(buffer, sizeof(buffer), "%u", *(Cardinal *)fromVal->addr); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtAtomToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char *buffer = NULL; + static char *nullatom = "NULL"; + Cardinal size; + Atom atom; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRAtom); + + if (buffer && buffer != nullatom) + XFree(buffer); + + atom = *(Atom *)fromVal[0].addr; + if (atom == 0) + buffer = nullatom; + else if ((buffer = XGetAtomName(dpy, *(Atom *)fromVal[0].addr)) == NULL) + { + XawTypeToStringWarning(dpy, XtRAtom); + toVal->addr = NULL; + toVal->size = sizeof(String); + return (False); + } + + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtPixelToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[19]; + Cardinal size; + Colormap colormap; + XColor color; + + if (*num_args != 1) + { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + XtNwrongParameters, "cvtPixelToString", + XtCToolkitError, + "Pixel to String conversion needs colormap argument", + NULL, NULL); + return (False); + } + + colormap = *(Colormap *)args[0].addr; + color.pixel = *(Pixel *)fromVal->addr; + + /* Note: + * If we know the visual type, we can calculate the xcolor + * without asking Xlib. + */ + XQueryColor(dpy, colormap, &color); + XmuSnprintf(buffer, sizeof(buffer), "rgb:%04hx/%04hx/%04hx", + color.red, color.green, color.blue); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtFontStructToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[128]; + Cardinal size; + Atom atom; + unsigned long value; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRFontStruct); + + if ((atom = XInternAtom(dpy, "FONT", True)) == None) + return (False); + + size = 0; + + if (XGetFontProperty(*(XFontStruct **)fromVal->addr, atom, &value)) + { + char *tmp = XGetAtomName(dpy, value); + + if (tmp) + { + XmuSnprintf(buffer, sizeof(buffer), "%s", tmp); + size = strlen(tmp); + XFree(tmp); + } + } + + if (size) + { + ++size; + string_done(buffer); + } + + XawTypeToStringWarning(dpy, XtRFontStruct); + + return (False); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtUnsignedCharToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char buffer[4]; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XtRUnsignedChar); + + XmuSnprintf(buffer, sizeof(buffer), "%u", + *(unsigned char *)fromVal->addr); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtStringToDisplayList(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + XawDisplayList *dlist; + Screen *screen; + Colormap colormap; + int depth; + String commands; + + if (*num_args != 3) + { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + XtNwrongParameters, "cvtStringToDisplayList", + XtCToolkitError, + "String to DisplayList conversion needs screen, " + "colormap, and depth arguments", + NULL, NULL); + return (False); + } + + screen = *(Screen **)args[0].addr; + colormap = *(Colormap *)args[1].addr; + depth = *(int *)args[2].addr; + + commands = (String)(fromVal[0].addr); + + dlist = XawCreateDisplayList(commands, screen, colormap, depth); + + if (!dlist) + { + XtDisplayStringConversionWarning(dpy, (String)fromVal->addr, + XawRDisplayList); + toVal->addr = NULL; + toVal->size = sizeof(XawDisplayList*); + return (False); + } + + done(XawDisplayList*, dlist); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtDisplayListToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + String buffer; + Cardinal size; + + if (*num_args != 0) + TypeToStringNoArgsWarning(dpy, XawRDisplayList); + + buffer = XawDisplayListString(*(XawDisplayList **)(fromVal[0].addr)); + size = strlen(buffer) + 1; + + string_done(buffer); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtStringToPixmap(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + XawPixmap *xaw_pixmap; + Pixmap pixmap; + Screen *screen; + Colormap colormap; + int depth; + String name; + + if (*num_args != 3) + { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + XtNwrongParameters, "cvtStringToPixmap", + XtCToolkitError, + "String to Pixmap conversion needs screen, " + "colormap, and depth arguments", + NULL, NULL); + return (False); + } + + screen = *(Screen **)args[0].addr; + colormap = *(Colormap *)args[1].addr; + depth = *(int *)args[2].addr; + + name = (String)(fromVal[0].addr); + + if (XmuCompareISOLatin1(name, "None") == 0) + pixmap = None; + else if (XmuCompareISOLatin1(name, "ParentRelative") == 0) + pixmap = ParentRelative; + else if (XmuCompareISOLatin1(name, "XtUnspecifiedPixmap") == 0) + pixmap = XtUnspecifiedPixmap; + else + { + xaw_pixmap = XawLoadPixmap(name, screen, colormap, depth); + if (!xaw_pixmap) + { + XtDisplayStringConversionWarning(dpy, (String)fromVal->addr, + XtRPixmap); + toVal->addr = (XtPointer)XtUnspecifiedPixmap; + toVal->size = sizeof(Pixmap); + return (False); + } + else + pixmap = xaw_pixmap->pixmap; + } + + done(Pixmap, pixmap); +} + +/*ARGSUSED*/ +static Boolean +_XawCvtPixmapToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + XawPixmap *xaw_pixmap; + Pixmap pixmap; + Screen *screen; + Colormap colormap; + int depth; + String buffer = NULL; + Cardinal size; + + if (*num_args != 3) + { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + XtNwrongParameters, "cvtPixmapToString", + XtCToolkitError, + "Pixmap to String conversion needs screen, " + "colormap, and depth arguments", + NULL, NULL); + return (False); + } + + screen = *(Screen **)args[0].addr; + colormap = *(Colormap *)args[1].addr; + depth = *(int *)args[2].addr; + + pixmap = *(Pixmap *)(fromVal[0].addr); + + switch (pixmap) + { + case None: + buffer = "None"; + break; + case ParentRelative: + buffer = "ParentRelative"; + break; + case XtUnspecifiedPixmap: + buffer = "XtUnspecifiedPixmap"; + break; + default: + xaw_pixmap = XawPixmapFromXPixmap(pixmap, screen, colormap, depth); + if (xaw_pixmap) + buffer = xaw_pixmap->name; + break; + } + + if (!buffer) + /* Bad Pixmap or Pixmap was not loaded by XawLoadPixmap() */ + return (_XawCvtCARD32ToString(dpy, args, num_args, fromVal, toVal, + converter_data)); + + size = strlen(buffer) + 1; + + string_done(buffer); +} + +#endif /* OLDXAW */ diff --git a/libXaw/src/Dialog.c b/libXaw/src/Dialog.c index 7bb232b12..7accb8caa 100644 --- a/libXaw/src/Dialog.c +++ b/libXaw/src/Dialog.c @@ -1,460 +1,460 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xos.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xaw/AsciiText.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/Command.h>
-#include <X11/Xaw/Label.h>
-#include <X11/Xaw/DialogP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * After we have set the string in the value widget we set the
- * string to a magic value. So that when a SetValues request is made
- * on the dialog value we will notice it, and reset the string
- */
-#define MAGIC_VALUE ((char *)3)
-
-#define streq(a,b) (strcmp((a), (b)) == 0)
-
-/*
- * Class Methods
- */
-static void XawDialogConstraintInitialize(Widget, Widget,
- ArgList, Cardinal*);
-static void XawDialogGetValuesHook(Widget, ArgList, Cardinal*);
-static void XawDialogInitialize(Widget, Widget, ArgList, Cardinal*);
-static Boolean XawDialogSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void CreateDialogValueWidget(Widget);
-
-/*
- * Initialization
- */
-static XtResource resources[] = {
- {
- XtNlabel,
- XtCLabel,
- XtRString,
- sizeof(String),
- XtOffsetOf(DialogRec, dialog.label),
- XtRString,
- NULL
- },
- {
- XtNvalue,
- XtCValue,
- XtRString,
- sizeof(String),
- XtOffsetOf(DialogRec, dialog.value),
- XtRString,
- NULL
- },
- {
- XtNicon,
- XtCIcon,
- XtRBitmap,
- sizeof(Pixmap),
- XtOffsetOf(DialogRec, dialog.icon),
- XtRImmediate,
- NULL
- },
-};
-
-DialogClassRec dialogClassRec = {
- /* core */
- {
- (WidgetClass)&formClassRec, /* superclass */
- "Dialog", /* class_name */
- sizeof(DialogRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part init */
- False, /* class_inited */
- XawDialogInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- XtInheritResize, /* resize */
- XtInheritExpose, /* expose */
- XawDialogSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- XawDialogGetValuesHook, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* composite */
- {
- XtInheritGeometryManager, /* geometry_manager */
- XtInheritChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- /* constraint */
- {
- NULL, /* subresourses */
- 0, /* subresource_count */
- sizeof(DialogConstraintsRec), /* constraint_size */
- XawDialogConstraintInitialize, /* initialize */
- NULL, /* destroy */
- NULL, /* set_values */
- NULL, /* extension */
- },
- /* form */
- {
- XtInheritLayout, /* layout */
- },
- /* dialog */
- {
- NULL, /* extension */
- }
-};
-
-WidgetClass dialogWidgetClass = (WidgetClass)&dialogClassRec;
-
-/*
- * Implementation
- */
-/*ARGSUSED*/
-static void
-XawDialogInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- DialogWidget dw = (DialogWidget)cnew;
- Arg arglist[9];
- Cardinal arg_cnt = 0;
-
- XtSetArg(arglist[arg_cnt], XtNborderWidth, 0); arg_cnt++;
- XtSetArg(arglist[arg_cnt], XtNleft, XtChainLeft); arg_cnt++;
-
- if (dw->dialog.icon != (Pixmap)0) {
- XtSetArg(arglist[arg_cnt], XtNbitmap, dw->dialog.icon); arg_cnt++;
- XtSetArg(arglist[arg_cnt], XtNright, XtChainLeft); arg_cnt++;
- dw->dialog.iconW = XtCreateManagedWidget("icon", labelWidgetClass,
- cnew, arglist, arg_cnt);
- arg_cnt = 2;
- XtSetArg(arglist[arg_cnt], XtNfromHoriz, dw->dialog.iconW); arg_cnt++;
- }
- else
- dw->dialog.iconW = NULL;
-
- XtSetArg(arglist[arg_cnt], XtNlabel, dw->dialog.label); arg_cnt++;
- XtSetArg(arglist[arg_cnt], XtNright, XtChainRight); arg_cnt++;
-
- dw->dialog.labelW = XtCreateManagedWidget("label", labelWidgetClass,
- cnew, arglist, arg_cnt);
-
- if (dw->dialog.iconW != NULL &&
- XtHeight(dw->dialog.labelW) < XtHeight(dw->dialog.iconW)) {
- XtSetArg(arglist[0], XtNheight, XtHeight(dw->dialog.iconW));
- XtSetValues(dw->dialog.labelW, arglist, 1);
- }
- if (dw->dialog.value != NULL)
- CreateDialogValueWidget((Widget)dw);
- else
- dw->dialog.valueW = NULL;
-}
-
-/*ARGSUSED*/
-static void
-XawDialogConstraintInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- DialogWidget dw = (DialogWidget)cnew->core.parent;
- DialogConstraints constraint = (DialogConstraints)cnew->core.constraints;
-
- if (!XtIsSubclass(cnew, commandWidgetClass)) /* if not a button */
- return; /* then just use defaults */
-
- constraint->form.left = constraint->form.right = XtChainLeft;
- if (dw->dialog.valueW == NULL)
- constraint->form.vert_base = dw->dialog.labelW;
- else
- constraint->form.vert_base = dw->dialog.valueW;
-
- if (dw->composite.num_children > 1) {
- WidgetList children = dw->composite.children;
- Widget *childP;
-
- for (childP = children + dw->composite.num_children - 1;
- childP >= children; childP-- ) {
- if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW)
- break;
- if (XtIsManaged(*childP) &&
- XtIsSubclass(*childP, commandWidgetClass)) {
- constraint->form.horiz_base = *childP;
- break;
- }
- }
- }
-}
-
-#define ICON 0
-#define LABEL 1
-#define NUM_CHECKS 2
-/*ARGSUSED*/
-static Boolean
-XawDialogSetValues(Widget current, Widget request, Widget cnew,
- ArgList in_args, Cardinal *in_num_args)
-{
- DialogWidget w = (DialogWidget)cnew;
- DialogWidget old = (DialogWidget)current;
- Arg args[5];
- Cardinal num_args;
- unsigned int i;
- Bool checks[NUM_CHECKS];
-
- for (i = 0; i < NUM_CHECKS; i++)
- checks[i] = False;
-
- for (i = 0; i < *in_num_args; i++) {
- if (streq(XtNicon, in_args[i].name))
- checks[ICON] = True;
- else if (streq(XtNlabel, in_args[i].name))
- checks[LABEL] = True;
- }
-
- if (checks[ICON]) {
- if (w->dialog.icon != 0) {
- XtSetArg(args[0], XtNbitmap, w->dialog.icon);
- if (old->dialog.iconW != NULL)
- XtSetValues(old->dialog.iconW, args, 1);
- else {
- XtSetArg(args[1], XtNborderWidth, 0);
- XtSetArg(args[2], XtNleft, XtChainLeft);
- XtSetArg(args[3], XtNright, XtChainLeft);
- w->dialog.iconW = XtCreateWidget("icon", labelWidgetClass,
- cnew, args, 4);
- ((DialogConstraints)w->dialog.labelW->core.constraints)->
- form.horiz_base = w->dialog.iconW;
- XtManageChild(w->dialog.iconW);
- }
- }
- else if (old->dialog.icon != 0) {
- ((DialogConstraints)w->dialog.labelW->core.constraints)->
- form.horiz_base = NULL;
- XtDestroyWidget(old->dialog.iconW);
- w->dialog.iconW = NULL;
- }
- }
-
- if (checks[LABEL]) {
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, w->dialog.label); num_args++;
- if (w->dialog.iconW != NULL &&
- XtHeight(w->dialog.labelW) <= XtHeight(w->dialog.iconW)) {
- XtSetArg(args[num_args], XtNheight, XtHeight(w->dialog.iconW));
- num_args++;
- }
- XtSetValues(w->dialog.labelW, args, num_args);
- }
-
- if (w->dialog.value != old->dialog.value) {
- if (w->dialog.value == NULL) /* only get here if it
- wasn't NULL before */
- XtDestroyWidget(old->dialog.valueW);
- else if (old->dialog.value == NULL) { /* create a new value widget */
- XtWidth(w) = XtWidth(old);
- XtHeight(w) = XtHeight(old);
- CreateDialogValueWidget(cnew);
- }
- else { /* Widget ok, just change string */
- Arg nargs[1];
-
- XtSetArg(nargs[0], XtNstring, w->dialog.value);
- XtSetValues(w->dialog.valueW, nargs, 1);
- w->dialog.value = MAGIC_VALUE;
- }
- }
-
- return (False);
-}
-
-/*
- * Function:
- * XawDialogGetValuesHook
- *
- * Parameters:
- * w - Dialog Widget
- * args - argument list
- * num_args - number of args
- *
- * Description:
- * This is a get values hook routine that gets the values in the dialog.
- */
-static void
-XawDialogGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
-{
- Arg a[1];
- String s;
- DialogWidget src = (DialogWidget)w;
- unsigned int i;
-
- for (i = 0; i < *num_args; i++)
- if (streq(args[i].name, XtNvalue)) {
- XtSetArg(a[0], XtNstring, &s);
- XtGetValues(src->dialog.valueW, a, 1);
- *((char **)args[i].value) = s;
- }
- else if (streq(args[i].name, XtNlabel)) {
- XtSetArg(a[0], XtNlabel, &s);
- XtGetValues(src->dialog.labelW, a, 1);
- *((char **)args[i].value) = s;
- }
-}
-
-/*
- * Function:
- * CreateDialogValueWidget
- *
- * Parameters:
- * w - dialog widget
- *
- * Description:
- * Creates the dialog widgets value widget.
- *
- * Note
- * Must be called only when w->dialog.value is non-nil
- */
-static void
-CreateDialogValueWidget(Widget w)
-{
- DialogWidget dw = (DialogWidget)w;
- Arg arglist[10];
- Cardinal num_args = 0;
-
- XtSetArg(arglist[num_args], XtNstring, dw->dialog.value); num_args++;
- XtSetArg(arglist[num_args], XtNresizable, True); num_args++;
- XtSetArg(arglist[num_args], XtNeditType, XawtextEdit); num_args++;
- XtSetArg(arglist[num_args], XtNfromVert, dw->dialog.labelW); num_args++;
- XtSetArg(arglist[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(arglist[num_args], XtNright, XtChainRight); num_args++;
-
- dw->dialog.valueW = XtCreateWidget("value", asciiTextWidgetClass,
- w, arglist, num_args);
-
- /* if the value widget is being added after buttons,
- * then the buttons need new layout constraints
- */
- if (dw->composite.num_children > 1) {
- WidgetList children = dw->composite.children;
- Widget *childP;
-
- for (childP = children + dw->composite.num_children - 1;
- childP >= children; childP-- ) {
- if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW)
- continue;
-
- if (XtIsManaged(*childP) &&
- XtIsSubclass(*childP, commandWidgetClass)) {
- ((DialogConstraints)(*childP)->core.constraints)->
- form.vert_base = dw->dialog.valueW;
- }
- }
- }
- XtManageChild(dw->dialog.valueW);
-
- /*
- * Value widget gets the keyboard focus
- */
- XtSetKeyboardFocus(w, dw->dialog.valueW);
- dw->dialog.value = MAGIC_VALUE;
-}
-
-void
-XawDialogAddButton(Widget dialog, _Xconst char* name, XtCallbackProc function,
- XtPointer param)
-{
- /*
- * Correct Constraints are all set in ConstraintInitialize()
- */
- Widget button;
-
- button = XtCreateManagedWidget(name, commandWidgetClass, dialog, NULL, 0);
-
- if (function != NULL) /* don't add NULL callback func */
- XtAddCallback(button, XtNcallback, function, param);
-}
-
-char *
-XawDialogGetValueString(Widget w)
-{
- Arg args[1];
- char *value;
-
- XtSetArg(args[0], XtNstring, &value);
- XtGetValues(((DialogWidget)w)->dialog.valueW, args, 1);
-
- return(value);
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw/AsciiText.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/Command.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/DialogP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * After we have set the string in the value widget we set the + * string to a magic value. So that when a SetValues request is made + * on the dialog value we will notice it, and reset the string + */ +#define MAGIC_VALUE ((char *)3) + +#define streq(a,b) (strcmp((a), (b)) == 0) + +/* + * Class Methods + */ +static void XawDialogConstraintInitialize(Widget, Widget, + ArgList, Cardinal*); +static void XawDialogGetValuesHook(Widget, ArgList, Cardinal*); +static void XawDialogInitialize(Widget, Widget, ArgList, Cardinal*); +static Boolean XawDialogSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void CreateDialogValueWidget(Widget); + +/* + * Initialization + */ +static XtResource resources[] = { + { + XtNlabel, + XtCLabel, + XtRString, + sizeof(String), + XtOffsetOf(DialogRec, dialog.label), + XtRString, + NULL + }, + { + XtNvalue, + XtCValue, + XtRString, + sizeof(String), + XtOffsetOf(DialogRec, dialog.value), + XtRString, + NULL + }, + { + XtNicon, + XtCIcon, + XtRBitmap, + sizeof(Pixmap), + XtOffsetOf(DialogRec, dialog.icon), + XtRImmediate, + NULL + }, +}; + +DialogClassRec dialogClassRec = { + /* core */ + { + (WidgetClass)&formClassRec, /* superclass */ + "Dialog", /* class_name */ + sizeof(DialogRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part init */ + False, /* class_inited */ + XawDialogInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + XawDialogSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + XawDialogGetValuesHook, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* composite */ + { + XtInheritGeometryManager, /* geometry_manager */ + XtInheritChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + /* constraint */ + { + NULL, /* subresourses */ + 0, /* subresource_count */ + sizeof(DialogConstraintsRec), /* constraint_size */ + XawDialogConstraintInitialize, /* initialize */ + NULL, /* destroy */ + NULL, /* set_values */ + NULL, /* extension */ + }, + /* form */ + { + XtInheritLayout, /* layout */ + }, + /* dialog */ + { + NULL, /* extension */ + } +}; + +WidgetClass dialogWidgetClass = (WidgetClass)&dialogClassRec; + +/* + * Implementation + */ +/*ARGSUSED*/ +static void +XawDialogInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + DialogWidget dw = (DialogWidget)cnew; + Arg arglist[9]; + Cardinal arg_cnt = 0; + + XtSetArg(arglist[arg_cnt], XtNborderWidth, 0); arg_cnt++; + XtSetArg(arglist[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; + + if (dw->dialog.icon != (Pixmap)0) { + XtSetArg(arglist[arg_cnt], XtNbitmap, dw->dialog.icon); arg_cnt++; + XtSetArg(arglist[arg_cnt], XtNright, XtChainLeft); arg_cnt++; + dw->dialog.iconW = XtCreateManagedWidget("icon", labelWidgetClass, + cnew, arglist, arg_cnt); + arg_cnt = 2; + XtSetArg(arglist[arg_cnt], XtNfromHoriz, dw->dialog.iconW); arg_cnt++; + } + else + dw->dialog.iconW = NULL; + + XtSetArg(arglist[arg_cnt], XtNlabel, dw->dialog.label); arg_cnt++; + XtSetArg(arglist[arg_cnt], XtNright, XtChainRight); arg_cnt++; + + dw->dialog.labelW = XtCreateManagedWidget("label", labelWidgetClass, + cnew, arglist, arg_cnt); + + if (dw->dialog.iconW != NULL && + XtHeight(dw->dialog.labelW) < XtHeight(dw->dialog.iconW)) { + XtSetArg(arglist[0], XtNheight, XtHeight(dw->dialog.iconW)); + XtSetValues(dw->dialog.labelW, arglist, 1); + } + if (dw->dialog.value != NULL) + CreateDialogValueWidget((Widget)dw); + else + dw->dialog.valueW = NULL; +} + +/*ARGSUSED*/ +static void +XawDialogConstraintInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + DialogWidget dw = (DialogWidget)cnew->core.parent; + DialogConstraints constraint = (DialogConstraints)cnew->core.constraints; + + if (!XtIsSubclass(cnew, commandWidgetClass)) /* if not a button */ + return; /* then just use defaults */ + + constraint->form.left = constraint->form.right = XtChainLeft; + if (dw->dialog.valueW == NULL) + constraint->form.vert_base = dw->dialog.labelW; + else + constraint->form.vert_base = dw->dialog.valueW; + + if (dw->composite.num_children > 1) { + WidgetList children = dw->composite.children; + Widget *childP; + + for (childP = children + dw->composite.num_children - 1; + childP >= children; childP-- ) { + if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW) + break; + if (XtIsManaged(*childP) && + XtIsSubclass(*childP, commandWidgetClass)) { + constraint->form.horiz_base = *childP; + break; + } + } + } +} + +#define ICON 0 +#define LABEL 1 +#define NUM_CHECKS 2 +/*ARGSUSED*/ +static Boolean +XawDialogSetValues(Widget current, Widget request, Widget cnew, + ArgList in_args, Cardinal *in_num_args) +{ + DialogWidget w = (DialogWidget)cnew; + DialogWidget old = (DialogWidget)current; + Arg args[5]; + Cardinal num_args; + unsigned int i; + Bool checks[NUM_CHECKS]; + + for (i = 0; i < NUM_CHECKS; i++) + checks[i] = False; + + for (i = 0; i < *in_num_args; i++) { + if (streq(XtNicon, in_args[i].name)) + checks[ICON] = True; + else if (streq(XtNlabel, in_args[i].name)) + checks[LABEL] = True; + } + + if (checks[ICON]) { + if (w->dialog.icon != 0) { + XtSetArg(args[0], XtNbitmap, w->dialog.icon); + if (old->dialog.iconW != NULL) + XtSetValues(old->dialog.iconW, args, 1); + else { + XtSetArg(args[1], XtNborderWidth, 0); + XtSetArg(args[2], XtNleft, XtChainLeft); + XtSetArg(args[3], XtNright, XtChainLeft); + w->dialog.iconW = XtCreateWidget("icon", labelWidgetClass, + cnew, args, 4); + ((DialogConstraints)w->dialog.labelW->core.constraints)-> + form.horiz_base = w->dialog.iconW; + XtManageChild(w->dialog.iconW); + } + } + else if (old->dialog.icon != 0) { + ((DialogConstraints)w->dialog.labelW->core.constraints)-> + form.horiz_base = NULL; + XtDestroyWidget(old->dialog.iconW); + w->dialog.iconW = NULL; + } + } + + if (checks[LABEL]) { + num_args = 0; + XtSetArg(args[num_args], XtNlabel, w->dialog.label); num_args++; + if (w->dialog.iconW != NULL && + XtHeight(w->dialog.labelW) <= XtHeight(w->dialog.iconW)) { + XtSetArg(args[num_args], XtNheight, XtHeight(w->dialog.iconW)); + num_args++; + } + XtSetValues(w->dialog.labelW, args, num_args); + } + + if (w->dialog.value != old->dialog.value) { + if (w->dialog.value == NULL) /* only get here if it + wasn't NULL before */ + XtDestroyWidget(old->dialog.valueW); + else if (old->dialog.value == NULL) { /* create a new value widget */ + XtWidth(w) = XtWidth(old); + XtHeight(w) = XtHeight(old); + CreateDialogValueWidget(cnew); + } + else { /* Widget ok, just change string */ + Arg nargs[1]; + + XtSetArg(nargs[0], XtNstring, w->dialog.value); + XtSetValues(w->dialog.valueW, nargs, 1); + w->dialog.value = MAGIC_VALUE; + } + } + + return (False); +} + +/* + * Function: + * XawDialogGetValuesHook + * + * Parameters: + * w - Dialog Widget + * args - argument list + * num_args - number of args + * + * Description: + * This is a get values hook routine that gets the values in the dialog. + */ +static void +XawDialogGetValuesHook(Widget w, ArgList args, Cardinal *num_args) +{ + Arg a[1]; + String s; + DialogWidget src = (DialogWidget)w; + unsigned int i; + + for (i = 0; i < *num_args; i++) + if (streq(args[i].name, XtNvalue)) { + XtSetArg(a[0], XtNstring, &s); + XtGetValues(src->dialog.valueW, a, 1); + *((char **)args[i].value) = s; + } + else if (streq(args[i].name, XtNlabel)) { + XtSetArg(a[0], XtNlabel, &s); + XtGetValues(src->dialog.labelW, a, 1); + *((char **)args[i].value) = s; + } +} + +/* + * Function: + * CreateDialogValueWidget + * + * Parameters: + * w - dialog widget + * + * Description: + * Creates the dialog widgets value widget. + * + * Note + * Must be called only when w->dialog.value is non-nil + */ +static void +CreateDialogValueWidget(Widget w) +{ + DialogWidget dw = (DialogWidget)w; + Arg arglist[10]; + Cardinal num_args = 0; + + XtSetArg(arglist[num_args], XtNstring, dw->dialog.value); num_args++; + XtSetArg(arglist[num_args], XtNresizable, True); num_args++; + XtSetArg(arglist[num_args], XtNeditType, XawtextEdit); num_args++; + XtSetArg(arglist[num_args], XtNfromVert, dw->dialog.labelW); num_args++; + XtSetArg(arglist[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(arglist[num_args], XtNright, XtChainRight); num_args++; + + dw->dialog.valueW = XtCreateWidget("value", asciiTextWidgetClass, + w, arglist, num_args); + + /* if the value widget is being added after buttons, + * then the buttons need new layout constraints + */ + if (dw->composite.num_children > 1) { + WidgetList children = dw->composite.children; + Widget *childP; + + for (childP = children + dw->composite.num_children - 1; + childP >= children; childP-- ) { + if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW) + continue; + + if (XtIsManaged(*childP) && + XtIsSubclass(*childP, commandWidgetClass)) { + ((DialogConstraints)(*childP)->core.constraints)-> + form.vert_base = dw->dialog.valueW; + } + } + } + XtManageChild(dw->dialog.valueW); + + /* + * Value widget gets the keyboard focus + */ + XtSetKeyboardFocus(w, dw->dialog.valueW); + dw->dialog.value = MAGIC_VALUE; +} + +void +XawDialogAddButton(Widget dialog, _Xconst char* name, XtCallbackProc function, + XtPointer param) +{ + /* + * Correct Constraints are all set in ConstraintInitialize() + */ + Widget button; + + button = XtCreateManagedWidget(name, commandWidgetClass, dialog, NULL, 0); + + if (function != NULL) /* don't add NULL callback func */ + XtAddCallback(button, XtNcallback, function, param); +} + +char * +XawDialogGetValueString(Widget w) +{ + Arg args[1]; + char *value; + + XtSetArg(args[0], XtNstring, &value); + XtGetValues(((DialogWidget)w)->dialog.valueW, args, 1); + + return(value); +} diff --git a/libXaw/src/DisplayList.c b/libXaw/src/DisplayList.c index 1bef9945f..6549650e7 100644 --- a/libXaw/src/DisplayList.c +++ b/libXaw/src/DisplayList.c @@ -1,2255 +1,2255 @@ -/*
- * Copyright (c) 1998 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the XFree86 Project shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from the
- * XFree86 Project.
- *
- * Author: Paulo César Pereira de Andrade
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <ctype.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/CoreP.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/SysUtil.h>
-#include "Private.h"
-
-#ifdef __UNIXOS2__
-static char dummy;
-#endif
-
-#ifndef OLDXAW
-
-/*
- * Types
- */
-typedef struct _XawDLProc XawDLProc;
-typedef struct _XawDLData XawDLData;
-typedef struct _XawDLInfo XawDLInfo;
-
-struct _XawDLProc {
- XrmQuark qname;
- String *params;
- Cardinal num_params;
- XawDisplayListProc proc;
- XtPointer args;
- XawDLData *data;
-};
-
-struct _XawDLData {
- XawDLClass *dlclass;
- XtPointer data;
-};
-
-struct _XawDLInfo {
- String name;
- XrmQuark qname;
- XawDisplayListProc proc;
-};
-
-struct _XawDL {
- XawDLProc **procs;
- Cardinal num_procs;
- XawDLData **data;
- Cardinal num_data;
- Screen *screen;
- Colormap colormap;
- int depth;
- XrmQuark qrep; /* for cache lookup */
-};
-
-struct _XawDLClass {
- String name;
- XawDLInfo **infos;
- Cardinal num_infos;
- XawDLArgsInitProc args_init;
- XawDLArgsDestructor args_destructor;
- XawDLDataInitProc data_init;
- XawDLDataDestructor data_destructor;
-};
-
-/*
- * Private Methods
- */
-static XawDLClass *_XawFindDLClass(String);
-static int qcmp_dlist_class(_Xconst void*, _Xconst void*);
-static int bcmp_dlist_class(_Xconst void*, _Xconst void*);
-static XawDLInfo *_XawFindDLInfo(XawDLClass*, String);
-static int qcmp_dlist_info(_Xconst void*, _Xconst void*);
-static int bcmp_dlist_info(_Xconst void*, _Xconst void*);
-static void *_Xaw_Xlib_ArgsInitProc(String, String*, Cardinal*,
- Screen*, Colormap, int);
-static void _Xaw_Xlib_ArgsDestructor(Display*, String, XtPointer,
- String*, Cardinal*);
-static void *_Xaw_Xlib_DataInitProc(String, Screen*, Colormap, int);
-static void _Xaw_Xlib_DataDestructor(Display*, String, XtPointer);
-
-/*
- * Initialization
- */
-static XawDLClass **classes;
-static Cardinal num_classes;
-static String xlib = "xlib";
-
-/*
- * Implementation
- */
-void
-XawRunDisplayList(Widget w, _XawDisplayList *list,
- XEvent *event, Region region)
-{
- XawDLProc *proc;
- Cardinal i;
-
- if (!XtIsRealized(w))
- return;
-
- for (i = 0; i < list->num_procs; i++)
- {
- proc = list->procs[i];
- proc->proc(w, proc->args, proc->data->data, event, region);
- }
-}
-
-#define DLERR -2
-#define DLEOF -1
-#define DLEND 1
-#define DLNAME 2
-#define DLARG 3
-static char *
-read_token(char *src, char *dst, Cardinal size, int *status)
-{
- int ch;
- Bool esc, quote;
- Cardinal i;
-
- i = 0;
- esc = quote = False;
-
- /*CONSTCOND*/
- while (1)
- {
- ch = *src;
- if (ch != '\n' && isspace(ch))
- ++src;
- else
- break;
- }
-
- for (; i < size - 1; src++)
- {
- ch = *src;
- if (ch == '"')
- {
- if (quote)
- {
- quote = False;
- continue;
- }
- quote = True;
- continue;
- }
- if (ch == '\\')
- {
- if (esc)
- {
- dst[i++] = ch;
- esc = False;
- continue;
- }
- esc = True;
- continue;
- }
- if (ch == '\0')
- {
- *status = DLEOF;
- dst[i] = '\0';
- return (src);
- }
- else if (!esc)
- {
- if (!quote)
- {
- if (ch == ',')
- {
- *status = DLARG;
- dst[i] = '\0';
- return (++src);
- }
- else if (ch == ' ' || ch == '\t')
- {
- *status = DLNAME;
- dst[i] = '\0';
- return (++src);
- }
- else if (ch == ';' || ch == '\n')
- {
- *status = DLEND;
- dst[i] = '\0';
- return (++src);
- }
- }
- }
- else
- esc = False;
- dst[i++] = ch;
- }
-
- *status = DLERR;
- dst[i] = '\0';
-
- return (src);
-}
-
-_XawDisplayList *XawCreateDisplayList(String string, Screen *screen,
- Colormap colormap, int depth)
-{
- _XawDisplayList *dlist;
- XawDLClass *lc, *xlibc;
- XawDLData *data;
- XawDLInfo *info;
- XawDLProc *proc;
- char cname[64], fname[64], aname[1024];
- Cardinal i;
- char *cp, *fp, *lp;
- int status;
-
- xlibc = XawGetDisplayListClass(xlib);
- if (!xlibc)
- {
- XawDisplayListInitialize();
- xlibc = XawGetDisplayListClass(xlib);
- }
-
- dlist = (_XawDisplayList *)XtMalloc(sizeof(_XawDisplayList));
- dlist->procs = NULL;
- dlist->num_procs = 0;
- dlist->data = NULL;
- dlist->num_data = 0;
- dlist->screen = screen;
- dlist->colormap = colormap;
- dlist->depth = depth;
- dlist->qrep = NULLQUARK;
- if (!string || !string[0])
- return (dlist);
-
- cp = string;
-
- status = 0;
- while (status != DLEOF)
- {
- lp = cp;
- cp = read_token(cp, fname, sizeof(fname), &status);
-
- if (status != DLNAME && status != DLEND && status != DLEOF)
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "Error parsing displayList at \"%s\"", lp);
- XtAppWarning(XtDisplayToApplicationContext(DisplayOfScreen(screen)),
- msg);
- XawDestroyDisplayList(dlist);
- return (NULL);
- }
- fp = fname;
- /*CONSTCOND*/
- while (1)
- {
- fp = strchr(fp, ':');
- if (!fp || (fp == cp || fp[-1] != '\\'))
- break;
- ++fp;
- }
- if (fp)
- {
- XmuSnprintf(cname, fp - fname + 1, fname);
- memmove(fname, fp + 1, strlen(fp));
- lc = cname[0] ? XawGetDisplayListClass(cname) : xlibc;
- if (!lc)
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "Cannot find displayList class \"%s\"", cname);
- XtAppWarning(XtDisplayToApplicationContext
- (DisplayOfScreen(screen)), msg);
- XawDestroyDisplayList(dlist);
- return (NULL);
- }
- }
- else
- lc = xlibc;
-
- if (status == DLEOF && !fname[0])
- break;
-
- if ((info = _XawFindDLInfo(lc, fname)) == NULL)
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "Cannot find displayList procedure \"%s\"", fname);
- XtAppWarning(XtDisplayToApplicationContext(DisplayOfScreen(screen)),
- msg);
- XawDestroyDisplayList(dlist);
- return (NULL);
- }
-
- proc = (XawDLProc *)XtMalloc(sizeof(XawDLProc));
- proc->qname = info->qname;
- proc->params = NULL;
- proc->num_params = 0;
- proc->proc = info->proc;
- proc->args = NULL;
- proc->data = NULL;
-
- if (!dlist->procs)
- {
- dlist->num_procs = 1;
- dlist->procs = (XawDLProc**)XtMalloc(sizeof(XawDLProc*));
- }
- else
- {
- ++dlist->num_procs;
- dlist->procs = (XawDLProc**)
- XtRealloc((char *)dlist->procs, sizeof(XawDLProc*) *
- dlist->num_procs);
- }
- dlist->procs[dlist->num_procs - 1] = proc;
-
- while (status != DLEND && status != DLEOF)
- {
- lp = cp;
- cp = read_token(cp, aname, sizeof(aname), &status);
-
- if (status != DLARG && status != DLEND && status != DLEOF)
- {
- char msg[256];
-
- XmuSnprintf(msg, sizeof(msg),
- "Error parsing displayList at \"%s\"", lp);
- XtAppWarning(XtDisplayToApplicationContext
- (DisplayOfScreen(screen)), msg);
- XawDestroyDisplayList(dlist);
- return (NULL);
- }
-
- if (!proc->num_params)
- {
- proc->num_params = 1;
- proc->params = (String *)XtMalloc(sizeof(String));
- }
- else
- {
- ++proc->num_params;
- proc->params = (String *)XtRealloc((char *)proc->params,
- sizeof(String) *
- proc->num_params);
- }
- proc->params[proc->num_params - 1] = XtNewString(aname);
- }
-
- /* verify if data is already created for lc */
- data = NULL;
- for (i = 0; i < dlist->num_data; i++)
- if (dlist->data[i]->dlclass == lc)
- {
- data = dlist->data[i];
- break;
- }
-
- if (!data)
- {
- data = (XawDLData *)XtMalloc(sizeof(XawDLData));
- data->dlclass = lc;
- if (lc->data_init)
- data->data = lc->data_init(lc->name, screen, colormap, depth);
- else
- data->data = NULL;
-
- if (!dlist->data)
- {
- dlist->num_data = 1;
- dlist->data = (XawDLData **)XtMalloc(sizeof(XawDLData*));
- }
- else
- {
- ++dlist->num_data;
- dlist->data = (XawDLData **)
- XtRealloc((char *)dlist->data, sizeof(XawDLData*) *
- dlist->num_data);
- }
- dlist->data[dlist->num_data - 1] = data;
- }
-
- if (lc->args_init)
- {
- proc->args = lc->args_init(fname, proc->params, &proc->num_params,
- screen, colormap, depth);
- if (proc->args == XAWDL_CONVERT_ERROR)
- {
- char msg[256];
-
- proc->args = NULL;
- XmuSnprintf(msg, sizeof(msg),
- "Cannot convert arguments to displayList function \"%s\"", fname);
- XtAppWarning(XtDisplayToApplicationContext
- (DisplayOfScreen(screen)), msg);
- XawDestroyDisplayList(dlist);
- return (NULL);
- }
- }
- else
- proc->args = NULL;
-
- proc->data = data;
- }
-
- dlist->qrep = XrmStringToQuark(string);
- return (dlist);
-}
-
-String
-XawDisplayListString(_XawDisplayList *dlist)
-{
- if (!dlist || dlist->qrep == NULLQUARK)
- return ("");
- return (XrmQuarkToString(dlist->qrep));
-}
-
-void
-XawDestroyDisplayList(_XawDisplayList *dlist)
-{
- Cardinal i, j;
- XawDLProc *proc;
- XawDLData *data;
-
- if (!dlist)
- return;
-
- for (i = 0; i < dlist->num_procs; i++)
- {
- proc = dlist->procs[i];
- data = proc->data;
-
- if (data)
- {
- if (data->dlclass->args_destructor)
- data->dlclass->args_destructor(DisplayOfScreen(dlist->screen),
- XrmQuarkToString(proc->qname),
- proc->args,
- proc->params, &proc->num_params);
- if (data->data)
- {
- if (data->dlclass->data_destructor)
- {
- data->dlclass
- ->data_destructor(DisplayOfScreen(dlist->screen),
- data->dlclass->name, data->data);
- data->data = NULL;
- }
- }
- }
-
- for (j = 0; j < proc->num_params; j++)
- XtFree(proc->params[j]);
- if (proc->num_params)
- XtFree((char *)proc->params);
- XtFree((char *)proc);
- }
-
- if (dlist->num_procs)
- XtFree((char *)dlist->procs);
-
- XtFree((char *)dlist);
-}
-
-/**********************************************************************
- * If you want to implement your own class of procedures, look at
- * the code bellow.
- **********************************************************************/
-/* Start of Implementation of class "xlib" */
-typedef struct _XawXlibData {
- GC gc;
- unsigned long mask;
- XGCValues values;
- int shape;
- int mode;
- char *dashes;
- /* these fields can be used for optimization, to
- * avoid unnecessary coordinates recalculation.
- */
- Position x, y;
- Dimension width, height;
-} XawXlibData;
-
-typedef struct _XawDLPosition {
- Position pos;
- short denom;
- Boolean high;
-} XawDLPosition;
-
-typedef struct _XawDLPositionPtr {
- XawDLPosition *pos;
- Cardinal num_pos;
-} XawDLPositionPtr;
-
-typedef struct _XawDLArcArgs {
- XawDLPosition pos[4];
- int angle1;
- int angle2;
-} XawDLArcArgs;
-
-typedef struct _XawDLStringArgs {
- XawDLPosition pos[2];
- char *string;
- int length;
-} XawDLStringArgs;
-
-typedef struct _XawDLCopyArgs {
- XawPixmap *pixmap;
- XawDLPosition pos[6];
- int plane;
-} XawDLCopyArgs;
-
-typedef struct _XawDLImageArgs {
- XawPixmap *pixmap;
- XawDLPosition pos[4];
- int depth;
-} XawDLImageArgs;
-
-#define X_ARG(x) (Position)(((x).denom != 0) ? \
- ((float)XtWidth(w) * ((float)(x).pos / (float)(x).denom)) : \
- ((x).high ? XtWidth(w) - (x).pos : (x).pos))
-#define Y_ARG(x) (Position)(((x).denom != 0) ? \
- ((float)XtHeight(w) * ((float)(x).pos / (float)(x).denom)): \
- ((x).high ? XtHeight(w) - (x).pos : (x).pos))
-#define DRECT 0
-#define FRECT 1
-#define LINE 2
-#define GCFG 3
-#define GCBG 4
-#define FPOLY 5
-#define DARC 6
-#define FARC 7
-#define DLINES 8
-#define MASK 9
-#define UMASK 10
-#define LWIDTH 11
-#define POINT 12
-#define POINTS 13
-#define SEGMENTS 14
-#define ARCMODE 15
-#define COORDMODE 16
-#define SHAPEMODE 17
-#define LINESTYLE 18
-#define CAPSTYLE 19
-#define JOINSTYLE 20
-#define FILLSTYLE 21
-#define FILLRULE 22
-#define TILE 23
-#define STIPPLE 24
-#define TSORIGIN 25
-#define FUNCTION 26
-#define PLANEMASK 27
-#define DSTRING 28
-#define PSTRING 29
-#define FONT 30
-#define DASHES 31
-#define SUBWMODE 32
-#define EXPOSURES 33
-#define CLIPORIGIN 34
-#define CLIPMASK 35
-#define CLIPRECTS 36
-#define COPYAREA 37
-#define COPYPLANE 38
-#define IMAGE 39
-
-static void
-Dl1Point(Widget w, XtPointer args, XtPointer data, int id)
-{
- XawDLPosition *pos = (XawDLPosition *)args;
- XawXlibData *xdata = (XawXlibData *)data;
- Display *display;
- Window window;
- Position x, y;
-
- x = X_ARG(pos[0]);
- y = Y_ARG(pos[1]);
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- x += xpad;
- y += ypad;
- display = XtDisplayOfObject(w);
- window = XtWindowOfObject(w);
- }
- else
- {
- display = XtDisplay(w);
- window = XtWindow(w);
- }
-
- if (id == POINT)
- XDrawPoint(display, window, xdata->gc, x, y);
- else if (id == TSORIGIN)
- {
- xdata->values.ts_x_origin = x;
- xdata->values.ts_y_origin = y;
- xdata->mask |= GCTileStipXOrigin | GCTileStipYOrigin;
- XSetTSOrigin(display, xdata->gc, x, y);
- }
- else if (id == CLIPORIGIN)
- {
- xdata->values.clip_x_origin = x;
- xdata->values.clip_y_origin = y;
- xdata->mask |= GCClipXOrigin | GCClipYOrigin;
- XSetClipOrigin(display, xdata->gc, x, y);
- }
-}
-
-static void
-Dl2Points(Widget w, XtPointer args, XtPointer data, int id)
-{
- XawDLPosition *pos = (XawDLPosition *)args;
- XawXlibData *xdata = (XawXlibData *)data;
- Display *display;
- Window window;
- Position x1, y1, x2, y2;
-
- x1 = X_ARG(pos[0]);
- y1 = Y_ARG(pos[1]);
- x2 = X_ARG(pos[2]);
- y2 = Y_ARG(pos[3]);
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- x1 += xpad; y1 += ypad;
- x2 += xpad; y2 += ypad;
- display = XtDisplayOfObject(w);
- window = XtWindowOfObject(w);
- }
- else
- {
- display = XtDisplay(w);
- window = XtWindow(w);
- }
-
- if (id == DRECT)
- XDrawRectangle(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1);
- else if (id == FRECT)
- XFillRectangle(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1);
- else if (id == LINE)
- XDrawLine(display, window, xdata->gc, x1, y1, x2, y2);
-}
-
-/* ARGSUSED */
-static void
-DlLine(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
-{
- Dl2Points(w, args, data, LINE);
-}
-
-/* ARGSUSED */
-static void
-DlDrawRectangle(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- Dl2Points(w, args, data, DRECT);
-}
-
-/* ARGSUSED */
-static void
-DlFillRectangle(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- Dl2Points(w, args, data, FRECT);
-}
-
-static void
-DlXPoints(Widget w, XtPointer args, XtPointer data, int id)
-{
- XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args;
- XawXlibData *xdata = (XawXlibData *)data;
- XawDLPosition *pos;
- XPoint points_buf[16];
- XPoint *points;
- Display *display;
- Window window;
- Cardinal num_points, i, j;
-
- num_points = pos_ptr->num_pos>>1;
- points = (XPoint *)XawStackAlloc(sizeof(XPoint) * num_points, points_buf);
-
- for (i = j = 0; i < num_points; i++, j = i << 1)
- {
- pos = &pos_ptr->pos[j];
- points[i].x = X_ARG(pos[0]);
- points[i].y = Y_ARG(pos[1]);
- }
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- if (xdata->mode != CoordModePrevious)
- {
- for (i = 0; i < num_points; i++)
- {
- points[i].x += xpad;
- points[i].y += ypad;
- }
- }
- else
- {
- points[0].x += xpad;
- points[0].y += ypad;
- }
- display = XtDisplayOfObject(w);
- window = XtWindowOfObject(w);
- }
- else
- {
- display = XtDisplay(w);
- window = XtWindow(w);
- }
-
- if (id == FPOLY)
- XFillPolygon(display, window, xdata->gc, points, num_points,
- xdata->shape, xdata->mode);
- else if (id == DLINES)
- XDrawLines(display, window, xdata->gc, points, num_points, xdata->mode);
- else if (id == POINTS)
- XDrawPoints(display, window, xdata->gc, points, num_points, xdata->mode);
-
- XawStackFree(points, points_buf);
-}
-
-/* ARGSUSED */
-static void
-DlFillPolygon(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlXPoints(w, args, data, FPOLY);
-}
-
-/* ARGSUSED */
-static void
-DlDrawLines(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlXPoints(w, args, data, DLINES);
-}
-
-/* ARGSUSED */
-static void
-DlDrawPoints(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlXPoints(w, args, data, POINTS);
-}
-
-/* ARGSUSED */
-static void
-DlForeground(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- Pixel foreground = (Pixel)args;
-
- if (xdata->values.foreground != foreground)
- {
- xdata->mask |= GCForeground;
- xdata->values.foreground = foreground;
- XSetForeground(XtDisplayOfObject(w), xdata->gc, foreground);
- }
-}
-
-/* ARGSUSED */
-static void
-DlBackground(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- Pixel background = (Pixel)args;
-
- if (xdata->values.background != background)
- {
- xdata->mask |= GCBackground;
- xdata->values.background = background;
- XSetBackground(XtDisplayOfObject(w), xdata->gc, background);
- }
-}
-
-static void
-DlArc(Widget w, XtPointer args, XtPointer data, Bool fill)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- XawDLArcArgs *arc = (XawDLArcArgs *)args;
- Position x1, y1, x2, y2;
- Display *display;
- Window window;
-
- x1 = X_ARG(arc->pos[0]);
- y1 = Y_ARG(arc->pos[1]);
- x2 = X_ARG(arc->pos[2]);
- y2 = Y_ARG(arc->pos[3]);
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- x1 += xpad;
- y1 += ypad;
- x2 += xpad;
- y2 += ypad;
- display = XtDisplayOfObject(w);
- window = XtWindowOfObject(w);
- }
- else
- {
- display = XtDisplay(w);
- window = XtWindow(w);
- }
-
- if (fill)
- XFillArc(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1,
- arc->angle1, arc->angle2);
- else
- XDrawArc(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1,
- arc->angle1, arc->angle2);
-}
-
-/* ARGSUSED */
-static void
-DlDrawArc(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlArc(w, args, data, False);
-}
-
-/* ARGSUSED */
-static void
-DlFillArc(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlArc(w, args, data, True);
-}
-
-/*ARGSUSED*/
-static void
-DlMask(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- Display *display = XtDisplayOfObject(w);
-
- if (region)
- XSetRegion(display, xdata->gc, region);
- else if (event)
- {
- XRectangle rect;
-
- rect.x = event->xexpose.x;
- rect.y = event->xexpose.y;
- rect.width = event->xexpose.width;
- rect.height = event->xexpose.height;
- XSetClipRectangles(display, xdata->gc, 0, 0, &rect, 1, Unsorted);
- }
-}
-
-/* ARGSUSED */
-static void
-DlUmask(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
-
- XSetClipMask(XtDisplayOfObject(w), xdata->gc, None);
-}
-
-/* ARGSUSED */
-static void
-DlLineWidth(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- unsigned line_width = (unsigned long)args;
-
- if (xdata->values.line_width != line_width)
- {
- xdata->mask |= GCLineWidth;
- xdata->values.line_width = line_width;
- XChangeGC(XtDisplayOfObject(w), xdata->gc, GCLineWidth, &xdata->values);
- }
-}
-
-/* ARGSUSED */
-static void
-DlDrawPoint(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
-{
- Dl1Point(w, args, data, POINT);
-}
-
-/* ARGSUSED */
-static void
-DlDrawSegments(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args;
- XawXlibData *xdata = (XawXlibData *)data;
- XawDLPosition *pos;
- XSegment *segments;
- XSegment segments_buf[8];
- Display *display;
- Window window;
- Cardinal num_segments, i, j;
-
- num_segments = pos_ptr->num_pos>>2;
- segments = (XSegment *)XawStackAlloc(sizeof(XSegment) * num_segments, segments_buf);
-
- for (i = j = 0; i < num_segments; i++, j = i << 2)
- {
- pos = &pos_ptr->pos[j];
- segments[i].x1 = X_ARG(pos[0]);
- segments[i].y1 = Y_ARG(pos[1]);
- segments[i].x2 = X_ARG(pos[2]);
- segments[i].y2 = Y_ARG(pos[3]);
- }
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- for (i = 0; i < num_segments; i++)
- {
- segments[i].x1 += xpad;
- segments[i].y1 += ypad;
- segments[i].x2 += xpad;
- segments[i].y2 += ypad;
- }
- display = XtDisplayOfObject(w);
- window = XtWindowOfObject(w);
- }
- else
- {
- display = XtDisplay(w);
- window = XtWindow(w);
- }
-
- XDrawSegments(display, window, xdata->gc, segments, num_segments);
-
- XawStackFree(segments, segments_buf);
-}
-
-/* ARGSUSED */
-static void
-DlArcMode(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int arc_mode = (long)args;
-
- if (xdata->values.arc_mode != arc_mode)
- {
- xdata->mask |= GCArcMode;
- xdata->values.arc_mode = arc_mode;
- XSetArcMode(XtDisplayOfObject(w), xdata->gc, arc_mode);
- }
-}
-
-/* ARGSUSED */
-static void
-DlCoordMode(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int mode = (long)args;
-
- xdata->mode = mode;
-}
-
-/* ARGSUSED */
-static void
-DlShapeMode(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int shape = (long)args;
-
- xdata->shape = shape;
-}
-
-/* ARGSUSED */
-static void
-DlLineStyle(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int line_style = (long)args;
-
- if (xdata->values.line_style != line_style)
- {
- xdata->mask |= GCLineStyle;
- xdata->values.line_style = line_style;
- XChangeGC(XtDisplayOfObject(w), xdata->gc, GCLineStyle, &xdata->values);
- }
-}
-
-/* ARGSUSED */
-static void
-DlCapStyle(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int cap_style = (long)args;
-
- if (xdata->values.cap_style != cap_style)
- {
- xdata->mask |= GCCapStyle;
- xdata->values.cap_style = cap_style;
- XChangeGC(XtDisplayOfObject(w), xdata->gc, GCCapStyle, &xdata->values);
- }
-}
-
-/* ARGSUSED */
-static void
-DlJoinStyle(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int join_style = (long)args;
-
- if (xdata->values.join_style != join_style)
- {
- xdata->mask |= GCJoinStyle;
- xdata->values.join_style = join_style;
- XChangeGC(XtDisplayOfObject(w), xdata->gc, GCJoinStyle, &xdata->values);
- }
-}
-
-/* ARGSUSED */
-static void
-DlFillStyle(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int fill_style = (long)args;
-
- if (xdata->values.fill_style != fill_style)
- {
- xdata->mask |= GCFillStyle;
- xdata->values.fill_style = fill_style;
- XSetFillStyle(XtDisplayOfObject(w), xdata->gc, fill_style);
- }
-}
-
-/* ARGSUSED */
-static void
-DlFillRule(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int fill_rule = (long)args;
-
- if (xdata->values.fill_rule != fill_rule)
- {
- xdata->mask |= GCFillRule;
- xdata->values.fill_rule = fill_rule;
- XSetFillRule(XtDisplayOfObject(w), xdata->gc, fill_rule);
- }
-}
-
-/* ARGSUSED */
-static void
-DlTile(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- XawPixmap *pixmap = (XawPixmap *)args;
-
- if (pixmap && xdata->values.tile != pixmap->pixmap)
- {
- xdata->mask |= GCTile;
- xdata->values.tile = pixmap->pixmap;
- XSetTile(XtDisplayOfObject(w), xdata->gc, xdata->values.tile);
- }
-}
-
-/* ARGSUSED */
-static void
-DlStipple(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- XawPixmap *pixmap = (XawPixmap *)args;
-
- if (pixmap && xdata->values.stipple != pixmap->pixmap)
- {
- xdata->mask |= GCStipple;
- xdata->values.stipple = pixmap->pixmap;
- XSetStipple(XtDisplayOfObject(w), xdata->gc, xdata->values.stipple);
- }
-}
-
-/* ARGSUSED */
-static void
-DlTSOrigin(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
-{
- Dl1Point(w, args, data, TSORIGIN);
-}
-
-/* ARGSUSED */
-static void
-DlFunction(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int function = (long)args;
-
- if (function != xdata->values.function)
- {
- xdata->mask |= GCFunction;
- xdata->values.function = function;
- XSetFunction(XtDisplayOfObject(w), xdata->gc, function);
- }
-}
-
-/* ARGSUSED */
-static void
-DlPlaneMask(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- unsigned long plane_mask = (unsigned long)args;
-
- if (xdata->values.plane_mask != plane_mask)
- {
- xdata->mask |= GCPlaneMask;
- xdata->values.plane_mask = plane_mask;
- XSetPlaneMask(XtDisplayOfObject(w), xdata->gc, plane_mask);
- }
-}
-
-static void
-DlString(Widget w, XtPointer args, XtPointer data, Bool image)
-{
- XawDLStringArgs *string = (XawDLStringArgs *)args;
- XawXlibData *xdata = (XawXlibData *)data;
- Display *display;
- Window window;
- Position x, y;
-
- x = X_ARG(string->pos[0]);
- y = Y_ARG(string->pos[1]);
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- x += xpad;
- y += ypad;
- display = XtDisplayOfObject(w);
- window = XtWindowOfObject(w);
- }
- else
- {
- display = XtDisplay(w);
- window = XtWindow(w);
- }
-
- if (image)
- XDrawImageString(display, window, xdata->gc, x, y, string->string, string->length);
- else
- XDrawString(display, window, xdata->gc, x, y, string->string, string->length);
-}
-
-/* ARGSUSED */
-static void
-DlDrawString(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlString(w, args, data, False);
-}
-
-/* ARGSUSED */
-static void
-DlPaintString(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlString(w, args, data, True);
-}
-
-/* ARGSUSED */
-static void
-DlFont(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- Font font = (Font)args;
-
- if (xdata->values.font != font)
- {
- xdata->mask |= GCFont;
- xdata->values.font = font;
- XSetFont(XtDisplayOfObject(w), xdata->gc, font);
- }
-}
-
-/* ARGSUSED */
-static void
-DlDashes(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- char *dashes = args;
-
- if (xdata->dashes != dashes)
- {
- xdata->mask |= GCDashOffset | GCDashList;
- xdata->dashes = dashes;
- XSetDashes(XtDisplayOfObject(w), xdata->gc, 0, dashes + 1, *dashes);
- }
-}
-
-/* ARGSUSED */
-static void
-DlSubwindowMode(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- int subwindow_mode = (long)args;
-
- if (xdata->values.subwindow_mode != subwindow_mode)
- {
- xdata->mask |= GCSubwindowMode;
- xdata->values.subwindow_mode = subwindow_mode;
- XSetSubwindowMode(XtDisplayOfObject(w), xdata->gc, subwindow_mode);
- }
-}
-
-/* ARGSUSED */
-static void
-DlExposures(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- Bool graphics_exposures = (Bool)(long)args;
-
- if (xdata->values.graphics_exposures != graphics_exposures)
- {
- xdata->mask |= GCGraphicsExposures;
- xdata->values.graphics_exposures = graphics_exposures;
- XSetGraphicsExposures(XtDisplayOfObject(w), xdata->gc, graphics_exposures);
- }
-}
-
-/* ARGSUSED */
-static void
-DlClipOrigin(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
-{
- Dl1Point(w, args, data, CLIPORIGIN);
-}
-
-/* ARGSUSED */
-static void
-DlClipMask(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawXlibData *xdata = (XawXlibData *)data;
- XawPixmap *pixmap = (XawPixmap *)args;
- Pixmap clip_mask;
-
- if (pixmap)
- clip_mask = pixmap->mask ? pixmap->mask : pixmap->pixmap;
- else
- clip_mask = None;
-
- if (xdata->values.clip_mask != clip_mask)
- {
- xdata->mask |= GCClipMask;
- XSetClipMask(XtDisplayOfObject(w), xdata->gc, clip_mask);
- }
-}
-
-/* ARGSUSED */
-static void
-DlClipRectangles(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args;
- XawXlibData *xdata = (XawXlibData *)data;
- XawDLPosition *pos;
- XRectangle *rects;
- XRectangle rects_buf[8];
- Position x1, y1, x2, y2;
- Cardinal num_rects, i, j;
-
- num_rects = pos_ptr->num_pos>>2;
- rects = (XRectangle *)XawStackAlloc(sizeof(XRectangle) * num_rects, rects_buf);
-
- for (i = j = 0; i < num_rects; i++, j = i << 2)
- {
- pos = &pos_ptr->pos[j];
- x1 = X_ARG(pos[0]);
- y1 = Y_ARG(pos[1]);
- x2 = X_ARG(pos[2]);
- y2 = Y_ARG(pos[3]);
- rects[i].x = XawMin(x1, x2);
- rects[i].y = XawMin(y1, y2);
- rects[i].width = XawMax(x1, x2) - rects[i].x;
- rects[i].height = XawMax(y1, y2) - rects[i].y;
- }
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- for (i = 0; i < num_rects; i++)
- {
- rects[i].x += xpad;
- rects[i].y += ypad;
- }
- }
-
- XSetClipRectangles(XtDisplayOfObject(w), xdata->gc, 0, 0, rects, num_rects, Unsorted);
-
- XawStackFree(rects, rects_buf);
-}
-
-static void
-DlCopy(Widget w, XtPointer args, XtPointer data, Bool plane)
-{
- XawDLCopyArgs *copy = (XawDLCopyArgs *)args;
- XawXlibData *xdata = (XawXlibData *)data;
- int src_x, src_y, dst_x, dst_y, width, height, tmp1, tmp2;
-
- tmp1 = X_ARG(copy->pos[0]);
- tmp2 = X_ARG(copy->pos[2]);
- dst_x = XawMin(tmp1, tmp2);
- width = XawMax(tmp1, tmp2) - dst_x;
-
- tmp1 = Y_ARG(copy->pos[1]);
- tmp2 = Y_ARG(copy->pos[3]);
- dst_y = XawMin(tmp1, tmp2);
- height = XawMax(tmp1, tmp2) - dst_y;
-
- src_x = X_ARG(copy->pos[4]);
- src_y = Y_ARG(copy->pos[5]);
-
- if (width <= 0)
- {
- if (copy->pixmap)
- width = copy->pixmap->width;
- else
- {
- if ((width = XtWidth(w) - src_x) < 0)
- width = 0;
- }
- }
- if (height <= 0)
- {
- if (copy->pixmap)
- height = copy->pixmap->height;
- else
- {
- if ((height = XtHeight(w) - src_y) < 0)
- height = 0;
- }
- }
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- src_x += xpad;
- src_y += ypad;
- dst_x += xpad;
- dst_y += ypad;
- }
-
- if (plane)
- XCopyPlane(XtDisplayOfObject(w), XtWindowOfObject(w),
- copy->pixmap ? copy->pixmap->pixmap : XtWindowOfObject(w),
- xdata->gc, src_x, src_y, width, height, dst_x, dst_y,
- copy->plane ? copy->plane : 1);
- else
- XCopyArea(XtDisplayOfObject(w),
- copy->pixmap ? copy->pixmap->pixmap : XtWindowOfObject(w),
- XtWindowOfObject(w), xdata->gc, src_x, src_y, width, height, dst_x, dst_y);
-}
-
-/* ARGSUSED */
-static void
-DlCopyArea(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlCopy(w, args, data, False);
-}
-
-/* ARGSUSED */
-static void
-DlCopyPlane(Widget w, XtPointer args, XtPointer data,
- XEvent *event, Region region)
-{
- DlCopy(w, args, data, True);
-}
-
-/*ARGSUSED*/
-/* Note:
- * This function is destructive if you set the ts_x_origin, ts_y_origin,
- * and/or clip-mask. It is meant to be the only function used in a display
- * list. If you need to use other functions (and those values), be sure to
- * set them after calling this function.
- */
-static void
-DlImage(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
-{
- XawDLImageArgs *image = (XawDLImageArgs *)args;
- XawXlibData *xdata = (XawXlibData *)data;
- int x, y, xs, ys, xe, ye, width, height;
- Display *display;
- Window window;
-
- width = image->pixmap->width;
- height = image->pixmap->height;
- xs = X_ARG(image->pos[0]);
- ys = Y_ARG(image->pos[1]);
- xe = X_ARG(image->pos[2]);
- ye = Y_ARG(image->pos[3]);
-
- if (xe <= 0)
- xe = xs + width;
- if (ye <= 0)
- ye = ys + height;
-
- if (!XtIsWidget(w))
- {
- Position xpad, ypad;
-
- xpad = XtX(w) + XtBorderWidth(w);
- ypad = XtY(w) + XtBorderWidth(w);
- xe += xpad;
- ye += ypad;
- xe += xpad;
- ye += ypad;
- display = XtDisplayOfObject(w);
- window = XtWindowOfObject(w);
- }
- else
- {
- display = XtDisplay(w);
- window = XtWindow(w);
- }
-
- for (y = ys; y < ye; y += height)
- for (x = xs; x < xe; x += width)
- {
- XSetClipOrigin(display, xdata->gc, x, y);
- if (image->pixmap->mask)
- XSetClipMask(display, xdata->gc, image->pixmap->mask);
- if (image->depth == 1)
- XCopyPlane(display, image->pixmap->pixmap, window, xdata->gc,
- 0, 0, XawMin(width, xe - x), XawMin(height, ye - y),
- x, y, 1L);
- else
- XCopyArea(display, image->pixmap->pixmap, window, xdata->gc, 0, 0,
- XawMin(width, xe - x), XawMin(height, ye - y), x, y);
- }
-
- XSetClipMask(display, xdata->gc, None);
-}
-
-typedef struct _Dl_init Dl_init;
-struct _Dl_init {
- String name;
- XawDisplayListProc proc;
- Cardinal id;
-};
-
-static Dl_init dl_init[] =
-{
- {"arc-mode", DlArcMode, ARCMODE},
- {"background", DlBackground, GCBG},
- {"bg", DlBackground, GCBG},
- {"cap-style", DlCapStyle, CAPSTYLE},
- {"clip-mask", DlClipMask, CLIPMASK},
- {"clip-origin", DlClipOrigin, CLIPORIGIN},
- {"clip-rectangles", DlClipRectangles, CLIPRECTS},
- {"clip-rects", DlClipRectangles, CLIPRECTS},
- {"coord-mode", DlCoordMode, COORDMODE},
- {"copy-area", DlCopyArea, COPYAREA},
- {"copy-plane", DlCopyPlane, COPYPLANE},
- {"dashes", DlDashes, DASHES},
- {"draw-arc", DlDrawArc, DARC},
- {"draw-line", DlLine, LINE},
- {"draw-lines", DlDrawLines, DLINES},
- {"draw-point", DlDrawPoint, POINT},
- {"draw-points", DlDrawPoints, POINTS},
- {"draw-rect", DlDrawRectangle, DRECT},
- {"draw-rectangle", DlDrawRectangle, DRECT},
- {"draw-segments", DlDrawSegments, SEGMENTS},
- {"draw-string", DlDrawString, DSTRING},
- {"exposures", DlExposures, EXPOSURES},
- {"fg", DlForeground, GCFG},
- {"fill-arc", DlFillArc, FARC},
- {"fill-poly", DlFillPolygon, FPOLY},
- {"fill-polygon", DlFillPolygon, FPOLY},
- {"fill-rect", DlFillRectangle, FRECT},
- {"fill-rectangle", DlFillRectangle, FRECT},
- {"fill-rule", DlFillRule, FILLRULE},
- {"fill-style", DlFillStyle, FILLSTYLE},
- {"font", DlFont, FONT},
- {"foreground", DlForeground, GCFG},
- {"function", DlFunction, FUNCTION},
- {"image", DlImage, IMAGE},
- {"join-style", DlJoinStyle, JOINSTYLE},
- {"line", DlLine, LINE},
- {"line-style", DlLineStyle, LINESTYLE},
- {"line-width", DlLineWidth, LWIDTH},
- {"lines", DlDrawLines, DLINES},
- {"mask", DlMask, MASK},
- {"paint-string", DlPaintString, PSTRING},
- {"plane-mask", DlPlaneMask, PLANEMASK},
- {"point", DlDrawPoint, POINT},
- {"points", DlDrawPoints, POINTS},
- {"segments", DlDrawSegments, SEGMENTS},
- {"shape-mode", DlShapeMode, SHAPEMODE},
- {"stipple", DlStipple, STIPPLE},
- {"subwindow-mode", DlSubwindowMode, SUBWMODE},
- {"tile", DlTile, TILE},
- {"ts-origin", DlTSOrigin, TSORIGIN},
- {"umask", DlUmask, UMASK},
-};
-
-void
-XawDisplayListInitialize(void)
-{
- static Bool first_time = True;
- XawDLClass *lc;
- Cardinal i;
-
- if (first_time == False)
- return;
-
- first_time = False;
-
- lc = XawCreateDisplayListClass(xlib,
- _Xaw_Xlib_ArgsInitProc,
- _Xaw_Xlib_ArgsDestructor,
- _Xaw_Xlib_DataInitProc,
- _Xaw_Xlib_DataDestructor);
- for (i = 0; i < sizeof(dl_init) / sizeof(dl_init[0]); i++)
- (void)XawDeclareDisplayListProc(lc, dl_init[i].name, dl_init[i].proc);
-}
-
-static int
-bcmp_cvt_proc(register _Xconst void *string,
- register _Xconst void *dlinfo)
-{
- return (strcmp((String)string, ((Dl_init*)dlinfo)->name));
-}
-
-static long
-read_int(char *cp, char **cpp)
-{
- long value = 0, sign = 1;
-
- if (*cp == '-')
- {
- sign = -1;
- ++cp;
- }
- else if (*cp == '+')
- ++cp;
- value = 0;
- while (*cp >= '0' && *cp <= '9')
- {
- value = value * 10 + *cp - '0';
- ++cp;
- }
- if (cpp)
- *cpp = cp;
- return (value * sign);
-}
-
-static void
-read_position(char *arg, XawDLPosition *pos)
-{
- int ch;
- char *str = arg;
-
- ch = *str;
- if (ch == '-' || ch == '+')
- {
- ++str;
- if (ch == '-')
- pos->high = True;
- pos->pos = read_int(str, NULL);
- }
- else if (isdigit(ch))
- {
- pos->pos = read_int(str, &str);
- ch = *str++;
- if (ch == '/')
- pos->denom = read_int(str, NULL);
- }
-}
-
-/* ARGSUSED */
-static void *
-_Xaw_Xlib_ArgsInitProc(String proc_name, String *params, Cardinal *num_params,
- Screen *screen, Colormap colormap, int depth)
-{
- Cardinal id, i;
- Dl_init *init;
- void *retval = XAWDL_CONVERT_ERROR;
-
- init = (Dl_init *)bsearch(proc_name, dl_init,
- sizeof(dl_init) / sizeof(dl_init[0]),
- sizeof(dl_init[0]),
- bcmp_cvt_proc);
-
- id = init->id;
-
- switch (id)
- {
- case LINE:
- case DRECT:
- case FRECT:
- if (*num_params == 4)
- {
- XawDLPosition *pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) * 4);
-
- for (i = 0; i < 4; i++)
- read_position(params[i], &pos[i]);
- retval = (void *)pos;
- }
- break;
- case POINT:
- case TSORIGIN:
- case CLIPORIGIN:
- if (*num_params == 2)
- {
- XawDLPosition *pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) * 2);
-
- read_position(params[0], &pos[0]);
- read_position(params[1], &pos[1]);
- retval = (void *)pos;
- }
- break;
- case DLINES:
- case FPOLY:
- case POINTS:
- if (*num_params >= 4 && !(*num_params & 1))
- {
- XawDLPositionPtr *pos = XtNew(XawDLPositionPtr);
-
- pos->pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) *
- *num_params);
- pos->num_pos = *num_params;
- for (i = 0; i < *num_params; i++)
- read_position(params[i], &pos->pos[i]);
- retval = (void *)pos;
- }
- break;
- case SEGMENTS:
- case CLIPRECTS:
- if (*num_params >= 4 && !(*num_params % 4))
- {
- XawDLPositionPtr *pos = XtNew(XawDLPositionPtr);
-
- pos->pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) *
- *num_params);
- pos->num_pos = *num_params;
- for (i = 0; i < *num_params; i++)
- read_position(params[i], &pos->pos[i]);
- retval = (void *)pos;
- }
- break;
- case DARC:
- case FARC:
- if (*num_params >= 4 && *num_params <= 6)
- {
- XawDLArcArgs *args = (XawDLArcArgs *)XtCalloc(1, sizeof(XawDLArcArgs));
-
- args->angle1 = 0;
- args->angle2 = 360;
- for (i = 0; i < 4; i++)
- read_position(params[i], &args->pos[i]);
- if (*num_params > 4)
- args->angle1 = read_int(params[4], NULL);
- if (*num_params > 5)
- args->angle2 = read_int(params[5], NULL);
- args->angle1 *= 64;
- args->angle2 *= 64;
- retval = (void *)args;
- }
- break;
- case GCFG:
- case GCBG:
- {
- XColor xcolor;
-
- if (*num_params == 1 &&
- XAllocNamedColor(DisplayOfScreen(screen), colormap,
- params[0], &xcolor, &xcolor))
- retval = (void *)xcolor.pixel;
- } break;
- case MASK:
- case UMASK:
- if (*num_params == 0)
- retval = NULL;
- break;
- case LWIDTH:
- if (*num_params == 1)
- retval = (void *)read_int(params[0], NULL);
- break;
- case ARCMODE:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "pieslice") == 0)
- retval = (void *)ArcPieSlice;
- else if (XmuCompareISOLatin1(params[0], "chord") == 0)
- retval = (void *)ArcChord;
- }
- break;
- case COORDMODE:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "origin") == 0)
- retval = (void *)CoordModeOrigin;
- else if (XmuCompareISOLatin1(params[0], "previous") == 0)
- retval = (void *)CoordModePrevious;
- }
- break;
- case SHAPEMODE:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "complex") == 0)
- retval = (void *)Complex;
- else if (XmuCompareISOLatin1(params[0], "convex") == 0)
- retval = (void *)Convex;
- else if (XmuCompareISOLatin1(params[0], "nonconvex") == 0)
- retval = (void *)Nonconvex;
- }
- break;
- case LINESTYLE:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "solid") == 0)
- retval = (void *)LineSolid;
- else if (XmuCompareISOLatin1(params[0], "onoffdash") == 0)
- retval = (void *)LineOnOffDash;
- else if (XmuCompareISOLatin1(params[0], "doubledash") == 0)
- retval = (void *)LineDoubleDash;
- }
- break;
- case CAPSTYLE:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "notlast") == 0)
- retval = (void *)CapNotLast;
- else if (XmuCompareISOLatin1(params[0], "butt") == 0)
- retval = (void *)CapButt;
- else if (XmuCompareISOLatin1(params[0], "round") == 0)
- retval = (void *)CapRound;
- else if (XmuCompareISOLatin1(params[0], "projecting") == 0)
- retval = (void *)CapProjecting;
- }
- break;
- case JOINSTYLE:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "miter") == 0)
- retval = (void *)JoinMiter;
- else if (XmuCompareISOLatin1(params[0], "round") == 0)
- retval = (void *)JoinRound;
- else if (XmuCompareISOLatin1(params[0], "bevel") == 0)
- retval = (void *)JoinBevel;
- }
- break;
- case FILLSTYLE:
- if (*num_params == 1)
- {
- if (*num_params && XmuCompareISOLatin1(params[0], "solid") == 0)
- retval = (void *)FillSolid;
- else if (*num_params && XmuCompareISOLatin1(params[0], "tiled") == 0)
- retval = (void *)FillTiled;
- else if (*num_params && XmuCompareISOLatin1(params[0], "stippled") == 0)
- retval = (void *)FillStippled;
- else if (*num_params && XmuCompareISOLatin1(params[0], "opaquestippled") == 0)
- retval = (void *)FillOpaqueStippled;
- }
- break;
- case FILLRULE:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "evenodd") == 0)
- retval = (void *)EvenOddRule;
- else if (XmuCompareISOLatin1(params[0], "winding") == 0)
- retval = (void *)WindingRule;
- }
- break;
- case TILE:
- if (*num_params == 1)
- retval = (void *)XawLoadPixmap(params[0], screen, colormap, depth);
- if (retval == NULL)
- {
- XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0],
- XtRPixmap);
- retval = XAWDL_CONVERT_ERROR;
- }
- break;
- case STIPPLE:
- if (*num_params == 1)
- retval = (void *)XawLoadPixmap(params[0], screen, colormap, 1);
- if (retval == NULL)
- {
- XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0],
- XtRBitmap);
- retval = XAWDL_CONVERT_ERROR;
- }
- break;
- case FUNCTION:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "set") == 0)
- retval = (void *)GXset;
- else if (XmuCompareISOLatin1(params[0], "clear") == 0)
- retval = (void *)GXclear;
- else if (XmuCompareISOLatin1(params[0], "and") == 0)
- retval = (void *)GXand;
- else if (XmuCompareISOLatin1(params[0], "andreverse") == 0)
- retval = (void *)GXandReverse;
- else if (XmuCompareISOLatin1(params[0], "copy") == 0)
- retval = (void *)GXcopy;
- else if (XmuCompareISOLatin1(params[0], "andinverted") == 0)
- retval = (void *)GXandInverted;
- else if (XmuCompareISOLatin1(params[0], "noop") == 0)
- retval = (void *)GXnoop;
- else if (XmuCompareISOLatin1(params[0], "xor") == 0)
- retval = (void *)GXxor;
- else if (XmuCompareISOLatin1(params[0], "or") == 0)
- retval = (void *)GXor;
- else if (XmuCompareISOLatin1(params[0], "nor") == 0)
- retval = (void *)GXnor;
- else if (XmuCompareISOLatin1(params[0], "equiv") == 0)
- retval = (void *)GXequiv;
- else if (XmuCompareISOLatin1(params[0], "invert") == 0)
- retval = (void *)GXinvert;
- else if (XmuCompareISOLatin1(params[0], "orreverse") == 0)
- retval = (void *)GXorReverse;
- else if (XmuCompareISOLatin1(params[0], "copyinverted") == 0)
- retval = (void *)GXcopyInverted;
- else if (XmuCompareISOLatin1(params[0], "nand") == 0)
- retval = (void *)GXnand;
- }
- break;
- case PLANEMASK:
- if (*num_params == 1)
- retval = (void *)read_int(params[0], NULL);
- break;
- case DSTRING:
- case PSTRING:
- if (*num_params == 3)
- {
- XawDLStringArgs *string = (XawDLStringArgs *)
- XtCalloc(1, sizeof(XawDLStringArgs));
-
- read_position(params[0], &string->pos[0]);
- read_position(params[1], &string->pos[1]);
- string->string = XtNewString(params[2]);
- string->length = strlen(string->string);
- retval = string;
- }
- break;
- case FONT:
- if (*num_params == 1)
- retval = (void *)XLoadFont(DisplayOfScreen(screen), params[0]);
- break;
- case DASHES:
- if (*num_params && *num_params < 127)
- {
- char *dashes;
-
- dashes = XtMalloc(*num_params + 1);
-
- for (i = 0; i < *num_params; i++)
- dashes[i + 1] = read_int(params[i], NULL);
- *dashes = *num_params;
- retval = dashes;
- }
- break;
- case SUBWMODE:
- if (*num_params == 1)
- {
- if (XmuCompareISOLatin1(params[0], "clipbychildren") == 0)
- retval = (void *)ClipByChildren;
- else if (XmuCompareISOLatin1(params[0], "includeinferiors") == 0)
- retval = (void *)IncludeInferiors;
- }
- break;
- case EXPOSURES:
- if (*num_params == 1)
- {
- if (isdigit(params[0][0]) || params[0][0] == '+' || params[0][0] == '-')
- retval = (void *)read_int(params[0], NULL);
- else if (XmuCompareISOLatin1(params[0], "true") == 0 ||
- XmuCompareISOLatin1(params[0], "on") == 0)
- retval = (void *)True;
- else if (XmuCompareISOLatin1(params[0], "false") == 0 ||
- XmuCompareISOLatin1(params[0], "off") == 0)
- retval = (void *)False;
- }
- break;
- case CLIPMASK:
- if (*num_params == 1)
- retval = (void *)XawLoadPixmap(params[0], screen, colormap, 1);
- if (retval == NULL)
- {
- retval = XAWDL_CONVERT_ERROR;
- XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0],
- XtRPixmap);
- }
- break;
- case COPYAREA:
- case COPYPLANE:
- if (*num_params > 2 && *num_params <= 7 + (id == COPYPLANE))
- {
- XawDLCopyArgs *args = (XawDLCopyArgs *)
- XtCalloc(1, sizeof(XawDLCopyArgs));
-
- retval = args;
- if (params[0][0] == '\0' || strcmp(params[0], ".") == 0)
- args->pixmap = NULL;
- else
- {
- args->pixmap = XawLoadPixmap(params[0], screen, colormap, id == COPYPLANE ? 1 : depth);
- if (args->pixmap == NULL)
- {
- XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0],
- XtRBitmap);
- retval = XAWDL_CONVERT_ERROR;
- XtFree((char *)args);
- }
- }
- if (retval != XAWDL_CONVERT_ERROR)
- {
- for (i = 1; i < *num_params && i < 7; i++)
- read_position(params[i], &args->pos[i - 1]);
- if (*num_params > 7)
- args->plane = read_int(params[7], NULL);
- }
- }
- break;
- case IMAGE:
- if (*num_params > 2 && *num_params <= 7)
- {
- XawDLImageArgs *args = (XawDLImageArgs *)
- XtCalloc(1, sizeof(XawDLImageArgs));
-
- retval = args;
- args->pixmap = XawLoadPixmap(params[0], screen, colormap, depth);
- if (args->pixmap == NULL)
- {
- XtDisplayStringConversionWarning(DisplayOfScreen(screen),
- (String)params[0], XtRPixmap);
- retval = XAWDL_CONVERT_ERROR;
- XtFree((char *)args);
- }
- else
- {
- args->depth = depth;
- for (i = 1; i < *num_params && i < 5; i++)
- read_position(params[i], &args->pos[i - 1]);
- }
- }
- break;
- }
-
- return (retval);
-}
-
-/* ARGSUSED */
-static void *
-_Xaw_Xlib_DataInitProc(String class_name,
- Screen *screen, Colormap colormap, int depth)
-{
- XawXlibData *data;
- Window tmp_win;
-
- data = (XawXlibData *)XtMalloc(sizeof(XawXlibData));
-
- tmp_win = XCreateWindow(DisplayOfScreen(screen),
- RootWindowOfScreen(screen),
- 0, 0, 1, 1, 1, depth,
- InputOutput, (Visual *)CopyFromParent, 0, NULL);
- data->mask = 0;
- data->gc = XCreateGC(DisplayOfScreen(screen), tmp_win, 0, &data->values);
- XDestroyWindow(DisplayOfScreen(screen), tmp_win);
- data->shape = Complex;
- data->mode = CoordModeOrigin;
- data->dashes = NULL;
-
- return ((void *)data);
-}
-
-/* ARGSUSED */
-static void
-_Xaw_Xlib_ArgsDestructor(Display *display, String proc_name, XtPointer args,
- String *params, Cardinal *num_params)
-{
- Cardinal id;
- Dl_init *init;
-
- init = (Dl_init *)bsearch(proc_name, dl_init,
- sizeof(dl_init) / sizeof(dl_init[0]),
- sizeof(dl_init[0]),
- bcmp_cvt_proc);
-
- id = init->id;
-
- switch (id)
- {
- case LINE:
- case DRECT:
- case FRECT:
- case DARC:
- case FARC:
- case POINT:
- case TSORIGIN:
- case DASHES:
- case CLIPORIGIN:
- case COPYAREA:
- case COPYPLANE:
- case IMAGE:
- XtFree(args);
- break;
- case DSTRING:
- case PSTRING:
- {
- XawDLStringArgs *string = (XawDLStringArgs *)args;
- XtFree(string->string);
- XtFree(args);
- } break;
- case DLINES:
- case FPOLY:
- case POINTS:
- case SEGMENTS:
- case CLIPRECTS:
- {
- XawDLPositionPtr *ptr = (XawDLPositionPtr *)args;
-
- XtFree((char *)ptr->pos);
- XtFree(args);
- } break;
- }
-}
-
-/* ARGSUSED */
-static void
-_Xaw_Xlib_DataDestructor(Display *display, String class_name, XtPointer data)
-{
- if (data)
- {
- XawXlibData *xdata = (XawXlibData *)data;
-
- XFreeGC(display, xdata->gc);
- if (xdata->dashes)
- XtFree(xdata->dashes);
- XtFree((char *)data);
- }
-}
-
-/* Start of DLInfo Management Functions */
-static int
-qcmp_dlist_info(register _Xconst void *left, register _Xconst void *right)
-{
- return (strcmp((*(XawDLInfo **)left)->name, (*(XawDLInfo **)right)->name));
-}
-
-Bool XawDeclareDisplayListProc(XawDLClass *lc, String name,
- XawDisplayListProc proc)
-{
- XawDLInfo *info;
-
- if (!lc || !proc || !name || name[0] == '\0')
- return (False);
-
- if ((info = _XawFindDLInfo(lc, name)) != NULL)
- /* Since the data structures to the displayList classes are(should be)
- * opaque, it is not a good idea to allow overriding a displayList
- * procedure; it's better to choose another name or class name!
- */
- return (False);
-
- info = (XawDLInfo *)XtMalloc(sizeof(XawDLInfo));
- info->name = XtNewString(name);
- info->qname = XrmStringToQuark(info->name);
- info->proc = proc;
-
- if (!lc->num_infos)
- {
- lc->num_infos = 1;
- lc->infos = (XawDLInfo **)XtMalloc(sizeof(XawDLInfo*));
- }
- else
- {
- ++lc->num_infos;
- lc->infos = (XawDLInfo **)
- XtRealloc((char *)lc->infos, sizeof(XawDLInfo*) * lc->num_infos);
- }
- lc->infos[lc->num_infos - 1] = info;
-
- if (lc->num_infos > 1)
- qsort(lc->infos, lc->num_infos, sizeof(XawDLInfo*), qcmp_dlist_info);
-
- return (True);
-}
-
-static int
-bcmp_dlist_info(register _Xconst void *string,
- register _Xconst void *dlinfo)
-{
- return (strcmp((String)string, (*(XawDLClass **)dlinfo)->name));
-}
-
-static XawDLInfo *
-_XawFindDLInfo(XawDLClass *lc, String name)
-{
- XawDLInfo **info;
-
- if (!lc->infos)
- return (NULL);
-
- info = (XawDLInfo **)bsearch(name, lc->infos, lc->num_infos,
- sizeof(XawDLInfo*), bcmp_dlist_info);
-
- return (info ? *info : NULL);
-}
-
-/* Start of DLClass Management Functions */
-XawDLClass *
-XawGetDisplayListClass(String name)
-{
- return (_XawFindDLClass(name));
-}
-
-static int
-qcmp_dlist_class(register _Xconst void *left, register _Xconst void *right)
-{
- return (strcmp((*(XawDLClass **)left)->name, (*(XawDLClass **)right)->name));
-}
-
-XawDLClass *
-XawCreateDisplayListClass(String name,
- XawDLArgsInitProc args_init,
- XawDLArgsDestructor args_destructor,
- XawDLDataInitProc data_init,
- XawDLDataDestructor data_destructor)
-{
- XawDLClass *lc;
-
- if (!name || name[0] == '\0')
- return (NULL);
-
- lc = (XawDLClass *)XtMalloc(sizeof(XawDLClass));
- lc->name = XtNewString(name);
- lc->infos = NULL;
- lc->num_infos = 0;
- lc->args_init = args_init;
- lc->args_destructor = args_destructor;
- lc->data_init = data_init;
- lc->data_destructor = data_destructor;
-
- if (!classes)
- {
- num_classes = 1;
- classes = (XawDLClass **)XtMalloc(sizeof(XawDLClass));
- }
- else
- {
- ++num_classes;
- classes = (XawDLClass **)XtRealloc((char *)classes,
- sizeof(XawDLClass) * num_classes);
- }
- classes[num_classes - 1] = lc;
-
- if (num_classes > 1)
- qsort(&classes[0], num_classes, sizeof(XawDLClass*), qcmp_dlist_class);
-
- return (lc);
-}
-
-static int
-bcmp_dlist_class(register _Xconst void *string,
- register _Xconst void *dlist)
-{
- return (strcmp((String)string, (*(XawDLClass **)dlist)->name));
-}
-
-static XawDLClass *
-_XawFindDLClass(String name)
-{
- XawDLClass **lc;
-
- if (!classes)
- return (NULL);
-
- lc = (XawDLClass **)bsearch(name, &classes[0], num_classes,
- sizeof(XawDLClass*), bcmp_dlist_class);
-
- return (lc ? *lc : NULL);
-}
-
-#endif /* OLDXAW */
+/* + * Copyright (c) 1998 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + * + * Author: Paulo César Pereira de Andrade + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <ctype.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/CoreP.h> +#include <X11/Xfuncs.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/SysUtil.h> +#include "Private.h" + +#ifdef __UNIXOS2__ +static char dummy; +#endif + +#ifndef OLDXAW + +/* + * Types + */ +typedef struct _XawDLProc XawDLProc; +typedef struct _XawDLData XawDLData; +typedef struct _XawDLInfo XawDLInfo; + +struct _XawDLProc { + XrmQuark qname; + String *params; + Cardinal num_params; + XawDisplayListProc proc; + XtPointer args; + XawDLData *data; +}; + +struct _XawDLData { + XawDLClass *dlclass; + XtPointer data; +}; + +struct _XawDLInfo { + String name; + XrmQuark qname; + XawDisplayListProc proc; +}; + +struct _XawDL { + XawDLProc **procs; + Cardinal num_procs; + XawDLData **data; + Cardinal num_data; + Screen *screen; + Colormap colormap; + int depth; + XrmQuark qrep; /* for cache lookup */ +}; + +struct _XawDLClass { + String name; + XawDLInfo **infos; + Cardinal num_infos; + XawDLArgsInitProc args_init; + XawDLArgsDestructor args_destructor; + XawDLDataInitProc data_init; + XawDLDataDestructor data_destructor; +}; + +/* + * Private Methods + */ +static XawDLClass *_XawFindDLClass(String); +static int qcmp_dlist_class(_Xconst void*, _Xconst void*); +static int bcmp_dlist_class(_Xconst void*, _Xconst void*); +static XawDLInfo *_XawFindDLInfo(XawDLClass*, String); +static int qcmp_dlist_info(_Xconst void*, _Xconst void*); +static int bcmp_dlist_info(_Xconst void*, _Xconst void*); +static void *_Xaw_Xlib_ArgsInitProc(String, String*, Cardinal*, + Screen*, Colormap, int); +static void _Xaw_Xlib_ArgsDestructor(Display*, String, XtPointer, + String*, Cardinal*); +static void *_Xaw_Xlib_DataInitProc(String, Screen*, Colormap, int); +static void _Xaw_Xlib_DataDestructor(Display*, String, XtPointer); + +/* + * Initialization + */ +static XawDLClass **classes; +static Cardinal num_classes; +static String xlib = "xlib"; + +/* + * Implementation + */ +void +XawRunDisplayList(Widget w, _XawDisplayList *list, + XEvent *event, Region region) +{ + XawDLProc *proc; + Cardinal i; + + if (!XtIsRealized(w)) + return; + + for (i = 0; i < list->num_procs; i++) + { + proc = list->procs[i]; + proc->proc(w, proc->args, proc->data->data, event, region); + } +} + +#define DLERR -2 +#define DLEOF -1 +#define DLEND 1 +#define DLNAME 2 +#define DLARG 3 +static char * +read_token(char *src, char *dst, Cardinal size, int *status) +{ + int ch; + Bool esc, quote; + Cardinal i; + + i = 0; + esc = quote = False; + + /*CONSTCOND*/ + while (1) + { + ch = *src; + if (ch != '\n' && isspace(ch)) + ++src; + else + break; + } + + for (; i < size - 1; src++) + { + ch = *src; + if (ch == '"') + { + if (quote) + { + quote = False; + continue; + } + quote = True; + continue; + } + if (ch == '\\') + { + if (esc) + { + dst[i++] = ch; + esc = False; + continue; + } + esc = True; + continue; + } + if (ch == '\0') + { + *status = DLEOF; + dst[i] = '\0'; + return (src); + } + else if (!esc) + { + if (!quote) + { + if (ch == ',') + { + *status = DLARG; + dst[i] = '\0'; + return (++src); + } + else if (ch == ' ' || ch == '\t') + { + *status = DLNAME; + dst[i] = '\0'; + return (++src); + } + else if (ch == ';' || ch == '\n') + { + *status = DLEND; + dst[i] = '\0'; + return (++src); + } + } + } + else + esc = False; + dst[i++] = ch; + } + + *status = DLERR; + dst[i] = '\0'; + + return (src); +} + +_XawDisplayList *XawCreateDisplayList(String string, Screen *screen, + Colormap colormap, int depth) +{ + _XawDisplayList *dlist; + XawDLClass *lc, *xlibc; + XawDLData *data; + XawDLInfo *info; + XawDLProc *proc; + char cname[64], fname[64], aname[1024]; + Cardinal i; + char *cp, *fp, *lp; + int status; + + xlibc = XawGetDisplayListClass(xlib); + if (!xlibc) + { + XawDisplayListInitialize(); + xlibc = XawGetDisplayListClass(xlib); + } + + dlist = (_XawDisplayList *)XtMalloc(sizeof(_XawDisplayList)); + dlist->procs = NULL; + dlist->num_procs = 0; + dlist->data = NULL; + dlist->num_data = 0; + dlist->screen = screen; + dlist->colormap = colormap; + dlist->depth = depth; + dlist->qrep = NULLQUARK; + if (!string || !string[0]) + return (dlist); + + cp = string; + + status = 0; + while (status != DLEOF) + { + lp = cp; + cp = read_token(cp, fname, sizeof(fname), &status); + + if (status != DLNAME && status != DLEND && status != DLEOF) + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "Error parsing displayList at \"%s\"", lp); + XtAppWarning(XtDisplayToApplicationContext(DisplayOfScreen(screen)), + msg); + XawDestroyDisplayList(dlist); + return (NULL); + } + fp = fname; + /*CONSTCOND*/ + while (1) + { + fp = strchr(fp, ':'); + if (!fp || (fp == cp || fp[-1] != '\\')) + break; + ++fp; + } + if (fp) + { + XmuSnprintf(cname, fp - fname + 1, fname); + memmove(fname, fp + 1, strlen(fp)); + lc = cname[0] ? XawGetDisplayListClass(cname) : xlibc; + if (!lc) + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "Cannot find displayList class \"%s\"", cname); + XtAppWarning(XtDisplayToApplicationContext + (DisplayOfScreen(screen)), msg); + XawDestroyDisplayList(dlist); + return (NULL); + } + } + else + lc = xlibc; + + if (status == DLEOF && !fname[0]) + break; + + if ((info = _XawFindDLInfo(lc, fname)) == NULL) + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "Cannot find displayList procedure \"%s\"", fname); + XtAppWarning(XtDisplayToApplicationContext(DisplayOfScreen(screen)), + msg); + XawDestroyDisplayList(dlist); + return (NULL); + } + + proc = (XawDLProc *)XtMalloc(sizeof(XawDLProc)); + proc->qname = info->qname; + proc->params = NULL; + proc->num_params = 0; + proc->proc = info->proc; + proc->args = NULL; + proc->data = NULL; + + if (!dlist->procs) + { + dlist->num_procs = 1; + dlist->procs = (XawDLProc**)XtMalloc(sizeof(XawDLProc*)); + } + else + { + ++dlist->num_procs; + dlist->procs = (XawDLProc**) + XtRealloc((char *)dlist->procs, sizeof(XawDLProc*) * + dlist->num_procs); + } + dlist->procs[dlist->num_procs - 1] = proc; + + while (status != DLEND && status != DLEOF) + { + lp = cp; + cp = read_token(cp, aname, sizeof(aname), &status); + + if (status != DLARG && status != DLEND && status != DLEOF) + { + char msg[256]; + + XmuSnprintf(msg, sizeof(msg), + "Error parsing displayList at \"%s\"", lp); + XtAppWarning(XtDisplayToApplicationContext + (DisplayOfScreen(screen)), msg); + XawDestroyDisplayList(dlist); + return (NULL); + } + + if (!proc->num_params) + { + proc->num_params = 1; + proc->params = (String *)XtMalloc(sizeof(String)); + } + else + { + ++proc->num_params; + proc->params = (String *)XtRealloc((char *)proc->params, + sizeof(String) * + proc->num_params); + } + proc->params[proc->num_params - 1] = XtNewString(aname); + } + + /* verify if data is already created for lc */ + data = NULL; + for (i = 0; i < dlist->num_data; i++) + if (dlist->data[i]->dlclass == lc) + { + data = dlist->data[i]; + break; + } + + if (!data) + { + data = (XawDLData *)XtMalloc(sizeof(XawDLData)); + data->dlclass = lc; + if (lc->data_init) + data->data = lc->data_init(lc->name, screen, colormap, depth); + else + data->data = NULL; + + if (!dlist->data) + { + dlist->num_data = 1; + dlist->data = (XawDLData **)XtMalloc(sizeof(XawDLData*)); + } + else + { + ++dlist->num_data; + dlist->data = (XawDLData **) + XtRealloc((char *)dlist->data, sizeof(XawDLData*) * + dlist->num_data); + } + dlist->data[dlist->num_data - 1] = data; + } + + if (lc->args_init) + { + proc->args = lc->args_init(fname, proc->params, &proc->num_params, + screen, colormap, depth); + if (proc->args == XAWDL_CONVERT_ERROR) + { + char msg[256]; + + proc->args = NULL; + XmuSnprintf(msg, sizeof(msg), + "Cannot convert arguments to displayList function \"%s\"", fname); + XtAppWarning(XtDisplayToApplicationContext + (DisplayOfScreen(screen)), msg); + XawDestroyDisplayList(dlist); + return (NULL); + } + } + else + proc->args = NULL; + + proc->data = data; + } + + dlist->qrep = XrmStringToQuark(string); + return (dlist); +} + +String +XawDisplayListString(_XawDisplayList *dlist) +{ + if (!dlist || dlist->qrep == NULLQUARK) + return (""); + return (XrmQuarkToString(dlist->qrep)); +} + +void +XawDestroyDisplayList(_XawDisplayList *dlist) +{ + Cardinal i, j; + XawDLProc *proc; + XawDLData *data; + + if (!dlist) + return; + + for (i = 0; i < dlist->num_procs; i++) + { + proc = dlist->procs[i]; + data = proc->data; + + if (data) + { + if (data->dlclass->args_destructor) + data->dlclass->args_destructor(DisplayOfScreen(dlist->screen), + XrmQuarkToString(proc->qname), + proc->args, + proc->params, &proc->num_params); + if (data->data) + { + if (data->dlclass->data_destructor) + { + data->dlclass + ->data_destructor(DisplayOfScreen(dlist->screen), + data->dlclass->name, data->data); + data->data = NULL; + } + } + } + + for (j = 0; j < proc->num_params; j++) + XtFree(proc->params[j]); + if (proc->num_params) + XtFree((char *)proc->params); + XtFree((char *)proc); + } + + if (dlist->num_procs) + XtFree((char *)dlist->procs); + + XtFree((char *)dlist); +} + +/********************************************************************** + * If you want to implement your own class of procedures, look at + * the code bellow. + **********************************************************************/ +/* Start of Implementation of class "xlib" */ +typedef struct _XawXlibData { + GC gc; + unsigned long mask; + XGCValues values; + int shape; + int mode; + char *dashes; + /* these fields can be used for optimization, to + * avoid unnecessary coordinates recalculation. + */ + Position x, y; + Dimension width, height; +} XawXlibData; + +typedef struct _XawDLPosition { + Position pos; + short denom; + Boolean high; +} XawDLPosition; + +typedef struct _XawDLPositionPtr { + XawDLPosition *pos; + Cardinal num_pos; +} XawDLPositionPtr; + +typedef struct _XawDLArcArgs { + XawDLPosition pos[4]; + int angle1; + int angle2; +} XawDLArcArgs; + +typedef struct _XawDLStringArgs { + XawDLPosition pos[2]; + char *string; + int length; +} XawDLStringArgs; + +typedef struct _XawDLCopyArgs { + XawPixmap *pixmap; + XawDLPosition pos[6]; + int plane; +} XawDLCopyArgs; + +typedef struct _XawDLImageArgs { + XawPixmap *pixmap; + XawDLPosition pos[4]; + int depth; +} XawDLImageArgs; + +#define X_ARG(x) (Position)(((x).denom != 0) ? \ + ((float)XtWidth(w) * ((float)(x).pos / (float)(x).denom)) : \ + ((x).high ? XtWidth(w) - (x).pos : (x).pos)) +#define Y_ARG(x) (Position)(((x).denom != 0) ? \ + ((float)XtHeight(w) * ((float)(x).pos / (float)(x).denom)): \ + ((x).high ? XtHeight(w) - (x).pos : (x).pos)) +#define DRECT 0 +#define FRECT 1 +#define LINE 2 +#define GCFG 3 +#define GCBG 4 +#define FPOLY 5 +#define DARC 6 +#define FARC 7 +#define DLINES 8 +#define MASK 9 +#define UMASK 10 +#define LWIDTH 11 +#define POINT 12 +#define POINTS 13 +#define SEGMENTS 14 +#define ARCMODE 15 +#define COORDMODE 16 +#define SHAPEMODE 17 +#define LINESTYLE 18 +#define CAPSTYLE 19 +#define JOINSTYLE 20 +#define FILLSTYLE 21 +#define FILLRULE 22 +#define TILE 23 +#define STIPPLE 24 +#define TSORIGIN 25 +#define FUNCTION 26 +#define PLANEMASK 27 +#define DSTRING 28 +#define PSTRING 29 +#define FONT 30 +#define DASHES 31 +#define SUBWMODE 32 +#define EXPOSURES 33 +#define CLIPORIGIN 34 +#define CLIPMASK 35 +#define CLIPRECTS 36 +#define COPYAREA 37 +#define COPYPLANE 38 +#define IMAGE 39 + +static void +Dl1Point(Widget w, XtPointer args, XtPointer data, int id) +{ + XawDLPosition *pos = (XawDLPosition *)args; + XawXlibData *xdata = (XawXlibData *)data; + Display *display; + Window window; + Position x, y; + + x = X_ARG(pos[0]); + y = Y_ARG(pos[1]); + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + x += xpad; + y += ypad; + display = XtDisplayOfObject(w); + window = XtWindowOfObject(w); + } + else + { + display = XtDisplay(w); + window = XtWindow(w); + } + + if (id == POINT) + XDrawPoint(display, window, xdata->gc, x, y); + else if (id == TSORIGIN) + { + xdata->values.ts_x_origin = x; + xdata->values.ts_y_origin = y; + xdata->mask |= GCTileStipXOrigin | GCTileStipYOrigin; + XSetTSOrigin(display, xdata->gc, x, y); + } + else if (id == CLIPORIGIN) + { + xdata->values.clip_x_origin = x; + xdata->values.clip_y_origin = y; + xdata->mask |= GCClipXOrigin | GCClipYOrigin; + XSetClipOrigin(display, xdata->gc, x, y); + } +} + +static void +Dl2Points(Widget w, XtPointer args, XtPointer data, int id) +{ + XawDLPosition *pos = (XawDLPosition *)args; + XawXlibData *xdata = (XawXlibData *)data; + Display *display; + Window window; + Position x1, y1, x2, y2; + + x1 = X_ARG(pos[0]); + y1 = Y_ARG(pos[1]); + x2 = X_ARG(pos[2]); + y2 = Y_ARG(pos[3]); + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + x1 += xpad; y1 += ypad; + x2 += xpad; y2 += ypad; + display = XtDisplayOfObject(w); + window = XtWindowOfObject(w); + } + else + { + display = XtDisplay(w); + window = XtWindow(w); + } + + if (id == DRECT) + XDrawRectangle(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1); + else if (id == FRECT) + XFillRectangle(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1); + else if (id == LINE) + XDrawLine(display, window, xdata->gc, x1, y1, x2, y2); +} + +/* ARGSUSED */ +static void +DlLine(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region) +{ + Dl2Points(w, args, data, LINE); +} + +/* ARGSUSED */ +static void +DlDrawRectangle(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + Dl2Points(w, args, data, DRECT); +} + +/* ARGSUSED */ +static void +DlFillRectangle(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + Dl2Points(w, args, data, FRECT); +} + +static void +DlXPoints(Widget w, XtPointer args, XtPointer data, int id) +{ + XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args; + XawXlibData *xdata = (XawXlibData *)data; + XawDLPosition *pos; + XPoint points_buf[16]; + XPoint *points; + Display *display; + Window window; + Cardinal num_points, i, j; + + num_points = pos_ptr->num_pos>>1; + points = (XPoint *)XawStackAlloc(sizeof(XPoint) * num_points, points_buf); + + for (i = j = 0; i < num_points; i++, j = i << 1) + { + pos = &pos_ptr->pos[j]; + points[i].x = X_ARG(pos[0]); + points[i].y = Y_ARG(pos[1]); + } + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + if (xdata->mode != CoordModePrevious) + { + for (i = 0; i < num_points; i++) + { + points[i].x += xpad; + points[i].y += ypad; + } + } + else + { + points[0].x += xpad; + points[0].y += ypad; + } + display = XtDisplayOfObject(w); + window = XtWindowOfObject(w); + } + else + { + display = XtDisplay(w); + window = XtWindow(w); + } + + if (id == FPOLY) + XFillPolygon(display, window, xdata->gc, points, num_points, + xdata->shape, xdata->mode); + else if (id == DLINES) + XDrawLines(display, window, xdata->gc, points, num_points, xdata->mode); + else if (id == POINTS) + XDrawPoints(display, window, xdata->gc, points, num_points, xdata->mode); + + XawStackFree(points, points_buf); +} + +/* ARGSUSED */ +static void +DlFillPolygon(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlXPoints(w, args, data, FPOLY); +} + +/* ARGSUSED */ +static void +DlDrawLines(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlXPoints(w, args, data, DLINES); +} + +/* ARGSUSED */ +static void +DlDrawPoints(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlXPoints(w, args, data, POINTS); +} + +/* ARGSUSED */ +static void +DlForeground(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + Pixel foreground = (Pixel)args; + + if (xdata->values.foreground != foreground) + { + xdata->mask |= GCForeground; + xdata->values.foreground = foreground; + XSetForeground(XtDisplayOfObject(w), xdata->gc, foreground); + } +} + +/* ARGSUSED */ +static void +DlBackground(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + Pixel background = (Pixel)args; + + if (xdata->values.background != background) + { + xdata->mask |= GCBackground; + xdata->values.background = background; + XSetBackground(XtDisplayOfObject(w), xdata->gc, background); + } +} + +static void +DlArc(Widget w, XtPointer args, XtPointer data, Bool fill) +{ + XawXlibData *xdata = (XawXlibData *)data; + XawDLArcArgs *arc = (XawDLArcArgs *)args; + Position x1, y1, x2, y2; + Display *display; + Window window; + + x1 = X_ARG(arc->pos[0]); + y1 = Y_ARG(arc->pos[1]); + x2 = X_ARG(arc->pos[2]); + y2 = Y_ARG(arc->pos[3]); + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + x1 += xpad; + y1 += ypad; + x2 += xpad; + y2 += ypad; + display = XtDisplayOfObject(w); + window = XtWindowOfObject(w); + } + else + { + display = XtDisplay(w); + window = XtWindow(w); + } + + if (fill) + XFillArc(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1, + arc->angle1, arc->angle2); + else + XDrawArc(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1, + arc->angle1, arc->angle2); +} + +/* ARGSUSED */ +static void +DlDrawArc(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlArc(w, args, data, False); +} + +/* ARGSUSED */ +static void +DlFillArc(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlArc(w, args, data, True); +} + +/*ARGSUSED*/ +static void +DlMask(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + Display *display = XtDisplayOfObject(w); + + if (region) + XSetRegion(display, xdata->gc, region); + else if (event) + { + XRectangle rect; + + rect.x = event->xexpose.x; + rect.y = event->xexpose.y; + rect.width = event->xexpose.width; + rect.height = event->xexpose.height; + XSetClipRectangles(display, xdata->gc, 0, 0, &rect, 1, Unsorted); + } +} + +/* ARGSUSED */ +static void +DlUmask(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + + XSetClipMask(XtDisplayOfObject(w), xdata->gc, None); +} + +/* ARGSUSED */ +static void +DlLineWidth(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + unsigned line_width = (unsigned long)args; + + if (xdata->values.line_width != line_width) + { + xdata->mask |= GCLineWidth; + xdata->values.line_width = line_width; + XChangeGC(XtDisplayOfObject(w), xdata->gc, GCLineWidth, &xdata->values); + } +} + +/* ARGSUSED */ +static void +DlDrawPoint(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region) +{ + Dl1Point(w, args, data, POINT); +} + +/* ARGSUSED */ +static void +DlDrawSegments(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args; + XawXlibData *xdata = (XawXlibData *)data; + XawDLPosition *pos; + XSegment *segments; + XSegment segments_buf[8]; + Display *display; + Window window; + Cardinal num_segments, i, j; + + num_segments = pos_ptr->num_pos>>2; + segments = (XSegment *)XawStackAlloc(sizeof(XSegment) * num_segments, segments_buf); + + for (i = j = 0; i < num_segments; i++, j = i << 2) + { + pos = &pos_ptr->pos[j]; + segments[i].x1 = X_ARG(pos[0]); + segments[i].y1 = Y_ARG(pos[1]); + segments[i].x2 = X_ARG(pos[2]); + segments[i].y2 = Y_ARG(pos[3]); + } + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + for (i = 0; i < num_segments; i++) + { + segments[i].x1 += xpad; + segments[i].y1 += ypad; + segments[i].x2 += xpad; + segments[i].y2 += ypad; + } + display = XtDisplayOfObject(w); + window = XtWindowOfObject(w); + } + else + { + display = XtDisplay(w); + window = XtWindow(w); + } + + XDrawSegments(display, window, xdata->gc, segments, num_segments); + + XawStackFree(segments, segments_buf); +} + +/* ARGSUSED */ +static void +DlArcMode(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int arc_mode = (long)args; + + if (xdata->values.arc_mode != arc_mode) + { + xdata->mask |= GCArcMode; + xdata->values.arc_mode = arc_mode; + XSetArcMode(XtDisplayOfObject(w), xdata->gc, arc_mode); + } +} + +/* ARGSUSED */ +static void +DlCoordMode(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int mode = (long)args; + + xdata->mode = mode; +} + +/* ARGSUSED */ +static void +DlShapeMode(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int shape = (long)args; + + xdata->shape = shape; +} + +/* ARGSUSED */ +static void +DlLineStyle(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int line_style = (long)args; + + if (xdata->values.line_style != line_style) + { + xdata->mask |= GCLineStyle; + xdata->values.line_style = line_style; + XChangeGC(XtDisplayOfObject(w), xdata->gc, GCLineStyle, &xdata->values); + } +} + +/* ARGSUSED */ +static void +DlCapStyle(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int cap_style = (long)args; + + if (xdata->values.cap_style != cap_style) + { + xdata->mask |= GCCapStyle; + xdata->values.cap_style = cap_style; + XChangeGC(XtDisplayOfObject(w), xdata->gc, GCCapStyle, &xdata->values); + } +} + +/* ARGSUSED */ +static void +DlJoinStyle(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int join_style = (long)args; + + if (xdata->values.join_style != join_style) + { + xdata->mask |= GCJoinStyle; + xdata->values.join_style = join_style; + XChangeGC(XtDisplayOfObject(w), xdata->gc, GCJoinStyle, &xdata->values); + } +} + +/* ARGSUSED */ +static void +DlFillStyle(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int fill_style = (long)args; + + if (xdata->values.fill_style != fill_style) + { + xdata->mask |= GCFillStyle; + xdata->values.fill_style = fill_style; + XSetFillStyle(XtDisplayOfObject(w), xdata->gc, fill_style); + } +} + +/* ARGSUSED */ +static void +DlFillRule(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int fill_rule = (long)args; + + if (xdata->values.fill_rule != fill_rule) + { + xdata->mask |= GCFillRule; + xdata->values.fill_rule = fill_rule; + XSetFillRule(XtDisplayOfObject(w), xdata->gc, fill_rule); + } +} + +/* ARGSUSED */ +static void +DlTile(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + XawPixmap *pixmap = (XawPixmap *)args; + + if (pixmap && xdata->values.tile != pixmap->pixmap) + { + xdata->mask |= GCTile; + xdata->values.tile = pixmap->pixmap; + XSetTile(XtDisplayOfObject(w), xdata->gc, xdata->values.tile); + } +} + +/* ARGSUSED */ +static void +DlStipple(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + XawPixmap *pixmap = (XawPixmap *)args; + + if (pixmap && xdata->values.stipple != pixmap->pixmap) + { + xdata->mask |= GCStipple; + xdata->values.stipple = pixmap->pixmap; + XSetStipple(XtDisplayOfObject(w), xdata->gc, xdata->values.stipple); + } +} + +/* ARGSUSED */ +static void +DlTSOrigin(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region) +{ + Dl1Point(w, args, data, TSORIGIN); +} + +/* ARGSUSED */ +static void +DlFunction(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int function = (long)args; + + if (function != xdata->values.function) + { + xdata->mask |= GCFunction; + xdata->values.function = function; + XSetFunction(XtDisplayOfObject(w), xdata->gc, function); + } +} + +/* ARGSUSED */ +static void +DlPlaneMask(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + unsigned long plane_mask = (unsigned long)args; + + if (xdata->values.plane_mask != plane_mask) + { + xdata->mask |= GCPlaneMask; + xdata->values.plane_mask = plane_mask; + XSetPlaneMask(XtDisplayOfObject(w), xdata->gc, plane_mask); + } +} + +static void +DlString(Widget w, XtPointer args, XtPointer data, Bool image) +{ + XawDLStringArgs *string = (XawDLStringArgs *)args; + XawXlibData *xdata = (XawXlibData *)data; + Display *display; + Window window; + Position x, y; + + x = X_ARG(string->pos[0]); + y = Y_ARG(string->pos[1]); + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + x += xpad; + y += ypad; + display = XtDisplayOfObject(w); + window = XtWindowOfObject(w); + } + else + { + display = XtDisplay(w); + window = XtWindow(w); + } + + if (image) + XDrawImageString(display, window, xdata->gc, x, y, string->string, string->length); + else + XDrawString(display, window, xdata->gc, x, y, string->string, string->length); +} + +/* ARGSUSED */ +static void +DlDrawString(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlString(w, args, data, False); +} + +/* ARGSUSED */ +static void +DlPaintString(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlString(w, args, data, True); +} + +/* ARGSUSED */ +static void +DlFont(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + Font font = (Font)args; + + if (xdata->values.font != font) + { + xdata->mask |= GCFont; + xdata->values.font = font; + XSetFont(XtDisplayOfObject(w), xdata->gc, font); + } +} + +/* ARGSUSED */ +static void +DlDashes(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + char *dashes = args; + + if (xdata->dashes != dashes) + { + xdata->mask |= GCDashOffset | GCDashList; + xdata->dashes = dashes; + XSetDashes(XtDisplayOfObject(w), xdata->gc, 0, dashes + 1, *dashes); + } +} + +/* ARGSUSED */ +static void +DlSubwindowMode(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + int subwindow_mode = (long)args; + + if (xdata->values.subwindow_mode != subwindow_mode) + { + xdata->mask |= GCSubwindowMode; + xdata->values.subwindow_mode = subwindow_mode; + XSetSubwindowMode(XtDisplayOfObject(w), xdata->gc, subwindow_mode); + } +} + +/* ARGSUSED */ +static void +DlExposures(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + Bool graphics_exposures = (Bool)(long)args; + + if (xdata->values.graphics_exposures != graphics_exposures) + { + xdata->mask |= GCGraphicsExposures; + xdata->values.graphics_exposures = graphics_exposures; + XSetGraphicsExposures(XtDisplayOfObject(w), xdata->gc, graphics_exposures); + } +} + +/* ARGSUSED */ +static void +DlClipOrigin(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region) +{ + Dl1Point(w, args, data, CLIPORIGIN); +} + +/* ARGSUSED */ +static void +DlClipMask(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawXlibData *xdata = (XawXlibData *)data; + XawPixmap *pixmap = (XawPixmap *)args; + Pixmap clip_mask; + + if (pixmap) + clip_mask = pixmap->mask ? pixmap->mask : pixmap->pixmap; + else + clip_mask = None; + + if (xdata->values.clip_mask != clip_mask) + { + xdata->mask |= GCClipMask; + XSetClipMask(XtDisplayOfObject(w), xdata->gc, clip_mask); + } +} + +/* ARGSUSED */ +static void +DlClipRectangles(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args; + XawXlibData *xdata = (XawXlibData *)data; + XawDLPosition *pos; + XRectangle *rects; + XRectangle rects_buf[8]; + Position x1, y1, x2, y2; + Cardinal num_rects, i, j; + + num_rects = pos_ptr->num_pos>>2; + rects = (XRectangle *)XawStackAlloc(sizeof(XRectangle) * num_rects, rects_buf); + + for (i = j = 0; i < num_rects; i++, j = i << 2) + { + pos = &pos_ptr->pos[j]; + x1 = X_ARG(pos[0]); + y1 = Y_ARG(pos[1]); + x2 = X_ARG(pos[2]); + y2 = Y_ARG(pos[3]); + rects[i].x = XawMin(x1, x2); + rects[i].y = XawMin(y1, y2); + rects[i].width = XawMax(x1, x2) - rects[i].x; + rects[i].height = XawMax(y1, y2) - rects[i].y; + } + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + for (i = 0; i < num_rects; i++) + { + rects[i].x += xpad; + rects[i].y += ypad; + } + } + + XSetClipRectangles(XtDisplayOfObject(w), xdata->gc, 0, 0, rects, num_rects, Unsorted); + + XawStackFree(rects, rects_buf); +} + +static void +DlCopy(Widget w, XtPointer args, XtPointer data, Bool plane) +{ + XawDLCopyArgs *copy = (XawDLCopyArgs *)args; + XawXlibData *xdata = (XawXlibData *)data; + int src_x, src_y, dst_x, dst_y, width, height, tmp1, tmp2; + + tmp1 = X_ARG(copy->pos[0]); + tmp2 = X_ARG(copy->pos[2]); + dst_x = XawMin(tmp1, tmp2); + width = XawMax(tmp1, tmp2) - dst_x; + + tmp1 = Y_ARG(copy->pos[1]); + tmp2 = Y_ARG(copy->pos[3]); + dst_y = XawMin(tmp1, tmp2); + height = XawMax(tmp1, tmp2) - dst_y; + + src_x = X_ARG(copy->pos[4]); + src_y = Y_ARG(copy->pos[5]); + + if (width <= 0) + { + if (copy->pixmap) + width = copy->pixmap->width; + else + { + if ((width = XtWidth(w) - src_x) < 0) + width = 0; + } + } + if (height <= 0) + { + if (copy->pixmap) + height = copy->pixmap->height; + else + { + if ((height = XtHeight(w) - src_y) < 0) + height = 0; + } + } + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + src_x += xpad; + src_y += ypad; + dst_x += xpad; + dst_y += ypad; + } + + if (plane) + XCopyPlane(XtDisplayOfObject(w), XtWindowOfObject(w), + copy->pixmap ? copy->pixmap->pixmap : XtWindowOfObject(w), + xdata->gc, src_x, src_y, width, height, dst_x, dst_y, + copy->plane ? copy->plane : 1); + else + XCopyArea(XtDisplayOfObject(w), + copy->pixmap ? copy->pixmap->pixmap : XtWindowOfObject(w), + XtWindowOfObject(w), xdata->gc, src_x, src_y, width, height, dst_x, dst_y); +} + +/* ARGSUSED */ +static void +DlCopyArea(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlCopy(w, args, data, False); +} + +/* ARGSUSED */ +static void +DlCopyPlane(Widget w, XtPointer args, XtPointer data, + XEvent *event, Region region) +{ + DlCopy(w, args, data, True); +} + +/*ARGSUSED*/ +/* Note: + * This function is destructive if you set the ts_x_origin, ts_y_origin, + * and/or clip-mask. It is meant to be the only function used in a display + * list. If you need to use other functions (and those values), be sure to + * set them after calling this function. + */ +static void +DlImage(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region) +{ + XawDLImageArgs *image = (XawDLImageArgs *)args; + XawXlibData *xdata = (XawXlibData *)data; + int x, y, xs, ys, xe, ye, width, height; + Display *display; + Window window; + + width = image->pixmap->width; + height = image->pixmap->height; + xs = X_ARG(image->pos[0]); + ys = Y_ARG(image->pos[1]); + xe = X_ARG(image->pos[2]); + ye = Y_ARG(image->pos[3]); + + if (xe <= 0) + xe = xs + width; + if (ye <= 0) + ye = ys + height; + + if (!XtIsWidget(w)) + { + Position xpad, ypad; + + xpad = XtX(w) + XtBorderWidth(w); + ypad = XtY(w) + XtBorderWidth(w); + xe += xpad; + ye += ypad; + xe += xpad; + ye += ypad; + display = XtDisplayOfObject(w); + window = XtWindowOfObject(w); + } + else + { + display = XtDisplay(w); + window = XtWindow(w); + } + + for (y = ys; y < ye; y += height) + for (x = xs; x < xe; x += width) + { + XSetClipOrigin(display, xdata->gc, x, y); + if (image->pixmap->mask) + XSetClipMask(display, xdata->gc, image->pixmap->mask); + if (image->depth == 1) + XCopyPlane(display, image->pixmap->pixmap, window, xdata->gc, + 0, 0, XawMin(width, xe - x), XawMin(height, ye - y), + x, y, 1L); + else + XCopyArea(display, image->pixmap->pixmap, window, xdata->gc, 0, 0, + XawMin(width, xe - x), XawMin(height, ye - y), x, y); + } + + XSetClipMask(display, xdata->gc, None); +} + +typedef struct _Dl_init Dl_init; +struct _Dl_init { + String name; + XawDisplayListProc proc; + Cardinal id; +}; + +static Dl_init dl_init[] = +{ + {"arc-mode", DlArcMode, ARCMODE}, + {"background", DlBackground, GCBG}, + {"bg", DlBackground, GCBG}, + {"cap-style", DlCapStyle, CAPSTYLE}, + {"clip-mask", DlClipMask, CLIPMASK}, + {"clip-origin", DlClipOrigin, CLIPORIGIN}, + {"clip-rectangles", DlClipRectangles, CLIPRECTS}, + {"clip-rects", DlClipRectangles, CLIPRECTS}, + {"coord-mode", DlCoordMode, COORDMODE}, + {"copy-area", DlCopyArea, COPYAREA}, + {"copy-plane", DlCopyPlane, COPYPLANE}, + {"dashes", DlDashes, DASHES}, + {"draw-arc", DlDrawArc, DARC}, + {"draw-line", DlLine, LINE}, + {"draw-lines", DlDrawLines, DLINES}, + {"draw-point", DlDrawPoint, POINT}, + {"draw-points", DlDrawPoints, POINTS}, + {"draw-rect", DlDrawRectangle, DRECT}, + {"draw-rectangle", DlDrawRectangle, DRECT}, + {"draw-segments", DlDrawSegments, SEGMENTS}, + {"draw-string", DlDrawString, DSTRING}, + {"exposures", DlExposures, EXPOSURES}, + {"fg", DlForeground, GCFG}, + {"fill-arc", DlFillArc, FARC}, + {"fill-poly", DlFillPolygon, FPOLY}, + {"fill-polygon", DlFillPolygon, FPOLY}, + {"fill-rect", DlFillRectangle, FRECT}, + {"fill-rectangle", DlFillRectangle, FRECT}, + {"fill-rule", DlFillRule, FILLRULE}, + {"fill-style", DlFillStyle, FILLSTYLE}, + {"font", DlFont, FONT}, + {"foreground", DlForeground, GCFG}, + {"function", DlFunction, FUNCTION}, + {"image", DlImage, IMAGE}, + {"join-style", DlJoinStyle, JOINSTYLE}, + {"line", DlLine, LINE}, + {"line-style", DlLineStyle, LINESTYLE}, + {"line-width", DlLineWidth, LWIDTH}, + {"lines", DlDrawLines, DLINES}, + {"mask", DlMask, MASK}, + {"paint-string", DlPaintString, PSTRING}, + {"plane-mask", DlPlaneMask, PLANEMASK}, + {"point", DlDrawPoint, POINT}, + {"points", DlDrawPoints, POINTS}, + {"segments", DlDrawSegments, SEGMENTS}, + {"shape-mode", DlShapeMode, SHAPEMODE}, + {"stipple", DlStipple, STIPPLE}, + {"subwindow-mode", DlSubwindowMode, SUBWMODE}, + {"tile", DlTile, TILE}, + {"ts-origin", DlTSOrigin, TSORIGIN}, + {"umask", DlUmask, UMASK}, +}; + +void +XawDisplayListInitialize(void) +{ + static Bool first_time = True; + XawDLClass *lc; + Cardinal i; + + if (first_time == False) + return; + + first_time = False; + + lc = XawCreateDisplayListClass(xlib, + _Xaw_Xlib_ArgsInitProc, + _Xaw_Xlib_ArgsDestructor, + _Xaw_Xlib_DataInitProc, + _Xaw_Xlib_DataDestructor); + for (i = 0; i < sizeof(dl_init) / sizeof(dl_init[0]); i++) + (void)XawDeclareDisplayListProc(lc, dl_init[i].name, dl_init[i].proc); +} + +static int +bcmp_cvt_proc(register _Xconst void *string, + register _Xconst void *dlinfo) +{ + return (strcmp((String)string, ((Dl_init*)dlinfo)->name)); +} + +static long +read_int(char *cp, char **cpp) +{ + long value = 0, sign = 1; + + if (*cp == '-') + { + sign = -1; + ++cp; + } + else if (*cp == '+') + ++cp; + value = 0; + while (*cp >= '0' && *cp <= '9') + { + value = value * 10 + *cp - '0'; + ++cp; + } + if (cpp) + *cpp = cp; + return (value * sign); +} + +static void +read_position(char *arg, XawDLPosition *pos) +{ + int ch; + char *str = arg; + + ch = *str; + if (ch == '-' || ch == '+') + { + ++str; + if (ch == '-') + pos->high = True; + pos->pos = read_int(str, NULL); + } + else if (isdigit(ch)) + { + pos->pos = read_int(str, &str); + ch = *str++; + if (ch == '/') + pos->denom = read_int(str, NULL); + } +} + +/* ARGSUSED */ +static void * +_Xaw_Xlib_ArgsInitProc(String proc_name, String *params, Cardinal *num_params, + Screen *screen, Colormap colormap, int depth) +{ + Cardinal id, i; + Dl_init *init; + void *retval = XAWDL_CONVERT_ERROR; + + init = (Dl_init *)bsearch(proc_name, dl_init, + sizeof(dl_init) / sizeof(dl_init[0]), + sizeof(dl_init[0]), + bcmp_cvt_proc); + + id = init->id; + + switch (id) + { + case LINE: + case DRECT: + case FRECT: + if (*num_params == 4) + { + XawDLPosition *pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) * 4); + + for (i = 0; i < 4; i++) + read_position(params[i], &pos[i]); + retval = (void *)pos; + } + break; + case POINT: + case TSORIGIN: + case CLIPORIGIN: + if (*num_params == 2) + { + XawDLPosition *pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) * 2); + + read_position(params[0], &pos[0]); + read_position(params[1], &pos[1]); + retval = (void *)pos; + } + break; + case DLINES: + case FPOLY: + case POINTS: + if (*num_params >= 4 && !(*num_params & 1)) + { + XawDLPositionPtr *pos = XtNew(XawDLPositionPtr); + + pos->pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) * + *num_params); + pos->num_pos = *num_params; + for (i = 0; i < *num_params; i++) + read_position(params[i], &pos->pos[i]); + retval = (void *)pos; + } + break; + case SEGMENTS: + case CLIPRECTS: + if (*num_params >= 4 && !(*num_params % 4)) + { + XawDLPositionPtr *pos = XtNew(XawDLPositionPtr); + + pos->pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) * + *num_params); + pos->num_pos = *num_params; + for (i = 0; i < *num_params; i++) + read_position(params[i], &pos->pos[i]); + retval = (void *)pos; + } + break; + case DARC: + case FARC: + if (*num_params >= 4 && *num_params <= 6) + { + XawDLArcArgs *args = (XawDLArcArgs *)XtCalloc(1, sizeof(XawDLArcArgs)); + + args->angle1 = 0; + args->angle2 = 360; + for (i = 0; i < 4; i++) + read_position(params[i], &args->pos[i]); + if (*num_params > 4) + args->angle1 = read_int(params[4], NULL); + if (*num_params > 5) + args->angle2 = read_int(params[5], NULL); + args->angle1 *= 64; + args->angle2 *= 64; + retval = (void *)args; + } + break; + case GCFG: + case GCBG: + { + XColor xcolor; + + if (*num_params == 1 && + XAllocNamedColor(DisplayOfScreen(screen), colormap, + params[0], &xcolor, &xcolor)) + retval = (void *)xcolor.pixel; + } break; + case MASK: + case UMASK: + if (*num_params == 0) + retval = NULL; + break; + case LWIDTH: + if (*num_params == 1) + retval = (void *)read_int(params[0], NULL); + break; + case ARCMODE: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "pieslice") == 0) + retval = (void *)ArcPieSlice; + else if (XmuCompareISOLatin1(params[0], "chord") == 0) + retval = (void *)ArcChord; + } + break; + case COORDMODE: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "origin") == 0) + retval = (void *)CoordModeOrigin; + else if (XmuCompareISOLatin1(params[0], "previous") == 0) + retval = (void *)CoordModePrevious; + } + break; + case SHAPEMODE: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "complex") == 0) + retval = (void *)Complex; + else if (XmuCompareISOLatin1(params[0], "convex") == 0) + retval = (void *)Convex; + else if (XmuCompareISOLatin1(params[0], "nonconvex") == 0) + retval = (void *)Nonconvex; + } + break; + case LINESTYLE: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "solid") == 0) + retval = (void *)LineSolid; + else if (XmuCompareISOLatin1(params[0], "onoffdash") == 0) + retval = (void *)LineOnOffDash; + else if (XmuCompareISOLatin1(params[0], "doubledash") == 0) + retval = (void *)LineDoubleDash; + } + break; + case CAPSTYLE: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "notlast") == 0) + retval = (void *)CapNotLast; + else if (XmuCompareISOLatin1(params[0], "butt") == 0) + retval = (void *)CapButt; + else if (XmuCompareISOLatin1(params[0], "round") == 0) + retval = (void *)CapRound; + else if (XmuCompareISOLatin1(params[0], "projecting") == 0) + retval = (void *)CapProjecting; + } + break; + case JOINSTYLE: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "miter") == 0) + retval = (void *)JoinMiter; + else if (XmuCompareISOLatin1(params[0], "round") == 0) + retval = (void *)JoinRound; + else if (XmuCompareISOLatin1(params[0], "bevel") == 0) + retval = (void *)JoinBevel; + } + break; + case FILLSTYLE: + if (*num_params == 1) + { + if (*num_params && XmuCompareISOLatin1(params[0], "solid") == 0) + retval = (void *)FillSolid; + else if (*num_params && XmuCompareISOLatin1(params[0], "tiled") == 0) + retval = (void *)FillTiled; + else if (*num_params && XmuCompareISOLatin1(params[0], "stippled") == 0) + retval = (void *)FillStippled; + else if (*num_params && XmuCompareISOLatin1(params[0], "opaquestippled") == 0) + retval = (void *)FillOpaqueStippled; + } + break; + case FILLRULE: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "evenodd") == 0) + retval = (void *)EvenOddRule; + else if (XmuCompareISOLatin1(params[0], "winding") == 0) + retval = (void *)WindingRule; + } + break; + case TILE: + if (*num_params == 1) + retval = (void *)XawLoadPixmap(params[0], screen, colormap, depth); + if (retval == NULL) + { + XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0], + XtRPixmap); + retval = XAWDL_CONVERT_ERROR; + } + break; + case STIPPLE: + if (*num_params == 1) + retval = (void *)XawLoadPixmap(params[0], screen, colormap, 1); + if (retval == NULL) + { + XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0], + XtRBitmap); + retval = XAWDL_CONVERT_ERROR; + } + break; + case FUNCTION: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "set") == 0) + retval = (void *)GXset; + else if (XmuCompareISOLatin1(params[0], "clear") == 0) + retval = (void *)GXclear; + else if (XmuCompareISOLatin1(params[0], "and") == 0) + retval = (void *)GXand; + else if (XmuCompareISOLatin1(params[0], "andreverse") == 0) + retval = (void *)GXandReverse; + else if (XmuCompareISOLatin1(params[0], "copy") == 0) + retval = (void *)GXcopy; + else if (XmuCompareISOLatin1(params[0], "andinverted") == 0) + retval = (void *)GXandInverted; + else if (XmuCompareISOLatin1(params[0], "noop") == 0) + retval = (void *)GXnoop; + else if (XmuCompareISOLatin1(params[0], "xor") == 0) + retval = (void *)GXxor; + else if (XmuCompareISOLatin1(params[0], "or") == 0) + retval = (void *)GXor; + else if (XmuCompareISOLatin1(params[0], "nor") == 0) + retval = (void *)GXnor; + else if (XmuCompareISOLatin1(params[0], "equiv") == 0) + retval = (void *)GXequiv; + else if (XmuCompareISOLatin1(params[0], "invert") == 0) + retval = (void *)GXinvert; + else if (XmuCompareISOLatin1(params[0], "orreverse") == 0) + retval = (void *)GXorReverse; + else if (XmuCompareISOLatin1(params[0], "copyinverted") == 0) + retval = (void *)GXcopyInverted; + else if (XmuCompareISOLatin1(params[0], "nand") == 0) + retval = (void *)GXnand; + } + break; + case PLANEMASK: + if (*num_params == 1) + retval = (void *)read_int(params[0], NULL); + break; + case DSTRING: + case PSTRING: + if (*num_params == 3) + { + XawDLStringArgs *string = (XawDLStringArgs *) + XtCalloc(1, sizeof(XawDLStringArgs)); + + read_position(params[0], &string->pos[0]); + read_position(params[1], &string->pos[1]); + string->string = XtNewString(params[2]); + string->length = strlen(string->string); + retval = string; + } + break; + case FONT: + if (*num_params == 1) + retval = (void *)XLoadFont(DisplayOfScreen(screen), params[0]); + break; + case DASHES: + if (*num_params && *num_params < 127) + { + char *dashes; + + dashes = XtMalloc(*num_params + 1); + + for (i = 0; i < *num_params; i++) + dashes[i + 1] = read_int(params[i], NULL); + *dashes = *num_params; + retval = dashes; + } + break; + case SUBWMODE: + if (*num_params == 1) + { + if (XmuCompareISOLatin1(params[0], "clipbychildren") == 0) + retval = (void *)ClipByChildren; + else if (XmuCompareISOLatin1(params[0], "includeinferiors") == 0) + retval = (void *)IncludeInferiors; + } + break; + case EXPOSURES: + if (*num_params == 1) + { + if (isdigit(params[0][0]) || params[0][0] == '+' || params[0][0] == '-') + retval = (void *)read_int(params[0], NULL); + else if (XmuCompareISOLatin1(params[0], "true") == 0 || + XmuCompareISOLatin1(params[0], "on") == 0) + retval = (void *)True; + else if (XmuCompareISOLatin1(params[0], "false") == 0 || + XmuCompareISOLatin1(params[0], "off") == 0) + retval = (void *)False; + } + break; + case CLIPMASK: + if (*num_params == 1) + retval = (void *)XawLoadPixmap(params[0], screen, colormap, 1); + if (retval == NULL) + { + retval = XAWDL_CONVERT_ERROR; + XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0], + XtRPixmap); + } + break; + case COPYAREA: + case COPYPLANE: + if (*num_params > 2 && *num_params <= 7 + (id == COPYPLANE)) + { + XawDLCopyArgs *args = (XawDLCopyArgs *) + XtCalloc(1, sizeof(XawDLCopyArgs)); + + retval = args; + if (params[0][0] == '\0' || strcmp(params[0], ".") == 0) + args->pixmap = NULL; + else + { + args->pixmap = XawLoadPixmap(params[0], screen, colormap, id == COPYPLANE ? 1 : depth); + if (args->pixmap == NULL) + { + XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0], + XtRBitmap); + retval = XAWDL_CONVERT_ERROR; + XtFree((char *)args); + } + } + if (retval != XAWDL_CONVERT_ERROR) + { + for (i = 1; i < *num_params && i < 7; i++) + read_position(params[i], &args->pos[i - 1]); + if (*num_params > 7) + args->plane = read_int(params[7], NULL); + } + } + break; + case IMAGE: + if (*num_params > 2 && *num_params <= 7) + { + XawDLImageArgs *args = (XawDLImageArgs *) + XtCalloc(1, sizeof(XawDLImageArgs)); + + retval = args; + args->pixmap = XawLoadPixmap(params[0], screen, colormap, depth); + if (args->pixmap == NULL) + { + XtDisplayStringConversionWarning(DisplayOfScreen(screen), + (String)params[0], XtRPixmap); + retval = XAWDL_CONVERT_ERROR; + XtFree((char *)args); + } + else + { + args->depth = depth; + for (i = 1; i < *num_params && i < 5; i++) + read_position(params[i], &args->pos[i - 1]); + } + } + break; + } + + return (retval); +} + +/* ARGSUSED */ +static void * +_Xaw_Xlib_DataInitProc(String class_name, + Screen *screen, Colormap colormap, int depth) +{ + XawXlibData *data; + Window tmp_win; + + data = (XawXlibData *)XtMalloc(sizeof(XawXlibData)); + + tmp_win = XCreateWindow(DisplayOfScreen(screen), + RootWindowOfScreen(screen), + 0, 0, 1, 1, 1, depth, + InputOutput, (Visual *)CopyFromParent, 0, NULL); + data->mask = 0; + data->gc = XCreateGC(DisplayOfScreen(screen), tmp_win, 0, &data->values); + XDestroyWindow(DisplayOfScreen(screen), tmp_win); + data->shape = Complex; + data->mode = CoordModeOrigin; + data->dashes = NULL; + + return ((void *)data); +} + +/* ARGSUSED */ +static void +_Xaw_Xlib_ArgsDestructor(Display *display, String proc_name, XtPointer args, + String *params, Cardinal *num_params) +{ + Cardinal id; + Dl_init *init; + + init = (Dl_init *)bsearch(proc_name, dl_init, + sizeof(dl_init) / sizeof(dl_init[0]), + sizeof(dl_init[0]), + bcmp_cvt_proc); + + id = init->id; + + switch (id) + { + case LINE: + case DRECT: + case FRECT: + case DARC: + case FARC: + case POINT: + case TSORIGIN: + case DASHES: + case CLIPORIGIN: + case COPYAREA: + case COPYPLANE: + case IMAGE: + XtFree(args); + break; + case DSTRING: + case PSTRING: + { + XawDLStringArgs *string = (XawDLStringArgs *)args; + XtFree(string->string); + XtFree(args); + } break; + case DLINES: + case FPOLY: + case POINTS: + case SEGMENTS: + case CLIPRECTS: + { + XawDLPositionPtr *ptr = (XawDLPositionPtr *)args; + + XtFree((char *)ptr->pos); + XtFree(args); + } break; + } +} + +/* ARGSUSED */ +static void +_Xaw_Xlib_DataDestructor(Display *display, String class_name, XtPointer data) +{ + if (data) + { + XawXlibData *xdata = (XawXlibData *)data; + + XFreeGC(display, xdata->gc); + if (xdata->dashes) + XtFree(xdata->dashes); + XtFree((char *)data); + } +} + +/* Start of DLInfo Management Functions */ +static int +qcmp_dlist_info(register _Xconst void *left, register _Xconst void *right) +{ + return (strcmp((*(XawDLInfo **)left)->name, (*(XawDLInfo **)right)->name)); +} + +Bool XawDeclareDisplayListProc(XawDLClass *lc, String name, + XawDisplayListProc proc) +{ + XawDLInfo *info; + + if (!lc || !proc || !name || name[0] == '\0') + return (False); + + if ((info = _XawFindDLInfo(lc, name)) != NULL) + /* Since the data structures to the displayList classes are(should be) + * opaque, it is not a good idea to allow overriding a displayList + * procedure; it's better to choose another name or class name! + */ + return (False); + + info = (XawDLInfo *)XtMalloc(sizeof(XawDLInfo)); + info->name = XtNewString(name); + info->qname = XrmStringToQuark(info->name); + info->proc = proc; + + if (!lc->num_infos) + { + lc->num_infos = 1; + lc->infos = (XawDLInfo **)XtMalloc(sizeof(XawDLInfo*)); + } + else + { + ++lc->num_infos; + lc->infos = (XawDLInfo **) + XtRealloc((char *)lc->infos, sizeof(XawDLInfo*) * lc->num_infos); + } + lc->infos[lc->num_infos - 1] = info; + + if (lc->num_infos > 1) + qsort(lc->infos, lc->num_infos, sizeof(XawDLInfo*), qcmp_dlist_info); + + return (True); +} + +static int +bcmp_dlist_info(register _Xconst void *string, + register _Xconst void *dlinfo) +{ + return (strcmp((String)string, (*(XawDLClass **)dlinfo)->name)); +} + +static XawDLInfo * +_XawFindDLInfo(XawDLClass *lc, String name) +{ + XawDLInfo **info; + + if (!lc->infos) + return (NULL); + + info = (XawDLInfo **)bsearch(name, lc->infos, lc->num_infos, + sizeof(XawDLInfo*), bcmp_dlist_info); + + return (info ? *info : NULL); +} + +/* Start of DLClass Management Functions */ +XawDLClass * +XawGetDisplayListClass(String name) +{ + return (_XawFindDLClass(name)); +} + +static int +qcmp_dlist_class(register _Xconst void *left, register _Xconst void *right) +{ + return (strcmp((*(XawDLClass **)left)->name, (*(XawDLClass **)right)->name)); +} + +XawDLClass * +XawCreateDisplayListClass(String name, + XawDLArgsInitProc args_init, + XawDLArgsDestructor args_destructor, + XawDLDataInitProc data_init, + XawDLDataDestructor data_destructor) +{ + XawDLClass *lc; + + if (!name || name[0] == '\0') + return (NULL); + + lc = (XawDLClass *)XtMalloc(sizeof(XawDLClass)); + lc->name = XtNewString(name); + lc->infos = NULL; + lc->num_infos = 0; + lc->args_init = args_init; + lc->args_destructor = args_destructor; + lc->data_init = data_init; + lc->data_destructor = data_destructor; + + if (!classes) + { + num_classes = 1; + classes = (XawDLClass **)XtMalloc(sizeof(XawDLClass)); + } + else + { + ++num_classes; + classes = (XawDLClass **)XtRealloc((char *)classes, + sizeof(XawDLClass) * num_classes); + } + classes[num_classes - 1] = lc; + + if (num_classes > 1) + qsort(&classes[0], num_classes, sizeof(XawDLClass*), qcmp_dlist_class); + + return (lc); +} + +static int +bcmp_dlist_class(register _Xconst void *string, + register _Xconst void *dlist) +{ + return (strcmp((String)string, (*(XawDLClass **)dlist)->name)); +} + +static XawDLClass * +_XawFindDLClass(String name) +{ + XawDLClass **lc; + + if (!classes) + return (NULL); + + lc = (XawDLClass **)bsearch(name, &classes[0], num_classes, + sizeof(XawDLClass*), bcmp_dlist_class); + + return (lc ? *lc : NULL); +} + +#endif /* OLDXAW */ diff --git a/libXaw/src/Form.c b/libXaw/src/Form.c index 9f5ac8271..58723e845 100644 --- a/libXaw/src/Form.c +++ b/libXaw/src/Form.c @@ -1,1106 +1,1106 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/Converters.h>
-#include <X11/Xaw/FormP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * Class Methods
- */
-static void XawFormChangeManaged(Widget);
-static void XawFormClassInitialize(void);
-static void XawFormClassPartInitialize(WidgetClass);
-static void XawFormConstraintInitialize(Widget, Widget, ArgList, Cardinal*);
-static Boolean XawFormConstraintSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static XtGeometryResult XawFormGeometryManager(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawFormInitialize(Widget, Widget, ArgList, Cardinal*);
-#ifndef OLDXAW
-static void XawFormRealize(Widget, Mask*, XSetWindowAttributes*);
-static void XawFormRedisplay(Widget, XEvent*, Region);
-#endif
-static XtGeometryResult XawFormQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawFormResize(Widget);
-static Boolean XawFormSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool);
-
-/*
- * Prototypes
- */
-static void _CvtStringToEdgeType(XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr);
-static Bool ChangeFormGeometry(Widget, Bool, unsigned int, unsigned int,
- Dimension*, Dimension*);
-Boolean CvtEdgeTypeToString(Display*, XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr, XtPointer*);
-static void LayoutChild(Widget);
-static int TransformCoord(int, unsigned int, unsigned int, XtEdgeType);
-static void ResizeChildren(Widget);
-
-/*
- * Initialization
- */
-#ifndef OLDXAW
-static XtActionsRec actions[] = {
- {"set-values", XawSetValuesAction},
- {"get-values", XawGetValuesAction},
- {"declare", XawDeclareAction},
- {"call-proc", XawCallProcAction},
-};
-#endif
-
-static XrmQuark QchainLeft, QchainRight, QchainTop, QchainBottom, Qrubber;
-
-#define default_value -99999
-#define Offset(field) XtOffsetOf(FormRec, form.field)
-static XtResource resources[] = {
- {
- XtNdefaultDistance,
- XtCThickness,
- XtRInt,
- sizeof(int),
- Offset(default_spacing),
- XtRImmediate,
- (XtPointer)4
- },
-#ifndef OLDXAW
- {
- XawNdisplayList,
- XawCDisplayList,
- XawRDisplayList,
- sizeof(XawDisplayList*),
- Offset(display_list),
- XtRImmediate,
- NULL
- },
-#endif
-};
-#undef Offset
-
-#define defEdge XtRubber
-
-#define Offset(field) XtOffsetOf(FormConstraintsRec, form.field)
-static XtResource formConstraintResources[] = {
- {
- XtNtop,
- XtCEdge,
- XtREdgeType,
- sizeof(XtEdgeType),
- Offset(top),
- XtRImmediate,
- (XtPointer)defEdge
- },
- {
- XtNbottom,
- XtCEdge,
- XtREdgeType,
- sizeof(XtEdgeType),
- Offset(bottom),
- XtRImmediate,
- (XtPointer)defEdge
- },
- {
- XtNleft,
- XtCEdge,
- XtREdgeType,
- sizeof(XtEdgeType),
- Offset(left),
- XtRImmediate,
- (XtPointer)defEdge
- },
- {
- XtNright,
- XtCEdge,
- XtREdgeType,
- sizeof(XtEdgeType),
- Offset(right),
- XtRImmediate,
- (XtPointer)defEdge
- },
- {
- XtNhorizDistance,
- XtCThickness,
- XtRInt,
- sizeof(int),
- Offset(dx),
- XtRImmediate,
- (XtPointer)default_value
- },
- {
- XtNfromHoriz,
- XtCWidget,
- XtRWidget,
- sizeof(Widget),
- Offset(horiz_base),
- XtRWidget,
- NULL
- },
- {
- XtNvertDistance,
- XtCThickness,
- XtRInt,
- sizeof(int),
- Offset(dy),
- XtRImmediate,
- (XtPointer)default_value
- },
- {
- XtNfromVert,
- XtCWidget,
- XtRWidget,
- sizeof(Widget),
- Offset(vert_base),
- XtRWidget,
- NULL
- },
- {
- XtNresizable,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- Offset(allow_resize),
- XtRImmediate,
- (XtPointer)False
- },
-};
-#undef Offset
-
-FormClassRec formClassRec = {
- /* core */
- {
- (WidgetClass)&constraintClassRec, /* superclass */
- "Form", /* class_name */
- sizeof(FormRec), /* widget_size */
- XawFormClassInitialize, /* class_initialize */
- XawFormClassPartInitialize, /* class_part_init */
- False, /* class_inited */
- XawFormInitialize, /* initialize */
- NULL, /* initialize_hook */
-#ifndef OLDXAW
- XawFormRealize, /* realize */
- actions, /* actions */
- XtNumber(actions), /* num_actions */
-#else
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
-#endif
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- XawFormResize, /* resize */
-#ifndef OLDXAW
- XawFormRedisplay, /* expose */
-#else
- XtInheritExpose, /* expose */
-#endif
- XawFormSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XawFormQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* composite */
- {
- XawFormGeometryManager, /* geometry_manager */
- XawFormChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- /* constraint */
- {
- formConstraintResources, /* subresourses */
- XtNumber(formConstraintResources), /* subresource_count */
- sizeof(FormConstraintsRec), /* constraint_size */
- XawFormConstraintInitialize, /* initialize */
- NULL, /* destroy */
- XawFormConstraintSetValues, /* set_values */
- NULL, /* extension */
- },
- /* form */
- {
- Layout, /* layout */
- },
-};
-
-WidgetClass formWidgetClass = (WidgetClass)&formClassRec;
-
-/*
- * Implementation
- */
-#ifndef OLDXAW
-static void
-XawFormRealize(Widget w, Mask *mask, XSetWindowAttributes *attr)
-{
- XawPixmap *pixmap;
-
- (*formWidgetClass->core_class.superclass->core_class.realize)(w, mask, attr);
-
- if (w->core.background_pixmap > XtUnspecifiedPixmap) {
- pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
- w->core.colormap, w->core.depth);
- if (pixmap && pixmap->mask)
- XawReshapeWidget(w, pixmap);
- }
-}
-
-static void
-XawFormRedisplay(Widget w, XEvent *event, Region region)
-{
- FormWidget xaw = (FormWidget)w;
-
- if (xaw->form.display_list)
- XawRunDisplayList(w, xaw->form.display_list, event, region);
-}
-#endif
-
-/*ARGSUSED*/
-static void
-_CvtStringToEdgeType(XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal)
-{
- static XtEdgeType edgeType;
- XrmQuark q;
- char name[12];
-
- XmuNCopyISOLatin1Lowered(name, (char*)fromVal->addr, sizeof(name));
- q = XrmStringToQuark(name);
-
- if (q == QchainLeft)
- edgeType = XtChainLeft;
- else if (q == QchainRight)
- edgeType = XtChainRight;
- else if (q == QchainTop)
- edgeType = XtChainTop;
- else if (q == QchainBottom)
- edgeType = XtChainBottom;
- else if (q == Qrubber)
- edgeType = XtRubber;
- else {
- XtStringConversionWarning(fromVal->addr, XtREdgeType);
- toVal->size = 0;
- toVal->addr = NULL;
- return;
- }
-
- toVal->size = sizeof(XtEdgeType);
- toVal->addr = (XPointer)&edgeType;
-}
-
-/*ARGSUSED*/
-Boolean
-CvtEdgeTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data)
-{
- static String buffer;
- Cardinal size;
-
- switch (*(XtEdgeType *)fromVal->addr) {
- case XtChainLeft:
- buffer = XtEchainLeft;
- break;
- case XtChainRight:
- buffer = XtEchainRight;
- break;
- case XtChainTop:
- buffer = XtEchainTop;
- break;
- case XtChainBottom:
- buffer = XtEchainBottom;
- break;
- case XtRubber:
- buffer = XtErubber;
- break;
- default:
- XawTypeToStringWarning(dpy, XtREdgeType);
- toVal->addr = NULL;
- toVal->size = 0;
- return (False);
- }
-
- size = strlen(buffer) + 1;
- if (toVal->addr != NULL) {
- if (toVal->size < size) {
- toVal->size = size;
- return (False);
- }
- strcpy((char *)toVal->addr, buffer);
- }
- else
- toVal->addr = (XPointer)buffer;
- toVal->size = sizeof(String);
-
- return (True);
-}
-
-static void
-XawFormClassInitialize(void)
-{
- static XtConvertArgRec parentCvtArgs[] = {
- {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent),
- sizeof(Widget)}
- };
-
- char name[12];
-
- XawInitializeWidgetSet();
- XmuNCopyISOLatin1Lowered(name, XtEchainLeft, sizeof(name));
- QchainLeft = XrmStringToQuark(name);
- XmuNCopyISOLatin1Lowered(name, XtEchainRight, sizeof(name));
- QchainRight = XrmStringToQuark(name);
- XmuNCopyISOLatin1Lowered(name, XtEchainTop, sizeof(name));
- QchainTop = XrmStringToQuark(name);
- XmuNCopyISOLatin1Lowered(name, XtEchainBottom, sizeof(name));
- QchainBottom = XrmStringToQuark(name);
- XmuNCopyISOLatin1Lowered(name, XtErubber, sizeof(name));
- Qrubber = XrmStringToQuark(name);
-
- XtAddConverter(XtRString, XtREdgeType, _CvtStringToEdgeType, NULL, 0);
- XtSetTypeConverter(XtREdgeType, XtRString, CvtEdgeTypeToString,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget,
- parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
- NULL);
- XtSetTypeConverter(XtRWidget, XtRString, XmuCvtWidgetToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-static void
-XawFormClassPartInitialize(WidgetClass cclass)
-{
- FormWidgetClass c = (FormWidgetClass)cclass;
- FormWidgetClass super = (FormWidgetClass)c->core_class.superclass;
-
- if (c->form_class.layout == XtInheritLayout)
- c->form_class.layout = super->form_class.layout;
-}
-
-/*ARGSUSED*/
-static void
-XawFormInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- FormWidget fw = (FormWidget)cnew;
-
- fw->form.old_width = fw->form.old_height = 0;
- fw->form.no_refigure = False;
- fw->form.needs_relayout = False;
- fw->form.resize_in_layout = True;
- fw->form.resize_is_no_op = False;
-}
-
-/*
- * Function:
- * ChangeFormGeometry
- *
- * Parameters:
- * w - Form widget
- * query_only - is only a query?
- * width - new width and height
- * height - ""
- * ret_width - actual size the form is allowed to resize to (return)
- * ret_height - ""
- *
- * Description:
- * Ask the parent to change the form widget's geometry.
- *
- * Returns:
- * True of children may always be resized
- */
-static Bool
-ChangeFormGeometry(Widget w, Bool query_only,
- unsigned int width, unsigned int height,
- Dimension *ret_width, Dimension *ret_height)
-{
- FormWidget fw = (FormWidget)w;
- Boolean always_resize_children;
- XtGeometryResult result;
- XtWidgetGeometry request, return_request;
-
- /*
- * If we are already at the desired size then there is no need
- * to ask our parent of we can change size
- */
- if (width == XtWidth(fw) && height == XtHeight(fw))
- return (True);
-
- request.width = width;
- request.height = height;
- request.request_mode = CWWidth | CWHeight;
- if (query_only)
- request.request_mode |= XtCWQueryOnly;
-
- /*
- * Do no invoke the resize rules if our size changes here
- */
- fw->form.resize_is_no_op = True;
-
- result = XtMakeGeometryRequest(w, &request, &return_request);
- if (result == XtGeometryAlmost) {
- request = return_request;
- (void)XtMakeGeometryRequest(w, &request, &return_request);
- always_resize_children = False;
- }
- else
- always_resize_children = result == XtGeometryYes;
-
- fw->form.resize_is_no_op = False;
-
- if (ret_width != NULL)
- *ret_width = request.width;
- if (ret_height != NULL)
- *ret_height = request.height;
-
- return (always_resize_children);
-}
-
-/*
- * Function:
- * Layout
- *
- * Parameters:
- * fw - Form widget
- * width - unused
- * height - ""
- * force_relayout - will force the children to be moved, even if some
- * go past the edge of the form
- *
- * Description:
- * Moves all the children around.
- *
- * Returns:
- * True if the children are allowed to move from their
- * current locations to the new ones.
- */
-/*ARGSUSED*/
-static Boolean
-Layout(FormWidget fw, unsigned int width, unsigned int height,
- Bool force_relayout)
-{
- int num_children = fw->composite.num_children;
- WidgetList children = fw->composite.children;
- Widget *childP;
- Dimension maxx, maxy;
- Boolean ret_val;
-
- for (childP = children; childP - children < num_children; childP++) {
- FormConstraints form = (FormConstraints)(*childP)->core.constraints;
- form->form.layout_state = LayoutPending;
- }
-
- maxx = maxy = 1;
- for (childP = children; childP - children < num_children; childP++) {
- if (XtIsManaged(*childP)) {
- FormConstraints form;
- Position x, y;
-
- form = (FormConstraints)(*childP)->core.constraints;
-
- LayoutChild(*childP);
-
- x = form->form.new_x + XtWidth(*childP)
- + (XtBorderWidth(*childP) << 1);
- if (x > (int)maxx)
- maxx = x;
-
- y = form->form.new_y + XtHeight(*childP)
- + (XtBorderWidth(*childP) << 1);
- if (y > (int)maxy)
- maxy = y;
- }
- }
-
- fw->form.preferred_width = (maxx += fw->form.default_spacing);
- fw->form.preferred_height = (maxy += fw->form.default_spacing);
-
- if (fw->form.resize_in_layout) {
- Boolean always_resize_children;
-
- always_resize_children =
- ChangeFormGeometry((Widget)fw, False, maxx, maxy, NULL, NULL);
-
-#ifdef OLDXAW
- fw->form.old_width = fw->core.width;
- fw->form.old_height = fw->core.height;
-#endif
-
- if (force_relayout)
- ret_val = True;
- else
- ret_val = always_resize_children ||
- (XtWidth(fw) >= maxx && XtHeight(fw) >= maxy);
-
- if (ret_val)
- ResizeChildren((Widget)fw);
- }
- else
- ret_val = False;
-
- fw->form.needs_relayout = False;
-
- return (ret_val);
-}
-
-/*
- * Function:
- * ResizeChildren
- *
- * Parameters:
- * w - form widget
- *
- * Description:
- * Resizes all children to new_x and new_y.
- */
-static void
-ResizeChildren(Widget w)
-{
- FormWidget fw = (FormWidget)w;
- int num_children = fw->composite.num_children;
- WidgetList children = fw->composite.children;
- Widget *childP;
-
- for (childP = children; childP - children < num_children; childP++) {
- FormConstraints form;
- Position x, y;
-
- if (!XtIsManaged(*childP))
- continue;
-
- form = (FormConstraints)(*childP)->core.constraints;
-
- if (fw->form.old_width && fw->form.old_height) {
- x = TransformCoord(form->form.new_x, fw->form.old_width,
- XtWidth(fw), form->form.left);
- y = TransformCoord(form->form.new_y, fw->form.old_height,
- XtHeight(fw), form->form.top);
- }
- else {
- x = form->form.new_x;
- y = form->form.new_y;
- }
-
- if (fw->form.no_refigure) {
- /*
- * I am changing the widget wrapper w/o modifing the window. This is
- * risky, but I can get away with it since I am the parent of this
- * widget, and he must ask me for any geometry changes
- *
- * The window will be updated when no_refigure is set back to False
- */
- XtX(*childP) = x;
- XtY(*childP) = y;
- }
- else
- XtMoveWidget(*childP, x, y);
- }
-}
-
-static void
-LayoutChild(Widget w)
-{
- FormConstraints form = (FormConstraints)w->core.constraints;
- Widget ref;
-
- switch (form->form.layout_state) {
- case LayoutPending:
- form->form.layout_state = LayoutInProgress;
- break;
- case LayoutDone:
- return;
- case LayoutInProgress: {
- String subs[2];
- Cardinal num_subs = 2;
- subs[0] = w->core.name;
- subs[1] = w->core.parent->core.name;
-
- XtAppWarningMsg(XtWidgetToApplicationContext(w),
- "constraintLoop", "xawFormLayout", "XawToolkitError",
- "constraint loop detected while laying out "
- "child '%s' in FormWidget '%s'",
- subs, &num_subs);
- } return;
- }
-
- form->form.new_x = form->form.dx;
- form->form.new_y = form->form.dy;
- if ((ref = form->form.horiz_base) != NULL) {
- FormConstraints ref_form = (FormConstraints)ref->core.constraints;
-
- LayoutChild(ref);
- form->form.new_x += ref_form->form.new_x + XtWidth(ref) +
- (XtBorderWidth(ref) << 1);
- }
- if ((ref = form->form.vert_base) != NULL) {
- FormConstraints ref_form = (FormConstraints)ref->core.constraints;
-
- LayoutChild(ref);
- form->form.new_y += ref_form->form.new_y + XtHeight(ref) +
- (XtBorderWidth(ref) << 1);
- }
-
- form->form.layout_state = LayoutDone;
-}
-
-static int
-TransformCoord(int loc, unsigned int old, unsigned int cnew, XtEdgeType type)
-{
- if (type == XtRubber) {
- if ((int)old > 0)
- loc = (int)(loc * ((double)cnew / (double)old));
- }
- else if (type == XtChainBottom || type == XtChainRight)
- loc += (int)cnew - (int)old;
-
- return (loc);
-}
-
-static void
-XawFormResize(Widget w)
-{
- FormWidget fw = (FormWidget)w;
- WidgetList children = fw->composite.children;
- int num_children = fw->composite.num_children;
- Widget *childP;
- int x, y;
- int width, height;
- Boolean unmap = XtIsRealized(w) && w->core.mapped_when_managed &&
- XtIsManaged(w);
-
- if (unmap)
- XtUnmapWidget(w);
-
- if (!fw->form.resize_is_no_op)
- for (childP = children; childP - children < num_children; childP++) {
- FormConstraints form = (FormConstraints)(*childP)->core.constraints;
-
- if (!XtIsManaged(*childP))
- continue;
-
-#ifndef OLDXAW
- x = TransformCoord(form->form.virtual_x, fw->form.old_width,
- XtWidth(fw), form->form.left);
- y = TransformCoord(form->form.virtual_y, fw->form.old_height,
- XtHeight(fw), form->form.top);
- width = TransformCoord(form->form.virtual_x +
- form->form.virtual_width +
- (XtBorderWidth(*childP) << 1),
- fw->form.old_width, XtWidth(fw),
- form->form.right) -
- (x + (XtBorderWidth(*childP) << 1));
- height = TransformCoord(form->form.virtual_y +
- form->form.virtual_height +
- (XtBorderWidth(*childP) << 1),
- fw->form.old_height, XtHeight(fw),
- form->form.bottom) -
- (y + (XtBorderWidth(*childP) << 1));
-#else
- x = TransformCoord(XtX(*childP), fw->form.old_width,
- XtWidth(fw), form->form.left);
- y = TransformCoord(XtY(*childP), fw->form.old_height,
- XtHeight(fw), form->form.top);
- width = TransformCoord(XtX(*childP) + form->form.virtual_width +
- (XtBorderWidth(*childP) << 1),
- fw->form.old_width, XtWidth(fw),
- form->form.right) -
- (x + (XtBorderWidth(*childP) << 1));
- height = TransformCoord(XtY(*childP) + form->form.virtual_height +
- (XtBorderWidth(*childP) << 1),
- fw->form.old_height, XtHeight(fw),
- form->form.bottom) -
- (y + (XtBorderWidth(*childP) << 1));
- form->form.virtual_width = width;
- form->form.virtual_height = height;
-#endif
-
- width = width < 1 ? 1 : width;
- height = height < 1 ? 1 : height;
-
- XtConfigureWidget(*childP, x, y, width, height,
- XtBorderWidth(*childP));
- }
-
- if (unmap)
- XtMapWidget(w);
-
-#ifdef OLDXAW
- fw->form.old_width = XtWidth(fw);
- fw->form.old_height = XtHeight(fw);
-#endif
-}
-
-/*ARGSUSED*/
-static XtGeometryResult
-XawFormGeometryManager(Widget w, XtWidgetGeometry *request,
- XtWidgetGeometry *reply)
-{
- Dimension old_width, old_height;
- FormWidget fw = (FormWidget)XtParent(w);
- FormConstraints form = (FormConstraints)w->core.constraints;
- XtWidgetGeometry allowed;
- XtGeometryResult ret_val;
-
- if ((request->request_mode & (unsigned)~(XtCWQueryOnly | CWWidth | CWHeight))
- || !form->form.allow_resize) {
- /* If GeometryManager is invoked during a SetValues call on a child
- * then it is necessary to compute a new layout if ConstraintSetValues
- * allowed any constraint changes
- */
- if (fw->form.needs_relayout)
- (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
- (fw, 0, 0, True);
- return (XtGeometryNo);
- }
-
- if (request->request_mode & CWWidth)
- allowed.width = request->width;
- else
- allowed.width = XtWidth(w);
-
- if (request->request_mode & CWHeight)
- allowed.height = request->height;
- else
- allowed.height = XtHeight(w);
-
- if (allowed.width == XtWidth(w) && allowed.height == XtHeight(w)) {
- /* If GeometryManager is invoked during a SetValues call on a child
- * then it is necessary to compute a new layout if ConstraintSetValues
- * allowed any constraint changes
- */
- if (fw->form.needs_relayout)
- (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
- (fw, 0, 0, True);
- return (XtGeometryNo);
- }
-
- /*
- * Remember the old size, and then set the size to the requested size
- */
- old_width = XtWidth(w);
- old_height = XtHeight(w);
- XtWidth(w) = allowed.width;
- XtHeight(w) = allowed.height;
-
- if (request->request_mode & XtCWQueryOnly) {
- Boolean always_resize_children;
- Dimension ret_width, ret_height;
-
- fw->form.resize_in_layout = False;
-
- (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
- (fw, XtWidth(w), XtHeight(w), False);
-
- /*
- * Reset the size of this child back to what it used to be
- */
- XtWidth(w) = old_width;
- XtHeight(w) = old_height;
-
- fw->form.resize_in_layout = True;
-
- always_resize_children = ChangeFormGeometry(w, True,
- fw->form.preferred_width,
- fw->form.preferred_height,
- &ret_width, &ret_height);
-
- if (always_resize_children
- || (ret_width >= fw->form.preferred_width
- && ret_height >= fw->form.preferred_height))
- ret_val = XtGeometryYes;
- else
- ret_val = XtGeometryNo;
- }
- else {
- if ((*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
- (fw, XtWidth(w), XtHeight(w), False)) {
- Widget *childP;
- int num_children = fw->composite.num_children;
- WidgetList children = fw->composite.children;
-
- if (fw->form.no_refigure) {
- /*
- * I am changing the widget wrapper w/o modifing the window.
- * This is risky, but I can get away with it since I am the
- * parent of this widget, and he must ask me for any geometry
- * changes
- *
- * The window will be updated when no_refigure is set back
- * to False
- */
- form->form.deferred_resize = True;
- ret_val = XtGeometryDone;
- }
- else
- ret_val = XtGeometryYes;
-
- /*
- * Resets everything.
- */
- fw->form.old_width = XtWidth(fw);
- fw->form.old_height = XtHeight(fw);
- for (childP = children; childP - children < num_children; childP++) {
- Widget nw = *childP;
-
- if (XtIsManaged(nw)) {
- FormConstraints nform = (FormConstraints)nw->core.constraints;
-
-#ifndef OLDXAW
- nform->form.virtual_x = XtX(nw);
- nform->form.virtual_y = XtY(nw);
-#endif
- nform->form.virtual_width = XtWidth(nw);
- nform->form.virtual_height = XtHeight(nw);
- }
- }
- }
- else {
- XtWidth(w) = old_width;
- XtHeight(w) = old_height;
- ret_val = XtGeometryNo;
- }
- }
-
- return (ret_val);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawFormSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
-#ifndef OLDXAW
- FormWidget f_old = (FormWidget)current;
- FormWidget f_new = (FormWidget)cnew;
-
- if (f_old->core.background_pixmap != f_new->core.background_pixmap) {
- XawPixmap *opix, *npix;
-
- opix = XawPixmapFromXPixmap(f_old->core.background_pixmap, XtScreen(f_old),
- f_old->core.colormap, f_old->core.depth);
- npix = XawPixmapFromXPixmap(f_new->core.background_pixmap, XtScreen(f_new),
- f_new->core.colormap, f_new->core.depth);
- if ((npix && npix->mask) || (opix && opix->mask))
- XawReshapeWidget(cnew, npix);
- }
-#endif /* OLDXAW */
-
- return (False);
-}
-
-/* ARGSUSED */
-static void
-XawFormConstraintInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- FormConstraints form = (FormConstraints)cnew->core.constraints;
- FormWidget fw = (FormWidget)cnew->core.parent;
-
-#ifndef OLDXAW
- form->form.virtual_x = XtX(cnew);
- form->form.virtual_y = XtY(cnew);
-#endif
- form->form.virtual_width = XtWidth(cnew);
- form->form.virtual_height = XtHeight(cnew);
-
- if (form->form.dx == default_value)
- form->form.dx = fw->form.default_spacing;
-
- if (form->form.dy == default_value)
- form->form.dy = fw->form.default_spacing;
-
- form->form.deferred_resize = False;
-}
-
-/*ARGSUSED*/
-static Boolean
-XawFormConstraintSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- FormConstraints cfc = (FormConstraints)current->core.constraints;
- FormConstraints nfc = (FormConstraints)cnew->core.constraints;
-
- if (cfc->form.top != nfc->form.top || cfc->form.bottom != nfc->form.bottom
- || cfc->form.left != nfc->form.left || cfc->form.right != nfc->form.right
- || cfc->form.dx != nfc->form.dx || cfc->form.dy != nfc->form.dy
- || cfc->form.horiz_base != nfc->form.horiz_base
- || cfc->form.vert_base != nfc->form.vert_base) {
- FormWidget fp = (FormWidget)XtParent(cnew);
-
- /* If there are no subclass ConstraintSetValues procedures remaining
- * to be invoked, and if there is no geometry request about to be
- * made, then invoke the new layout now; else defer it
- */
- if (XtClass(XtParent(cnew)) == formWidgetClass
- && XtX(current) == XtX(cnew)
- && XtY(current) == XtY(cnew)
- && XtWidth(current) == XtWidth(cnew)
- && XtHeight(current) == XtHeight(cnew)
- && XtBorderWidth(current) == XtBorderWidth(cnew))
- Layout(fp, 0, 0, True);
- else
- fp->form.needs_relayout = True;
- }
-
- return (False);
-}
-
-static void
-XawFormChangeManaged(Widget w)
-{
- FormWidget fw = (FormWidget)w;
- FormConstraints form;
- WidgetList children, childP;
- int num_children = fw->composite.num_children;
- Widget child;
-
- (*((FormWidgetClass)w->core.widget_class)->form_class.layout)
- (fw, XtWidth(w), XtHeight(w), True);
-
- fw->form.old_width = XtWidth(w);
- fw->form.old_height = XtHeight(w);
- for (children = childP = fw->composite.children;
- childP - children < num_children;
- childP++) {
- child = *childP;
- if (!XtIsManaged(child))
- continue;
- form = (FormConstraints)child->core.constraints;
-#ifndef OLDXAW
- form->form.virtual_x = XtX(child);
- form->form.virtual_y = XtY(child);
-#endif
- form->form.virtual_width = XtWidth(child);
- form->form.virtual_height = XtHeight(child);
- }
-}
-
-static XtGeometryResult
-XawFormQueryGeometry(Widget widget, XtWidgetGeometry *request,
- XtWidgetGeometry *reply)
-{
- FormWidget w = (FormWidget)widget;
-
- reply->width = w->form.preferred_width;
- reply->height = w->form.preferred_height;
- reply->request_mode = CWWidth | CWHeight;
-
- if ((request->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight)
- && request->width == reply->width
- && request->height == reply->height)
- return (XtGeometryYes);
- else if (reply->width == XtWidth(w) && reply->height == XtHeight(w))
- return (XtGeometryNo);
-
- return (XtGeometryAlmost);
-}
-
-/*
- * Public routines
- */
-/*
- * Set or reset figuring (ignored if not realized)
- */
-void
-XawFormDoLayout(Widget w,
-#if NeedWidePrototypes
- Bool force
-#else
- Boolean force
-#endif
-)
-{
- Widget *childP;
- FormWidget fw = (FormWidget)w;
- int num_children = fw->composite.num_children;
- WidgetList children = fw->composite.children;
-
- if ((fw->form.no_refigure = !force) == True || !XtIsRealized(w))
- return;
-
- for (childP = children; childP - children < num_children; childP++) {
- Widget nw = *childP;
-
- if (XtIsManaged(nw)) {
- FormConstraints form = (FormConstraints)nw->core.constraints;
-
- /*
- * Xt Configure widget is too smart, and optimizes out
- * my changes
- */
- XMoveResizeWindow(XtDisplay(nw), XtWindow(nw),
- XtX(nw), XtY(nw), XtWidth(nw), XtHeight(nw));
-
- if (form)
- if (form->form.deferred_resize &&
- XtClass(nw)->core_class.resize != NULL) {
- (*(XtClass(nw)->core_class.resize))(nw);
- form->form.deferred_resize = False;
- }
- }
- }
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xaw/FormP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * Class Methods + */ +static void XawFormChangeManaged(Widget); +static void XawFormClassInitialize(void); +static void XawFormClassPartInitialize(WidgetClass); +static void XawFormConstraintInitialize(Widget, Widget, ArgList, Cardinal*); +static Boolean XawFormConstraintSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static XtGeometryResult XawFormGeometryManager(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawFormInitialize(Widget, Widget, ArgList, Cardinal*); +#ifndef OLDXAW +static void XawFormRealize(Widget, Mask*, XSetWindowAttributes*); +static void XawFormRedisplay(Widget, XEvent*, Region); +#endif +static XtGeometryResult XawFormQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawFormResize(Widget); +static Boolean XawFormSetValues(Widget, Widget, Widget, ArgList, Cardinal*); +static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool); + +/* + * Prototypes + */ +static void _CvtStringToEdgeType(XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr); +static Bool ChangeFormGeometry(Widget, Bool, unsigned int, unsigned int, + Dimension*, Dimension*); +Boolean CvtEdgeTypeToString(Display*, XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr, XtPointer*); +static void LayoutChild(Widget); +static int TransformCoord(int, unsigned int, unsigned int, XtEdgeType); +static void ResizeChildren(Widget); + +/* + * Initialization + */ +#ifndef OLDXAW +static XtActionsRec actions[] = { + {"set-values", XawSetValuesAction}, + {"get-values", XawGetValuesAction}, + {"declare", XawDeclareAction}, + {"call-proc", XawCallProcAction}, +}; +#endif + +static XrmQuark QchainLeft, QchainRight, QchainTop, QchainBottom, Qrubber; + +#define default_value -99999 +#define Offset(field) XtOffsetOf(FormRec, form.field) +static XtResource resources[] = { + { + XtNdefaultDistance, + XtCThickness, + XtRInt, + sizeof(int), + Offset(default_spacing), + XtRImmediate, + (XtPointer)4 + }, +#ifndef OLDXAW + { + XawNdisplayList, + XawCDisplayList, + XawRDisplayList, + sizeof(XawDisplayList*), + Offset(display_list), + XtRImmediate, + NULL + }, +#endif +}; +#undef Offset + +#define defEdge XtRubber + +#define Offset(field) XtOffsetOf(FormConstraintsRec, form.field) +static XtResource formConstraintResources[] = { + { + XtNtop, + XtCEdge, + XtREdgeType, + sizeof(XtEdgeType), + Offset(top), + XtRImmediate, + (XtPointer)defEdge + }, + { + XtNbottom, + XtCEdge, + XtREdgeType, + sizeof(XtEdgeType), + Offset(bottom), + XtRImmediate, + (XtPointer)defEdge + }, + { + XtNleft, + XtCEdge, + XtREdgeType, + sizeof(XtEdgeType), + Offset(left), + XtRImmediate, + (XtPointer)defEdge + }, + { + XtNright, + XtCEdge, + XtREdgeType, + sizeof(XtEdgeType), + Offset(right), + XtRImmediate, + (XtPointer)defEdge + }, + { + XtNhorizDistance, + XtCThickness, + XtRInt, + sizeof(int), + Offset(dx), + XtRImmediate, + (XtPointer)default_value + }, + { + XtNfromHoriz, + XtCWidget, + XtRWidget, + sizeof(Widget), + Offset(horiz_base), + XtRWidget, + NULL + }, + { + XtNvertDistance, + XtCThickness, + XtRInt, + sizeof(int), + Offset(dy), + XtRImmediate, + (XtPointer)default_value + }, + { + XtNfromVert, + XtCWidget, + XtRWidget, + sizeof(Widget), + Offset(vert_base), + XtRWidget, + NULL + }, + { + XtNresizable, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + Offset(allow_resize), + XtRImmediate, + (XtPointer)False + }, +}; +#undef Offset + +FormClassRec formClassRec = { + /* core */ + { + (WidgetClass)&constraintClassRec, /* superclass */ + "Form", /* class_name */ + sizeof(FormRec), /* widget_size */ + XawFormClassInitialize, /* class_initialize */ + XawFormClassPartInitialize, /* class_part_init */ + False, /* class_inited */ + XawFormInitialize, /* initialize */ + NULL, /* initialize_hook */ +#ifndef OLDXAW + XawFormRealize, /* realize */ + actions, /* actions */ + XtNumber(actions), /* num_actions */ +#else + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ +#endif + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XawFormResize, /* resize */ +#ifndef OLDXAW + XawFormRedisplay, /* expose */ +#else + XtInheritExpose, /* expose */ +#endif + XawFormSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XawFormQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* composite */ + { + XawFormGeometryManager, /* geometry_manager */ + XawFormChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + /* constraint */ + { + formConstraintResources, /* subresourses */ + XtNumber(formConstraintResources), /* subresource_count */ + sizeof(FormConstraintsRec), /* constraint_size */ + XawFormConstraintInitialize, /* initialize */ + NULL, /* destroy */ + XawFormConstraintSetValues, /* set_values */ + NULL, /* extension */ + }, + /* form */ + { + Layout, /* layout */ + }, +}; + +WidgetClass formWidgetClass = (WidgetClass)&formClassRec; + +/* + * Implementation + */ +#ifndef OLDXAW +static void +XawFormRealize(Widget w, Mask *mask, XSetWindowAttributes *attr) +{ + XawPixmap *pixmap; + + (*formWidgetClass->core_class.superclass->core_class.realize)(w, mask, attr); + + if (w->core.background_pixmap > XtUnspecifiedPixmap) { + pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w), + w->core.colormap, w->core.depth); + if (pixmap && pixmap->mask) + XawReshapeWidget(w, pixmap); + } +} + +static void +XawFormRedisplay(Widget w, XEvent *event, Region region) +{ + FormWidget xaw = (FormWidget)w; + + if (xaw->form.display_list) + XawRunDisplayList(w, xaw->form.display_list, event, region); +} +#endif + +/*ARGSUSED*/ +static void +_CvtStringToEdgeType(XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal) +{ + static XtEdgeType edgeType; + XrmQuark q; + char name[12]; + + XmuNCopyISOLatin1Lowered(name, (char*)fromVal->addr, sizeof(name)); + q = XrmStringToQuark(name); + + if (q == QchainLeft) + edgeType = XtChainLeft; + else if (q == QchainRight) + edgeType = XtChainRight; + else if (q == QchainTop) + edgeType = XtChainTop; + else if (q == QchainBottom) + edgeType = XtChainBottom; + else if (q == Qrubber) + edgeType = XtRubber; + else { + XtStringConversionWarning(fromVal->addr, XtREdgeType); + toVal->size = 0; + toVal->addr = NULL; + return; + } + + toVal->size = sizeof(XtEdgeType); + toVal->addr = (XPointer)&edgeType; +} + +/*ARGSUSED*/ +Boolean +CvtEdgeTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) +{ + static String buffer; + Cardinal size; + + switch (*(XtEdgeType *)fromVal->addr) { + case XtChainLeft: + buffer = XtEchainLeft; + break; + case XtChainRight: + buffer = XtEchainRight; + break; + case XtChainTop: + buffer = XtEchainTop; + break; + case XtChainBottom: + buffer = XtEchainBottom; + break; + case XtRubber: + buffer = XtErubber; + break; + default: + XawTypeToStringWarning(dpy, XtREdgeType); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + + size = strlen(buffer) + 1; + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +static void +XawFormClassInitialize(void) +{ + static XtConvertArgRec parentCvtArgs[] = { + {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent), + sizeof(Widget)} + }; + + char name[12]; + + XawInitializeWidgetSet(); + XmuNCopyISOLatin1Lowered(name, XtEchainLeft, sizeof(name)); + QchainLeft = XrmStringToQuark(name); + XmuNCopyISOLatin1Lowered(name, XtEchainRight, sizeof(name)); + QchainRight = XrmStringToQuark(name); + XmuNCopyISOLatin1Lowered(name, XtEchainTop, sizeof(name)); + QchainTop = XrmStringToQuark(name); + XmuNCopyISOLatin1Lowered(name, XtEchainBottom, sizeof(name)); + QchainBottom = XrmStringToQuark(name); + XmuNCopyISOLatin1Lowered(name, XtErubber, sizeof(name)); + Qrubber = XrmStringToQuark(name); + + XtAddConverter(XtRString, XtREdgeType, _CvtStringToEdgeType, NULL, 0); + XtSetTypeConverter(XtREdgeType, XtRString, CvtEdgeTypeToString, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget, + parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone, + NULL); + XtSetTypeConverter(XtRWidget, XtRString, XmuCvtWidgetToString, + NULL, 0, XtCacheNone, NULL); +} + +static void +XawFormClassPartInitialize(WidgetClass cclass) +{ + FormWidgetClass c = (FormWidgetClass)cclass; + FormWidgetClass super = (FormWidgetClass)c->core_class.superclass; + + if (c->form_class.layout == XtInheritLayout) + c->form_class.layout = super->form_class.layout; +} + +/*ARGSUSED*/ +static void +XawFormInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + FormWidget fw = (FormWidget)cnew; + + fw->form.old_width = fw->form.old_height = 0; + fw->form.no_refigure = False; + fw->form.needs_relayout = False; + fw->form.resize_in_layout = True; + fw->form.resize_is_no_op = False; +} + +/* + * Function: + * ChangeFormGeometry + * + * Parameters: + * w - Form widget + * query_only - is only a query? + * width - new width and height + * height - "" + * ret_width - actual size the form is allowed to resize to (return) + * ret_height - "" + * + * Description: + * Ask the parent to change the form widget's geometry. + * + * Returns: + * True of children may always be resized + */ +static Bool +ChangeFormGeometry(Widget w, Bool query_only, + unsigned int width, unsigned int height, + Dimension *ret_width, Dimension *ret_height) +{ + FormWidget fw = (FormWidget)w; + Boolean always_resize_children; + XtGeometryResult result; + XtWidgetGeometry request, return_request; + + /* + * If we are already at the desired size then there is no need + * to ask our parent of we can change size + */ + if (width == XtWidth(fw) && height == XtHeight(fw)) + return (True); + + request.width = width; + request.height = height; + request.request_mode = CWWidth | CWHeight; + if (query_only) + request.request_mode |= XtCWQueryOnly; + + /* + * Do no invoke the resize rules if our size changes here + */ + fw->form.resize_is_no_op = True; + + result = XtMakeGeometryRequest(w, &request, &return_request); + if (result == XtGeometryAlmost) { + request = return_request; + (void)XtMakeGeometryRequest(w, &request, &return_request); + always_resize_children = False; + } + else + always_resize_children = result == XtGeometryYes; + + fw->form.resize_is_no_op = False; + + if (ret_width != NULL) + *ret_width = request.width; + if (ret_height != NULL) + *ret_height = request.height; + + return (always_resize_children); +} + +/* + * Function: + * Layout + * + * Parameters: + * fw - Form widget + * width - unused + * height - "" + * force_relayout - will force the children to be moved, even if some + * go past the edge of the form + * + * Description: + * Moves all the children around. + * + * Returns: + * True if the children are allowed to move from their + * current locations to the new ones. + */ +/*ARGSUSED*/ +static Boolean +Layout(FormWidget fw, unsigned int width, unsigned int height, + Bool force_relayout) +{ + int num_children = fw->composite.num_children; + WidgetList children = fw->composite.children; + Widget *childP; + Dimension maxx, maxy; + Boolean ret_val; + + for (childP = children; childP - children < num_children; childP++) { + FormConstraints form = (FormConstraints)(*childP)->core.constraints; + form->form.layout_state = LayoutPending; + } + + maxx = maxy = 1; + for (childP = children; childP - children < num_children; childP++) { + if (XtIsManaged(*childP)) { + FormConstraints form; + Position x, y; + + form = (FormConstraints)(*childP)->core.constraints; + + LayoutChild(*childP); + + x = form->form.new_x + XtWidth(*childP) + + (XtBorderWidth(*childP) << 1); + if (x > (int)maxx) + maxx = x; + + y = form->form.new_y + XtHeight(*childP) + + (XtBorderWidth(*childP) << 1); + if (y > (int)maxy) + maxy = y; + } + } + + fw->form.preferred_width = (maxx += fw->form.default_spacing); + fw->form.preferred_height = (maxy += fw->form.default_spacing); + + if (fw->form.resize_in_layout) { + Boolean always_resize_children; + + always_resize_children = + ChangeFormGeometry((Widget)fw, False, maxx, maxy, NULL, NULL); + +#ifdef OLDXAW + fw->form.old_width = fw->core.width; + fw->form.old_height = fw->core.height; +#endif + + if (force_relayout) + ret_val = True; + else + ret_val = always_resize_children || + (XtWidth(fw) >= maxx && XtHeight(fw) >= maxy); + + if (ret_val) + ResizeChildren((Widget)fw); + } + else + ret_val = False; + + fw->form.needs_relayout = False; + + return (ret_val); +} + +/* + * Function: + * ResizeChildren + * + * Parameters: + * w - form widget + * + * Description: + * Resizes all children to new_x and new_y. + */ +static void +ResizeChildren(Widget w) +{ + FormWidget fw = (FormWidget)w; + int num_children = fw->composite.num_children; + WidgetList children = fw->composite.children; + Widget *childP; + + for (childP = children; childP - children < num_children; childP++) { + FormConstraints form; + Position x, y; + + if (!XtIsManaged(*childP)) + continue; + + form = (FormConstraints)(*childP)->core.constraints; + + if (fw->form.old_width && fw->form.old_height) { + x = TransformCoord(form->form.new_x, fw->form.old_width, + XtWidth(fw), form->form.left); + y = TransformCoord(form->form.new_y, fw->form.old_height, + XtHeight(fw), form->form.top); + } + else { + x = form->form.new_x; + y = form->form.new_y; + } + + if (fw->form.no_refigure) { + /* + * I am changing the widget wrapper w/o modifing the window. This is + * risky, but I can get away with it since I am the parent of this + * widget, and he must ask me for any geometry changes + * + * The window will be updated when no_refigure is set back to False + */ + XtX(*childP) = x; + XtY(*childP) = y; + } + else + XtMoveWidget(*childP, x, y); + } +} + +static void +LayoutChild(Widget w) +{ + FormConstraints form = (FormConstraints)w->core.constraints; + Widget ref; + + switch (form->form.layout_state) { + case LayoutPending: + form->form.layout_state = LayoutInProgress; + break; + case LayoutDone: + return; + case LayoutInProgress: { + String subs[2]; + Cardinal num_subs = 2; + subs[0] = w->core.name; + subs[1] = w->core.parent->core.name; + + XtAppWarningMsg(XtWidgetToApplicationContext(w), + "constraintLoop", "xawFormLayout", "XawToolkitError", + "constraint loop detected while laying out " + "child '%s' in FormWidget '%s'", + subs, &num_subs); + } return; + } + + form->form.new_x = form->form.dx; + form->form.new_y = form->form.dy; + if ((ref = form->form.horiz_base) != NULL) { + FormConstraints ref_form = (FormConstraints)ref->core.constraints; + + LayoutChild(ref); + form->form.new_x += ref_form->form.new_x + XtWidth(ref) + + (XtBorderWidth(ref) << 1); + } + if ((ref = form->form.vert_base) != NULL) { + FormConstraints ref_form = (FormConstraints)ref->core.constraints; + + LayoutChild(ref); + form->form.new_y += ref_form->form.new_y + XtHeight(ref) + + (XtBorderWidth(ref) << 1); + } + + form->form.layout_state = LayoutDone; +} + +static int +TransformCoord(int loc, unsigned int old, unsigned int cnew, XtEdgeType type) +{ + if (type == XtRubber) { + if ((int)old > 0) + loc = (int)(loc * ((double)cnew / (double)old)); + } + else if (type == XtChainBottom || type == XtChainRight) + loc += (int)cnew - (int)old; + + return (loc); +} + +static void +XawFormResize(Widget w) +{ + FormWidget fw = (FormWidget)w; + WidgetList children = fw->composite.children; + int num_children = fw->composite.num_children; + Widget *childP; + int x, y; + int width, height; + Boolean unmap = XtIsRealized(w) && w->core.mapped_when_managed && + XtIsManaged(w); + + if (unmap) + XtUnmapWidget(w); + + if (!fw->form.resize_is_no_op) + for (childP = children; childP - children < num_children; childP++) { + FormConstraints form = (FormConstraints)(*childP)->core.constraints; + + if (!XtIsManaged(*childP)) + continue; + +#ifndef OLDXAW + x = TransformCoord(form->form.virtual_x, fw->form.old_width, + XtWidth(fw), form->form.left); + y = TransformCoord(form->form.virtual_y, fw->form.old_height, + XtHeight(fw), form->form.top); + width = TransformCoord(form->form.virtual_x + + form->form.virtual_width + + (XtBorderWidth(*childP) << 1), + fw->form.old_width, XtWidth(fw), + form->form.right) - + (x + (XtBorderWidth(*childP) << 1)); + height = TransformCoord(form->form.virtual_y + + form->form.virtual_height + + (XtBorderWidth(*childP) << 1), + fw->form.old_height, XtHeight(fw), + form->form.bottom) - + (y + (XtBorderWidth(*childP) << 1)); +#else + x = TransformCoord(XtX(*childP), fw->form.old_width, + XtWidth(fw), form->form.left); + y = TransformCoord(XtY(*childP), fw->form.old_height, + XtHeight(fw), form->form.top); + width = TransformCoord(XtX(*childP) + form->form.virtual_width + + (XtBorderWidth(*childP) << 1), + fw->form.old_width, XtWidth(fw), + form->form.right) - + (x + (XtBorderWidth(*childP) << 1)); + height = TransformCoord(XtY(*childP) + form->form.virtual_height + + (XtBorderWidth(*childP) << 1), + fw->form.old_height, XtHeight(fw), + form->form.bottom) - + (y + (XtBorderWidth(*childP) << 1)); + form->form.virtual_width = width; + form->form.virtual_height = height; +#endif + + width = width < 1 ? 1 : width; + height = height < 1 ? 1 : height; + + XtConfigureWidget(*childP, x, y, width, height, + XtBorderWidth(*childP)); + } + + if (unmap) + XtMapWidget(w); + +#ifdef OLDXAW + fw->form.old_width = XtWidth(fw); + fw->form.old_height = XtHeight(fw); +#endif +} + +/*ARGSUSED*/ +static XtGeometryResult +XawFormGeometryManager(Widget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + Dimension old_width, old_height; + FormWidget fw = (FormWidget)XtParent(w); + FormConstraints form = (FormConstraints)w->core.constraints; + XtWidgetGeometry allowed; + XtGeometryResult ret_val; + + if ((request->request_mode & (unsigned)~(XtCWQueryOnly | CWWidth | CWHeight)) + || !form->form.allow_resize) { + /* If GeometryManager is invoked during a SetValues call on a child + * then it is necessary to compute a new layout if ConstraintSetValues + * allowed any constraint changes + */ + if (fw->form.needs_relayout) + (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) + (fw, 0, 0, True); + return (XtGeometryNo); + } + + if (request->request_mode & CWWidth) + allowed.width = request->width; + else + allowed.width = XtWidth(w); + + if (request->request_mode & CWHeight) + allowed.height = request->height; + else + allowed.height = XtHeight(w); + + if (allowed.width == XtWidth(w) && allowed.height == XtHeight(w)) { + /* If GeometryManager is invoked during a SetValues call on a child + * then it is necessary to compute a new layout if ConstraintSetValues + * allowed any constraint changes + */ + if (fw->form.needs_relayout) + (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) + (fw, 0, 0, True); + return (XtGeometryNo); + } + + /* + * Remember the old size, and then set the size to the requested size + */ + old_width = XtWidth(w); + old_height = XtHeight(w); + XtWidth(w) = allowed.width; + XtHeight(w) = allowed.height; + + if (request->request_mode & XtCWQueryOnly) { + Boolean always_resize_children; + Dimension ret_width, ret_height; + + fw->form.resize_in_layout = False; + + (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) + (fw, XtWidth(w), XtHeight(w), False); + + /* + * Reset the size of this child back to what it used to be + */ + XtWidth(w) = old_width; + XtHeight(w) = old_height; + + fw->form.resize_in_layout = True; + + always_resize_children = ChangeFormGeometry(w, True, + fw->form.preferred_width, + fw->form.preferred_height, + &ret_width, &ret_height); + + if (always_resize_children + || (ret_width >= fw->form.preferred_width + && ret_height >= fw->form.preferred_height)) + ret_val = XtGeometryYes; + else + ret_val = XtGeometryNo; + } + else { + if ((*((FormWidgetClass)fw->core.widget_class)->form_class.layout) + (fw, XtWidth(w), XtHeight(w), False)) { + Widget *childP; + int num_children = fw->composite.num_children; + WidgetList children = fw->composite.children; + + if (fw->form.no_refigure) { + /* + * I am changing the widget wrapper w/o modifing the window. + * This is risky, but I can get away with it since I am the + * parent of this widget, and he must ask me for any geometry + * changes + * + * The window will be updated when no_refigure is set back + * to False + */ + form->form.deferred_resize = True; + ret_val = XtGeometryDone; + } + else + ret_val = XtGeometryYes; + + /* + * Resets everything. + */ + fw->form.old_width = XtWidth(fw); + fw->form.old_height = XtHeight(fw); + for (childP = children; childP - children < num_children; childP++) { + Widget nw = *childP; + + if (XtIsManaged(nw)) { + FormConstraints nform = (FormConstraints)nw->core.constraints; + +#ifndef OLDXAW + nform->form.virtual_x = XtX(nw); + nform->form.virtual_y = XtY(nw); +#endif + nform->form.virtual_width = XtWidth(nw); + nform->form.virtual_height = XtHeight(nw); + } + } + } + else { + XtWidth(w) = old_width; + XtHeight(w) = old_height; + ret_val = XtGeometryNo; + } + } + + return (ret_val); +} + +/*ARGSUSED*/ +static Boolean +XawFormSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ +#ifndef OLDXAW + FormWidget f_old = (FormWidget)current; + FormWidget f_new = (FormWidget)cnew; + + if (f_old->core.background_pixmap != f_new->core.background_pixmap) { + XawPixmap *opix, *npix; + + opix = XawPixmapFromXPixmap(f_old->core.background_pixmap, XtScreen(f_old), + f_old->core.colormap, f_old->core.depth); + npix = XawPixmapFromXPixmap(f_new->core.background_pixmap, XtScreen(f_new), + f_new->core.colormap, f_new->core.depth); + if ((npix && npix->mask) || (opix && opix->mask)) + XawReshapeWidget(cnew, npix); + } +#endif /* OLDXAW */ + + return (False); +} + +/* ARGSUSED */ +static void +XawFormConstraintInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + FormConstraints form = (FormConstraints)cnew->core.constraints; + FormWidget fw = (FormWidget)cnew->core.parent; + +#ifndef OLDXAW + form->form.virtual_x = XtX(cnew); + form->form.virtual_y = XtY(cnew); +#endif + form->form.virtual_width = XtWidth(cnew); + form->form.virtual_height = XtHeight(cnew); + + if (form->form.dx == default_value) + form->form.dx = fw->form.default_spacing; + + if (form->form.dy == default_value) + form->form.dy = fw->form.default_spacing; + + form->form.deferred_resize = False; +} + +/*ARGSUSED*/ +static Boolean +XawFormConstraintSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + FormConstraints cfc = (FormConstraints)current->core.constraints; + FormConstraints nfc = (FormConstraints)cnew->core.constraints; + + if (cfc->form.top != nfc->form.top || cfc->form.bottom != nfc->form.bottom + || cfc->form.left != nfc->form.left || cfc->form.right != nfc->form.right + || cfc->form.dx != nfc->form.dx || cfc->form.dy != nfc->form.dy + || cfc->form.horiz_base != nfc->form.horiz_base + || cfc->form.vert_base != nfc->form.vert_base) { + FormWidget fp = (FormWidget)XtParent(cnew); + + /* If there are no subclass ConstraintSetValues procedures remaining + * to be invoked, and if there is no geometry request about to be + * made, then invoke the new layout now; else defer it + */ + if (XtClass(XtParent(cnew)) == formWidgetClass + && XtX(current) == XtX(cnew) + && XtY(current) == XtY(cnew) + && XtWidth(current) == XtWidth(cnew) + && XtHeight(current) == XtHeight(cnew) + && XtBorderWidth(current) == XtBorderWidth(cnew)) + Layout(fp, 0, 0, True); + else + fp->form.needs_relayout = True; + } + + return (False); +} + +static void +XawFormChangeManaged(Widget w) +{ + FormWidget fw = (FormWidget)w; + FormConstraints form; + WidgetList children, childP; + int num_children = fw->composite.num_children; + Widget child; + + (*((FormWidgetClass)w->core.widget_class)->form_class.layout) + (fw, XtWidth(w), XtHeight(w), True); + + fw->form.old_width = XtWidth(w); + fw->form.old_height = XtHeight(w); + for (children = childP = fw->composite.children; + childP - children < num_children; + childP++) { + child = *childP; + if (!XtIsManaged(child)) + continue; + form = (FormConstraints)child->core.constraints; +#ifndef OLDXAW + form->form.virtual_x = XtX(child); + form->form.virtual_y = XtY(child); +#endif + form->form.virtual_width = XtWidth(child); + form->form.virtual_height = XtHeight(child); + } +} + +static XtGeometryResult +XawFormQueryGeometry(Widget widget, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + FormWidget w = (FormWidget)widget; + + reply->width = w->form.preferred_width; + reply->height = w->form.preferred_height; + reply->request_mode = CWWidth | CWHeight; + + if ((request->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight) + && request->width == reply->width + && request->height == reply->height) + return (XtGeometryYes); + else if (reply->width == XtWidth(w) && reply->height == XtHeight(w)) + return (XtGeometryNo); + + return (XtGeometryAlmost); +} + +/* + * Public routines + */ +/* + * Set or reset figuring (ignored if not realized) + */ +void +XawFormDoLayout(Widget w, +#if NeedWidePrototypes + Bool force +#else + Boolean force +#endif +) +{ + Widget *childP; + FormWidget fw = (FormWidget)w; + int num_children = fw->composite.num_children; + WidgetList children = fw->composite.children; + + if ((fw->form.no_refigure = !force) == True || !XtIsRealized(w)) + return; + + for (childP = children; childP - children < num_children; childP++) { + Widget nw = *childP; + + if (XtIsManaged(nw)) { + FormConstraints form = (FormConstraints)nw->core.constraints; + + /* + * Xt Configure widget is too smart, and optimizes out + * my changes + */ + XMoveResizeWindow(XtDisplay(nw), XtWindow(nw), + XtX(nw), XtY(nw), XtWidth(nw), XtHeight(nw)); + + if (form) + if (form->form.deferred_resize && + XtClass(nw)->core_class.resize != NULL) { + (*(XtClass(nw)->core_class.resize))(nw); + form->form.deferred_resize = False; + } + } + } +} diff --git a/libXaw/src/Grip.c b/libXaw/src/Grip.c index 19b4eb487..93ddfbeda 100644 --- a/libXaw/src/Grip.c +++ b/libXaw/src/Grip.c @@ -1,185 +1,185 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
- * Grip.c - Grip Widget (Used by Paned Widget)
- *
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/GripP.h>
-#include <X11/Xaw/XawInit.h>
-
-/*
- * Prototypes
- */
-static void
-GripAction(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * Initialization
- */
-static XtResource resources[] = {
- {
- XtNwidth,
- XtCWidth,
- XtRDimension,
- sizeof(Dimension),
- XtOffsetOf(GripRec, core.width),
- XtRImmediate,
- (XtPointer)DEFAULT_GRIP_SIZE
- },
- {
- XtNheight,
- XtCHeight,
- XtRDimension,
- sizeof(Dimension),
- XtOffsetOf(GripRec, core.height),
- XtRImmediate,
- (XtPointer)DEFAULT_GRIP_SIZE
- },
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- XtOffsetOf(GripRec, core.background_pixel),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNborderWidth,
- XtCBorderWidth,
- XtRDimension,
- sizeof(Dimension),
- XtOffsetOf(GripRec, core.border_width),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNcallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- XtOffsetOf(GripRec, grip.grip_action),
- XtRCallback,
- NULL
- },
-};
-
-static XtActionsRec actionsList[] =
-{
- {"GripAction", GripAction},
-};
-
-#define Superclass (&simpleClassRec)
-
-GripClassRec gripClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "Grip", /* class name */
- sizeof(GripRec), /* size */
- XawInitializeWidgetSet, /* class initialize */
- NULL, /* class_part_init */
- False, /* class_inited */
- NULL, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- actionsList, /* actions */
- XtNumber(actionsList), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- NULL, /* resize */
- XtInheritExpose, /* expose */
- NULL, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* grip */
- {
- NULL, /* extension */
- }
-};
-
-WidgetClass gripWidgetClass = (WidgetClass)&gripClassRec;
-
-/*
- * Implementation
- */
-static void
-GripAction(Widget widget, XEvent *event, String *params, Cardinal *num_params)
-{
- XawGripCallDataRec call_data;
-
- call_data.event = event;
- call_data.params = params;
- call_data.num_params = *num_params;
-
- XtCallCallbacks(widget, XtNcallback, (XtPointer)&call_data);
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Grip.c - Grip Widget (Used by Paned Widget) + * + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/GripP.h> +#include <X11/Xaw/XawInit.h> + +/* + * Prototypes + */ +static void +GripAction(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +static XtResource resources[] = { + { + XtNwidth, + XtCWidth, + XtRDimension, + sizeof(Dimension), + XtOffsetOf(GripRec, core.width), + XtRImmediate, + (XtPointer)DEFAULT_GRIP_SIZE + }, + { + XtNheight, + XtCHeight, + XtRDimension, + sizeof(Dimension), + XtOffsetOf(GripRec, core.height), + XtRImmediate, + (XtPointer)DEFAULT_GRIP_SIZE + }, + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + XtOffsetOf(GripRec, core.background_pixel), + XtRString, + XtDefaultForeground + }, + { + XtNborderWidth, + XtCBorderWidth, + XtRDimension, + sizeof(Dimension), + XtOffsetOf(GripRec, core.border_width), + XtRImmediate, + (XtPointer)0 + }, + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + XtOffsetOf(GripRec, grip.grip_action), + XtRCallback, + NULL + }, +}; + +static XtActionsRec actionsList[] = +{ + {"GripAction", GripAction}, +}; + +#define Superclass (&simpleClassRec) + +GripClassRec gripClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Grip", /* class name */ + sizeof(GripRec), /* size */ + XawInitializeWidgetSet, /* class initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + NULL, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + actionsList, /* actions */ + XtNumber(actionsList), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + NULL, /* resize */ + XtInheritExpose, /* expose */ + NULL, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* grip */ + { + NULL, /* extension */ + } +}; + +WidgetClass gripWidgetClass = (WidgetClass)&gripClassRec; + +/* + * Implementation + */ +static void +GripAction(Widget widget, XEvent *event, String *params, Cardinal *num_params) +{ + XawGripCallDataRec call_data; + + call_data.event = event; + call_data.params = params; + call_data.num_params = *num_params; + + XtCallCallbacks(widget, XtNcallback, (XtPointer)&call_data); +} diff --git a/libXaw/src/Label.c b/libXaw/src/Label.c index 2eea91ff9..5ce3b7dca 100644 --- a/libXaw/src/Label.c +++ b/libXaw/src/Label.c @@ -1,821 +1,821 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <ctype.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xos.h>
-#include <X11/Xmu/Converters.h>
-#include <X11/Xmu/Drawing.h>
-#include <X11/Xaw/LabelP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
-#define MULTI_LINE_LABEL 32767
-
-#ifdef CRAY
-#define WORD64
-#endif
-
-/*
- * Class Methods
- */
-static void XawLabelClassInitialize(void);
-static void XawLabelDestroy(Widget);
-static void XawLabelInitialize(Widget, Widget, ArgList, Cardinal*);
-static XtGeometryResult XawLabelQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawLabelRedisplay(Widget, XEvent*, Region);
-static void XawLabelResize(Widget);
-static Boolean XawLabelSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-#ifdef WORD64
-static int _XawLabelWidth16(XFontStruct*, char*, int);
-static void _XawLabelDraw16(Display*, Drawable, GC, int, int, char*, int);
-#endif
-static void compute_bitmap_offsets(LabelWidget);
-static void GetGrayGC(LabelWidget);
-static void GetNormalGC(LabelWidget);
-static void _Reposition(LabelWidget, unsigned int, unsigned int,
- Position*, Position*);
-static void set_bitmap_info(LabelWidget);
-static void SetTextWidthAndHeight(LabelWidget);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(LabelRec, field)
-static XtResource resources[] = {
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(label.foreground),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNfont,
- XtCFont,
- XtRFontStruct,
- sizeof(XFontStruct*),
- offset(label.font),
- XtRString,
- XtDefaultFont
- },
- {
- XtNfontSet,
- XtCFontSet,
- XtRFontSet,
- sizeof(XFontSet),
- offset(label.fontset),
- XtRString,
- XtDefaultFontSet
- },
- {
- XtNlabel,
- XtCLabel,
- XtRString,
- sizeof(String),
- offset(label.label),
- XtRString,
- NULL
- },
- {
- XtNencoding,
- XtCEncoding,
- XtRUnsignedChar,
- sizeof(unsigned char),
- offset(label.encoding),
- XtRImmediate,
- (XtPointer)XawTextEncoding8bit
- },
- {
- XtNjustify,
- XtCJustify,
- XtRJustify,
- sizeof(XtJustify),
- offset(label.justify),
- XtRImmediate,
- (XtPointer)XtJustifyCenter
- },
- {
- XtNinternalWidth,
- XtCWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(label.internal_width),
- XtRImmediate,
- (XtPointer)4
- },
- {
- XtNinternalHeight,
- XtCHeight,
- XtRDimension,
- sizeof(Dimension),
- offset(label.internal_height),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNleftBitmap,
- XtCLeftBitmap,
- XtRBitmap,
- sizeof(Pixmap),
- offset(label.left_bitmap),
- XtRImmediate,
- (XtPointer)None
- },
- {
- XtNbitmap,
- XtCPixmap,
- XtRBitmap,
- sizeof(Pixmap),
- offset(label.pixmap),
- XtRImmediate,
- (XtPointer)None
- },
- {
- XtNresize,
- XtCResize,
- XtRBoolean,
- sizeof(Boolean),
- offset(label.resize),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNlabelX,
- XtCPosition,
- XtRPosition,
- sizeof(Position),
- offset(label.label_x),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNlabelY,
- XtCPosition,
- XtRPosition,
- sizeof(Position),
- offset(label.label_y),
- XtRImmediate,
- (XtPointer)0
- },
-};
-#undef offset
-
-#define Superclass (&simpleClassRec)
-LabelClassRec labelClassRec = {
- /* core */
- {
- (WidgetClass)&simpleClassRec, /* superclass */
- "Label", /* class_name */
- sizeof(LabelRec), /* widget_size */
- XawLabelClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawLabelInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawLabelDestroy, /* destroy */
- XawLabelResize, /* resize */
- XawLabelRedisplay, /* expose */
- XawLabelSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XawLabelQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* label */
- {
- NULL, /* extension */
- }
-};
-
-WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec;
-
-/*
- * Implementation
- */
-static void
-XawLabelClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0);
- XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-#ifndef WORD64
-#define TXT16 XChar2b
-#else
-#define TXT16 char
-
-static XChar2b *buf2b;
-static int buf2blen = 0;
-
-static int
-_XawLabelWidth16(XFontStruct *fs, char *str, int n)
-{
- int i;
- XChar2b *ptr;
-
- if (n > buf2blen) {
- buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
- buf2blen = n;
- }
- for (ptr = buf2b, i = n; --i >= 0; ptr++) {
- ptr->byte1 = *str++;
- ptr->byte2 = *str++;
- }
-
- return (XTextWidth16(fs, buf2b, n));
-}
-
-static void
-_XawLabelDraw16(Display *dpy, Drawable d, GC gc, int x, int y,
- char *str, int n)
-{
- int i;
- XChar2b *ptr;
-
- if (n > buf2blen) {
- buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
- buf2blen = n;
- }
- for (ptr = buf2b, i = n; --i >= 0; ptr++) {
- ptr->byte1 = *str++;
- ptr->byte2 = *str++;
- }
- XDrawString16(dpy, d, gc, x, y, buf2b, n);
-}
-
-#define XTextWidth16 _XawLabelWidth16
-#define XDrawString16 _XawLabelDraw16
-#endif /* WORD64 */
-
-/*
- * Calculate width and height of displayed text in pixels
- */
-static void
-SetTextWidthAndHeight(LabelWidget lw)
-{
- XFontStruct *fs = lw->label.font;
- char *nl;
-
- if (lw->label.pixmap != None) {
- Window root;
- int x, y;
- unsigned int width, height, bw, depth;
-
- if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y,
- &width, &height, &bw, &depth)) {
- lw->label.label_height = height;
- lw->label.label_width = width;
- lw->label.label_len = depth;
- return;
- }
- }
- if (lw->simple.international == True) {
- XFontSet fset = lw->label.fontset;
- XFontSetExtents *ext = XExtentsOfFontSet(fset);
-
- lw->label.label_height = ext->max_ink_extent.height;
- if (lw->label.label == NULL) {
- lw->label.label_len = 0;
- lw->label.label_width = 0;
- }
- else if ((nl = index(lw->label.label, '\n')) != NULL) {
- char *label;
-
- lw->label.label_len = MULTI_LINE_LABEL;
- lw->label.label_width = 0;
- for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
- int width = XmbTextEscapement(fset, label, (int)(nl - label));
-
- if (width > (int)lw->label.label_width)
- lw->label.label_width = width;
- label = nl + 1;
- if (*label)
- lw->label.label_height += ext->max_ink_extent.height;
- }
- if (*label) {
- int width = XmbTextEscapement(fset, label, strlen(label));
-
- if (width > (int)lw->label.label_width)
- lw->label.label_width = width;
- }
- }
- else {
- lw->label.label_len = strlen(lw->label.label);
- lw->label.label_width =
- XmbTextEscapement(fset, lw->label.label, lw->label.label_len);
- }
- }
- else {
- lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent;
- if (lw->label.label == NULL) {
- lw->label.label_len = 0;
- lw->label.label_width = 0;
- }
- else if ((nl = index(lw->label.label, '\n')) != NULL) {
- char *label;
-
- lw->label.label_len = MULTI_LINE_LABEL;
- lw->label.label_width = 0;
- for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
- int width;
-
- if (lw->label.encoding)
- width = XTextWidth16(fs, (TXT16*)label, (int)(nl - label) / 2);
- else
- width = XTextWidth(fs, label, (int)(nl - label));
- if (width > (int)lw->label.label_width)
- lw->label.label_width = width;
- label = nl + 1;
- if (*label)
- lw->label.label_height +=
- fs->max_bounds.ascent + fs->max_bounds.descent;
- }
- if (*label) {
- int width = XTextWidth(fs, label, strlen(label));
-
- if (lw->label.encoding)
- width = XTextWidth16(fs, (TXT16*)label, strlen(label) / 2);
- else
- width = XTextWidth(fs, label, strlen(label));
- if (width > (int) lw->label.label_width)
- lw->label.label_width = width;
- }
- }
- else {
- lw->label.label_len = strlen(lw->label.label);
- if (lw->label.encoding)
- lw->label.label_width =
- XTextWidth16(fs, (TXT16*)lw->label.label,
- (int)lw->label.label_len / 2);
- else
- lw->label.label_width =
- XTextWidth(fs, lw->label.label, (int)lw->label.label_len);
- }
- }
-}
-
-static void
-GetNormalGC(LabelWidget lw)
-{
- XGCValues values;
-
- values.foreground = lw->label.foreground;
- values.background = lw->core.background_pixel;
- values.font = lw->label.font->fid;
- values.graphics_exposures = False;
-
- if (lw->simple.international == True)
- /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */
- lw->label.normal_GC = XtAllocateGC((Widget)lw, 0,
- GCForeground | GCBackground |
- GCGraphicsExposures,
- &values, GCFont, 0);
- else
- lw->label.normal_GC = XtGetGC((Widget)lw,
- GCForeground | GCBackground | GCFont |
- GCGraphicsExposures, &values);
-}
-
-static void
-GetGrayGC(LabelWidget lw)
-{
- XGCValues values;
-
- values.foreground = lw->label.foreground;
- values.background = lw->core.background_pixel;
- values.font = lw->label.font->fid;
- values.fill_style = FillTiled;
- values.tile = XmuCreateStippledPixmap(XtScreen((Widget)lw),
- lw->label.foreground,
- lw->core.background_pixel,
- lw->core.depth);
- values.graphics_exposures = False;
-
- lw->label.stipple = values.tile;
- if (lw->simple.international == True)
- /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */
- lw->label.gray_GC = XtAllocateGC((Widget)lw, 0,
- GCForeground | GCBackground |
- GCTile | GCFillStyle |
- GCGraphicsExposures,
- &values, GCFont, 0);
- else
- lw->label.gray_GC = XtGetGC((Widget)lw,
- GCForeground | GCBackground |
- GCFont | GCTile | GCFillStyle |
- GCGraphicsExposures,
- &values);
-}
-
-static void
-compute_bitmap_offsets(LabelWidget lw)
-{
- /*
- * bitmap will be eventually be displayed at
- * (internal_width, internal_height + lbm_y)
- */
- if (lw->label.lbm_height != 0)
- lw->label.lbm_y = (XtHeight(lw) - (lw->label.internal_height * 2 +
- lw->label.lbm_height)) / 2;
- else
- lw->label.lbm_y = 0;
-}
-
-static void
-set_bitmap_info(LabelWidget lw)
-{
- Window root;
- int x, y;
- unsigned int bw, depth;
-
- if (!(lw->label.left_bitmap
- && XGetGeometry(XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y,
- &lw->label.lbm_width, &lw->label.lbm_height,
- &bw, &depth)))
- lw->label.lbm_width = lw->label.lbm_height = 0;
-
- compute_bitmap_offsets(lw);
-}
-
-/*ARGSUSED*/
-static void
-XawLabelInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- LabelWidget lw = (LabelWidget)cnew;
-
- if (!lw->label.font) XtError("Aborting: no font found\n");
- if (lw->simple.international && !lw->label.fontset)
- XtError("Aborting: no fontset found\n");
-
- if (lw->label.label == NULL)
- lw->label.label = XtNewString(lw->core.name);
- else
- lw->label.label = XtNewString(lw->label.label);
-
- GetNormalGC(lw);
- GetGrayGC(lw);
-
- SetTextWidthAndHeight(lw);
-
- if (XtHeight(lw) == 0)
- XtHeight(lw) = lw->label.label_height + 2 * lw->label.internal_height;
-
- set_bitmap_info(lw); /* need core.height */
-
- if (XtWidth(lw) == 0) /* need label.lbm_width */
- XtWidth(lw) = lw->label.label_width + 2 * lw->label.internal_width +
- LEFT_OFFSET(lw);
-
- lw->label.label_x = lw->label.label_y = 0;
- (*XtClass(cnew)->core_class.resize)((Widget)lw);
-}
-
-/*ARGSUSED*/
-static void
-XawLabelRedisplay(Widget gw, XEvent *event, Region region)
-{
- LabelWidget w = (LabelWidget)gw;
- GC gc;
-
- if (*Superclass->core_class.expose != NULL)
- (*Superclass->core_class.expose)(gw, event, region);
-
- gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC;
-#ifdef notdef
- if (region != NULL)
- XSetRegion(XtDisplay(gw), gc, region);
-#endif /*notdef*/
-
- if (w->label.pixmap == None) {
- int len = w->label.label_len;
- char *label = w->label.label;
- Position y = w->label.label_y + w->label.font->max_bounds.ascent;
- Position ksy = w->label.label_y;
-
- /* display left bitmap */
- if (w->label.left_bitmap && w->label.lbm_width != 0)
- XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc,
- 0, 0, w->label.lbm_width, w->label.lbm_height,
- w->label.internal_width,
- w->label.internal_height + w->label.lbm_y, 1L);
-
- if (w->simple.international == True) {
- XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset);
-
- ksy += XawAbs(ext->max_ink_extent.y);
-
- if (len == MULTI_LINE_LABEL) {
- char *nl;
-
- while ((nl = index(label, '\n')) != NULL) {
- XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset,
- gc, w->label.label_x, ksy, label,
- (int)(nl - label));
- ksy += ext->max_ink_extent.height;
- label = nl + 1;
- }
- len = strlen(label);
- }
- if (len)
- XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
- w->label.label_x, ksy, label, len);
- }
- else {
- if (len == MULTI_LINE_LABEL) {
- char *nl;
-
- while ((nl = index(label, '\n')) != NULL) {
- if (w->label.encoding)
- XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
- w->label.label_x, y,
- (TXT16*)label, (int)(nl - label) / 2);
- else
- XDrawString(XtDisplay(gw), XtWindow(gw), gc,
- w->label.label_x, y, label, (int)(nl - label));
- y += w->label.font->max_bounds.ascent +
- w->label.font->max_bounds.descent;
- label = nl + 1;
- }
- len = strlen(label);
- }
- if (len) {
- if (w->label.encoding)
- XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
- w->label.label_x, y, (TXT16*)label, len / 2);
- else
- XDrawString(XtDisplay(gw), XtWindow(gw), gc,
- w->label.label_x, y, label, len);
- }
- }
- }
- else if (w->label.label_len == 1)
- XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
- 0, 0, w->label.label_width, w->label.label_height,
- w->label.label_x, w->label.label_y, 1L);
- else
- XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
- 0, 0, w->label.label_width, w->label.label_height,
- w->label.label_x, w->label.label_y);
-
-#ifdef notdef
- if (region != NULL)
- XSetClipMask(XtDisplay(gw), gc, (Pixmap)None);
-#endif /* notdef */
-}
-
-static void
-_Reposition(LabelWidget lw, unsigned int width, unsigned int height,
- Position *dx, Position *dy)
-{
- Position newPos;
- Position leftedge = lw->label.internal_width + LEFT_OFFSET(lw);
-
- switch (lw->label.justify) {
- case XtJustifyLeft:
- newPos = leftedge;
- break;
- case XtJustifyRight:
- newPos = width - (lw->label.label_width + lw->label.internal_width);
- break;
- case XtJustifyCenter:
- /*FALLTRHOUGH*/
- default:
- newPos = (int)(width - lw->label.label_width) >> 1;
- break;
- }
- if (newPos < (Position)leftedge)
- newPos = leftedge;
- *dx = newPos - lw->label.label_x;
- lw->label.label_x = newPos;
-
- newPos = ((int)(height - lw->label.label_height)) >> 1;
- *dy = newPos - lw->label.label_y;
- lw->label.label_y = newPos;
-}
-
-static void
-XawLabelResize(Widget w)
-{
- LabelWidget lw = (LabelWidget)w;
- Position dx, dy;
-
- _Reposition(lw, XtWidth(w), XtHeight(w), &dx, &dy);
- compute_bitmap_offsets(lw);
-}
-
-#define PIXMAP 0
-#define WIDTH 1
-#define HEIGHT 2
-#define NUM_CHECKS 3
-static Boolean
-XawLabelSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- LabelWidget curlw = (LabelWidget)current;
- LabelWidget reqlw = (LabelWidget)request;
- LabelWidget newlw = (LabelWidget)cnew;
- unsigned int i;
- Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS];
-
- for (i = 0; i < NUM_CHECKS; i++)
- checks[i] = False;
-
- for (i = 0; i < *num_args; i++) {
- if (streq(XtNbitmap, args[i].name))
- checks[PIXMAP] = True;
- else if (streq(XtNwidth, args[i].name))
- checks[WIDTH] = True;
- else if (streq(XtNheight, args[i].name))
- checks[HEIGHT] = True;
- }
-
- if (newlw->label.label == NULL)
- newlw->label.label = newlw->core.name;
-
- /*
- * resize on bitmap change
- */
- if (curlw->label.left_bitmap != newlw->label.left_bitmap)
- was_resized = True;
-
- if (curlw->label.encoding != newlw->label.encoding)
- was_resized = True;
-
- if (curlw->simple.international
- && curlw->label.fontset != newlw->label.fontset)
- was_resized = True;
-
- if (curlw->label.label != newlw->label.label) {
- if (curlw->label.label != curlw->core.name)
- XtFree((char *)curlw->label.label);
-
- if (newlw->label.label != newlw->core.name)
- newlw->label.label = XtNewString(newlw->label.label);
-
- was_resized = True;
- }
-
- if (was_resized || (curlw->label.font != newlw->label.font) ||
- curlw->label.justify != newlw->label.justify || checks[PIXMAP]) {
- SetTextWidthAndHeight(newlw);
- was_resized = True;
- }
-
- /* recalculate the window size if something has changed */
- if (newlw->label.resize && was_resized) {
- if (XtHeight(curlw) == XtHeight(reqlw) && !checks[HEIGHT])
- XtHeight(newlw) = newlw->label.label_height +
- (newlw->label.internal_height << 1);
-
- set_bitmap_info(newlw);
-
- if (XtWidth(curlw) == XtWidth(reqlw) && !checks[WIDTH])
- XtWidth(newlw) = newlw->label.label_width + LEFT_OFFSET(newlw) +
- (newlw->label.internal_width << 1);
- }
-
- if (curlw->label.foreground != newlw->label.foreground
- || curlw->core.background_pixel != newlw->core.background_pixel
- || curlw->label.font->fid != newlw->label.font->fid) {
- /* The Fontset is not in the GC - don't make a new GC if FS changes! */
- XtReleaseGC(cnew, curlw->label.normal_GC);
- XtReleaseGC(cnew, curlw->label.gray_GC);
- XmuReleaseStippledPixmap(XtScreen(current), curlw->label.stipple);
- GetNormalGC(newlw);
- GetGrayGC(newlw);
- redisplay = True;
- }
-
- if (curlw->label.label_x != newlw->label.label_x ||
- curlw->label.label_y != newlw->label.label_y)
- redisplay = True;
-
- if (curlw->label.internal_width != newlw->label.internal_width
- || curlw->label.internal_height != newlw->label.internal_height
- || was_resized) {
- /* Resize() will be called if geometry changes succeed */
- Position dx, dy;
-
- _Reposition(newlw, XtWidth(curlw), XtHeight(curlw), &dx, &dy);
- }
-
- return (was_resized || redisplay ||
- XtIsSensitive(current) != XtIsSensitive(cnew));
-}
-
-static void
-XawLabelDestroy(Widget w)
-{
- LabelWidget lw = (LabelWidget)w;
-
- if (lw->label.label != lw->core.name)
- XtFree(lw->label.label);
- XtReleaseGC(w, lw->label.normal_GC);
- XtReleaseGC(w, lw->label.gray_GC);
- XmuReleaseStippledPixmap(XtScreen(w), lw->label.stipple);
-}
-
-static XtGeometryResult
-XawLabelQueryGeometry(Widget w, XtWidgetGeometry *intended,
- XtWidgetGeometry *preferred)
-{
- LabelWidget lw = (LabelWidget)w;
-
- preferred->request_mode = CWWidth | CWHeight;
- preferred->width = lw->label.label_width +
- (lw->label.internal_width << 1) + LEFT_OFFSET(lw);
- preferred->height = lw->label.label_height +
- (lw->label.internal_height << 1);
-
- if (((intended->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight))
- && intended->width == preferred->width
- && intended->height == preferred->height)
- return (XtGeometryYes);
- else if (preferred->width == XtWidth(w) && preferred->height == XtHeight(w))
- return (XtGeometryNo);
-
- return (XtGeometryAlmost);
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <ctype.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xaw/LabelP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define streq(a, b) (strcmp((a), (b)) == 0) + +#define MULTI_LINE_LABEL 32767 + +#ifdef CRAY +#define WORD64 +#endif + +/* + * Class Methods + */ +static void XawLabelClassInitialize(void); +static void XawLabelDestroy(Widget); +static void XawLabelInitialize(Widget, Widget, ArgList, Cardinal*); +static XtGeometryResult XawLabelQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawLabelRedisplay(Widget, XEvent*, Region); +static void XawLabelResize(Widget); +static Boolean XawLabelSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +#ifdef WORD64 +static int _XawLabelWidth16(XFontStruct*, char*, int); +static void _XawLabelDraw16(Display*, Drawable, GC, int, int, char*, int); +#endif +static void compute_bitmap_offsets(LabelWidget); +static void GetGrayGC(LabelWidget); +static void GetNormalGC(LabelWidget); +static void _Reposition(LabelWidget, unsigned int, unsigned int, + Position*, Position*); +static void set_bitmap_info(LabelWidget); +static void SetTextWidthAndHeight(LabelWidget); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(LabelRec, field) +static XtResource resources[] = { + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(label.foreground), + XtRString, + XtDefaultForeground + }, + { + XtNfont, + XtCFont, + XtRFontStruct, + sizeof(XFontStruct*), + offset(label.font), + XtRString, + XtDefaultFont + }, + { + XtNfontSet, + XtCFontSet, + XtRFontSet, + sizeof(XFontSet), + offset(label.fontset), + XtRString, + XtDefaultFontSet + }, + { + XtNlabel, + XtCLabel, + XtRString, + sizeof(String), + offset(label.label), + XtRString, + NULL + }, + { + XtNencoding, + XtCEncoding, + XtRUnsignedChar, + sizeof(unsigned char), + offset(label.encoding), + XtRImmediate, + (XtPointer)XawTextEncoding8bit + }, + { + XtNjustify, + XtCJustify, + XtRJustify, + sizeof(XtJustify), + offset(label.justify), + XtRImmediate, + (XtPointer)XtJustifyCenter + }, + { + XtNinternalWidth, + XtCWidth, + XtRDimension, + sizeof(Dimension), + offset(label.internal_width), + XtRImmediate, + (XtPointer)4 + }, + { + XtNinternalHeight, + XtCHeight, + XtRDimension, + sizeof(Dimension), + offset(label.internal_height), + XtRImmediate, + (XtPointer)2 + }, + { + XtNleftBitmap, + XtCLeftBitmap, + XtRBitmap, + sizeof(Pixmap), + offset(label.left_bitmap), + XtRImmediate, + (XtPointer)None + }, + { + XtNbitmap, + XtCPixmap, + XtRBitmap, + sizeof(Pixmap), + offset(label.pixmap), + XtRImmediate, + (XtPointer)None + }, + { + XtNresize, + XtCResize, + XtRBoolean, + sizeof(Boolean), + offset(label.resize), + XtRImmediate, + (XtPointer)True + }, + { + XtNlabelX, + XtCPosition, + XtRPosition, + sizeof(Position), + offset(label.label_x), + XtRImmediate, + (XtPointer)0 + }, + { + XtNlabelY, + XtCPosition, + XtRPosition, + sizeof(Position), + offset(label.label_y), + XtRImmediate, + (XtPointer)0 + }, +}; +#undef offset + +#define Superclass (&simpleClassRec) +LabelClassRec labelClassRec = { + /* core */ + { + (WidgetClass)&simpleClassRec, /* superclass */ + "Label", /* class_name */ + sizeof(LabelRec), /* widget_size */ + XawLabelClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawLabelInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawLabelDestroy, /* destroy */ + XawLabelResize, /* resize */ + XawLabelRedisplay, /* expose */ + XawLabelSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XawLabelQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* label */ + { + NULL, /* extension */ + } +}; + +WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec; + +/* + * Implementation + */ +static void +XawLabelClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0); + XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString, + NULL, 0, XtCacheNone, NULL); +} + +#ifndef WORD64 +#define TXT16 XChar2b +#else +#define TXT16 char + +static XChar2b *buf2b; +static int buf2blen = 0; + +static int +_XawLabelWidth16(XFontStruct *fs, char *str, int n) +{ + int i; + XChar2b *ptr; + + if (n > buf2blen) { + buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b)); + buf2blen = n; + } + for (ptr = buf2b, i = n; --i >= 0; ptr++) { + ptr->byte1 = *str++; + ptr->byte2 = *str++; + } + + return (XTextWidth16(fs, buf2b, n)); +} + +static void +_XawLabelDraw16(Display *dpy, Drawable d, GC gc, int x, int y, + char *str, int n) +{ + int i; + XChar2b *ptr; + + if (n > buf2blen) { + buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b)); + buf2blen = n; + } + for (ptr = buf2b, i = n; --i >= 0; ptr++) { + ptr->byte1 = *str++; + ptr->byte2 = *str++; + } + XDrawString16(dpy, d, gc, x, y, buf2b, n); +} + +#define XTextWidth16 _XawLabelWidth16 +#define XDrawString16 _XawLabelDraw16 +#endif /* WORD64 */ + +/* + * Calculate width and height of displayed text in pixels + */ +static void +SetTextWidthAndHeight(LabelWidget lw) +{ + XFontStruct *fs = lw->label.font; + char *nl; + + if (lw->label.pixmap != None) { + Window root; + int x, y; + unsigned int width, height, bw, depth; + + if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y, + &width, &height, &bw, &depth)) { + lw->label.label_height = height; + lw->label.label_width = width; + lw->label.label_len = depth; + return; + } + } + if (lw->simple.international == True) { + XFontSet fset = lw->label.fontset; + XFontSetExtents *ext = XExtentsOfFontSet(fset); + + lw->label.label_height = ext->max_ink_extent.height; + if (lw->label.label == NULL) { + lw->label.label_len = 0; + lw->label.label_width = 0; + } + else if ((nl = index(lw->label.label, '\n')) != NULL) { + char *label; + + lw->label.label_len = MULTI_LINE_LABEL; + lw->label.label_width = 0; + for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) { + int width = XmbTextEscapement(fset, label, (int)(nl - label)); + + if (width > (int)lw->label.label_width) + lw->label.label_width = width; + label = nl + 1; + if (*label) + lw->label.label_height += ext->max_ink_extent.height; + } + if (*label) { + int width = XmbTextEscapement(fset, label, strlen(label)); + + if (width > (int)lw->label.label_width) + lw->label.label_width = width; + } + } + else { + lw->label.label_len = strlen(lw->label.label); + lw->label.label_width = + XmbTextEscapement(fset, lw->label.label, lw->label.label_len); + } + } + else { + lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent; + if (lw->label.label == NULL) { + lw->label.label_len = 0; + lw->label.label_width = 0; + } + else if ((nl = index(lw->label.label, '\n')) != NULL) { + char *label; + + lw->label.label_len = MULTI_LINE_LABEL; + lw->label.label_width = 0; + for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) { + int width; + + if (lw->label.encoding) + width = XTextWidth16(fs, (TXT16*)label, (int)(nl - label) / 2); + else + width = XTextWidth(fs, label, (int)(nl - label)); + if (width > (int)lw->label.label_width) + lw->label.label_width = width; + label = nl + 1; + if (*label) + lw->label.label_height += + fs->max_bounds.ascent + fs->max_bounds.descent; + } + if (*label) { + int width = XTextWidth(fs, label, strlen(label)); + + if (lw->label.encoding) + width = XTextWidth16(fs, (TXT16*)label, strlen(label) / 2); + else + width = XTextWidth(fs, label, strlen(label)); + if (width > (int) lw->label.label_width) + lw->label.label_width = width; + } + } + else { + lw->label.label_len = strlen(lw->label.label); + if (lw->label.encoding) + lw->label.label_width = + XTextWidth16(fs, (TXT16*)lw->label.label, + (int)lw->label.label_len / 2); + else + lw->label.label_width = + XTextWidth(fs, lw->label.label, (int)lw->label.label_len); + } + } +} + +static void +GetNormalGC(LabelWidget lw) +{ + XGCValues values; + + values.foreground = lw->label.foreground; + values.background = lw->core.background_pixel; + values.font = lw->label.font->fid; + values.graphics_exposures = False; + + if (lw->simple.international == True) + /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */ + lw->label.normal_GC = XtAllocateGC((Widget)lw, 0, + GCForeground | GCBackground | + GCGraphicsExposures, + &values, GCFont, 0); + else + lw->label.normal_GC = XtGetGC((Widget)lw, + GCForeground | GCBackground | GCFont | + GCGraphicsExposures, &values); +} + +static void +GetGrayGC(LabelWidget lw) +{ + XGCValues values; + + values.foreground = lw->label.foreground; + values.background = lw->core.background_pixel; + values.font = lw->label.font->fid; + values.fill_style = FillTiled; + values.tile = XmuCreateStippledPixmap(XtScreen((Widget)lw), + lw->label.foreground, + lw->core.background_pixel, + lw->core.depth); + values.graphics_exposures = False; + + lw->label.stipple = values.tile; + if (lw->simple.international == True) + /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */ + lw->label.gray_GC = XtAllocateGC((Widget)lw, 0, + GCForeground | GCBackground | + GCTile | GCFillStyle | + GCGraphicsExposures, + &values, GCFont, 0); + else + lw->label.gray_GC = XtGetGC((Widget)lw, + GCForeground | GCBackground | + GCFont | GCTile | GCFillStyle | + GCGraphicsExposures, + &values); +} + +static void +compute_bitmap_offsets(LabelWidget lw) +{ + /* + * bitmap will be eventually be displayed at + * (internal_width, internal_height + lbm_y) + */ + if (lw->label.lbm_height != 0) + lw->label.lbm_y = (XtHeight(lw) - (lw->label.internal_height * 2 + + lw->label.lbm_height)) / 2; + else + lw->label.lbm_y = 0; +} + +static void +set_bitmap_info(LabelWidget lw) +{ + Window root; + int x, y; + unsigned int bw, depth; + + if (!(lw->label.left_bitmap + && XGetGeometry(XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y, + &lw->label.lbm_width, &lw->label.lbm_height, + &bw, &depth))) + lw->label.lbm_width = lw->label.lbm_height = 0; + + compute_bitmap_offsets(lw); +} + +/*ARGSUSED*/ +static void +XawLabelInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + LabelWidget lw = (LabelWidget)cnew; + + if (!lw->label.font) XtError("Aborting: no font found\n"); + if (lw->simple.international && !lw->label.fontset) + XtError("Aborting: no fontset found\n"); + + if (lw->label.label == NULL) + lw->label.label = XtNewString(lw->core.name); + else + lw->label.label = XtNewString(lw->label.label); + + GetNormalGC(lw); + GetGrayGC(lw); + + SetTextWidthAndHeight(lw); + + if (XtHeight(lw) == 0) + XtHeight(lw) = lw->label.label_height + 2 * lw->label.internal_height; + + set_bitmap_info(lw); /* need core.height */ + + if (XtWidth(lw) == 0) /* need label.lbm_width */ + XtWidth(lw) = lw->label.label_width + 2 * lw->label.internal_width + + LEFT_OFFSET(lw); + + lw->label.label_x = lw->label.label_y = 0; + (*XtClass(cnew)->core_class.resize)((Widget)lw); +} + +/*ARGSUSED*/ +static void +XawLabelRedisplay(Widget gw, XEvent *event, Region region) +{ + LabelWidget w = (LabelWidget)gw; + GC gc; + + if (*Superclass->core_class.expose != NULL) + (*Superclass->core_class.expose)(gw, event, region); + + gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC; +#ifdef notdef + if (region != NULL) + XSetRegion(XtDisplay(gw), gc, region); +#endif /*notdef*/ + + if (w->label.pixmap == None) { + int len = w->label.label_len; + char *label = w->label.label; + Position y = w->label.label_y + w->label.font->max_bounds.ascent; + Position ksy = w->label.label_y; + + /* display left bitmap */ + if (w->label.left_bitmap && w->label.lbm_width != 0) + XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc, + 0, 0, w->label.lbm_width, w->label.lbm_height, + w->label.internal_width, + w->label.internal_height + w->label.lbm_y, 1L); + + if (w->simple.international == True) { + XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset); + + ksy += XawAbs(ext->max_ink_extent.y); + + if (len == MULTI_LINE_LABEL) { + char *nl; + + while ((nl = index(label, '\n')) != NULL) { + XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, + gc, w->label.label_x, ksy, label, + (int)(nl - label)); + ksy += ext->max_ink_extent.height; + label = nl + 1; + } + len = strlen(label); + } + if (len) + XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc, + w->label.label_x, ksy, label, len); + } + else { + if (len == MULTI_LINE_LABEL) { + char *nl; + + while ((nl = index(label, '\n')) != NULL) { + if (w->label.encoding) + XDrawString16(XtDisplay(gw), XtWindow(gw), gc, + w->label.label_x, y, + (TXT16*)label, (int)(nl - label) / 2); + else + XDrawString(XtDisplay(gw), XtWindow(gw), gc, + w->label.label_x, y, label, (int)(nl - label)); + y += w->label.font->max_bounds.ascent + + w->label.font->max_bounds.descent; + label = nl + 1; + } + len = strlen(label); + } + if (len) { + if (w->label.encoding) + XDrawString16(XtDisplay(gw), XtWindow(gw), gc, + w->label.label_x, y, (TXT16*)label, len / 2); + else + XDrawString(XtDisplay(gw), XtWindow(gw), gc, + w->label.label_x, y, label, len); + } + } + } + else if (w->label.label_len == 1) + XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc, + 0, 0, w->label.label_width, w->label.label_height, + w->label.label_x, w->label.label_y, 1L); + else + XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc, + 0, 0, w->label.label_width, w->label.label_height, + w->label.label_x, w->label.label_y); + +#ifdef notdef + if (region != NULL) + XSetClipMask(XtDisplay(gw), gc, (Pixmap)None); +#endif /* notdef */ +} + +static void +_Reposition(LabelWidget lw, unsigned int width, unsigned int height, + Position *dx, Position *dy) +{ + Position newPos; + Position leftedge = lw->label.internal_width + LEFT_OFFSET(lw); + + switch (lw->label.justify) { + case XtJustifyLeft: + newPos = leftedge; + break; + case XtJustifyRight: + newPos = width - (lw->label.label_width + lw->label.internal_width); + break; + case XtJustifyCenter: + /*FALLTRHOUGH*/ + default: + newPos = (int)(width - lw->label.label_width) >> 1; + break; + } + if (newPos < (Position)leftedge) + newPos = leftedge; + *dx = newPos - lw->label.label_x; + lw->label.label_x = newPos; + + newPos = ((int)(height - lw->label.label_height)) >> 1; + *dy = newPos - lw->label.label_y; + lw->label.label_y = newPos; +} + +static void +XawLabelResize(Widget w) +{ + LabelWidget lw = (LabelWidget)w; + Position dx, dy; + + _Reposition(lw, XtWidth(w), XtHeight(w), &dx, &dy); + compute_bitmap_offsets(lw); +} + +#define PIXMAP 0 +#define WIDTH 1 +#define HEIGHT 2 +#define NUM_CHECKS 3 +static Boolean +XawLabelSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + LabelWidget curlw = (LabelWidget)current; + LabelWidget reqlw = (LabelWidget)request; + LabelWidget newlw = (LabelWidget)cnew; + unsigned int i; + Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS]; + + for (i = 0; i < NUM_CHECKS; i++) + checks[i] = False; + + for (i = 0; i < *num_args; i++) { + if (streq(XtNbitmap, args[i].name)) + checks[PIXMAP] = True; + else if (streq(XtNwidth, args[i].name)) + checks[WIDTH] = True; + else if (streq(XtNheight, args[i].name)) + checks[HEIGHT] = True; + } + + if (newlw->label.label == NULL) + newlw->label.label = newlw->core.name; + + /* + * resize on bitmap change + */ + if (curlw->label.left_bitmap != newlw->label.left_bitmap) + was_resized = True; + + if (curlw->label.encoding != newlw->label.encoding) + was_resized = True; + + if (curlw->simple.international + && curlw->label.fontset != newlw->label.fontset) + was_resized = True; + + if (curlw->label.label != newlw->label.label) { + if (curlw->label.label != curlw->core.name) + XtFree((char *)curlw->label.label); + + if (newlw->label.label != newlw->core.name) + newlw->label.label = XtNewString(newlw->label.label); + + was_resized = True; + } + + if (was_resized || (curlw->label.font != newlw->label.font) || + curlw->label.justify != newlw->label.justify || checks[PIXMAP]) { + SetTextWidthAndHeight(newlw); + was_resized = True; + } + + /* recalculate the window size if something has changed */ + if (newlw->label.resize && was_resized) { + if (XtHeight(curlw) == XtHeight(reqlw) && !checks[HEIGHT]) + XtHeight(newlw) = newlw->label.label_height + + (newlw->label.internal_height << 1); + + set_bitmap_info(newlw); + + if (XtWidth(curlw) == XtWidth(reqlw) && !checks[WIDTH]) + XtWidth(newlw) = newlw->label.label_width + LEFT_OFFSET(newlw) + + (newlw->label.internal_width << 1); + } + + if (curlw->label.foreground != newlw->label.foreground + || curlw->core.background_pixel != newlw->core.background_pixel + || curlw->label.font->fid != newlw->label.font->fid) { + /* The Fontset is not in the GC - don't make a new GC if FS changes! */ + XtReleaseGC(cnew, curlw->label.normal_GC); + XtReleaseGC(cnew, curlw->label.gray_GC); + XmuReleaseStippledPixmap(XtScreen(current), curlw->label.stipple); + GetNormalGC(newlw); + GetGrayGC(newlw); + redisplay = True; + } + + if (curlw->label.label_x != newlw->label.label_x || + curlw->label.label_y != newlw->label.label_y) + redisplay = True; + + if (curlw->label.internal_width != newlw->label.internal_width + || curlw->label.internal_height != newlw->label.internal_height + || was_resized) { + /* Resize() will be called if geometry changes succeed */ + Position dx, dy; + + _Reposition(newlw, XtWidth(curlw), XtHeight(curlw), &dx, &dy); + } + + return (was_resized || redisplay || + XtIsSensitive(current) != XtIsSensitive(cnew)); +} + +static void +XawLabelDestroy(Widget w) +{ + LabelWidget lw = (LabelWidget)w; + + if (lw->label.label != lw->core.name) + XtFree(lw->label.label); + XtReleaseGC(w, lw->label.normal_GC); + XtReleaseGC(w, lw->label.gray_GC); + XmuReleaseStippledPixmap(XtScreen(w), lw->label.stipple); +} + +static XtGeometryResult +XawLabelQueryGeometry(Widget w, XtWidgetGeometry *intended, + XtWidgetGeometry *preferred) +{ + LabelWidget lw = (LabelWidget)w; + + preferred->request_mode = CWWidth | CWHeight; + preferred->width = lw->label.label_width + + (lw->label.internal_width << 1) + LEFT_OFFSET(lw); + preferred->height = lw->label.label_height + + (lw->label.internal_height << 1); + + if (((intended->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight)) + && intended->width == preferred->width + && intended->height == preferred->height) + return (XtGeometryYes); + else if (preferred->width == XtWidth(w) && preferred->height == XtHeight(w)) + return (XtGeometryNo); + + return (XtGeometryAlmost); +} diff --git a/libXaw/src/List.c b/libXaw/src/List.c index 14e351842..287151d50 100644 --- a/libXaw/src/List.c +++ b/libXaw/src/List.c @@ -1,1270 +1,1270 @@ -/*
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-*/
-
-/*
- * List.c - List widget
- *
- * This is a List widget. It allows the user to select an item in a list and
- * notifies the application through a callback function.
- *
- * Created: 8/13/88
- * By: Chris D. Peterson
- * MIT X Consortium
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <ctype.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/Drawing.h>
-#include <X11/Xaw/ListP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#define HeightLock 1
-#define WidthLock 2
-#define LongestLock 4
-
-#define HeightFree(w) !(((ListWidget)(w))->list.freedoms & HeightLock)
-#define WidthFree(w) !(((ListWidget)(w))->list.freedoms & WidthLock)
-#define LongestFree(w) !(((ListWidget)(w))->list.freedoms & LongestLock)
-
-#define MaxSize 32767
-
-/*
- * Class Methods
- */
-static void XawListDestroy(Widget);
-static void XawListInitialize(Widget, Widget, ArgList, Cardinal*);
-static XtGeometryResult XawListQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawListRedisplay(Widget, XEvent*, Region);
-static void XawListResize(Widget);
-static Boolean XawListSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void CalculatedValues(Widget);
-static void ChangeSize(Widget, unsigned int, unsigned int);
-static void ClipToShadowInteriorAndLongest(ListWidget, GC*, unsigned int);
-static int CvtToItem(Widget, int, int, int*);
-static void FindCornerItems(Widget, XEvent*, int*, int*);
-static void GetGCs(Widget);
-static void HighlightBackground(Widget, int, int, GC);
-static Bool ItemInRectangle(Widget, int, int, int);
-static Bool Layout(Widget, Bool, Bool, Dimension*, Dimension*);
-static void PaintItemName(Widget, int);
-static void ResetList(Widget, Bool, Bool);
-
-/*
- * Actions
- */
-static void Notify(Widget, XEvent*, String*, Cardinal*);
-static void Set(Widget, XEvent*, String*, Cardinal*);
-static void Unset(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * Initialization
- */
-static char defaultTranslations[] =
-"<Btn1Down>:" "Set()\n"
-"<Btn1Up>:" "Notify()\n"
-;
-
-#define offset(field) XtOffsetOf(ListRec, field)
-static XtResource resources[] = {
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(list.foreground),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNcursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(simple.cursor),
- XtRString,
- "left_ptr"
- },
- {
- XtNfont,
- XtCFont,
- XtRFontStruct,
- sizeof(XFontStruct*),
- offset(list.font),
- XtRString,
- XtDefaultFont
- },
- {
- XtNfontSet,
- XtCFontSet,
- XtRFontSet,
- sizeof(XFontSet),
- offset(list.fontset),
- XtRString,
- XtDefaultFontSet
- },
- {
- XtNlist,
- XtCList,
- XtRPointer,
- sizeof(char**),
- offset(list.list),
-#ifdef notyet
- XtRStringArray,
-#else
- XtRString,
-#endif
- NULL
- },
- {
- XtNdefaultColumns,
- XtCColumns,
- XtRInt,
- sizeof(int),
- offset(list.default_cols),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNlongest,
- XtCLongest,
- XtRInt,
- sizeof(int),
- offset(list.longest),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNnumberStrings,
- XtCNumberStrings,
- XtRInt,
- sizeof(int),
- offset(list.nitems),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNpasteBuffer,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(list.paste),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNforceColumns,
- XtCColumns,
- XtRBoolean,
- sizeof(Boolean),
- offset(list.force_cols),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNverticalList,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(list.vertical_cols),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNinternalWidth,
- XtCWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(list.internal_width),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNinternalHeight,
- XtCHeight,
- XtRDimension,
- sizeof(Dimension),
- offset(list.internal_height),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNcolumnSpacing,
- XtCSpacing,
- XtRDimension,
- sizeof(Dimension),
- offset(list.column_space),
- XtRImmediate,
- (XtPointer)6
- },
- {
- XtNrowSpacing,
- XtCSpacing,
- XtRDimension,
- sizeof(Dimension),
- offset(list.row_space),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNcallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(list.callback),
- XtRCallback,
- NULL
- },
-#ifndef OLDXAW
- {
- XtNshowCurrent,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(list.show_current),
- XtRImmediate,
- (XtPointer)False
- },
-#endif
-};
-#undef offset
-
-static XtActionsRec actions[] = {
- {"Notify", Notify},
- {"Set", Set},
- {"Unset", Unset},
-};
-
-#define Superclass (&simpleClassRec)
-ListClassRec listClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "List", /* class_name */
- sizeof(ListRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawListInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- actions, /* actions */
- XtNumber(actions), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- False, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawListDestroy, /* destroy */
- XawListResize, /* resize */
- XawListRedisplay, /* expose */
- XawListSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- defaultTranslations, /* tm_table */
- XawListQueryGeometry, /* query_geometry */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* list */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass listWidgetClass = (WidgetClass)&listClassRec;
-
-/*
- * Implementation
- */
-static void
-GetGCs(Widget w)
-{
- XGCValues values;
- ListWidget lw = (ListWidget)w;
-
- values.foreground = lw->list.foreground;
- values.font = lw->list.font->fid;
-
- if (lw->simple.international == True)
- lw->list.normgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0);
- else
- lw->list.normgc = XtGetGC(w, GCForeground | GCFont, &values);
-
- values.foreground = lw->core.background_pixel;
-
- if (lw->simple.international == True)
- lw->list.revgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0);
- else
- lw->list.revgc = XtGetGC(w, GCForeground | GCFont, &values);
-
- values.tile = XmuCreateStippledPixmap(XtScreen(w),
- lw->list.foreground,
- lw->core.background_pixel,
- lw->core.depth);
- values.fill_style = FillTiled;
-
- if (lw->simple.international == True)
- lw->list.graygc = XtAllocateGC(w, 0, GCTile | GCFillStyle,
- &values, GCFont, 0);
- else
- lw->list.graygc = XtGetGC(w, GCFont | GCTile | GCFillStyle, &values);
-}
-
-static void
-CalculatedValues(Widget w)
-{
- int i, len;
- ListWidget lw = (ListWidget)w;
-
- /* If list is NULL then the list will just be the name of the widget */
- if (lw->list.list == NULL) {
- lw->list.list = &lw->core.name;
- lw->list.nitems = 1;
- }
-
- /* Get number of items */
- if (lw->list.nitems == 0)
- for (; lw->list.list[lw->list.nitems] != NULL ; lw->list.nitems++)
- ;
-
- /* Get column width */
- if (LongestFree(lw)) {
- lw->list.longest = 0; /* so it will accumulate real longest below */
-
- for (i = 0 ; i < lw->list.nitems; i++) {
- if (lw->simple.international == True)
- len = XmbTextEscapement(lw->list.fontset, lw->list.list[i],
- strlen(lw->list.list[i]));
- else
- len = XTextWidth(lw->list.font, lw->list.list[i],
- strlen(lw->list.list[i]));
- if (len > lw->list.longest)
- lw->list.longest = len;
- }
- }
-
- lw->list.col_width = lw->list.longest + lw->list.column_space;
-}
-
-/*
- * Function:
- * ResetList
- *
- * Parameters:
- * w - list widget
- * changex - allow the height or width to change?
- * changey - ""
- *
- * Description:
- * Resets the new list when important things change.
- *
- * Returns:
- * True if width or height have been changed
- */
-static void
-ResetList(Widget w, Bool changex, Bool changey)
-{
- Dimension width = XtWidth(w);
- Dimension height = XtHeight(w);
-
- CalculatedValues(w);
-
- if (Layout(w, changex, changey, &width, &height)) {
- if (XtIsComposite(XtParent(w)))
- ChangeSize(w, width, height);
- else {
- XtWidth(w) = width;
- XtHeight(w) = height;
- }
- }
-}
-
-/*
- * Function:
- * ChangeSize
- *
- * Parameters:
- * w - widget to try change the size of
- *
- * Description:
- * Laysout the widget.
- */
-static void
-ChangeSize(Widget w, unsigned int width, unsigned int height)
-{
- XtWidgetGeometry request, reply;
-
- request.request_mode = CWWidth | CWHeight;
- request.width = width;
- request.height = height;
-
- switch (XtMakeGeometryRequest(w, &request, &reply)) {
- case XtGeometryYes:
- case XtGeometryNo:
- break;
- case XtGeometryAlmost:
- Layout(w, request.height != reply.height,
- request.width != reply.width, &reply.width, &reply.height);
- request = reply;
- switch (XtMakeGeometryRequest(w, &request, &reply)) {
- case XtGeometryYes:
- case XtGeometryNo:
- break;
- case XtGeometryAlmost:
- request = reply;
- Layout(w, False, False, &request.width, &request.height);
- request.request_mode = CWWidth | CWHeight;
- XtMakeGeometryRequest(w, &request, &reply);
- /*FALLTROUGH*/
- default:
- break;
- }
- /*FALLTROUGH*/
- default:
- break;
- }
-}
-
-/*ARGSUSED*/
-static void
-XawListInitialize(Widget temp1, Widget cnew, ArgList args, Cardinal *num_args)
-{
- ListWidget lw = (ListWidget)cnew;
-
- if (!lw->list.font) XtError("Aborting: no font found\n");
- if (lw->simple.international && !lw->list.fontset)
- XtError("Aborting: no fontset found\n");
-
- /*
- * Initialize all private resources
- */
- /* record for posterity if we are free */
- lw->list.freedoms = ((XtWidth(lw) != 0) * WidthLock +
- (XtHeight(lw) != 0) * HeightLock +
- (lw->list.longest != 0) * LongestLock);
-
- GetGCs(cnew);
-
- /* Set row height, based on font or fontset */
- if (lw->simple.international == True)
- lw->list.row_height =
- XExtentsOfFontSet(lw->list.fontset)->max_ink_extent.height +
- lw->list.row_space;
- else
- lw->list.row_height = lw->list.font->max_bounds.ascent +
- lw->list.font->max_bounds.descent +
- lw->list.row_space;
-
- ResetList(cnew, WidthFree(lw), HeightFree(lw));
-
- lw->list.highlight = lw->list.is_highlighted = NO_HIGHLIGHT;
-}
-
-/*
- * Function:
- * CvtToItem
- *
- * Parameters:
- * w - list widget
- * xloc - x location
- * yloc - y location
- *
- * Description:
- * Converts Xcoord to item number of item containing that point.
- *
- * Returns:
- * Item number
- */
-static int
-CvtToItem(Widget w, int xloc, int yloc, int *item)
-{
- int one, another;
- ListWidget lw = (ListWidget)w;
- int ret_val = OKAY;
-
- if (lw->list.vertical_cols) {
- one = lw->list.nrows * ((xloc - (int)lw->list.internal_width)
- / lw->list.col_width);
- another = (yloc - (int)lw->list.internal_height) / lw->list.row_height;
- /* If out of range, return minimum possible value */
- if (another >= lw->list.nrows) {
- another = lw->list.nrows - 1;
- ret_val = OUT_OF_RANGE;
- }
- }
- else {
- one = (lw->list.ncols * ((yloc - (int)lw->list.internal_height)
- / lw->list.row_height));
- /* If in right margin handle things right */
- another = (xloc - (int)lw->list.internal_width) / lw->list.col_width;
- if (another >= lw->list.ncols) {
- another = lw->list.ncols - 1;
- ret_val = OUT_OF_RANGE;
- }
- }
- if (xloc < 0 || yloc < 0)
- ret_val = OUT_OF_RANGE;
- if (one < 0)
- one = 0;
- if (another < 0)
- another = 0;
- *item = one + another;
- if (*item >= lw->list.nitems)
- return (OUT_OF_RANGE);
-
- return (ret_val);
-}
-
-/*
- * Function:
- * FindCornerItems
- *
- * Arguments:
- * w - list widget
- * event - event structure that has the rectangle it it
- * ul_ret - the corners (return)
- * lr_ret - ""
- *
- * Description:
- * Find the corners of the rectangle in item space.
- */
-static void
-FindCornerItems(Widget w, XEvent *event, int *ul_ret, int *lr_ret)
-{
- int xloc, yloc;
-
- xloc = event->xexpose.x;
- yloc = event->xexpose.y;
- CvtToItem(w, xloc, yloc, ul_ret);
- xloc += event->xexpose.width;
- yloc += event->xexpose.height;
- CvtToItem(w, xloc, yloc, lr_ret);
-}
-
-/*
- * Function:
- * ItemInRectangle
- *
- * Parameters:
- * w - list widget
- * ul - corners of the rectangle in item space
- * lr - ""
- * item - item to check
- *
- * Returns:
- * True if the item passed is in the given rectangle
- */
-static Bool
-ItemInRectangle(Widget w, int ul, int lr, int item)
-{
- ListWidget lw = (ListWidget)w;
- int mod_item;
- int things;
-
- if (item < ul || item > lr)
- return (False);
- if (lw->list.vertical_cols)
- things = lw->list.nrows;
- else
- things = lw->list.ncols;
-
- mod_item = item % things;
- if ((mod_item >= ul % things) && (mod_item <= lr % things))
- return (True);
-
- return (False);
-}
-
-/* HighlightBackground()
- *
- * Paints the color of the background for the given item. It performs
- * clipping to the interior of internal_width/height by hand, as its a
- * simple calculation and probably much faster than using Xlib and a clip mask.
- *
- * x, y - ul corner of the area item occupies.
- * gc - the gc to use to paint this rectangle
- */
-static void
-HighlightBackground(Widget w, int x, int y, GC gc)
-{
- ListWidget lw = (ListWidget)w;
- Dimension width = lw->list.col_width;
- Dimension height = lw->list.row_height;
- Dimension frame_limited_width = XtWidth(w) - lw->list.internal_width - x;
- Dimension frame_limited_height= XtHeight(w) - lw->list.internal_height - y;
-
- /* Clip the rectangle width and height to the edge of the drawable area */
- if (width > frame_limited_width)
- width = frame_limited_width;
- if (height > frame_limited_height)
- height = frame_limited_height;
-
- /* Clip the rectangle x and y to the edge of the drawable area */
- if (x < lw->list.internal_width) {
- width = width - (lw->list.internal_width - x);
- x = lw->list.internal_width;
- }
- if (y < lw->list.internal_height) {
- height = height - (lw->list.internal_height - y);
- y = lw->list.internal_height;
- }
-
- if (gc == lw->list.revgc && lw->core.background_pixmap != XtUnspecifiedPixmap)
- XClearArea(XtDisplay(w), XtWindow(w), x, y, width, height, False);
- else
- XFillRectangle(XtDisplay(w), XtWindow(w), gc, x, y, width, height);
-}
-
-
-/* ClipToShadowInteriorAndLongest()
- *
- * Converts the passed gc so that any drawing done with that GC will not
- * write in the empty margin (specified by internal_width/height) (which also
- * prevents erasing the shadow. It also clips against the value longest.
- * If the user doesn't set longest, this has no effect (as longest is the
- * maximum of all item lengths). If the user does specify, say, 80 pixel
- * columns, though, this prevents items from overwriting other items.
- */
-static void
-ClipToShadowInteriorAndLongest(ListWidget lw, GC *gc_p, unsigned int x)
-{
- XRectangle rect;
-
- rect.x = x;
- rect.y = lw->list.internal_height;
- rect.height = XtHeight(lw) - (lw->list.internal_height << 1);
- rect.width = XtWidth(lw) - lw->list.internal_width - x;
- if (rect.width > lw->list.longest)
- rect.width = lw->list.longest;
-
- XSetClipRectangles(XtDisplay((Widget)lw), *gc_p, 0, 0, &rect, 1, YXBanded);
-}
-
-static void
-PaintItemName(Widget w, int item)
-{
- char *str;
- GC gc;
- int x, y, str_y;
- ListWidget lw = (ListWidget)w;
- XFontSetExtents *ext = XExtentsOfFontSet(lw->list.fontset);
-
- if (!XtIsRealized(w) || item > lw->list.nitems)
- return;
-
- if (lw->list.vertical_cols) {
- x = lw->list.col_width * (item / lw->list.nrows)
- + lw->list.internal_width;
- y = lw->list.row_height * (item % lw->list.nrows)
- + lw->list.internal_height;
- }
- else {
- x = lw->list.col_width * (item % lw->list.ncols)
- + lw->list.internal_width;
- y = lw->list.row_height * (item / lw->list.ncols)
- + lw->list.internal_height;
- }
-
- if ( lw->simple.international == True )
- str_y = y + XawAbs(ext->max_ink_extent.y);
- else
- str_y = y + lw->list.font->max_bounds.ascent;
-
- if (item == lw->list.is_highlighted) {
- if (item == lw->list.highlight) {
- gc = lw->list.revgc;
- HighlightBackground(w, x, y, lw->list.normgc);
- }
- else {
- if (XtIsSensitive(w))
- gc = lw->list.normgc;
- else
- gc = lw->list.graygc;
- HighlightBackground(w, x, y, lw->list.revgc);
- lw->list.is_highlighted = NO_HIGHLIGHT;
- }
- }
- else {
- if (item == lw->list.highlight) {
- gc = lw->list.revgc;
- HighlightBackground(w, x, y, lw->list.normgc);
- lw->list.is_highlighted = item;
- }
- else {
- if (XtIsSensitive(w))
- gc = lw->list.normgc;
- else
- gc = lw->list.graygc;
- }
- }
-
- /* List's overall width contains the same number of inter-column
- column_space's as columns. There should thus be a half
- column_width margin on each side of each column.
- The row case is symmetric */
-
- x += lw->list.column_space >> 1;
- str_y += lw->list.row_space >> 1;
-
- str = lw->list.list[item]; /* draw it */
-
- ClipToShadowInteriorAndLongest(lw, &gc, x);
-
- if (lw->simple.international == True)
- XmbDrawString(XtDisplay(w), XtWindow(w), lw->list.fontset,
- gc, x, str_y, str, strlen(str));
- else
- XDrawString(XtDisplay(w), XtWindow(w), gc, x, str_y, str, strlen(str));
-
- XSetClipMask(XtDisplay(w), gc, None);
-}
-
-static void
-XawListRedisplay(Widget w, XEvent *event, Region region)
-{
- int item; /* an item to work with */
- int ul_item, lr_item; /* corners of items we need to paint */
- ListWidget lw = (ListWidget)w;
-
- if (event == NULL) {
- ul_item = 0;
- lr_item = lw->list.nrows * lw->list.ncols - 1;
- XClearWindow(XtDisplay(w), XtWindow(w));
- }
- else
- FindCornerItems(w, event, &ul_item, &lr_item);
-
- if (Superclass->core_class.expose)
- (Superclass->core_class.expose)(w, event, region);
-
- for (item = ul_item; item <= lr_item && item < lw->list.nitems; item++)
- if (ItemInRectangle(w, ul_item, lr_item, item))
- PaintItemName(w, item);
-}
-
-/* XawListQueryGeometry()
- *
- * This tells the parent what size we would like to be
- * given certain constraints.
- * w - the widget.
- * intended - what the parent intends to do with us.
- * requested - what we want to happen */
-static XtGeometryResult
-XawListQueryGeometry(Widget w, XtWidgetGeometry *intended,
- XtWidgetGeometry *requested)
-{
- Dimension new_width, new_height;
- Bool change, width_req, height_req;
-
- width_req = intended->request_mode & CWWidth;
- height_req = intended->request_mode & CWHeight;
-
- if (width_req)
- new_width = intended->width;
- else
- new_width = XtWidth(w);
-
- if (height_req)
- new_height = intended->height;
- else
- new_height = XtHeight(w);
-
- requested->request_mode = 0;
-
- /*
- * We only care about our height and width
- */
- if (!width_req && !height_req)
- return (XtGeometryYes);
-
- change = Layout(w, !width_req, !height_req, &new_width, &new_height);
-
- requested->request_mode |= CWWidth;
- requested->width = new_width;
- requested->request_mode |= CWHeight;
- requested->height = new_height;
-
- if (change)
- return (XtGeometryAlmost);
-
- return (XtGeometryYes);
-}
-
-static void
-XawListResize(Widget w)
-{
- Dimension width, height;
-
- width = XtWidth(w);
- height = XtHeight(w);
-
- if (Layout(w, False, False, &width, &height))
- XtAppWarning(XtWidgetToApplicationContext(w),
- "List Widget: Size changed when it shouldn't "
- "have when resising.");
-}
-
-/* Layout()
- *
- * lays out the item in the list.
- * w - the widget.
- * xfree, yfree - True if we are free to resize the widget in
- * this direction.
- * width, height- the is the current width and height that we are going
- * we are going to layout the list widget to,
- * depending on xfree and yfree of course.
- *
- * Return:
- * True if width or height have been changed */
-static Bool
-Layout(Widget w, Bool xfree, Bool yfree, Dimension *width, Dimension *height)
-{
- ListWidget lw = (ListWidget)w;
- Bool change = False;
- unsigned long width2 = 0, height2 = 0;
-
- /*
- * If force columns is set then always use number of columns specified
- * by default_cols
- */
- if (lw->list.force_cols) {
- lw->list.ncols = lw->list.default_cols;
- if (lw->list.ncols <= 0)
- lw->list.ncols = 1;
- lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1;
- if (xfree) {
- /* this counts the same number
- of inter-column column_space 's as columns. There should thus
- be a half column_space margin on each side of each column...*/
- width2 = lw->list.ncols * lw->list.col_width +
- (lw->list.internal_width << 1);
- change = True;
- }
- if (yfree) {
- height2 = lw->list.nrows * lw->list.row_height +
- (lw->list.internal_height << 1);
- change = True;
- }
- }
-
- /*
- * If both width and height are free to change the use default_cols
- * to determine the number columns and set new width and height to
- * just fit the window
- */
- else if (xfree && yfree) {
- lw->list.ncols = lw->list.default_cols;
- if (lw->list.ncols <= 0) {
- int wid = (int)XtWidth(lw) - (int)(lw->list.internal_width << 1)
- + (int)lw->list.column_space;
-
- if (wid <= 0 || lw->list.col_width <= 0
- || (lw->list.ncols = wid / lw->list.col_width) <= 0)
- lw->list.ncols = 1;
- }
- width2 = lw->list.ncols * lw->list.col_width
- + (lw->list.internal_width << 1);
- height2 = (lw->list.nrows * lw->list.row_height)
- + (lw->list.internal_height << 1);
- change = True;
- }
-
- /*
- * If the width is fixed then use it to determine the number of columns.
- * If the height is free to move (width still fixed) then resize the height
- * of the widget to fit the current list exactly
- */
- else if (!xfree) {
- lw->list.ncols = ((int)(*width - (lw->list.internal_width << 1))
- / (int)lw->list.col_width);
- if (lw->list.ncols <= 0)
- lw->list.ncols = 1;
- lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1;
- if (yfree) {
- height2 = lw->list.nrows * lw->list.row_height +
- (lw->list.internal_height << 1);
- change = True;
- }
- }
-
- /*
- * The last case is xfree and !yfree we use the height to determine
- * the number of rows and then set the width to just fit the resulting
- * number of columns
- */
- else if (!yfree) {
- lw->list.nrows = ((int)(*height - (lw->list.internal_height << 1))
- / (int)lw->list.row_height);
- if (lw->list.nrows <= 0)
- lw->list.nrows = 1;
- lw->list.ncols = ((lw->list.nitems - 1) / lw->list.nrows) + 1;
- width2 = lw->list.ncols * lw->list.col_width +
- (lw->list.internal_width << 1);
- change = True;
- }
-
- if (!lw->list.force_cols && lw->list.nrows) {
- /*CONSTCOND*/
- while (1) {
- lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1;
- width2 = lw->list.ncols * lw->list.col_width +
- (lw->list.internal_width << 1);
- height2 = lw->list.nrows * lw->list.row_height +
- (lw->list.internal_height << 1);
- if (width2 >= MaxSize && height2 >= MaxSize)
- break;
- if (height2 > MaxSize)
- ++lw->list.ncols;
- else if (width2 > MaxSize && lw->list.ncols > 1)
- --lw->list.ncols;
- else
- break;
- }
- }
- if (width2)
- *width = width2;
- if (height2)
- *height = height2;
-
- return (change);
-}
-
-/* Notify() - Action
- *
- * Notifies the user that a button has been pressed, and
- * calls the callback; if the XtNpasteBuffer resource is true
- * then the name of the item is also put in CUT_BUFFER0 */
-/*ARGSUSED*/
-static void
-Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- ListWidget lw = (ListWidget)w;
- int item, item_len;
- XawListReturnStruct ret_value;
-
- /*
- * Find item and if out of range then unhighlight and return
- *
- * If the current item is unhighlighted then the user has aborted the
- * notify, so unhighlight and return
- */
- if ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE)
- || lw->list.highlight != item) {
-#ifndef OLDXAW
- if (!lw->list.show_current || lw->list.selected == NO_HIGHLIGHT)
- XawListUnhighlight(w);
- else
- XawListHighlight(w, lw->list.selected);
-#else
- XawListUnhighlight(w);
-#endif
- return;
- }
-
- item_len = strlen(lw->list.list[item]);
-
- if (lw->list.paste) /* if XtNpasteBuffer set then paste it */
- XStoreBytes(XtDisplay(w), lw->list.list[item], item_len);
-
-#ifndef OLDXAW
- lw->list.selected = item;
-#endif
- /*
- * Call Callback function
- */
- ret_value.string = lw->list.list[item];
- ret_value.list_index = item;
-
- XtCallCallbacks(w, XtNcallback, (XtPointer)&ret_value);
-}
-
-/* Unset() - Action
- *
- * unhighlights the current element */
-/*ARGSUSED*/
-static void
-Unset(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- XawListUnhighlight(w);
-}
-
-/* Set() - Action
- *
- * Highlights the current element */
-/*ARGSUSED*/
-static void
-Set(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- int item;
- ListWidget lw = (ListWidget)w;
-
-#ifndef OLDXAW
- lw->list.selected = lw->list.highlight;
-#endif
- if (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE)
- XawListUnhighlight(w); /* Unhighlight current item */
- else if (lw->list.is_highlighted != item) /* If this item is not */
- XawListHighlight(w, item); /* highlighted then do it */
-}
-
-/*
- * Set specified arguments into widget
- */
-/*ARGSUSED*/
-static Boolean
-XawListSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- ListWidget cl = (ListWidget)current;
- ListWidget rl = (ListWidget)request;
- ListWidget nl = (ListWidget)cnew;
- Bool redraw = False;
- XFontSetExtents *ext = XExtentsOfFontSet(nl->list.fontset);
-
- /* If the request height/width is different, lock it. Unless its 0. If
- neither new nor 0, leave it as it was. Not in R5 */
- if (XtWidth(nl) != XtWidth(cl))
- nl->list.freedoms |= WidthLock;
- if (XtWidth(nl) == 0)
- nl->list.freedoms &= ~WidthLock;
-
- if (XtHeight(nl) != XtHeight(cl))
- nl->list.freedoms |= HeightLock;
- if (XtHeight(nl) == 0)
- nl->list.freedoms &= ~HeightLock;
-
- if (nl->list.longest != cl->list.longest)
- nl->list.freedoms |= LongestLock;
- if (nl->list.longest == 0)
- nl->list.freedoms &= ~LongestLock;
-
- if (cl->list.foreground != nl->list.foreground ||
- cl->core.background_pixel != nl->core.background_pixel ||
- cl->list.font != nl->list.font) {
- XGCValues values;
-
- XGetGCValues(XtDisplay(current), cl->list.graygc, GCTile, &values);
- XmuReleaseStippledPixmap(XtScreen(current), values.tile);
- XtReleaseGC(current, cl->list.graygc);
- XtReleaseGC(current, cl->list.revgc);
- XtReleaseGC(current, cl->list.normgc);
- GetGCs(cnew);
- redraw = True;
- }
-
- if (cl->list.font != nl->list.font && cl->simple.international == False)
- nl->list.row_height = nl->list.font->max_bounds.ascent
- + nl->list.font->max_bounds.descent
- + nl->list.row_space;
- else if (cl->list.fontset != nl->list.fontset
- && cl->simple.international == True)
- nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space;
-
- /* ...If the above two font(set) change checkers above both failed, check
- if row_space was altered. If one of the above passed, row_height will
- already have been re-calculated */
- else if (cl->list.row_space != nl->list.row_space) {
- if (cl->simple.international == True)
- nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space;
- else
- nl->list.row_height = nl->list.font->max_bounds.ascent
- + nl->list.font->max_bounds.descent
- + nl->list.row_space;
- }
-
- if (XtWidth(cl) != XtWidth(nl) || XtHeight(cl) != XtHeight(nl)
- || cl->list.internal_width != nl->list.internal_width
- || cl->list.internal_height != nl->list.internal_height
- || cl->list.column_space != nl->list.column_space
- || cl->list.row_space != nl->list.row_space
- || cl->list.default_cols != nl->list.default_cols
- || (cl->list.force_cols != nl->list.force_cols
- && rl->list.force_cols != nl->list.ncols)
- || cl->list.vertical_cols != nl->list.vertical_cols
- || cl->list.longest != nl->list.longest
- || cl->list.nitems != nl->list.nitems
- || cl->list.font != nl->list.font
- /* Equiv. fontsets might have different values, but the same fonts,
- so the next comparison is sloppy but not dangerous */
- || cl->list.fontset != nl->list.fontset
- || cl->list.list != nl->list.list) {
- CalculatedValues(cnew);
- Layout(cnew, WidthFree(nl), HeightFree(nl),
- &nl->core.width, &nl->core.height);
- redraw = True;
- }
-
- if (cl->list.list != nl->list.list || cl->list.nitems != nl->list.nitems)
- nl->list.is_highlighted = nl->list.highlight = NO_HIGHLIGHT;
-
- if (cl->core.sensitive != nl->core.sensitive
- || cl->core.ancestor_sensitive != nl->core.ancestor_sensitive) {
- nl->list.highlight = NO_HIGHLIGHT;
- redraw = True;
- }
-
- return (redraw);
-}
-
-static void
-XawListDestroy(Widget w)
-{
- ListWidget lw = (ListWidget)w;
- XGCValues values;
-
- XGetGCValues(XtDisplay(w), lw->list.graygc, GCTile, &values);
- XmuReleaseStippledPixmap(XtScreen(w), values.tile);
- XtReleaseGC(w, lw->list.graygc);
- XtReleaseGC(w, lw->list.revgc);
- XtReleaseGC(w, lw->list.normgc);
-}
-
-/*
- * Function:
- * XawListChange
- *
- * Parameters:
- * w - list widget
- * list - new list
- * nitems - number of items in the list
- * longest - length (in Pixels) of the longest element in the list
- * resize - if True the the list widget will try to resize itself
- *
- * Description:
- * Changes the list being used and shown.
- *
- * Note:
- * If nitems of longest are <= 0 then they will be calculated
- * If nitems is <= 0 then the list needs to be NULL terminated
- */
-void
-XawListChange(Widget w, char **list, int nitems, int longest,
-#if NeedWidePrototypes
- int resize_it
-#else
- Boolean resize_it
-#endif
-)
-{
- ListWidget lw = (ListWidget)w;
- Dimension new_width = XtWidth(w);
- Dimension new_height = XtHeight(w);
-
- lw->list.list = list;
-
- if (nitems <= 0)
- nitems = 0;
- lw->list.nitems = nitems;
- if (longest <= 0)
- longest = 0;
-
- /* If the user passes 0 meaning "calculate it", it must be free */
- if (longest != 0)
- lw->list.freedoms |= LongestLock;
- else
- lw->list.freedoms &= ~LongestLock;
-
- if (resize_it)
- lw->list.freedoms &= ~WidthLock & ~HeightLock;
-
- lw->list.longest = longest;
-
- CalculatedValues(w);
-
- if (Layout(w, WidthFree(w), HeightFree(w), &new_width, &new_height))
- ChangeSize(w, new_width, new_height);
-
- lw->list.is_highlighted = lw->list.highlight = NO_HIGHLIGHT;
- if (XtIsRealized(w))
- XawListRedisplay(w, NULL, NULL);
-}
-
-void
-XawListUnhighlight(Widget w)
-{
- ListWidget lw = (ListWidget)w;
-
- lw->list.highlight = NO_HIGHLIGHT;
- if (lw->list.is_highlighted != NO_HIGHLIGHT)
- PaintItemName(w, lw->list.is_highlighted);
-}
-
-void
-XawListHighlight(Widget w, int item)
-{
- ListWidget lw = (ListWidget)w;
-
- if (XtIsSensitive(w)) {
- lw->list.highlight = item;
- if (lw->list.is_highlighted != NO_HIGHLIGHT)
- PaintItemName(w, lw->list.is_highlighted);
- PaintItemName(w, item);
- }
-}
-
-/*
- * Function:
- * XawListShowCurrent
- *
- * Parameters:
- * w - list widget
- *
- * Returns:
- * Info about the currently highlighted object
- */
-XawListReturnStruct *
-XawListShowCurrent(Widget w)
-{
- ListWidget lw = (ListWidget)w;
- XawListReturnStruct *ret_val;
-
- ret_val = (XawListReturnStruct *)XtMalloc(sizeof(XawListReturnStruct));
-
- ret_val->list_index = lw->list.highlight;
- if (ret_val->list_index == XAW_LIST_NONE)
- ret_val->string = "";
- else
- ret_val->string = lw->list.list[ret_val->list_index];
-
- return (ret_val);
-}
+/* +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/* + * List.c - List widget + * + * This is a List widget. It allows the user to select an item in a list and + * notifies the application through a callback function. + * + * Created: 8/13/88 + * By: Chris D. Peterson + * MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <ctype.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xaw/ListP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define HeightLock 1 +#define WidthLock 2 +#define LongestLock 4 + +#define HeightFree(w) !(((ListWidget)(w))->list.freedoms & HeightLock) +#define WidthFree(w) !(((ListWidget)(w))->list.freedoms & WidthLock) +#define LongestFree(w) !(((ListWidget)(w))->list.freedoms & LongestLock) + +#define MaxSize 32767 + +/* + * Class Methods + */ +static void XawListDestroy(Widget); +static void XawListInitialize(Widget, Widget, ArgList, Cardinal*); +static XtGeometryResult XawListQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawListRedisplay(Widget, XEvent*, Region); +static void XawListResize(Widget); +static Boolean XawListSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +static void CalculatedValues(Widget); +static void ChangeSize(Widget, unsigned int, unsigned int); +static void ClipToShadowInteriorAndLongest(ListWidget, GC*, unsigned int); +static int CvtToItem(Widget, int, int, int*); +static void FindCornerItems(Widget, XEvent*, int*, int*); +static void GetGCs(Widget); +static void HighlightBackground(Widget, int, int, GC); +static Bool ItemInRectangle(Widget, int, int, int); +static Bool Layout(Widget, Bool, Bool, Dimension*, Dimension*); +static void PaintItemName(Widget, int); +static void ResetList(Widget, Bool, Bool); + +/* + * Actions + */ +static void Notify(Widget, XEvent*, String*, Cardinal*); +static void Set(Widget, XEvent*, String*, Cardinal*); +static void Unset(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +static char defaultTranslations[] = +"<Btn1Down>:" "Set()\n" +"<Btn1Up>:" "Notify()\n" +; + +#define offset(field) XtOffsetOf(ListRec, field) +static XtResource resources[] = { + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(list.foreground), + XtRString, + XtDefaultForeground + }, + { + XtNcursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(simple.cursor), + XtRString, + "left_ptr" + }, + { + XtNfont, + XtCFont, + XtRFontStruct, + sizeof(XFontStruct*), + offset(list.font), + XtRString, + XtDefaultFont + }, + { + XtNfontSet, + XtCFontSet, + XtRFontSet, + sizeof(XFontSet), + offset(list.fontset), + XtRString, + XtDefaultFontSet + }, + { + XtNlist, + XtCList, + XtRPointer, + sizeof(char**), + offset(list.list), +#ifdef notyet + XtRStringArray, +#else + XtRString, +#endif + NULL + }, + { + XtNdefaultColumns, + XtCColumns, + XtRInt, + sizeof(int), + offset(list.default_cols), + XtRImmediate, + (XtPointer)2 + }, + { + XtNlongest, + XtCLongest, + XtRInt, + sizeof(int), + offset(list.longest), + XtRImmediate, + (XtPointer)0 + }, + { + XtNnumberStrings, + XtCNumberStrings, + XtRInt, + sizeof(int), + offset(list.nitems), + XtRImmediate, + (XtPointer)0 + }, + { + XtNpasteBuffer, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(list.paste), + XtRImmediate, + (XtPointer)False + }, + { + XtNforceColumns, + XtCColumns, + XtRBoolean, + sizeof(Boolean), + offset(list.force_cols), + XtRImmediate, + (XtPointer)False + }, + { + XtNverticalList, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(list.vertical_cols), + XtRImmediate, + (XtPointer)False + }, + { + XtNinternalWidth, + XtCWidth, + XtRDimension, + sizeof(Dimension), + offset(list.internal_width), + XtRImmediate, + (XtPointer)2 + }, + { + XtNinternalHeight, + XtCHeight, + XtRDimension, + sizeof(Dimension), + offset(list.internal_height), + XtRImmediate, + (XtPointer)2 + }, + { + XtNcolumnSpacing, + XtCSpacing, + XtRDimension, + sizeof(Dimension), + offset(list.column_space), + XtRImmediate, + (XtPointer)6 + }, + { + XtNrowSpacing, + XtCSpacing, + XtRDimension, + sizeof(Dimension), + offset(list.row_space), + XtRImmediate, + (XtPointer)2 + }, + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(list.callback), + XtRCallback, + NULL + }, +#ifndef OLDXAW + { + XtNshowCurrent, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(list.show_current), + XtRImmediate, + (XtPointer)False + }, +#endif +}; +#undef offset + +static XtActionsRec actions[] = { + {"Notify", Notify}, + {"Set", Set}, + {"Unset", Unset}, +}; + +#define Superclass (&simpleClassRec) +ListClassRec listClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "List", /* class_name */ + sizeof(ListRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawListInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + actions, /* actions */ + XtNumber(actions), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + False, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawListDestroy, /* destroy */ + XawListResize, /* resize */ + XawListRedisplay, /* expose */ + XawListSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XawListQueryGeometry, /* query_geometry */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* list */ + { + NULL, /* extension */ + }, +}; + +WidgetClass listWidgetClass = (WidgetClass)&listClassRec; + +/* + * Implementation + */ +static void +GetGCs(Widget w) +{ + XGCValues values; + ListWidget lw = (ListWidget)w; + + values.foreground = lw->list.foreground; + values.font = lw->list.font->fid; + + if (lw->simple.international == True) + lw->list.normgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0); + else + lw->list.normgc = XtGetGC(w, GCForeground | GCFont, &values); + + values.foreground = lw->core.background_pixel; + + if (lw->simple.international == True) + lw->list.revgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0); + else + lw->list.revgc = XtGetGC(w, GCForeground | GCFont, &values); + + values.tile = XmuCreateStippledPixmap(XtScreen(w), + lw->list.foreground, + lw->core.background_pixel, + lw->core.depth); + values.fill_style = FillTiled; + + if (lw->simple.international == True) + lw->list.graygc = XtAllocateGC(w, 0, GCTile | GCFillStyle, + &values, GCFont, 0); + else + lw->list.graygc = XtGetGC(w, GCFont | GCTile | GCFillStyle, &values); +} + +static void +CalculatedValues(Widget w) +{ + int i, len; + ListWidget lw = (ListWidget)w; + + /* If list is NULL then the list will just be the name of the widget */ + if (lw->list.list == NULL) { + lw->list.list = &lw->core.name; + lw->list.nitems = 1; + } + + /* Get number of items */ + if (lw->list.nitems == 0) + for (; lw->list.list[lw->list.nitems] != NULL ; lw->list.nitems++) + ; + + /* Get column width */ + if (LongestFree(lw)) { + lw->list.longest = 0; /* so it will accumulate real longest below */ + + for (i = 0 ; i < lw->list.nitems; i++) { + if (lw->simple.international == True) + len = XmbTextEscapement(lw->list.fontset, lw->list.list[i], + strlen(lw->list.list[i])); + else + len = XTextWidth(lw->list.font, lw->list.list[i], + strlen(lw->list.list[i])); + if (len > lw->list.longest) + lw->list.longest = len; + } + } + + lw->list.col_width = lw->list.longest + lw->list.column_space; +} + +/* + * Function: + * ResetList + * + * Parameters: + * w - list widget + * changex - allow the height or width to change? + * changey - "" + * + * Description: + * Resets the new list when important things change. + * + * Returns: + * True if width or height have been changed + */ +static void +ResetList(Widget w, Bool changex, Bool changey) +{ + Dimension width = XtWidth(w); + Dimension height = XtHeight(w); + + CalculatedValues(w); + + if (Layout(w, changex, changey, &width, &height)) { + if (XtIsComposite(XtParent(w))) + ChangeSize(w, width, height); + else { + XtWidth(w) = width; + XtHeight(w) = height; + } + } +} + +/* + * Function: + * ChangeSize + * + * Parameters: + * w - widget to try change the size of + * + * Description: + * Laysout the widget. + */ +static void +ChangeSize(Widget w, unsigned int width, unsigned int height) +{ + XtWidgetGeometry request, reply; + + request.request_mode = CWWidth | CWHeight; + request.width = width; + request.height = height; + + switch (XtMakeGeometryRequest(w, &request, &reply)) { + case XtGeometryYes: + case XtGeometryNo: + break; + case XtGeometryAlmost: + Layout(w, request.height != reply.height, + request.width != reply.width, &reply.width, &reply.height); + request = reply; + switch (XtMakeGeometryRequest(w, &request, &reply)) { + case XtGeometryYes: + case XtGeometryNo: + break; + case XtGeometryAlmost: + request = reply; + Layout(w, False, False, &request.width, &request.height); + request.request_mode = CWWidth | CWHeight; + XtMakeGeometryRequest(w, &request, &reply); + /*FALLTROUGH*/ + default: + break; + } + /*FALLTROUGH*/ + default: + break; + } +} + +/*ARGSUSED*/ +static void +XawListInitialize(Widget temp1, Widget cnew, ArgList args, Cardinal *num_args) +{ + ListWidget lw = (ListWidget)cnew; + + if (!lw->list.font) XtError("Aborting: no font found\n"); + if (lw->simple.international && !lw->list.fontset) + XtError("Aborting: no fontset found\n"); + + /* + * Initialize all private resources + */ + /* record for posterity if we are free */ + lw->list.freedoms = ((XtWidth(lw) != 0) * WidthLock + + (XtHeight(lw) != 0) * HeightLock + + (lw->list.longest != 0) * LongestLock); + + GetGCs(cnew); + + /* Set row height, based on font or fontset */ + if (lw->simple.international == True) + lw->list.row_height = + XExtentsOfFontSet(lw->list.fontset)->max_ink_extent.height + + lw->list.row_space; + else + lw->list.row_height = lw->list.font->max_bounds.ascent + + lw->list.font->max_bounds.descent + + lw->list.row_space; + + ResetList(cnew, WidthFree(lw), HeightFree(lw)); + + lw->list.highlight = lw->list.is_highlighted = NO_HIGHLIGHT; +} + +/* + * Function: + * CvtToItem + * + * Parameters: + * w - list widget + * xloc - x location + * yloc - y location + * + * Description: + * Converts Xcoord to item number of item containing that point. + * + * Returns: + * Item number + */ +static int +CvtToItem(Widget w, int xloc, int yloc, int *item) +{ + int one, another; + ListWidget lw = (ListWidget)w; + int ret_val = OKAY; + + if (lw->list.vertical_cols) { + one = lw->list.nrows * ((xloc - (int)lw->list.internal_width) + / lw->list.col_width); + another = (yloc - (int)lw->list.internal_height) / lw->list.row_height; + /* If out of range, return minimum possible value */ + if (another >= lw->list.nrows) { + another = lw->list.nrows - 1; + ret_val = OUT_OF_RANGE; + } + } + else { + one = (lw->list.ncols * ((yloc - (int)lw->list.internal_height) + / lw->list.row_height)); + /* If in right margin handle things right */ + another = (xloc - (int)lw->list.internal_width) / lw->list.col_width; + if (another >= lw->list.ncols) { + another = lw->list.ncols - 1; + ret_val = OUT_OF_RANGE; + } + } + if (xloc < 0 || yloc < 0) + ret_val = OUT_OF_RANGE; + if (one < 0) + one = 0; + if (another < 0) + another = 0; + *item = one + another; + if (*item >= lw->list.nitems) + return (OUT_OF_RANGE); + + return (ret_val); +} + +/* + * Function: + * FindCornerItems + * + * Arguments: + * w - list widget + * event - event structure that has the rectangle it it + * ul_ret - the corners (return) + * lr_ret - "" + * + * Description: + * Find the corners of the rectangle in item space. + */ +static void +FindCornerItems(Widget w, XEvent *event, int *ul_ret, int *lr_ret) +{ + int xloc, yloc; + + xloc = event->xexpose.x; + yloc = event->xexpose.y; + CvtToItem(w, xloc, yloc, ul_ret); + xloc += event->xexpose.width; + yloc += event->xexpose.height; + CvtToItem(w, xloc, yloc, lr_ret); +} + +/* + * Function: + * ItemInRectangle + * + * Parameters: + * w - list widget + * ul - corners of the rectangle in item space + * lr - "" + * item - item to check + * + * Returns: + * True if the item passed is in the given rectangle + */ +static Bool +ItemInRectangle(Widget w, int ul, int lr, int item) +{ + ListWidget lw = (ListWidget)w; + int mod_item; + int things; + + if (item < ul || item > lr) + return (False); + if (lw->list.vertical_cols) + things = lw->list.nrows; + else + things = lw->list.ncols; + + mod_item = item % things; + if ((mod_item >= ul % things) && (mod_item <= lr % things)) + return (True); + + return (False); +} + +/* HighlightBackground() + * + * Paints the color of the background for the given item. It performs + * clipping to the interior of internal_width/height by hand, as its a + * simple calculation and probably much faster than using Xlib and a clip mask. + * + * x, y - ul corner of the area item occupies. + * gc - the gc to use to paint this rectangle + */ +static void +HighlightBackground(Widget w, int x, int y, GC gc) +{ + ListWidget lw = (ListWidget)w; + Dimension width = lw->list.col_width; + Dimension height = lw->list.row_height; + Dimension frame_limited_width = XtWidth(w) - lw->list.internal_width - x; + Dimension frame_limited_height= XtHeight(w) - lw->list.internal_height - y; + + /* Clip the rectangle width and height to the edge of the drawable area */ + if (width > frame_limited_width) + width = frame_limited_width; + if (height > frame_limited_height) + height = frame_limited_height; + + /* Clip the rectangle x and y to the edge of the drawable area */ + if (x < lw->list.internal_width) { + width = width - (lw->list.internal_width - x); + x = lw->list.internal_width; + } + if (y < lw->list.internal_height) { + height = height - (lw->list.internal_height - y); + y = lw->list.internal_height; + } + + if (gc == lw->list.revgc && lw->core.background_pixmap != XtUnspecifiedPixmap) + XClearArea(XtDisplay(w), XtWindow(w), x, y, width, height, False); + else + XFillRectangle(XtDisplay(w), XtWindow(w), gc, x, y, width, height); +} + + +/* ClipToShadowInteriorAndLongest() + * + * Converts the passed gc so that any drawing done with that GC will not + * write in the empty margin (specified by internal_width/height) (which also + * prevents erasing the shadow. It also clips against the value longest. + * If the user doesn't set longest, this has no effect (as longest is the + * maximum of all item lengths). If the user does specify, say, 80 pixel + * columns, though, this prevents items from overwriting other items. + */ +static void +ClipToShadowInteriorAndLongest(ListWidget lw, GC *gc_p, unsigned int x) +{ + XRectangle rect; + + rect.x = x; + rect.y = lw->list.internal_height; + rect.height = XtHeight(lw) - (lw->list.internal_height << 1); + rect.width = XtWidth(lw) - lw->list.internal_width - x; + if (rect.width > lw->list.longest) + rect.width = lw->list.longest; + + XSetClipRectangles(XtDisplay((Widget)lw), *gc_p, 0, 0, &rect, 1, YXBanded); +} + +static void +PaintItemName(Widget w, int item) +{ + char *str; + GC gc; + int x, y, str_y; + ListWidget lw = (ListWidget)w; + XFontSetExtents *ext = XExtentsOfFontSet(lw->list.fontset); + + if (!XtIsRealized(w) || item > lw->list.nitems) + return; + + if (lw->list.vertical_cols) { + x = lw->list.col_width * (item / lw->list.nrows) + + lw->list.internal_width; + y = lw->list.row_height * (item % lw->list.nrows) + + lw->list.internal_height; + } + else { + x = lw->list.col_width * (item % lw->list.ncols) + + lw->list.internal_width; + y = lw->list.row_height * (item / lw->list.ncols) + + lw->list.internal_height; + } + + if ( lw->simple.international == True ) + str_y = y + XawAbs(ext->max_ink_extent.y); + else + str_y = y + lw->list.font->max_bounds.ascent; + + if (item == lw->list.is_highlighted) { + if (item == lw->list.highlight) { + gc = lw->list.revgc; + HighlightBackground(w, x, y, lw->list.normgc); + } + else { + if (XtIsSensitive(w)) + gc = lw->list.normgc; + else + gc = lw->list.graygc; + HighlightBackground(w, x, y, lw->list.revgc); + lw->list.is_highlighted = NO_HIGHLIGHT; + } + } + else { + if (item == lw->list.highlight) { + gc = lw->list.revgc; + HighlightBackground(w, x, y, lw->list.normgc); + lw->list.is_highlighted = item; + } + else { + if (XtIsSensitive(w)) + gc = lw->list.normgc; + else + gc = lw->list.graygc; + } + } + + /* List's overall width contains the same number of inter-column + column_space's as columns. There should thus be a half + column_width margin on each side of each column. + The row case is symmetric */ + + x += lw->list.column_space >> 1; + str_y += lw->list.row_space >> 1; + + str = lw->list.list[item]; /* draw it */ + + ClipToShadowInteriorAndLongest(lw, &gc, x); + + if (lw->simple.international == True) + XmbDrawString(XtDisplay(w), XtWindow(w), lw->list.fontset, + gc, x, str_y, str, strlen(str)); + else + XDrawString(XtDisplay(w), XtWindow(w), gc, x, str_y, str, strlen(str)); + + XSetClipMask(XtDisplay(w), gc, None); +} + +static void +XawListRedisplay(Widget w, XEvent *event, Region region) +{ + int item; /* an item to work with */ + int ul_item, lr_item; /* corners of items we need to paint */ + ListWidget lw = (ListWidget)w; + + if (event == NULL) { + ul_item = 0; + lr_item = lw->list.nrows * lw->list.ncols - 1; + XClearWindow(XtDisplay(w), XtWindow(w)); + } + else + FindCornerItems(w, event, &ul_item, &lr_item); + + if (Superclass->core_class.expose) + (Superclass->core_class.expose)(w, event, region); + + for (item = ul_item; item <= lr_item && item < lw->list.nitems; item++) + if (ItemInRectangle(w, ul_item, lr_item, item)) + PaintItemName(w, item); +} + +/* XawListQueryGeometry() + * + * This tells the parent what size we would like to be + * given certain constraints. + * w - the widget. + * intended - what the parent intends to do with us. + * requested - what we want to happen */ +static XtGeometryResult +XawListQueryGeometry(Widget w, XtWidgetGeometry *intended, + XtWidgetGeometry *requested) +{ + Dimension new_width, new_height; + Bool change, width_req, height_req; + + width_req = intended->request_mode & CWWidth; + height_req = intended->request_mode & CWHeight; + + if (width_req) + new_width = intended->width; + else + new_width = XtWidth(w); + + if (height_req) + new_height = intended->height; + else + new_height = XtHeight(w); + + requested->request_mode = 0; + + /* + * We only care about our height and width + */ + if (!width_req && !height_req) + return (XtGeometryYes); + + change = Layout(w, !width_req, !height_req, &new_width, &new_height); + + requested->request_mode |= CWWidth; + requested->width = new_width; + requested->request_mode |= CWHeight; + requested->height = new_height; + + if (change) + return (XtGeometryAlmost); + + return (XtGeometryYes); +} + +static void +XawListResize(Widget w) +{ + Dimension width, height; + + width = XtWidth(w); + height = XtHeight(w); + + if (Layout(w, False, False, &width, &height)) + XtAppWarning(XtWidgetToApplicationContext(w), + "List Widget: Size changed when it shouldn't " + "have when resising."); +} + +/* Layout() + * + * lays out the item in the list. + * w - the widget. + * xfree, yfree - True if we are free to resize the widget in + * this direction. + * width, height- the is the current width and height that we are going + * we are going to layout the list widget to, + * depending on xfree and yfree of course. + * + * Return: + * True if width or height have been changed */ +static Bool +Layout(Widget w, Bool xfree, Bool yfree, Dimension *width, Dimension *height) +{ + ListWidget lw = (ListWidget)w; + Bool change = False; + unsigned long width2 = 0, height2 = 0; + + /* + * If force columns is set then always use number of columns specified + * by default_cols + */ + if (lw->list.force_cols) { + lw->list.ncols = lw->list.default_cols; + if (lw->list.ncols <= 0) + lw->list.ncols = 1; + lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; + if (xfree) { + /* this counts the same number + of inter-column column_space 's as columns. There should thus + be a half column_space margin on each side of each column...*/ + width2 = lw->list.ncols * lw->list.col_width + + (lw->list.internal_width << 1); + change = True; + } + if (yfree) { + height2 = lw->list.nrows * lw->list.row_height + + (lw->list.internal_height << 1); + change = True; + } + } + + /* + * If both width and height are free to change the use default_cols + * to determine the number columns and set new width and height to + * just fit the window + */ + else if (xfree && yfree) { + lw->list.ncols = lw->list.default_cols; + if (lw->list.ncols <= 0) { + int wid = (int)XtWidth(lw) - (int)(lw->list.internal_width << 1) + + (int)lw->list.column_space; + + if (wid <= 0 || lw->list.col_width <= 0 + || (lw->list.ncols = wid / lw->list.col_width) <= 0) + lw->list.ncols = 1; + } + width2 = lw->list.ncols * lw->list.col_width + + (lw->list.internal_width << 1); + height2 = (lw->list.nrows * lw->list.row_height) + + (lw->list.internal_height << 1); + change = True; + } + + /* + * If the width is fixed then use it to determine the number of columns. + * If the height is free to move (width still fixed) then resize the height + * of the widget to fit the current list exactly + */ + else if (!xfree) { + lw->list.ncols = ((int)(*width - (lw->list.internal_width << 1)) + / (int)lw->list.col_width); + if (lw->list.ncols <= 0) + lw->list.ncols = 1; + lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; + if (yfree) { + height2 = lw->list.nrows * lw->list.row_height + + (lw->list.internal_height << 1); + change = True; + } + } + + /* + * The last case is xfree and !yfree we use the height to determine + * the number of rows and then set the width to just fit the resulting + * number of columns + */ + else if (!yfree) { + lw->list.nrows = ((int)(*height - (lw->list.internal_height << 1)) + / (int)lw->list.row_height); + if (lw->list.nrows <= 0) + lw->list.nrows = 1; + lw->list.ncols = ((lw->list.nitems - 1) / lw->list.nrows) + 1; + width2 = lw->list.ncols * lw->list.col_width + + (lw->list.internal_width << 1); + change = True; + } + + if (!lw->list.force_cols && lw->list.nrows) { + /*CONSTCOND*/ + while (1) { + lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; + width2 = lw->list.ncols * lw->list.col_width + + (lw->list.internal_width << 1); + height2 = lw->list.nrows * lw->list.row_height + + (lw->list.internal_height << 1); + if (width2 >= MaxSize && height2 >= MaxSize) + break; + if (height2 > MaxSize) + ++lw->list.ncols; + else if (width2 > MaxSize && lw->list.ncols > 1) + --lw->list.ncols; + else + break; + } + } + if (width2) + *width = width2; + if (height2) + *height = height2; + + return (change); +} + +/* Notify() - Action + * + * Notifies the user that a button has been pressed, and + * calls the callback; if the XtNpasteBuffer resource is true + * then the name of the item is also put in CUT_BUFFER0 */ +/*ARGSUSED*/ +static void +Notify(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + ListWidget lw = (ListWidget)w; + int item, item_len; + XawListReturnStruct ret_value; + + /* + * Find item and if out of range then unhighlight and return + * + * If the current item is unhighlighted then the user has aborted the + * notify, so unhighlight and return + */ + if ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE) + || lw->list.highlight != item) { +#ifndef OLDXAW + if (!lw->list.show_current || lw->list.selected == NO_HIGHLIGHT) + XawListUnhighlight(w); + else + XawListHighlight(w, lw->list.selected); +#else + XawListUnhighlight(w); +#endif + return; + } + + item_len = strlen(lw->list.list[item]); + + if (lw->list.paste) /* if XtNpasteBuffer set then paste it */ + XStoreBytes(XtDisplay(w), lw->list.list[item], item_len); + +#ifndef OLDXAW + lw->list.selected = item; +#endif + /* + * Call Callback function + */ + ret_value.string = lw->list.list[item]; + ret_value.list_index = item; + + XtCallCallbacks(w, XtNcallback, (XtPointer)&ret_value); +} + +/* Unset() - Action + * + * unhighlights the current element */ +/*ARGSUSED*/ +static void +Unset(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XawListUnhighlight(w); +} + +/* Set() - Action + * + * Highlights the current element */ +/*ARGSUSED*/ +static void +Set(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + int item; + ListWidget lw = (ListWidget)w; + +#ifndef OLDXAW + lw->list.selected = lw->list.highlight; +#endif + if (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE) + XawListUnhighlight(w); /* Unhighlight current item */ + else if (lw->list.is_highlighted != item) /* If this item is not */ + XawListHighlight(w, item); /* highlighted then do it */ +} + +/* + * Set specified arguments into widget + */ +/*ARGSUSED*/ +static Boolean +XawListSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ListWidget cl = (ListWidget)current; + ListWidget rl = (ListWidget)request; + ListWidget nl = (ListWidget)cnew; + Bool redraw = False; + XFontSetExtents *ext = XExtentsOfFontSet(nl->list.fontset); + + /* If the request height/width is different, lock it. Unless its 0. If + neither new nor 0, leave it as it was. Not in R5 */ + if (XtWidth(nl) != XtWidth(cl)) + nl->list.freedoms |= WidthLock; + if (XtWidth(nl) == 0) + nl->list.freedoms &= ~WidthLock; + + if (XtHeight(nl) != XtHeight(cl)) + nl->list.freedoms |= HeightLock; + if (XtHeight(nl) == 0) + nl->list.freedoms &= ~HeightLock; + + if (nl->list.longest != cl->list.longest) + nl->list.freedoms |= LongestLock; + if (nl->list.longest == 0) + nl->list.freedoms &= ~LongestLock; + + if (cl->list.foreground != nl->list.foreground || + cl->core.background_pixel != nl->core.background_pixel || + cl->list.font != nl->list.font) { + XGCValues values; + + XGetGCValues(XtDisplay(current), cl->list.graygc, GCTile, &values); + XmuReleaseStippledPixmap(XtScreen(current), values.tile); + XtReleaseGC(current, cl->list.graygc); + XtReleaseGC(current, cl->list.revgc); + XtReleaseGC(current, cl->list.normgc); + GetGCs(cnew); + redraw = True; + } + + if (cl->list.font != nl->list.font && cl->simple.international == False) + nl->list.row_height = nl->list.font->max_bounds.ascent + + nl->list.font->max_bounds.descent + + nl->list.row_space; + else if (cl->list.fontset != nl->list.fontset + && cl->simple.international == True) + nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space; + + /* ...If the above two font(set) change checkers above both failed, check + if row_space was altered. If one of the above passed, row_height will + already have been re-calculated */ + else if (cl->list.row_space != nl->list.row_space) { + if (cl->simple.international == True) + nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space; + else + nl->list.row_height = nl->list.font->max_bounds.ascent + + nl->list.font->max_bounds.descent + + nl->list.row_space; + } + + if (XtWidth(cl) != XtWidth(nl) || XtHeight(cl) != XtHeight(nl) + || cl->list.internal_width != nl->list.internal_width + || cl->list.internal_height != nl->list.internal_height + || cl->list.column_space != nl->list.column_space + || cl->list.row_space != nl->list.row_space + || cl->list.default_cols != nl->list.default_cols + || (cl->list.force_cols != nl->list.force_cols + && rl->list.force_cols != nl->list.ncols) + || cl->list.vertical_cols != nl->list.vertical_cols + || cl->list.longest != nl->list.longest + || cl->list.nitems != nl->list.nitems + || cl->list.font != nl->list.font + /* Equiv. fontsets might have different values, but the same fonts, + so the next comparison is sloppy but not dangerous */ + || cl->list.fontset != nl->list.fontset + || cl->list.list != nl->list.list) { + CalculatedValues(cnew); + Layout(cnew, WidthFree(nl), HeightFree(nl), + &nl->core.width, &nl->core.height); + redraw = True; + } + + if (cl->list.list != nl->list.list || cl->list.nitems != nl->list.nitems) + nl->list.is_highlighted = nl->list.highlight = NO_HIGHLIGHT; + + if (cl->core.sensitive != nl->core.sensitive + || cl->core.ancestor_sensitive != nl->core.ancestor_sensitive) { + nl->list.highlight = NO_HIGHLIGHT; + redraw = True; + } + + return (redraw); +} + +static void +XawListDestroy(Widget w) +{ + ListWidget lw = (ListWidget)w; + XGCValues values; + + XGetGCValues(XtDisplay(w), lw->list.graygc, GCTile, &values); + XmuReleaseStippledPixmap(XtScreen(w), values.tile); + XtReleaseGC(w, lw->list.graygc); + XtReleaseGC(w, lw->list.revgc); + XtReleaseGC(w, lw->list.normgc); +} + +/* + * Function: + * XawListChange + * + * Parameters: + * w - list widget + * list - new list + * nitems - number of items in the list + * longest - length (in Pixels) of the longest element in the list + * resize - if True the the list widget will try to resize itself + * + * Description: + * Changes the list being used and shown. + * + * Note: + * If nitems of longest are <= 0 then they will be calculated + * If nitems is <= 0 then the list needs to be NULL terminated + */ +void +XawListChange(Widget w, char **list, int nitems, int longest, +#if NeedWidePrototypes + int resize_it +#else + Boolean resize_it +#endif +) +{ + ListWidget lw = (ListWidget)w; + Dimension new_width = XtWidth(w); + Dimension new_height = XtHeight(w); + + lw->list.list = list; + + if (nitems <= 0) + nitems = 0; + lw->list.nitems = nitems; + if (longest <= 0) + longest = 0; + + /* If the user passes 0 meaning "calculate it", it must be free */ + if (longest != 0) + lw->list.freedoms |= LongestLock; + else + lw->list.freedoms &= ~LongestLock; + + if (resize_it) + lw->list.freedoms &= ~WidthLock & ~HeightLock; + + lw->list.longest = longest; + + CalculatedValues(w); + + if (Layout(w, WidthFree(w), HeightFree(w), &new_width, &new_height)) + ChangeSize(w, new_width, new_height); + + lw->list.is_highlighted = lw->list.highlight = NO_HIGHLIGHT; + if (XtIsRealized(w)) + XawListRedisplay(w, NULL, NULL); +} + +void +XawListUnhighlight(Widget w) +{ + ListWidget lw = (ListWidget)w; + + lw->list.highlight = NO_HIGHLIGHT; + if (lw->list.is_highlighted != NO_HIGHLIGHT) + PaintItemName(w, lw->list.is_highlighted); +} + +void +XawListHighlight(Widget w, int item) +{ + ListWidget lw = (ListWidget)w; + + if (XtIsSensitive(w)) { + lw->list.highlight = item; + if (lw->list.is_highlighted != NO_HIGHLIGHT) + PaintItemName(w, lw->list.is_highlighted); + PaintItemName(w, item); + } +} + +/* + * Function: + * XawListShowCurrent + * + * Parameters: + * w - list widget + * + * Returns: + * Info about the currently highlighted object + */ +XawListReturnStruct * +XawListShowCurrent(Widget w) +{ + ListWidget lw = (ListWidget)w; + XawListReturnStruct *ret_val; + + ret_val = (XawListReturnStruct *)XtMalloc(sizeof(XawListReturnStruct)); + + ret_val->list_index = lw->list.highlight; + if (ret_val->list_index == XAW_LIST_NONE) + ret_val->string = ""; + else + ret_val->string = lw->list.list[ret_val->list_index]; + + return (ret_val); +} diff --git a/libXaw/src/Makefile.am b/libXaw/src/Makefile.am index 52c171857..3bc4b29b1 100644 --- a/libXaw/src/Makefile.am +++ b/libXaw/src/Makefile.am @@ -1,143 +1,143 @@ -lib_LTLIBRARIES =
-
-#
-# This doesn't appear to be used on any
-# current systems -- it requires SUNSHLIB and !SHAREDCODE,
-# but only sunLib.rules defines SUNSHLIB and that file also
-# always defines SHAREDCODE. Go figure
-#
-# SHAREDLIB_SOURCES = sharedlib.c
-
-COMMON_SOURCES = \
- Actions.c \
- AllWidgets.c \
- AsciiSink.c \
- AsciiSrc.c \
- AsciiText.c \
- Box.c \
- Command.c \
- Converters.c \
- Dialog.c \
- DisplayList.c \
- Form.c \
- Grip.c \
- Label.c \
- List.c \
- MenuButton.c \
- MultiSrc.c \
- MultiSink.c \
- OS.c \
- Paned.c \
- Panner.c \
- Pixmap.c \
- Porthole.c \
- Private.h \
- Repeater.c \
- Scrollbar.c \
- Simple.c \
- SimpleMenu.c \
- Sme.c \
- SmeBSB.c \
- SmeLine.c \
- StripChart.c \
- Text.c \
- TextSink.c \
- TextSrc.c \
- TextAction.c \
- TextPop.c \
- TextTr.c \
- Toggle.c \
- Tree.c \
- Vendor.c \
- Viewport.c \
- XawIm.c \
- XawInit.c \
- XawI18n.c \
- XawI18n.h
-
-COMMON_CFLAGS = \
- $(CWARNFLAGS)
-
-COMMON_CPPFLAGS = \
- -I${top_srcdir}/include \
- -I${top_srcdir}/include/X11/Xaw \
- -DPROJECT_ROOT=\"$(prefix)\"
-
-if BUILD_XAW6
-
-lib_LTLIBRARIES += libXaw6.la
-
-libXaw6_la_CPPFLAGS = \
- $(COMMON_CPPFLAGS)
-
-libXaw6_la_CFLAGS = \
- $(COMMON_CFLAGS) \
- -DOLDXAW \
- $(XAW6_CFLAGS)
-
-libXaw6_la_SOURCES = \
- $(COMMON_SOURCES)
-
-libXaw6_la_LDFLAGS = -version-info 6:1:0 -no-undefined
-libXaw6_la_LIBADD = $(XAW6_LIBS)
-
-if !PLATFORM_WIN32
-install-exec-hook::
-if PLATFORM_DARWIN
- -rm -f $(DESTDIR)$(libdir)/libXaw.6.@LIBEXT@
- (cd $(DESTDIR)$(libdir) && ln -s libXaw6.6.@LIBEXT@ libXaw.6.@LIBEXT@)
-else
- -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.6
- (cd $(DESTDIR)$(libdir) && ln -s libXaw6.@LIBEXT@.6 libXaw.@LIBEXT@.6)
-endif
-
-uninstall-local::
-if PLATFORM_DARWIN
- -rm -f $(DESTDIR)$(libdir)/libXaw.6.@LIBEXT@
-else
- -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.6
-endif
-endif
-
-endif
-
-if BUILD_XAW7
-
-lib_LTLIBRARIES += libXaw7.la
-
-libXaw7_la_CPPFLAGS = \
- $(COMMON_CPPFLAGS)
-
-libXaw7_la_CFLAGS = \
- $(COMMON_CFLAGS) \
- -DXAW7 \
- $(XAW7_CFLAGS)
-
-libXaw7_la_SOURCES = \
- $(COMMON_SOURCES) \
- Tip.c
-
-libXaw7_la_LDFLAGS = -version-info 7:0:0 -no-undefined
-libXaw7_la_LIBADD = $(XAW7_LIBS)
-
-if !PLATFORM_WIN32
-install-exec-hook::
-if PLATFORM_DARWIN
- -rm -f $(DESTDIR)$(libdir)/libXaw.7.@LIBEXT@
- (cd $(DESTDIR)$(libdir) && ln -s libXaw7.7.@LIBEXT@ libXaw.7.@LIBEXT@)
-else
- -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.7
- (cd $(DESTDIR)$(libdir) && ln -s libXaw7.@LIBEXT@.7 libXaw.@LIBEXT@.7)
-endif
-
-uninstall-local::
-if PLATFORM_DARWIN
- -rm -f $(DESTDIR)$(libdir)/libXaw.7.@LIBEXT@
-else
- -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.7
-endif
-endif
-
-endif
-
-EXTRA_DIST = sharedlib.c
+lib_LTLIBRARIES = + +# +# This doesn't appear to be used on any +# current systems -- it requires SUNSHLIB and !SHAREDCODE, +# but only sunLib.rules defines SUNSHLIB and that file also +# always defines SHAREDCODE. Go figure +# +# SHAREDLIB_SOURCES = sharedlib.c + +COMMON_SOURCES = \ + Actions.c \ + AllWidgets.c \ + AsciiSink.c \ + AsciiSrc.c \ + AsciiText.c \ + Box.c \ + Command.c \ + Converters.c \ + Dialog.c \ + DisplayList.c \ + Form.c \ + Grip.c \ + Label.c \ + List.c \ + MenuButton.c \ + MultiSrc.c \ + MultiSink.c \ + OS.c \ + Paned.c \ + Panner.c \ + Pixmap.c \ + Porthole.c \ + Private.h \ + Repeater.c \ + Scrollbar.c \ + Simple.c \ + SimpleMenu.c \ + Sme.c \ + SmeBSB.c \ + SmeLine.c \ + StripChart.c \ + Text.c \ + TextSink.c \ + TextSrc.c \ + TextAction.c \ + TextPop.c \ + TextTr.c \ + Toggle.c \ + Tree.c \ + Vendor.c \ + Viewport.c \ + XawIm.c \ + XawInit.c \ + XawI18n.c \ + XawI18n.h + +COMMON_CFLAGS = \ + $(CWARNFLAGS) + +COMMON_CPPFLAGS = \ + -I${top_srcdir}/include \ + -I${top_srcdir}/include/X11/Xaw \ + -DPROJECT_ROOT=\"$(prefix)\" + +if BUILD_XAW6 + +lib_LTLIBRARIES += libXaw6.la + +libXaw6_la_CPPFLAGS = \ + $(COMMON_CPPFLAGS) + +libXaw6_la_CFLAGS = \ + $(COMMON_CFLAGS) \ + -DOLDXAW \ + $(XAW6_CFLAGS) + +libXaw6_la_SOURCES = \ + $(COMMON_SOURCES) + +libXaw6_la_LDFLAGS = -version-info 6:1:0 -no-undefined +libXaw6_la_LIBADD = $(XAW6_LIBS) + +if !PLATFORM_WIN32 +install-exec-hook:: +if PLATFORM_DARWIN + -rm -f $(DESTDIR)$(libdir)/libXaw.6.@LIBEXT@ + (cd $(DESTDIR)$(libdir) && ln -s libXaw6.6.@LIBEXT@ libXaw.6.@LIBEXT@) +else + -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.6 + (cd $(DESTDIR)$(libdir) && ln -s libXaw6.@LIBEXT@.6 libXaw.@LIBEXT@.6) +endif + +uninstall-local:: +if PLATFORM_DARWIN + -rm -f $(DESTDIR)$(libdir)/libXaw.6.@LIBEXT@ +else + -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.6 +endif +endif + +endif + +if BUILD_XAW7 + +lib_LTLIBRARIES += libXaw7.la + +libXaw7_la_CPPFLAGS = \ + $(COMMON_CPPFLAGS) + +libXaw7_la_CFLAGS = \ + $(COMMON_CFLAGS) \ + -DXAW7 \ + $(XAW7_CFLAGS) + +libXaw7_la_SOURCES = \ + $(COMMON_SOURCES) \ + Tip.c + +libXaw7_la_LDFLAGS = -version-info 7:0:0 -no-undefined +libXaw7_la_LIBADD = $(XAW7_LIBS) + +if !PLATFORM_WIN32 +install-exec-hook:: +if PLATFORM_DARWIN + -rm -f $(DESTDIR)$(libdir)/libXaw.7.@LIBEXT@ + (cd $(DESTDIR)$(libdir) && ln -s libXaw7.7.@LIBEXT@ libXaw.7.@LIBEXT@) +else + -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.7 + (cd $(DESTDIR)$(libdir) && ln -s libXaw7.@LIBEXT@.7 libXaw.@LIBEXT@.7) +endif + +uninstall-local:: +if PLATFORM_DARWIN + -rm -f $(DESTDIR)$(libdir)/libXaw.7.@LIBEXT@ +else + -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.7 +endif +endif + +endif + +EXTRA_DIST = sharedlib.c diff --git a/libXaw/src/MenuButton.c b/libXaw/src/MenuButton.c index e1e97ed32..2732a72b3 100644 --- a/libXaw/src/MenuButton.c +++ b/libXaw/src/MenuButton.c @@ -1,272 +1,272 @@ -/*
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- */
-
-/*
- * MenuButton.c - Source code for MenuButton widget.
- *
- * This is the source code for the Athena MenuButton widget.
- * It is intended to provide an easy method of activating pulldown menus.
- *
- * Date: May 2, 1989
- *
- * By: Chris D. Peterson
- * MIT X Consortium
- * kit@expo.lcs.mit.edu
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/MenuButtoP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * Class Methods
- */
-static void XawMenuButtonClassInitialize(void);
-static void XawMenuButtonInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawMenuButtonDestroy(Widget);
-static Boolean XawMenuButtonSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-
-/*
- * Actions
- */
-static void PopupMenu(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * Initialization
- */
-#define superclass ((CommandWidgetClass)&commandClassRec)
-
-static char defaultTranslations[] =
-"<Enter>:" "highlight()\n"
-"<Leave>:" "reset()\n"
-"Any<BtnDown>:" "reset() PopupMenu()\n";
-
-static char default_menu_name[] = "menu";
-
-#define offset(field) XtOffsetOf(MenuButtonRec, field)
-static XtResource resources[] = {
- {
- XtNmenuName,
- XtCMenuName,
- XtRString,
- sizeof(String),
- offset(menu_button.menu_name),
- XtRString,
- (XtPointer)default_menu_name
- },
-};
-#undef offset
-
-static XtActionsRec actionsList[] =
-{
- {"PopupMenu", PopupMenu},
-};
-
-MenuButtonClassRec menuButtonClassRec = {
- /* core */
- {
- (WidgetClass)superclass, /* superclass */
- "MenuButton", /* class_name */
- sizeof(MenuButtonRec), /* size */
- XawMenuButtonClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawMenuButtonInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- actionsList, /* actions */
- XtNumber(actionsList), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawMenuButtonDestroy, /* destroy */
- XtInheritResize, /* resize */
- XtInheritExpose, /* expose */
- XawMenuButtonSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- defaultTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XtInheritChangeSensitive /* change_sensitive */
- },
- /* label */
- {
- NULL, /* extension */
- },
- /* command */
- {
- NULL, /* extension */
- },
- /* menu_button */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass menuButtonWidgetClass = (WidgetClass)&menuButtonClassRec;
-
-/*
- * Implementation
- */
-static void
-XawMenuButtonClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtRegisterGrabAction(PopupMenu, True,
- ButtonPressMask | ButtonReleaseMask,
- GrabModeAsync, GrabModeAsync);
-}
-
-/*ARGSUSED*/
-static void
-XawMenuButtonInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- MenuButtonWidget mbw = (MenuButtonWidget)cnew;
-
- if (mbw->menu_button.menu_name != default_menu_name)
- mbw->menu_button.menu_name = XtNewString(mbw->menu_button.menu_name);
-}
-
-static void
-XawMenuButtonDestroy(Widget w)
-{
- MenuButtonWidget mbw = (MenuButtonWidget)w;
-
- if (mbw->menu_button.menu_name != default_menu_name)
- XtFree(mbw->menu_button.menu_name);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawMenuButtonSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- MenuButtonWidget mbw_old = (MenuButtonWidget)current;
- MenuButtonWidget mbw_new = (MenuButtonWidget)cnew;
-
- if (mbw_old->menu_button.menu_name != mbw_new->menu_button.menu_name) {
- if (mbw_old->menu_button.menu_name != default_menu_name)
- XtFree(mbw_old->menu_button.menu_name);
- if (mbw_new->menu_button.menu_name != default_menu_name)
- mbw_new->menu_button.menu_name =
- XtNewString(mbw_new->menu_button.menu_name);
- }
-
- return (False);
-}
-
-/*ARGSUSED*/
-static void
-PopupMenu(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- MenuButtonWidget mbw = (MenuButtonWidget)w;
- Widget menu = NULL, temp;
- Arg arglist[2];
- Cardinal num_args;
- int menu_x, menu_y, menu_width, menu_height, button_height;
- Position button_x, button_y;
-
- temp = w;
- while(temp != NULL) {
- menu = XtNameToWidget(temp, mbw->menu_button.menu_name);
- if (menu == NULL)
- temp = XtParent(temp);
- else
- break;
- }
-
- if (menu == NULL) {
- char error_buf[BUFSIZ];
-
- (void)XmuSnprintf(error_buf, sizeof(error_buf),
- "MenuButton: Could not find menu widget named %s.",
- mbw->menu_button.menu_name);
- XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
- return;
- }
-
- if (!XtIsRealized(menu))
- XtRealizeWidget(menu);
-
- menu_width = XtWidth(menu) + (XtBorderWidth(menu) << 1);
- button_height = XtHeight(w) + (XtBorderWidth(w) << 1);
- menu_height = XtHeight(menu) + (XtBorderWidth(menu) << 1);
-
- XtTranslateCoords(w, 0, 0, &button_x, &button_y);
- menu_x = button_x;
- menu_y = button_y + button_height;
-
- if (menu_y >= 0) {
- int scr_height = HeightOfScreen(XtScreen(menu));
-
- if (menu_y + menu_height > scr_height)
- menu_y = button_y - menu_height;
- if (menu_y < 0) {
- menu_y = scr_height - menu_height;
- menu_x = button_x + XtWidth(w) + (XtBorderWidth(w) << 1);
- if (menu_x + menu_width > WidthOfScreen(XtScreen(menu)))
- menu_x = button_x - menu_width;
- }
- }
- if (menu_y < 0)
- menu_y = 0;
-
- if (menu_x >= 0) {
- int scr_width = WidthOfScreen(XtScreen(menu));
-
- if (menu_x + menu_width > scr_width)
- menu_x = scr_width - menu_width;
- }
- if (menu_x < 0)
- menu_x = 0;
-
- num_args = 0;
- XtSetArg(arglist[num_args], XtNx, menu_x); num_args++;
- XtSetArg(arglist[num_args], XtNy, menu_y); num_args++;
- XtSetValues(menu, arglist, num_args);
-
- XtPopupSpringLoaded(menu);
-}
+/* +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + */ + +/* + * MenuButton.c - Source code for MenuButton widget. + * + * This is the source code for the Athena MenuButton widget. + * It is intended to provide an easy method of activating pulldown menus. + * + * Date: May 2, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/MenuButtoP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * Class Methods + */ +static void XawMenuButtonClassInitialize(void); +static void XawMenuButtonInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawMenuButtonDestroy(Widget); +static Boolean XawMenuButtonSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Actions + */ +static void PopupMenu(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +#define superclass ((CommandWidgetClass)&commandClassRec) + +static char defaultTranslations[] = +"<Enter>:" "highlight()\n" +"<Leave>:" "reset()\n" +"Any<BtnDown>:" "reset() PopupMenu()\n"; + +static char default_menu_name[] = "menu"; + +#define offset(field) XtOffsetOf(MenuButtonRec, field) +static XtResource resources[] = { + { + XtNmenuName, + XtCMenuName, + XtRString, + sizeof(String), + offset(menu_button.menu_name), + XtRString, + (XtPointer)default_menu_name + }, +}; +#undef offset + +static XtActionsRec actionsList[] = +{ + {"PopupMenu", PopupMenu}, +}; + +MenuButtonClassRec menuButtonClassRec = { + /* core */ + { + (WidgetClass)superclass, /* superclass */ + "MenuButton", /* class_name */ + sizeof(MenuButtonRec), /* size */ + XawMenuButtonClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawMenuButtonInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + actionsList, /* actions */ + XtNumber(actionsList), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawMenuButtonDestroy, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + XawMenuButtonSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive /* change_sensitive */ + }, + /* label */ + { + NULL, /* extension */ + }, + /* command */ + { + NULL, /* extension */ + }, + /* menu_button */ + { + NULL, /* extension */ + }, +}; + +WidgetClass menuButtonWidgetClass = (WidgetClass)&menuButtonClassRec; + +/* + * Implementation + */ +static void +XawMenuButtonClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtRegisterGrabAction(PopupMenu, True, + ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync); +} + +/*ARGSUSED*/ +static void +XawMenuButtonInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + MenuButtonWidget mbw = (MenuButtonWidget)cnew; + + if (mbw->menu_button.menu_name != default_menu_name) + mbw->menu_button.menu_name = XtNewString(mbw->menu_button.menu_name); +} + +static void +XawMenuButtonDestroy(Widget w) +{ + MenuButtonWidget mbw = (MenuButtonWidget)w; + + if (mbw->menu_button.menu_name != default_menu_name) + XtFree(mbw->menu_button.menu_name); +} + +/*ARGSUSED*/ +static Boolean +XawMenuButtonSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + MenuButtonWidget mbw_old = (MenuButtonWidget)current; + MenuButtonWidget mbw_new = (MenuButtonWidget)cnew; + + if (mbw_old->menu_button.menu_name != mbw_new->menu_button.menu_name) { + if (mbw_old->menu_button.menu_name != default_menu_name) + XtFree(mbw_old->menu_button.menu_name); + if (mbw_new->menu_button.menu_name != default_menu_name) + mbw_new->menu_button.menu_name = + XtNewString(mbw_new->menu_button.menu_name); + } + + return (False); +} + +/*ARGSUSED*/ +static void +PopupMenu(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + MenuButtonWidget mbw = (MenuButtonWidget)w; + Widget menu = NULL, temp; + Arg arglist[2]; + Cardinal num_args; + int menu_x, menu_y, menu_width, menu_height, button_height; + Position button_x, button_y; + + temp = w; + while(temp != NULL) { + menu = XtNameToWidget(temp, mbw->menu_button.menu_name); + if (menu == NULL) + temp = XtParent(temp); + else + break; + } + + if (menu == NULL) { + char error_buf[BUFSIZ]; + + (void)XmuSnprintf(error_buf, sizeof(error_buf), + "MenuButton: Could not find menu widget named %s.", + mbw->menu_button.menu_name); + XtAppWarning(XtWidgetToApplicationContext(w), error_buf); + return; + } + + if (!XtIsRealized(menu)) + XtRealizeWidget(menu); + + menu_width = XtWidth(menu) + (XtBorderWidth(menu) << 1); + button_height = XtHeight(w) + (XtBorderWidth(w) << 1); + menu_height = XtHeight(menu) + (XtBorderWidth(menu) << 1); + + XtTranslateCoords(w, 0, 0, &button_x, &button_y); + menu_x = button_x; + menu_y = button_y + button_height; + + if (menu_y >= 0) { + int scr_height = HeightOfScreen(XtScreen(menu)); + + if (menu_y + menu_height > scr_height) + menu_y = button_y - menu_height; + if (menu_y < 0) { + menu_y = scr_height - menu_height; + menu_x = button_x + XtWidth(w) + (XtBorderWidth(w) << 1); + if (menu_x + menu_width > WidthOfScreen(XtScreen(menu))) + menu_x = button_x - menu_width; + } + } + if (menu_y < 0) + menu_y = 0; + + if (menu_x >= 0) { + int scr_width = WidthOfScreen(XtScreen(menu)); + + if (menu_x + menu_width > scr_width) + menu_x = scr_width - menu_width; + } + if (menu_x < 0) + menu_x = 0; + + num_args = 0; + XtSetArg(arglist[num_args], XtNx, menu_x); num_args++; + XtSetArg(arglist[num_args], XtNy, menu_y); num_args++; + XtSetValues(menu, arglist, num_args); + + XtPopupSpringLoaded(menu); +} diff --git a/libXaw/src/MultiSink.c b/libXaw/src/MultiSink.c index 39c7da212..129624e01 100644 --- a/libXaw/src/MultiSink.c +++ b/libXaw/src/MultiSink.c @@ -1,975 +1,975 @@ -/*
- * Copyright 1991 by OMRON Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of OMRON not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission. OMRON makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Li Yuhong OMRON Corporation
- */
-
-/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xatom.h>
-#include <X11/Xaw/XawInit.h>
-#include <X11/Xaw/MultiSinkP.h>
-#include <X11/Xaw/MultiSrcP.h>
-#include <X11/Xaw/TextP.h>
-#include "XawI18n.h"
-#include <stdio.h>
-#include <ctype.h>
-#include "Private.h"
-
-#ifdef GETLASTPOS
-#undef GETLASTPOS /* We will use our own GETLASTPOS */
-#endif
-
-#define GETLASTPOS \
- XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, True)
-
-/*
- * Class Methods
- */
-static void XawMultiSinkClassInitialize(void);
-static void XawMultiSinkInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawMultiSinkDestroy(Widget);
-static void XawMultiSinkResize(Widget);
-static Boolean XawMultiSinkSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static int MaxLines(Widget, unsigned int);
-static int MaxHeight(Widget, int);
-static void SetTabs(Widget, int, short*);
-static void DisplayText(Widget, int, int,
- XawTextPosition, XawTextPosition, Bool);
-static void InsertCursor(Widget, int, int, XawTextInsertState);
-static void FindPosition(Widget, XawTextPosition, int, int, Bool,
- XawTextPosition*, int*, int*);
-static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*,
- XawTextPosition*, int*);
-static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*);
-static void GetCursorBounds(Widget, XRectangle*);
-
-/*
- * Prototypes
- */
-static void GetGC(MultiSinkObject);
-static int CharWidth(MultiSinkObject, XFontSet, int, wchar_t);
-static unsigned int PaintText(Widget w, GC gc, int x, int y,
- wchar_t *buf, int len, Bool);
-
-/*
- * Defined in TextSink.c
- */
-void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
-
-/*
- * Initialization
- */
-static wchar_t wspace[2];
-
-#define offset(field) XtOffsetOf(MultiSinkRec, multi_sink.field)
-static XtResource resources[] = {
- {
- XtNfontSet,
- XtCFontSet,
- XtRFontSet,
- sizeof(XFontSet),
- offset(fontset),
- XtRString,
- XtDefaultFontSet
- },
- {
- XtNecho,
- XtCOutput,
- XtRBoolean,
- sizeof(Boolean),
- offset(echo),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNdisplayNonprinting,
- XtCOutput,
- XtRBoolean,
- sizeof(Boolean),
- offset(display_nonprinting),
- XtRImmediate,
- (XtPointer)True
- },
-};
-#undef offset
-
-#define SuperClass (&textSinkClassRec)
-MultiSinkClassRec multiSinkClassRec = {
- /* object */
- {
- (WidgetClass)SuperClass, /* superclass */
- "MultiSink", /* class_name */
- sizeof(MultiSinkRec), /* widget_size */
- XawMultiSinkClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawMultiSinkInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* obj1 */
- NULL, /* obj2 */
- 0, /* obj3 */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* obj4 */
- False, /* obj5 */
- False, /* obj6 */
- False, /* obj7 */
- XawMultiSinkDestroy, /* destroy */
- (XtProc)XawMultiSinkResize, /* obj8 */
- NULL, /* obj9 */
- XawMultiSinkSetValues, /* set_values */
- NULL, /* set_values_hook */
- NULL, /* obj10 */
- NULL, /* get_values_hook */
- NULL, /* obj11 */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* obj12 */
- NULL, /* obj13 */
- NULL, /* obj14 */
- NULL, /* extension */
- },
- /* text_sink */
- {
- DisplayText, /* DisplayText */
- InsertCursor, /* InsertCursor */
- XtInheritClearToBackground, /* ClearToBackground */
- FindPosition, /* FindPosition */
- FindDistance, /* FindDistance */
- Resolve, /* Resolve */
- MaxLines, /* MaxLines */
- MaxHeight, /* MaxHeight */
- SetTabs, /* SetTabs */
- GetCursorBounds, /* GetCursorBounds */
- },
- /* multi_sink */
- {
- NULL, /* extension */
- }
-};
-
-WidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec;
-
-/*
- * Implementation
- */
-static int
-CharWidth(MultiSinkObject sink, XFontSet fontset, int x, wchar_t c)
-{
- int width = 0;
-
- if (c == _Xaw_atowc(XawLF))
- return (0);
-
- if (c == _Xaw_atowc(XawTAB)) {
- int i;
- Position *tab;
-
- width = x;
- /* Adjust for Left Margin. */
- x -= ((TextWidget)XtParent((Widget)sink))->text.left_margin;
-
- i = 0;
- tab = sink->text_sink.tabs;
- /*CONSTCOND*/
- while (1) {
- if (x < *tab)
- return (*tab - x);
- /* Start again */
- if (++i >= sink->text_sink.tab_count) {
- x -= *tab;
- i = 0;
- tab = sink->text_sink.tabs;
- if (width == x)
- return (0);
- }
- else
- ++tab;
- }
- /*NOTREACHED*/
- }
-
- if (XwcTextEscapement(fontset, &c, 1) == 0) {
- if (sink->multi_sink.display_nonprinting)
- c = _Xaw_atowc('@');
- else
- c = _Xaw_atowc(XawSP);
- }
-
- /*
- * if more efficiency(suppose one column is one ASCII char)
-
- width = XwcGetColumn(fontset->font_charset, fontset->num_of_fonts, c) *
- fontset->font_struct_list[0]->min_bounds.width;
- *
- * WARNING: Very Slower!!!
- *
- * Li Yuhong.
- */
-
- width = XwcTextEscapement(fontset, &c, 1);
-
- return (width);
-}
-
-/*
- * Function:
- * PaintText
- *
- * Parameters:
- * w - text sink object
- * gc - gc to paint text
- * x - location to paint the text
- * y - ""
- * buf - buffer and length of text to paint
- * len - ""
- * clear_bg - clear background before drawing ?
- *
- * Description:
- * Actually paints the text into the window.
- *
- * Returns:
- * The width of the text painted
- */
-static unsigned int
-PaintText(Widget w, GC gc, int x, int y, wchar_t *buf, int len, Bool clear_bg)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
- TextWidget ctx = (TextWidget)XtParent(w);
- XFontSet fontset = sink->multi_sink.fontset;
- unsigned int width = XwcTextEscapement(fontset, buf, len);
-
- if (((int)width) <= -x) /* Don't draw if we can't see it */
- return (width);
-
- if (clear_bg) {
- XFontSetExtents *ext = XExtentsOfFontSet(fontset);
-
- _XawTextSinkClearToBackground(w, x, y - abs(ext->max_logical_extent.y),
- width, ext->max_logical_extent.height);
- XwcDrawString(XtDisplay(ctx), XtWindow(ctx), fontset, gc, x, y, buf, len);
- }
- else
- XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx), fontset, gc,
- x, y, buf, len);
-
- return (width);
-}
-
-/* Sink Object Functions */
-/*
- * This function does not know about drawing more than one line of text
- */
-static void
-DisplayText(Widget w, int x, int y,
- XawTextPosition pos1, XawTextPosition pos2, Bool highlight)
-{
- TextWidget ctx = (TextWidget)XtParent(w);
- MultiSinkObject sink = (MultiSinkObject)w;
- XFontSet fontset = sink->multi_sink.fontset;
- Widget source = XawTextGetSource(XtParent(w));
- wchar_t buf[256];
- XFontSetExtents *ext = XExtentsOfFontSet(fontset);
- int j, k;
- XawTextBlock blk;
- GC gc, invgc, tabgc;
- int max_x;
- Bool clear_bg;
-
- if (!sink->multi_sink.echo || !ctx->text.lt.lines)
- return;
-
- max_x = (int)XtWidth(ctx) - ctx->text.r_margin.right;
- clear_bg = !highlight && ctx->core.background_pixmap != XtUnspecifiedPixmap;
-
- gc = highlight ? sink->multi_sink.invgc : sink->multi_sink.normgc;
- invgc = highlight ? sink->multi_sink.normgc : sink->multi_sink.invgc;
-
- if (highlight && sink->multi_sink.xorgc)
- tabgc = sink->multi_sink.xorgc;
- else
- tabgc = invgc;
-
- y += abs(ext->max_logical_extent.y);
- for (j = 0; pos1 < pos2;) {
- pos1 = XawTextSourceRead(source, pos1, &blk, (int) pos2 - pos1);
- for (k = 0; k < blk.length; k++) {
- if ((unsigned) j >= (sizeof(buf) / sizeof(wchar_t)) - 1) {
- /* buffer full, dump the text */
- if ((x += PaintText(w, gc, x, y, buf, j, clear_bg)) >= max_x)
- return;
- j = 0;
- }
- buf[j] = ((wchar_t *)blk.ptr)[k];
- if (buf[j] == _Xaw_atowc(XawLF))
- continue;
-
- else if (buf[j] == _Xaw_atowc(XawTAB)) {
- unsigned int width;
-
- if (j != 0 &&
- (x += PaintText(w, gc, x, y, buf, j, clear_bg)) >= max_x)
- return;
-
- width = CharWidth(sink, fontset, x, _Xaw_atowc(XawTAB));
- if (clear_bg)
- _XawTextSinkClearToBackground(w,
- x, y - abs(ext->max_logical_extent.y),
- width, ext->max_logical_extent.height);
- else
- XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
- tabgc, x,
- y - abs(ext->max_logical_extent.y),
- width,
- ext->max_logical_extent.height);
- x += width;
- j = -1;
- }
- else if (XwcTextEscapement(sink->multi_sink.fontset, &buf[j], 1)
- == 0) {
- if (sink->multi_sink.display_nonprinting)
- buf[j] = _Xaw_atowc('@');
- else
- buf[j] = _Xaw_atowc(XawSP);
- }
- j++;
- }
- }
-
- if (j > 0)
- (void)PaintText(w, gc, x, y, buf, j, clear_bg);
-}
-
-/*
- * Function:
- * GetCursorBounds
- *
- * Parameters:
- * w - text sink object
- * rect - X rectangle to return the cursor bounds
- *
- * Description:
- * Returns the size and location of the cursor.
- */
-static void
-GetCursorBounds(Widget w, XRectangle *rect)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
-
- rect->width = CharWidth(sink, sink->multi_sink.fontset, 0, _Xaw_atowc(XawSP));
- rect->height = (XExtentsOfFontSet(sink->multi_sink.fontset)
- ->max_logical_extent.height);
- rect->x = sink->multi_sink.cursor_x;
- rect->y = sink->multi_sink.cursor_y - (short)rect->height;
-}
-
-/*
- * The following procedure manages the "insert" cursor
- */
-static void
-InsertCursor(Widget w, int x, int y, XawTextInsertState state)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
- XFontSet fontset = sink->multi_sink.fontset;
- Widget ctx = XtParent(w);
- XawTextPosition position = XawTextGetInsertionPoint(ctx);
-
- if (XtIsRealized(ctx)) {
- int fheight, fdiff;
- XawTextBlock block;
- wchar_t c;
- XawTextPosition selection_start, selection_end;
- Boolean has_selection;
- XFontSetExtents *ext = XExtentsOfFontSet(fontset);
-
- XawTextGetSelectionPos((Widget)ctx, &selection_start, &selection_end);
- has_selection = selection_start != selection_end;
-
- fheight = ext->max_logical_extent.height;
- fdiff = fheight - abs(ext->max_logical_extent.y);
-
- if ((sink->multi_sink.cursor_position != position || state == XawisOff)
- && !has_selection && sink->multi_sink.laststate != XawisOff) {
- wchar_t *ochar;
-
- (void)XawTextSourceRead(XawTextGetSource(ctx),
- sink->multi_sink.cursor_position,
- &block, 1);
- if (!block.length)
- ochar = NULL;
- else {
- c = ((wchar_t *)block.ptr)[0];
- if (c == _Xaw_atowc(XawLF))
- ochar = NULL;
- else if (c == _Xaw_atowc(XawTAB))
- ochar = wspace;
- else
- ochar = (wchar_t *)block.ptr;
- }
-
- if (!ochar)
- _XawTextSinkClearToBackground(w, sink->multi_sink.cursor_x,
- (sink->multi_sink.cursor_y - 1 -
- fheight), CharWidth(sink, fontset,
- 0, wspace[0]),
- fheight);
- else {
- if (XwcTextEscapement(sink->multi_sink.fontset, ochar, 1) != 0)
- DisplayText(w, sink->multi_sink.cursor_x,
- sink->multi_sink.cursor_y - 1 - fheight,
- sink->multi_sink.cursor_position,
- sink->multi_sink.cursor_position + 1,
- False);
- else
- PaintText(w, sink->multi_sink.normgc,
- sink->multi_sink.cursor_x,
- sink->multi_sink.cursor_y - 1 - fdiff,
- ochar, 1,
- ctx->core.background_pixmap != XtUnspecifiedPixmap);
- }
- }
-
- if (!has_selection && state != XawisOff) {
- wchar_t *nchar;
- Boolean focus = ((TextWidget)ctx)->text.hasfocus;
-
- (void)XawTextSourceRead(XawTextGetSource(ctx),
- position, &block, 1);
- c = ((wchar_t *)block.ptr)[0];
- if (!block.length || c == _Xaw_atowc(XawLF)
- || c == _Xaw_atowc(XawTAB))
- nchar = wspace;
- else
- nchar = (wchar_t *)block.ptr;
-
- if (focus) {
- if (XwcTextEscapement(sink->multi_sink.fontset, nchar, 1) != 0)
- XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx),
- fontset, sink->multi_sink.invgc,
- x, (y - 1 - fdiff), nchar, 1);
- else
- DisplayText(w, x, y - 1 - fheight,
- position, position + 1, True);
- }
- else
- XDrawRectangle(XtDisplay(ctx), XtWindow(ctx),
- sink->multi_sink.xorgc ?
- sink->multi_sink.xorgc : sink->multi_sink.normgc,
- x, y - 1 - fheight,
- CharWidth(sink, fontset, 0, *nchar) - 1,
- fheight - 1);
- }
- }
-
- sink->multi_sink.cursor_x = x;
- sink->multi_sink.cursor_y = y;
- sink->multi_sink.laststate = state;
- sink->multi_sink.cursor_position = position;
-}
-
-/*
- * Given two positions, find the distance between them
- */
-static void
-FindDistance(Widget w, XawTextPosition fromPos, int fromx,
- XawTextPosition toPos, int *resWidth,
- XawTextPosition *resPos, int *resHeight)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
- XFontSet fontset = sink->multi_sink.fontset;
- TextWidget ctx = (TextWidget)XtParent(w);
- Widget source = ctx->text.source;
- XawTextPosition idx, pos;
- wchar_t c;
- XFontSetExtents *ext = XExtentsOfFontSet(fontset);
- XawTextBlock blk;
- int i, rWidth;
-
- pos = XawTextSourceRead(source, fromPos, &blk, toPos - fromPos);
- rWidth = 0;
- for (i = 0, idx = fromPos; idx < toPos; i++, idx++) {
- if (i >= blk.length) {
- i = 0;
- XawTextSourceRead(source, pos, &blk, toPos - pos);
- if (blk.length == 0)
- break;
- }
- c = ((wchar_t *)blk.ptr)[i];
- rWidth += CharWidth(sink, fontset, fromx + rWidth, c);
- if (c == _Xaw_atowc(XawLF)) {
- idx++;
- break;
- }
- }
-
- *resPos = idx;
- *resWidth = rWidth;
- *resHeight = ext->max_logical_extent.height;
-}
-
-static void
-FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
- Bool stopAtWordBreak, XawTextPosition *resPos, int *resWidth,
- int *resHeight)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
- TextWidget ctx = (TextWidget)XtParent(w);
- Widget source = ctx->text.source;
- XFontSet fontset = sink->multi_sink.fontset;
- XawTextPosition idx, pos, whiteSpacePosition = 0;
- int i, lastWidth, whiteSpaceWidth, rWidth;
- Boolean whiteSpaceSeen;
- wchar_t c;
- XFontSetExtents *ext = XExtentsOfFontSet(fontset);
- XawTextBlock blk;
-
- pos = XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
- rWidth = lastWidth = whiteSpaceWidth = 0;
- whiteSpaceSeen = False;
- c = 0;
-
- for (i = 0, idx = fromPos; rWidth <= width; i++, idx++) {
- if (i >= blk.length) {
- i = 0;
- pos = XawTextSourceRead(source, pos, &blk, BUFSIZ);
- if (blk.length == 0)
- break;
- }
- c = ((wchar_t *)blk.ptr)[i];
- lastWidth = rWidth;
- rWidth += CharWidth(sink, fontset, fromx + rWidth, c);
-
- if (c == _Xaw_atowc(XawLF)) {
- idx++;
- break;
- }
- else if ((c == _Xaw_atowc(XawSP) || c == _Xaw_atowc(XawTAB))
- && rWidth <= width) {
- whiteSpaceSeen = True;
- whiteSpacePosition = idx;
- whiteSpaceWidth = rWidth;
- }
- }
-
- if (rWidth > width && idx > fromPos) {
- idx--;
- rWidth = lastWidth;
- if (stopAtWordBreak && whiteSpaceSeen) {
- idx = whiteSpacePosition + 1;
- rWidth = whiteSpaceWidth;
- }
- }
-
- if (idx >= ctx->text.lastPos && c != _Xaw_atowc(XawLF))
- idx = ctx->text.lastPos + 1;
-
- *resPos = idx;
- *resWidth = rWidth;
- *resHeight = ext->max_logical_extent.height;
-}
-
-static void
-Resolve(Widget w, XawTextPosition pos, int fromx, int width,
- XawTextPosition *pos_return)
-{
- int resWidth, resHeight;
- Widget source = XawTextGetSource(XtParent(w));
-
- FindPosition(w, pos, fromx, width, False, pos_return, &resWidth, &resHeight);
- if (*pos_return > GETLASTPOS)
- *pos_return = GETLASTPOS;
-}
-
-static void
-GetGC(MultiSinkObject sink)
-{
- XtGCMask valuemask = (GCGraphicsExposures | GCClipXOrigin |
- GCForeground | GCBackground);
- XGCValues values;
-
- /* XXX We dont want do share a gc that will change the clip-mask */
- values.clip_x_origin = (long)sink;
- values.clip_mask = None;
- values.graphics_exposures = False;
-
- values.foreground = sink->text_sink.foreground;
- values.background = sink->text_sink.background;
-
- sink->multi_sink.normgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
- GCFont | GCClipMask, 0);
-
- values.foreground = sink->text_sink.background;
-#ifndef OLDXAW
- values.background = sink->text_sink.cursor_color;
-#else
- values.background = sink->text_sink.foreground;
-#endif
- sink->multi_sink.invgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
- GCFont | GCClipMask, 0);
-#ifndef OLDXAW
- if (sink->text_sink.cursor_color != sink->text_sink.foreground) {
- values.foreground = sink->text_sink.cursor_color;
- values.background = sink->text_sink.foreground;
- sink->multi_sink.xorgc = XtAllocateGC((Widget)sink, 0, valuemask,
- &values, GCFont | GCClipMask, 0);
- }
- else
-#endif /* OLDXAW */
- sink->multi_sink.xorgc = NULL;
-
- XawMultiSinkResize((Widget)sink);
-}
-
-static void
-XawMultiSinkClassInitialize(void)
-{
- wspace[0] = _Xaw_atowc(XawSP);
- XawInitializeWidgetSet();
-}
-
-/*
- * Function:
- * XawMultiSinkInitialize
- *
- * Parameters:
- * request - requested and new values for the object instance
- * cnew - ""
- *
- * Description:
- * Initializes the TextSink Object.
- */
-/* ARGSUSED */
-static void
-XawMultiSinkInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- MultiSinkObject sink = (MultiSinkObject)cnew;
-
- GetGC(sink);
-
- if (!sink->multi_sink.fontset) XtError("Aborting: no fontset found\n");
-
- sink->multi_sink.cursor_position = 0;
- sink->multi_sink.laststate = XawisOff;
- sink->multi_sink.cursor_x = sink->multi_sink.cursor_y = 0;
-}
-
-/*
- * Function:
- * XawMultiSinkDestroy
- *
- * Parameters:
- * w - MultiSink Object
- *
- * Description:
- * This function cleans up when the object is destroyed.
- */
-static void
-XawMultiSinkDestroy(Widget w)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
-
- XtReleaseGC(w, sink->multi_sink.normgc);
- XtReleaseGC(w, sink->multi_sink.invgc);
- if (sink->multi_sink.xorgc)
- XtReleaseGC(w, sink->multi_sink.xorgc);
- sink->multi_sink.normgc =
- sink->multi_sink.invgc =
- sink->multi_sink.xorgc = NULL;
-}
-
-static void
-XawMultiSinkResize(Widget w)
-{
- TextWidget ctx = (TextWidget)XtParent(w);
- MultiSinkObject sink = (MultiSinkObject)w;
- XRectangle rect;
- int width, height;
-
- if (w->core.widget_class != multiSinkObjectClass)
- return;
-
- rect.x = ctx->text.r_margin.left;
- rect.y = ctx->text.r_margin.top;
- width = (int)XtWidth(ctx) -
- (int)ctx->text.r_margin.right - (int)ctx->text.r_margin.left;
- height = (int)XtHeight(ctx) -
- (int)ctx->text.r_margin.top - (int)ctx->text.r_margin.bottom;
- rect.width = width;
- rect.height = height;
-
- if (sink->multi_sink.normgc) {
- if (width >= 0 && height >= 0)
- XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.normgc,
- 0, 0, &rect, 1, Unsorted);
- else
- XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.normgc, None);
- }
- if (sink->multi_sink.invgc) {
- if (width >= 0 && height >= 0)
- XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.invgc,
- 0, 0, &rect, 1, Unsorted);
- else
- XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.invgc, None);
- }
- if (sink->multi_sink.xorgc) {
- if (width >= 0 && height >= 0)
- XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.xorgc,
- 0, 0, &rect, 1, Unsorted);
- else
- XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.xorgc, None);
- }
-}
-
-/*
- * Function:
- * XawMultiSinkSetValues
- *
- * Parameters:
- * current - current state of the object
- * request - what was requested
- * cnew - what the object will become
- *
- * Description:
- * Sets the values for the MultiSink.
- *
- * Returns:
- * True if redisplay is needed
- */
-/*ARGSUSED*/
-static Boolean
-XawMultiSinkSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- MultiSinkObject w = (MultiSinkObject)cnew;
- MultiSinkObject old_w = (MultiSinkObject)current;
-
- /* Font set is not in the GC! Do not make a new GC when font set changes! */
-
- if (w->multi_sink.fontset != old_w->multi_sink.fontset) {
- ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
-#ifndef NO_TAB_FIX
- SetTabs((Widget)w, w->text_sink.tab_count, w->text_sink.char_tabs);
-#endif
- }
-
- if (w->text_sink.background != old_w->text_sink.background
- || w->text_sink.foreground != old_w->text_sink.foreground
-#ifndef OLDXAW
- || w->text_sink.cursor_color != old_w->text_sink.cursor_color
-#endif
- ) {
- XtReleaseGC(cnew, w->multi_sink.normgc);
- XtReleaseGC(cnew, w->multi_sink.invgc);
- if (w->multi_sink.xorgc)
- XtReleaseGC(cnew, w->multi_sink.xorgc);
- GetGC(w);
- ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
- }
- else if (w->multi_sink.echo != old_w->multi_sink.echo
- || w->multi_sink.display_nonprinting
- != old_w->multi_sink.display_nonprinting)
- ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
-
- return (False);
-}
-
-/*
- * Function:
- * MaxLines
- *
- * Parameters:
- * w - MultiSink Object
- * height - height to fit lines into
- *
- * Description:
- * Finds the Maximum number of lines that will fit in a given height.
- *
- * Returns:
- * The number of lines that will fit
- */
-/*ARGSUSED*/
-static int
-MaxLines(Widget w, unsigned int height)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
- int font_height;
- XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
-
- font_height = ext->max_logical_extent.height;
- return (height / font_height);
-}
-
-/*
- * Function:
- * MaxHeight
- *
- * Parameters:
- * w - MultiSink Object
- * lines - number of lines
- *
- * Description:
- * Finds the Minium height that will contain a given number lines.
- * Returns:
- * The height
- */
-/*ARGSUSED*/
-static int
-MaxHeight(Widget w, int lines)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
- XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
-
- return (lines * ext->max_logical_extent.height);
-}
-
-/*
- * Function:
- * SetTabs
- *
- * Arguments:
- * w - MultiSink Object
- * tab_count - number of tabs in the list
- * tabs - text positions of the tabs
- *
- * Description:
- * Sets the Tab stops.
- */
-static void
-SetTabs(Widget w, int tab_count, short* tabs)
-{
- MultiSinkObject sink = (MultiSinkObject)w;
- int i;
- Atom XA_FIGURE_WIDTH;
- unsigned long figure_width = 0;
- XFontStruct *font;
-
- /*
- * Bug:
- * Suppose the first font of fontset stores the unit of column.
- *
- * By Li Yuhong, Mar. 14, 1991
- */
- {
- XFontStruct **f_list;
- char **f_name;
-
- (void)XFontsOfFontSet(sink->multi_sink.fontset, &f_list, &f_name);
- font = f_list[0];
- }
-
- /*
- * Find the figure width of the current font
- */
- XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", False);
- if (XA_FIGURE_WIDTH != None
- && (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)
- || figure_width == 0)) {
- if (font->per_char && font->min_char_or_byte2 <= '$'
- && font->max_char_or_byte2 >= '$')
- figure_width = font->per_char['$' - font->min_char_or_byte2].width;
- else
- figure_width = font->max_bounds.width;
- }
-
- if (tab_count > sink->text_sink.tab_count) {
- sink->text_sink.tabs = (Position *)
- XtRealloc((char *)sink->text_sink.tabs,
- (Cardinal)(tab_count * sizeof(Position)));
- sink->text_sink.char_tabs = (short *)
- XtRealloc((char *)sink->text_sink.char_tabs,
- (Cardinal)(tab_count * sizeof(short)));
- }
-
- for (i = 0 ; i < tab_count ; i++) {
- sink->text_sink.tabs[i] = tabs[i] * figure_width;
- sink->text_sink.char_tabs[i] = tabs[i];
- }
-
- sink->text_sink.tab_count = tab_count;
-
-#ifndef NO_TAB_FIX
- ((TextWidget)XtParent(w))->text.redisplay_needed = True;
-#endif
-}
-
-void
-_XawMultiSinkPosToXY(Widget w, XawTextPosition pos, Position *x, Position *y)
-{
- MultiSinkObject sink = (MultiSinkObject)((TextWidget)w)->text.sink;
- XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
-
- _XawTextPosToXY(w, pos, x, y);
- *y += abs(ext->max_logical_extent.y);
-}
+/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OMRON not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. OMRON makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Li Yuhong OMRON Corporation + */ + +/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xatom.h> +#include <X11/Xaw/XawInit.h> +#include <X11/Xaw/MultiSinkP.h> +#include <X11/Xaw/MultiSrcP.h> +#include <X11/Xaw/TextP.h> +#include "XawI18n.h" +#include <stdio.h> +#include <ctype.h> +#include "Private.h" + +#ifdef GETLASTPOS +#undef GETLASTPOS /* We will use our own GETLASTPOS */ +#endif + +#define GETLASTPOS \ + XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, True) + +/* + * Class Methods + */ +static void XawMultiSinkClassInitialize(void); +static void XawMultiSinkInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawMultiSinkDestroy(Widget); +static void XawMultiSinkResize(Widget); +static Boolean XawMultiSinkSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static int MaxLines(Widget, unsigned int); +static int MaxHeight(Widget, int); +static void SetTabs(Widget, int, short*); +static void DisplayText(Widget, int, int, + XawTextPosition, XawTextPosition, Bool); +static void InsertCursor(Widget, int, int, XawTextInsertState); +static void FindPosition(Widget, XawTextPosition, int, int, Bool, + XawTextPosition*, int*, int*); +static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*, + XawTextPosition*, int*); +static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*); +static void GetCursorBounds(Widget, XRectangle*); + +/* + * Prototypes + */ +static void GetGC(MultiSinkObject); +static int CharWidth(MultiSinkObject, XFontSet, int, wchar_t); +static unsigned int PaintText(Widget w, GC gc, int x, int y, + wchar_t *buf, int len, Bool); + +/* + * Defined in TextSink.c + */ +void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned); + +/* + * Initialization + */ +static wchar_t wspace[2]; + +#define offset(field) XtOffsetOf(MultiSinkRec, multi_sink.field) +static XtResource resources[] = { + { + XtNfontSet, + XtCFontSet, + XtRFontSet, + sizeof(XFontSet), + offset(fontset), + XtRString, + XtDefaultFontSet + }, + { + XtNecho, + XtCOutput, + XtRBoolean, + sizeof(Boolean), + offset(echo), + XtRImmediate, + (XtPointer)True + }, + { + XtNdisplayNonprinting, + XtCOutput, + XtRBoolean, + sizeof(Boolean), + offset(display_nonprinting), + XtRImmediate, + (XtPointer)True + }, +}; +#undef offset + +#define SuperClass (&textSinkClassRec) +MultiSinkClassRec multiSinkClassRec = { + /* object */ + { + (WidgetClass)SuperClass, /* superclass */ + "MultiSink", /* class_name */ + sizeof(MultiSinkRec), /* widget_size */ + XawMultiSinkClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawMultiSinkInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* obj1 */ + NULL, /* obj2 */ + 0, /* obj3 */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* obj4 */ + False, /* obj5 */ + False, /* obj6 */ + False, /* obj7 */ + XawMultiSinkDestroy, /* destroy */ + (XtProc)XawMultiSinkResize, /* obj8 */ + NULL, /* obj9 */ + XawMultiSinkSetValues, /* set_values */ + NULL, /* set_values_hook */ + NULL, /* obj10 */ + NULL, /* get_values_hook */ + NULL, /* obj11 */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* obj12 */ + NULL, /* obj13 */ + NULL, /* obj14 */ + NULL, /* extension */ + }, + /* text_sink */ + { + DisplayText, /* DisplayText */ + InsertCursor, /* InsertCursor */ + XtInheritClearToBackground, /* ClearToBackground */ + FindPosition, /* FindPosition */ + FindDistance, /* FindDistance */ + Resolve, /* Resolve */ + MaxLines, /* MaxLines */ + MaxHeight, /* MaxHeight */ + SetTabs, /* SetTabs */ + GetCursorBounds, /* GetCursorBounds */ + }, + /* multi_sink */ + { + NULL, /* extension */ + } +}; + +WidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec; + +/* + * Implementation + */ +static int +CharWidth(MultiSinkObject sink, XFontSet fontset, int x, wchar_t c) +{ + int width = 0; + + if (c == _Xaw_atowc(XawLF)) + return (0); + + if (c == _Xaw_atowc(XawTAB)) { + int i; + Position *tab; + + width = x; + /* Adjust for Left Margin. */ + x -= ((TextWidget)XtParent((Widget)sink))->text.left_margin; + + i = 0; + tab = sink->text_sink.tabs; + /*CONSTCOND*/ + while (1) { + if (x < *tab) + return (*tab - x); + /* Start again */ + if (++i >= sink->text_sink.tab_count) { + x -= *tab; + i = 0; + tab = sink->text_sink.tabs; + if (width == x) + return (0); + } + else + ++tab; + } + /*NOTREACHED*/ + } + + if (XwcTextEscapement(fontset, &c, 1) == 0) { + if (sink->multi_sink.display_nonprinting) + c = _Xaw_atowc('@'); + else + c = _Xaw_atowc(XawSP); + } + + /* + * if more efficiency(suppose one column is one ASCII char) + + width = XwcGetColumn(fontset->font_charset, fontset->num_of_fonts, c) * + fontset->font_struct_list[0]->min_bounds.width; + * + * WARNING: Very Slower!!! + * + * Li Yuhong. + */ + + width = XwcTextEscapement(fontset, &c, 1); + + return (width); +} + +/* + * Function: + * PaintText + * + * Parameters: + * w - text sink object + * gc - gc to paint text + * x - location to paint the text + * y - "" + * buf - buffer and length of text to paint + * len - "" + * clear_bg - clear background before drawing ? + * + * Description: + * Actually paints the text into the window. + * + * Returns: + * The width of the text painted + */ +static unsigned int +PaintText(Widget w, GC gc, int x, int y, wchar_t *buf, int len, Bool clear_bg) +{ + MultiSinkObject sink = (MultiSinkObject)w; + TextWidget ctx = (TextWidget)XtParent(w); + XFontSet fontset = sink->multi_sink.fontset; + unsigned int width = XwcTextEscapement(fontset, buf, len); + + if (((int)width) <= -x) /* Don't draw if we can't see it */ + return (width); + + if (clear_bg) { + XFontSetExtents *ext = XExtentsOfFontSet(fontset); + + _XawTextSinkClearToBackground(w, x, y - abs(ext->max_logical_extent.y), + width, ext->max_logical_extent.height); + XwcDrawString(XtDisplay(ctx), XtWindow(ctx), fontset, gc, x, y, buf, len); + } + else + XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx), fontset, gc, + x, y, buf, len); + + return (width); +} + +/* Sink Object Functions */ +/* + * This function does not know about drawing more than one line of text + */ +static void +DisplayText(Widget w, int x, int y, + XawTextPosition pos1, XawTextPosition pos2, Bool highlight) +{ + TextWidget ctx = (TextWidget)XtParent(w); + MultiSinkObject sink = (MultiSinkObject)w; + XFontSet fontset = sink->multi_sink.fontset; + Widget source = XawTextGetSource(XtParent(w)); + wchar_t buf[256]; + XFontSetExtents *ext = XExtentsOfFontSet(fontset); + int j, k; + XawTextBlock blk; + GC gc, invgc, tabgc; + int max_x; + Bool clear_bg; + + if (!sink->multi_sink.echo || !ctx->text.lt.lines) + return; + + max_x = (int)XtWidth(ctx) - ctx->text.r_margin.right; + clear_bg = !highlight && ctx->core.background_pixmap != XtUnspecifiedPixmap; + + gc = highlight ? sink->multi_sink.invgc : sink->multi_sink.normgc; + invgc = highlight ? sink->multi_sink.normgc : sink->multi_sink.invgc; + + if (highlight && sink->multi_sink.xorgc) + tabgc = sink->multi_sink.xorgc; + else + tabgc = invgc; + + y += abs(ext->max_logical_extent.y); + for (j = 0; pos1 < pos2;) { + pos1 = XawTextSourceRead(source, pos1, &blk, (int) pos2 - pos1); + for (k = 0; k < blk.length; k++) { + if ((unsigned) j >= (sizeof(buf) / sizeof(wchar_t)) - 1) { + /* buffer full, dump the text */ + if ((x += PaintText(w, gc, x, y, buf, j, clear_bg)) >= max_x) + return; + j = 0; + } + buf[j] = ((wchar_t *)blk.ptr)[k]; + if (buf[j] == _Xaw_atowc(XawLF)) + continue; + + else if (buf[j] == _Xaw_atowc(XawTAB)) { + unsigned int width; + + if (j != 0 && + (x += PaintText(w, gc, x, y, buf, j, clear_bg)) >= max_x) + return; + + width = CharWidth(sink, fontset, x, _Xaw_atowc(XawTAB)); + if (clear_bg) + _XawTextSinkClearToBackground(w, + x, y - abs(ext->max_logical_extent.y), + width, ext->max_logical_extent.height); + else + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + tabgc, x, + y - abs(ext->max_logical_extent.y), + width, + ext->max_logical_extent.height); + x += width; + j = -1; + } + else if (XwcTextEscapement(sink->multi_sink.fontset, &buf[j], 1) + == 0) { + if (sink->multi_sink.display_nonprinting) + buf[j] = _Xaw_atowc('@'); + else + buf[j] = _Xaw_atowc(XawSP); + } + j++; + } + } + + if (j > 0) + (void)PaintText(w, gc, x, y, buf, j, clear_bg); +} + +/* + * Function: + * GetCursorBounds + * + * Parameters: + * w - text sink object + * rect - X rectangle to return the cursor bounds + * + * Description: + * Returns the size and location of the cursor. + */ +static void +GetCursorBounds(Widget w, XRectangle *rect) +{ + MultiSinkObject sink = (MultiSinkObject)w; + + rect->width = CharWidth(sink, sink->multi_sink.fontset, 0, _Xaw_atowc(XawSP)); + rect->height = (XExtentsOfFontSet(sink->multi_sink.fontset) + ->max_logical_extent.height); + rect->x = sink->multi_sink.cursor_x; + rect->y = sink->multi_sink.cursor_y - (short)rect->height; +} + +/* + * The following procedure manages the "insert" cursor + */ +static void +InsertCursor(Widget w, int x, int y, XawTextInsertState state) +{ + MultiSinkObject sink = (MultiSinkObject)w; + XFontSet fontset = sink->multi_sink.fontset; + Widget ctx = XtParent(w); + XawTextPosition position = XawTextGetInsertionPoint(ctx); + + if (XtIsRealized(ctx)) { + int fheight, fdiff; + XawTextBlock block; + wchar_t c; + XawTextPosition selection_start, selection_end; + Boolean has_selection; + XFontSetExtents *ext = XExtentsOfFontSet(fontset); + + XawTextGetSelectionPos((Widget)ctx, &selection_start, &selection_end); + has_selection = selection_start != selection_end; + + fheight = ext->max_logical_extent.height; + fdiff = fheight - abs(ext->max_logical_extent.y); + + if ((sink->multi_sink.cursor_position != position || state == XawisOff) + && !has_selection && sink->multi_sink.laststate != XawisOff) { + wchar_t *ochar; + + (void)XawTextSourceRead(XawTextGetSource(ctx), + sink->multi_sink.cursor_position, + &block, 1); + if (!block.length) + ochar = NULL; + else { + c = ((wchar_t *)block.ptr)[0]; + if (c == _Xaw_atowc(XawLF)) + ochar = NULL; + else if (c == _Xaw_atowc(XawTAB)) + ochar = wspace; + else + ochar = (wchar_t *)block.ptr; + } + + if (!ochar) + _XawTextSinkClearToBackground(w, sink->multi_sink.cursor_x, + (sink->multi_sink.cursor_y - 1 - + fheight), CharWidth(sink, fontset, + 0, wspace[0]), + fheight); + else { + if (XwcTextEscapement(sink->multi_sink.fontset, ochar, 1) != 0) + DisplayText(w, sink->multi_sink.cursor_x, + sink->multi_sink.cursor_y - 1 - fheight, + sink->multi_sink.cursor_position, + sink->multi_sink.cursor_position + 1, + False); + else + PaintText(w, sink->multi_sink.normgc, + sink->multi_sink.cursor_x, + sink->multi_sink.cursor_y - 1 - fdiff, + ochar, 1, + ctx->core.background_pixmap != XtUnspecifiedPixmap); + } + } + + if (!has_selection && state != XawisOff) { + wchar_t *nchar; + Boolean focus = ((TextWidget)ctx)->text.hasfocus; + + (void)XawTextSourceRead(XawTextGetSource(ctx), + position, &block, 1); + c = ((wchar_t *)block.ptr)[0]; + if (!block.length || c == _Xaw_atowc(XawLF) + || c == _Xaw_atowc(XawTAB)) + nchar = wspace; + else + nchar = (wchar_t *)block.ptr; + + if (focus) { + if (XwcTextEscapement(sink->multi_sink.fontset, nchar, 1) != 0) + XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx), + fontset, sink->multi_sink.invgc, + x, (y - 1 - fdiff), nchar, 1); + else + DisplayText(w, x, y - 1 - fheight, + position, position + 1, True); + } + else + XDrawRectangle(XtDisplay(ctx), XtWindow(ctx), + sink->multi_sink.xorgc ? + sink->multi_sink.xorgc : sink->multi_sink.normgc, + x, y - 1 - fheight, + CharWidth(sink, fontset, 0, *nchar) - 1, + fheight - 1); + } + } + + sink->multi_sink.cursor_x = x; + sink->multi_sink.cursor_y = y; + sink->multi_sink.laststate = state; + sink->multi_sink.cursor_position = position; +} + +/* + * Given two positions, find the distance between them + */ +static void +FindDistance(Widget w, XawTextPosition fromPos, int fromx, + XawTextPosition toPos, int *resWidth, + XawTextPosition *resPos, int *resHeight) +{ + MultiSinkObject sink = (MultiSinkObject)w; + XFontSet fontset = sink->multi_sink.fontset; + TextWidget ctx = (TextWidget)XtParent(w); + Widget source = ctx->text.source; + XawTextPosition idx, pos; + wchar_t c; + XFontSetExtents *ext = XExtentsOfFontSet(fontset); + XawTextBlock blk; + int i, rWidth; + + pos = XawTextSourceRead(source, fromPos, &blk, toPos - fromPos); + rWidth = 0; + for (i = 0, idx = fromPos; idx < toPos; i++, idx++) { + if (i >= blk.length) { + i = 0; + XawTextSourceRead(source, pos, &blk, toPos - pos); + if (blk.length == 0) + break; + } + c = ((wchar_t *)blk.ptr)[i]; + rWidth += CharWidth(sink, fontset, fromx + rWidth, c); + if (c == _Xaw_atowc(XawLF)) { + idx++; + break; + } + } + + *resPos = idx; + *resWidth = rWidth; + *resHeight = ext->max_logical_extent.height; +} + +static void +FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width, + Bool stopAtWordBreak, XawTextPosition *resPos, int *resWidth, + int *resHeight) +{ + MultiSinkObject sink = (MultiSinkObject)w; + TextWidget ctx = (TextWidget)XtParent(w); + Widget source = ctx->text.source; + XFontSet fontset = sink->multi_sink.fontset; + XawTextPosition idx, pos, whiteSpacePosition = 0; + int i, lastWidth, whiteSpaceWidth, rWidth; + Boolean whiteSpaceSeen; + wchar_t c; + XFontSetExtents *ext = XExtentsOfFontSet(fontset); + XawTextBlock blk; + + pos = XawTextSourceRead(source, fromPos, &blk, BUFSIZ); + rWidth = lastWidth = whiteSpaceWidth = 0; + whiteSpaceSeen = False; + c = 0; + + for (i = 0, idx = fromPos; rWidth <= width; i++, idx++) { + if (i >= blk.length) { + i = 0; + pos = XawTextSourceRead(source, pos, &blk, BUFSIZ); + if (blk.length == 0) + break; + } + c = ((wchar_t *)blk.ptr)[i]; + lastWidth = rWidth; + rWidth += CharWidth(sink, fontset, fromx + rWidth, c); + + if (c == _Xaw_atowc(XawLF)) { + idx++; + break; + } + else if ((c == _Xaw_atowc(XawSP) || c == _Xaw_atowc(XawTAB)) + && rWidth <= width) { + whiteSpaceSeen = True; + whiteSpacePosition = idx; + whiteSpaceWidth = rWidth; + } + } + + if (rWidth > width && idx > fromPos) { + idx--; + rWidth = lastWidth; + if (stopAtWordBreak && whiteSpaceSeen) { + idx = whiteSpacePosition + 1; + rWidth = whiteSpaceWidth; + } + } + + if (idx >= ctx->text.lastPos && c != _Xaw_atowc(XawLF)) + idx = ctx->text.lastPos + 1; + + *resPos = idx; + *resWidth = rWidth; + *resHeight = ext->max_logical_extent.height; +} + +static void +Resolve(Widget w, XawTextPosition pos, int fromx, int width, + XawTextPosition *pos_return) +{ + int resWidth, resHeight; + Widget source = XawTextGetSource(XtParent(w)); + + FindPosition(w, pos, fromx, width, False, pos_return, &resWidth, &resHeight); + if (*pos_return > GETLASTPOS) + *pos_return = GETLASTPOS; +} + +static void +GetGC(MultiSinkObject sink) +{ + XtGCMask valuemask = (GCGraphicsExposures | GCClipXOrigin | + GCForeground | GCBackground); + XGCValues values; + + /* XXX We dont want do share a gc that will change the clip-mask */ + values.clip_x_origin = (long)sink; + values.clip_mask = None; + values.graphics_exposures = False; + + values.foreground = sink->text_sink.foreground; + values.background = sink->text_sink.background; + + sink->multi_sink.normgc = XtAllocateGC((Widget)sink, 0, valuemask, &values, + GCFont | GCClipMask, 0); + + values.foreground = sink->text_sink.background; +#ifndef OLDXAW + values.background = sink->text_sink.cursor_color; +#else + values.background = sink->text_sink.foreground; +#endif + sink->multi_sink.invgc = XtAllocateGC((Widget)sink, 0, valuemask, &values, + GCFont | GCClipMask, 0); +#ifndef OLDXAW + if (sink->text_sink.cursor_color != sink->text_sink.foreground) { + values.foreground = sink->text_sink.cursor_color; + values.background = sink->text_sink.foreground; + sink->multi_sink.xorgc = XtAllocateGC((Widget)sink, 0, valuemask, + &values, GCFont | GCClipMask, 0); + } + else +#endif /* OLDXAW */ + sink->multi_sink.xorgc = NULL; + + XawMultiSinkResize((Widget)sink); +} + +static void +XawMultiSinkClassInitialize(void) +{ + wspace[0] = _Xaw_atowc(XawSP); + XawInitializeWidgetSet(); +} + +/* + * Function: + * XawMultiSinkInitialize + * + * Parameters: + * request - requested and new values for the object instance + * cnew - "" + * + * Description: + * Initializes the TextSink Object. + */ +/* ARGSUSED */ +static void +XawMultiSinkInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + MultiSinkObject sink = (MultiSinkObject)cnew; + + GetGC(sink); + + if (!sink->multi_sink.fontset) XtError("Aborting: no fontset found\n"); + + sink->multi_sink.cursor_position = 0; + sink->multi_sink.laststate = XawisOff; + sink->multi_sink.cursor_x = sink->multi_sink.cursor_y = 0; +} + +/* + * Function: + * XawMultiSinkDestroy + * + * Parameters: + * w - MultiSink Object + * + * Description: + * This function cleans up when the object is destroyed. + */ +static void +XawMultiSinkDestroy(Widget w) +{ + MultiSinkObject sink = (MultiSinkObject)w; + + XtReleaseGC(w, sink->multi_sink.normgc); + XtReleaseGC(w, sink->multi_sink.invgc); + if (sink->multi_sink.xorgc) + XtReleaseGC(w, sink->multi_sink.xorgc); + sink->multi_sink.normgc = + sink->multi_sink.invgc = + sink->multi_sink.xorgc = NULL; +} + +static void +XawMultiSinkResize(Widget w) +{ + TextWidget ctx = (TextWidget)XtParent(w); + MultiSinkObject sink = (MultiSinkObject)w; + XRectangle rect; + int width, height; + + if (w->core.widget_class != multiSinkObjectClass) + return; + + rect.x = ctx->text.r_margin.left; + rect.y = ctx->text.r_margin.top; + width = (int)XtWidth(ctx) - + (int)ctx->text.r_margin.right - (int)ctx->text.r_margin.left; + height = (int)XtHeight(ctx) - + (int)ctx->text.r_margin.top - (int)ctx->text.r_margin.bottom; + rect.width = width; + rect.height = height; + + if (sink->multi_sink.normgc) { + if (width >= 0 && height >= 0) + XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.normgc, + 0, 0, &rect, 1, Unsorted); + else + XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.normgc, None); + } + if (sink->multi_sink.invgc) { + if (width >= 0 && height >= 0) + XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.invgc, + 0, 0, &rect, 1, Unsorted); + else + XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.invgc, None); + } + if (sink->multi_sink.xorgc) { + if (width >= 0 && height >= 0) + XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.xorgc, + 0, 0, &rect, 1, Unsorted); + else + XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.xorgc, None); + } +} + +/* + * Function: + * XawMultiSinkSetValues + * + * Parameters: + * current - current state of the object + * request - what was requested + * cnew - what the object will become + * + * Description: + * Sets the values for the MultiSink. + * + * Returns: + * True if redisplay is needed + */ +/*ARGSUSED*/ +static Boolean +XawMultiSinkSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + MultiSinkObject w = (MultiSinkObject)cnew; + MultiSinkObject old_w = (MultiSinkObject)current; + + /* Font set is not in the GC! Do not make a new GC when font set changes! */ + + if (w->multi_sink.fontset != old_w->multi_sink.fontset) { + ((TextWidget)XtParent(cnew))->text.redisplay_needed = True; +#ifndef NO_TAB_FIX + SetTabs((Widget)w, w->text_sink.tab_count, w->text_sink.char_tabs); +#endif + } + + if (w->text_sink.background != old_w->text_sink.background + || w->text_sink.foreground != old_w->text_sink.foreground +#ifndef OLDXAW + || w->text_sink.cursor_color != old_w->text_sink.cursor_color +#endif + ) { + XtReleaseGC(cnew, w->multi_sink.normgc); + XtReleaseGC(cnew, w->multi_sink.invgc); + if (w->multi_sink.xorgc) + XtReleaseGC(cnew, w->multi_sink.xorgc); + GetGC(w); + ((TextWidget)XtParent(cnew))->text.redisplay_needed = True; + } + else if (w->multi_sink.echo != old_w->multi_sink.echo + || w->multi_sink.display_nonprinting + != old_w->multi_sink.display_nonprinting) + ((TextWidget)XtParent(cnew))->text.redisplay_needed = True; + + return (False); +} + +/* + * Function: + * MaxLines + * + * Parameters: + * w - MultiSink Object + * height - height to fit lines into + * + * Description: + * Finds the Maximum number of lines that will fit in a given height. + * + * Returns: + * The number of lines that will fit + */ +/*ARGSUSED*/ +static int +MaxLines(Widget w, unsigned int height) +{ + MultiSinkObject sink = (MultiSinkObject)w; + int font_height; + XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset); + + font_height = ext->max_logical_extent.height; + return (height / font_height); +} + +/* + * Function: + * MaxHeight + * + * Parameters: + * w - MultiSink Object + * lines - number of lines + * + * Description: + * Finds the Minium height that will contain a given number lines. + * Returns: + * The height + */ +/*ARGSUSED*/ +static int +MaxHeight(Widget w, int lines) +{ + MultiSinkObject sink = (MultiSinkObject)w; + XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset); + + return (lines * ext->max_logical_extent.height); +} + +/* + * Function: + * SetTabs + * + * Arguments: + * w - MultiSink Object + * tab_count - number of tabs in the list + * tabs - text positions of the tabs + * + * Description: + * Sets the Tab stops. + */ +static void +SetTabs(Widget w, int tab_count, short* tabs) +{ + MultiSinkObject sink = (MultiSinkObject)w; + int i; + Atom XA_FIGURE_WIDTH; + unsigned long figure_width = 0; + XFontStruct *font; + + /* + * Bug: + * Suppose the first font of fontset stores the unit of column. + * + * By Li Yuhong, Mar. 14, 1991 + */ + { + XFontStruct **f_list; + char **f_name; + + (void)XFontsOfFontSet(sink->multi_sink.fontset, &f_list, &f_name); + font = f_list[0]; + } + + /* + * Find the figure width of the current font + */ + XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", False); + if (XA_FIGURE_WIDTH != None + && (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width) + || figure_width == 0)) { + if (font->per_char && font->min_char_or_byte2 <= '$' + && font->max_char_or_byte2 >= '$') + figure_width = font->per_char['$' - font->min_char_or_byte2].width; + else + figure_width = font->max_bounds.width; + } + + if (tab_count > sink->text_sink.tab_count) { + sink->text_sink.tabs = (Position *) + XtRealloc((char *)sink->text_sink.tabs, + (Cardinal)(tab_count * sizeof(Position))); + sink->text_sink.char_tabs = (short *) + XtRealloc((char *)sink->text_sink.char_tabs, + (Cardinal)(tab_count * sizeof(short))); + } + + for (i = 0 ; i < tab_count ; i++) { + sink->text_sink.tabs[i] = tabs[i] * figure_width; + sink->text_sink.char_tabs[i] = tabs[i]; + } + + sink->text_sink.tab_count = tab_count; + +#ifndef NO_TAB_FIX + ((TextWidget)XtParent(w))->text.redisplay_needed = True; +#endif +} + +void +_XawMultiSinkPosToXY(Widget w, XawTextPosition pos, Position *x, Position *y) +{ + MultiSinkObject sink = (MultiSinkObject)((TextWidget)w)->text.sink; + XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset); + + _XawTextPosToXY(w, pos, x, y); + *y += abs(ext->max_logical_extent.y); +} diff --git a/libXaw/src/MultiSrc.c b/libXaw/src/MultiSrc.c index affdd6d89..e9e4bda12 100644 --- a/libXaw/src/MultiSrc.c +++ b/libXaw/src/MultiSrc.c @@ -1,1617 +1,1617 @@ -/*
- * Copyright 1991 by OMRON Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name OMRON not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. OMRON makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
- *
- * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors: Chris Peterson MIT X Consortium
- * Li Yuhong OMRON Corporation
- * Frank Sheeran OMRON Corporation
- *
- * Much code taken from X11R3 String and Disk Sources.
- */
-
-/*
-
-Copyright 1991, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xos.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xaw/XawInit.h>
-#include <X11/Xaw/MultiSrcP.h>
-#include <X11/Xaw/XawImP.h>
-#include "XawI18n.h"
-#include "Private.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#define MAGIC_VALUE ((XawTextPosition)-1)
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
-#ifdef X_NOT_POSIX
-#define Off_t long
-#define Size_t unsigned int
-#else
-#define Off_t off_t
-#define Size_t size_t
-#endif
-
-
-/*
- * Class Methods
- */
-static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int);
-static int ReplaceText(Widget, XawTextPosition, XawTextPosition,
- XawTextBlock*);
-static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType,
- XawTextScanDirection, int, Bool);
-static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection,
- XawTextBlock*);
-static void XawMultiSrcClassInitialize(void);
-static void XawMultiSrcDestroy(Widget);
-static void XawMultiSrcInitialize(Widget, Widget, ArgList, Cardinal*);
-static Boolean XawMultiSrcSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static void XawMultiSrcGetValuesHook(Widget, ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static MultiPiece *AllocNewPiece(MultiSrcObject, MultiPiece*);
-static void BreakPiece(MultiSrcObject, MultiPiece*);
-static Boolean CvtMultiTypeToString(Display*, XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr, XtPointer*);
-static void CvtStringToMultiType(XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr);
-static MultiPiece *FindPiece(MultiSrcObject, XawTextPosition,
- XawTextPosition*);
-static void FreeAllPieces(MultiSrcObject);
-static FILE *InitStringOrFile(MultiSrcObject, Bool);
-static void LoadPieces(MultiSrcObject, FILE*, char*);
-static void RemovePiece(MultiSrcObject, MultiPiece*);
-static void RemoveOldStringOrFile(MultiSrcObject, Bool);
-static String StorePiecesInString(MultiSrcObject);
-static Bool WriteToFile(String, String);
-static void GetDefaultPieceSize(Widget, int, XrmValue*);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(MultiSrcRec, multi_src.field)
-static XtResource resources[] = {
- {
- XtNstring,
- XtCString,
- XtRString,
- sizeof(XtPointer),
- offset(string),
- XtRPointer,
- NULL
- },
- {
- XtNtype,
- XtCType,
- XtRMultiType,
- sizeof(XawAsciiType),
- offset(type),
- XtRImmediate,
- (XtPointer)XawAsciiString
- },
- {
- XtNdataCompression,
- XtCDataCompression,
- XtRBoolean,
- sizeof(Boolean),
- offset(data_compression),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNpieceSize,
- XtCPieceSize,
- XtRInt,
- sizeof(XawTextPosition),
- offset(piece_size),
- XtRCallProc,
- (XtPointer)GetDefaultPieceSize
- },
-#ifdef OLDXAW
- {
- XtNcallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(callback),
- XtRCallback,
- (XtPointer)NULL
- },
-#endif
- {
- XtNuseStringInPlace,
- XtCUseStringInPlace,
- XtRBoolean,
- sizeof(Boolean),
- offset(use_string_in_place),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNlength,
- XtCLength,
- XtRInt,
- sizeof(int),
- offset(multi_length),
- XtRImmediate,
- (XtPointer)MAGIC_VALUE
- },
-};
-#undef offset
-
-#define superclass (&textSrcClassRec)
-MultiSrcClassRec multiSrcClassRec = {
- /* object */
- {
- (WidgetClass)superclass, /* superclass */
- "MultiSrc", /* class_name */
- sizeof(MultiSrcRec), /* widget_size */
- XawMultiSrcClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawMultiSrcInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* obj1 */
- NULL, /* obj2 */
- 0, /* obj3 */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* obj4 */
- False, /* obj5 */
- False, /* obj6 */
- False, /* obj7 */
- XawMultiSrcDestroy, /* destroy */
- NULL, /* obj8 */
- NULL, /* obj9 */
- XawMultiSrcSetValues, /* set_values */
- NULL, /* set_values_hook */
- NULL, /* obj10 */
- XawMultiSrcGetValuesHook, /* get_values_hook */
- NULL, /* obj11 */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* obj12 */
- NULL, /* obj13 */
- NULL, /* obj14 */
- NULL, /* extension */
- },
- /* text_src */
- {
- ReadText, /* Read */
- ReplaceText, /* Replace */
- Scan, /* Scan */
- Search, /* Search */
- XtInheritSetSelection, /* SetSelection */
- XtInheritConvertSelection, /* ConvertSelection */
- },
- /* multi_src */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec;
-
-static XrmQuark Qstring, Qfile;
-
-/*
- * Implementation
- */
-static void
-XawMultiSrcClassInitialize(void)
-{
- XawInitializeWidgetSet();
- Qstring = XrmPermStringToQuark(XtEstring);
- Qfile = XrmPermStringToQuark(XtEfile);
- XtAddConverter(XtRString, XtRMultiType, CvtStringToMultiType, NULL, 0);
- XtSetTypeConverter(XtRMultiType, XtRString, CvtMultiTypeToString, NULL, 0,
- XtCacheNone, NULL);
-}
-
-/*
- * Function:
- * XawMultiSrcInitialize
- *
- * Parameters:
- * request - widget requested by the argument list
- * cnew - the new widget with both resource and non resource values
- * args - (unused)
- * num_args - (unused)
- *
- * Description:
- * Initializes the multi src object
- */
-/*ARGSUSED*/
-static void
-XawMultiSrcInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- MultiSrcObject src = (MultiSrcObject)cnew;
- FILE *file;
-
- /*
- * Set correct flags (override resources) depending upon widget class
- */
-#ifdef OLDXAW
- src->multi_src.changes = False;
-#else
- src->text_src.changed = False;
-#endif
- src->multi_src.allocated_string = False;
-
- if (src->multi_src.use_string_in_place && src->multi_src.string == NULL)
- src->multi_src.use_string_in_place = False;
-
- file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile);
- LoadPieces(src, file, NULL);
-
- if (file != NULL)
- fclose(file);
- src->text_src.text_format = XawFmtWide;
-}
-
-/*
- * Function:
- * ReadText
- *
- * Parameters:
- * w - MultiSource object
- * pos - position of the text to retrieve
- * text - text block that will contain returned text
- * length - maximum number of characters to read
- *
- * Description:
- * This function reads the source.
- *
- * Returns:
- * The character position following the retrieved text.
- */
-static XawTextPosition
-ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length)
-{
- MultiSrcObject src = (MultiSrcObject)w;
- XawTextPosition count, start;
- MultiPiece *piece = FindPiece(src, pos, &start);
-
- text->format = XawFmtWide;
- text->firstPos = pos;
- text->ptr = (char *)(piece->text + (pos - start));
- count = piece->used - (pos - start);
- text->length = Max(0, (length > count) ? count : length);
-
- return (pos + text->length);
-}
-
-/*
- * Function:
- * ReplaceText
- *
- * Parameters:
- * w - MultiSource object
- * startPos - ends of text that will be removed
- * endPos - ""
- * text - new text to be inserted into buffer at startPos
- *
- * Description:
- * Replaces a block of text with new text.
- *
- * Returns:
- * XawEditDone on success, XawEditError otherwise
- */
-/*ARGSUSED*/
-static int
-ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos,
- XawTextBlock *u_text_p)
-{
- MultiSrcObject src = (MultiSrcObject)w;
- MultiPiece *start_piece, *end_piece, *temp_piece;
- XawTextPosition start_first, end_first;
- int length, firstPos;
- wchar_t *wptr;
- Bool local_artificial_block = False;
- XawTextBlock text;
-
- /* STEP 1: The user handed me a text block called `u_text' that may be
- * in either FMTWIDE or FMT8BIT (ie MB.) Later code needs the block
- * `text' to hold FMTWIDE. So, this copies `u_text' to `text', and if
- * `u_text' was MB, I knock it up to WIDE
- */
- if (u_text_p->length == 0) /* if so, the block contents never ref'd */
- text.length = 0;
-
- else if (u_text_p->format == XawFmtWide) {
- local_artificial_block = False; /* don't have to free it ourselves */
- text.firstPos = u_text_p->firstPos;
- text.length = u_text_p->length;
- text.ptr = u_text_p->ptr;
- }
- else {
- /*
- * WARNING! u_text->firstPos and length are in units of CHAR,
- * not CHARACTERS!
- */
- local_artificial_block = True; /* have to free it ourselves */
- text.firstPos = 0;
- text.length = u_text_p->length; /* _XawTextMBToWC converts this
- * to wchar len
- */
-
- text.ptr = (char*)_XawTextMBToWC(XtDisplay(XtParent(w)),
- &u_text_p->ptr[u_text_p->firstPos],
- &text.length);
-
- /* I assert the following assignment is not needed - since Step 4
- depends on length, it has no need of a terminating NULL. I think
- the ASCII-version has the same needless NULL. */
- /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/
- }
-
- /* STEP 2: some initialization... */
- if (src->text_src.edit_mode == XawtextRead)
- return (XawEditError);
-
- start_piece = FindPiece(src, startPos, &start_first);
- end_piece = FindPiece(src, endPos, &end_first);
-
- /* STEP 3: remove the empty pieces... */
- if (start_piece != end_piece) {
- temp_piece = start_piece->next;
-
- /* If empty and not the only piece then remove it */
- if (((start_piece->used = startPos - start_first) == 0)
- && !(start_piece->next == NULL && start_piece->prev == NULL))
- RemovePiece(src, start_piece);
-
- while (temp_piece != end_piece) {
- temp_piece = temp_piece->next;
- RemovePiece(src, temp_piece->prev);
- }
- end_piece->used -= endPos - end_first;
- if (end_piece->used != 0)
- memmove(end_piece->text, end_piece->text + endPos - end_first,
- end_piece->used * sizeof(wchar_t));
- }
- else { /* We are fully in one piece */
- if ((start_piece->used -= endPos - startPos) == 0) {
- if (!(start_piece->next == NULL && start_piece->prev == NULL))
- RemovePiece(src, start_piece);
- }
- else {
- memmove(start_piece->text + (startPos - start_first),
- start_piece->text + (endPos - start_first),
- (start_piece->used - (startPos - start_first)) *
- sizeof(wchar_t));
- if (src->multi_src.use_string_in_place &&
- ((src->multi_src.length - (endPos - startPos))
- < src->multi_src.piece_size - 1))
- start_piece->text[src->multi_src.length - (endPos - startPos)] =
- (wchar_t)0;
- }
- }
-
- src->multi_src.length += text.length -(endPos - startPos);
-
- /* STEP 4: insert the new stuff */
- if ( text.length != 0) {
- start_piece = FindPiece(src, startPos, &start_first);
- length = text.length;
- firstPos = text.firstPos;
-
- while (length > 0) {
- wchar_t *ptr;
- int fill;
-
- if (src->multi_src.use_string_in_place) {
- if (start_piece->used == src->multi_src.piece_size - 1) {
-
- /*
- * The string is used in place, then the string
- * is not allowed to grow
- */
- start_piece->used = src->multi_src.length =
- src->multi_src.piece_size - 1;
-
- start_piece->text[src->multi_src.length] = (wchar_t)0;
- return (XawEditError);
- }
- }
-
- if (start_piece->used == src->multi_src.piece_size) {
- BreakPiece(src, start_piece);
- start_piece = FindPiece(src, startPos, &start_first);
- }
-
- fill = Min((int)(src->multi_src.piece_size - start_piece->used), length);
-
- ptr = start_piece->text + (startPos - start_first);
- memmove(ptr + fill, ptr, (start_piece->used -
- (startPos - start_first)) * sizeof(wchar_t));
- wptr =(wchar_t *)text.ptr;
- (void)wcsncpy(ptr, wptr + firstPos, fill);
-
- startPos += fill;
- firstPos += fill;
- start_piece->used += fill;
- length -= fill;
- }
- }
-
- if (local_artificial_block == True)
- /* In other words, text is not the u_text that the user handed me but
- one I made myself. I only care, because I need to free the string */
- XtFree(text.ptr);
-
- if (src->multi_src.use_string_in_place)
- start_piece->text[start_piece->used] = (wchar_t)0;
-
-#ifdef OLDXAW
- src->multi_src.changes = True;
- XtCallCallbacks(w, XtNcallback, NULL);
-#endif
-
- return (XawEditDone);
-}
-
-/*
- * Function:
- * Scan
- *
- * Parameters:
- * w - MultiSource widget
- * position - position to start scanning
- * type - type of thing to scan for
- * dir - direction to scan
- * count - which occurance if this thing to search for
- * include - whether or not to include the character found in
- * the position that is returned
- *
- * Description:
- * Scans the text source for the number and type of item specified.
- *
- * Returns:
- * The position of the item found
- *
- * Note:
- * While there are only 'n' characters in the file there are n+1
- * possible cursor positions (one before the first character and
- * one after the last character
- */
-static XawTextPosition
-Scan(Widget w, register XawTextPosition position, XawTextScanType type,
- XawTextScanDirection dir, int count, Bool include)
-{
- MultiSrcObject src = (MultiSrcObject)w;
- register char inc;
- MultiPiece *piece;
- XawTextPosition first, first_eol_position = position;
- register wchar_t *ptr;
- int cnt = count;
-
- if (type == XawstAll) {
- if (dir == XawsdRight)
- return (src->multi_src.length);
- return (0);
- }
-
- /* STEP 1: basic sanity checks */
- if (position > src->multi_src.length)
- position = src->multi_src.length;
-
- if (dir == XawsdRight) {
- if (position == src->multi_src.length)
- return (src->multi_src.length);
- inc = 1;
- }
- else {
- if (position == 0)
- return (0);
- inc = -1;
- position--;
- }
-
- piece = FindPiece(src, position, &first);
-
- if (piece->used == 0)
- return (0);
-
- ptr = (position - first) + piece->text;
-
- switch (type) {
- case XawstEOL:
- case XawstParagraph:
- case XawstWhiteSpace:
- case XawstAlphaNumeric:
- for (; cnt > 0 ; cnt--) {
- Bool non_space = False, first_eol = True;
-
- /*CONSTCOND*/
- while (True) {
- register wchar_t c;
-
- if (ptr < piece->text) {
- piece = piece->prev;
- if (piece == NULL) /* Begining of text */
- return (0);
- ptr = piece->text + piece->used - 1;
- c = *ptr;
- }
- else if (ptr >= piece->text + piece->used) {
- piece = piece->next;
- if (piece == NULL) /* End of text */
- return (src->multi_src.length);
- ptr = piece->text;
- }
-
- c = *ptr;
- ptr += inc;
- position += inc;
-
- if (type == XawstAlphaNumeric) {
- if (!iswalnum(c)) {
- if (non_space)
- break;
- }
- else
- non_space = True;
- }
- else if (type == XawstWhiteSpace) {
- if (iswspace(c)) {
- if (non_space)
- break;
- }
- else
- non_space = True;
- }
- else if (type == XawstEOL) {
- if (c == _Xaw_atowc(XawLF))
- break;
- }
- else { /* XawstParagraph */
- if (first_eol) {
- if (c == _Xaw_atowc(XawLF)) {
- first_eol_position = position;
- first_eol = False;
- }
- }
- else
- if (c == _Xaw_atowc(XawLF))
- break;
- else if (!iswspace(c))
- first_eol = True;
- }
- }
- }
- if (!include) {
- if (type == XawstParagraph)
- position = first_eol_position;
- if (count)
- position -= inc;
- }
- break;
- case XawstPositions:
- position += count * inc;
- break;
- default:
- break;
- }
-
- if (dir == XawsdLeft)
- position++;
-
- if (position >= src->multi_src.length)
- return (src->multi_src.length);
- if (position < 0)
- return (0);
-
- return (position);
-}
-
-/*
- * Function:
- * Search
- *
- * Parameters:
- * w - MultiSource objecy
- * position - position to start scanning
- * dir - direction to scan
- * text - text block to search for
- *
- * Description:
- * Searchs the text source for the text block passed.
- *
- * Returns:
- * The position of the item found
- */
-static XawTextPosition
-Search(Widget w, register XawTextPosition position, XawTextScanDirection dir,
- XawTextBlock *text)
-{
- MultiSrcObject src = (MultiSrcObject)w;
- register int count = 0;
- wchar_t *ptr;
- wchar_t *wtarget;
- int wtarget_len;
- Display *d = XtDisplay(XtParent(w));
- MultiPiece *piece;
- wchar_t *buf;
- XawTextPosition first;
- register char inc;
- int cnt;
-
- /* STEP 1: First, a brief sanity check */
- if (dir == XawsdRight)
- inc = 1;
- else {
- inc = -1;
- if (position == 0)
- return (XawTextSearchError);
- position--;
- }
-
- /* STEP 2: Ensure I have a local wide string.. */
-
- /* Since this widget stores 32bit chars, I check here to see if
- I'm being passed a string claiming to be 8bit chars (ie, MB text.)
- If that is the case, naturally I convert to 32bit format */
-
- /*if the block was FMT8BIT, length will convert to REAL wchar count bellow */
- wtarget_len = text->length;
-
- if (text->format == XawFmtWide)
- wtarget = &(((wchar_t*)text->ptr) [text->firstPos]);
- else {
- /* The following converts wtarget_len from byte len to wchar count */
- wtarget = _XawTextMBToWC(d, &text->ptr[text->firstPos], &wtarget_len);
- }
-
- /* OK, I can now assert that wtarget holds wide characters, wtarget_len
- holds an accurate count of those characters, and that firstPos has been
- effectively factored out of the following computations */
-
- /* STEP 3: SEARCH! */
- buf = (wchar_t *)XtMalloc(sizeof(wchar_t) * wtarget_len);
- (void)wcsncpy(buf, wtarget, wtarget_len);
- piece = FindPiece(src, position, &first);
- ptr = (position - first) + piece->text;
-
- /*CONSTCOND*/
- while (True) {
- if (*ptr == (dir == XawsdRight ? *(buf + count)
- : *(buf + wtarget_len - count - 1))) {
- if (count == text->length - 1)
- break;
- else
- count++;
- }
- else {
- if (count != 0) {
- position -=inc * count;
- ptr -= inc * count;
- }
- count = 0;
- }
-
- ptr += inc;
- position += inc;
-
- while (ptr < piece->text) {
- cnt = piece->text - ptr;
-
- piece = piece->prev;
- if (piece == NULL) { /* Begining of text */
- XtFree((char *)buf);
- return (XawTextSearchError);
- }
- ptr = piece->text + piece->used - cnt;
- }
-
- while (ptr >= piece->text + piece->used) {
- cnt = ptr - (piece->text + piece->used);
-
- piece = piece->next;
- if (piece == NULL) { /* End of text */
- XtFree((char *)buf);
- return (XawTextSearchError);
- }
- ptr = piece->text + cnt;
- }
- }
-
- XtFree((char *)buf);
- if (dir == XawsdLeft)
- return(position);
-
- return(position - (wtarget_len - 1));
-}
-
-/*
- * Function:
- * XawMultiSrcSetValues
- *
- * Parameters:
- * current - current state of the widget
- * request - what was requested
- * cnew - what the widget will become
- * args - representation of resources that have changed
- * num_args - number of changed resources
- *
- * Description:
- * Sets the values for the MultiSource.
- *
- * Returns:
- * True if redisplay is needed
- */
-static Boolean
-XawMultiSrcSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- MultiSrcObject src = (MultiSrcObject)cnew;
- MultiSrcObject old_src = (MultiSrcObject)current;
- XtAppContext app_con = XtWidgetToApplicationContext(cnew);
- Bool total_reset = False, string_set = False;
- FILE *file;
- unsigned int i;
-
- if (old_src->multi_src.use_string_in_place
- != src->multi_src.use_string_in_place) {
- XtAppWarning(app_con,
- "MultiSrc: The XtNuseStringInPlace resources "
- "may not be changed.");
- src->multi_src.use_string_in_place =
- old_src->multi_src.use_string_in_place;
- }
-
- for (i = 0; i < *num_args ; i++)
- if (streq(args[i].name, XtNstring)) {
- string_set = True;
- break;
- }
-
- if (string_set || old_src->multi_src.type != src->multi_src.type) {
- RemoveOldStringOrFile(old_src, string_set);
- src->multi_src.allocated_string = old_src->multi_src.allocated_string;
- file = InitStringOrFile(src, string_set);
-
- LoadPieces(src, file, NULL);
- if (file != NULL)
- fclose(file);
-#ifndef OLDXAW
- for (i = 0; i < src->text_src.num_text; i++)
- /* Tell text widget what happened */
- XawTextSetSource(src->text_src.text[i], cnew, 0);
-#else
- XawTextSetSource(XtParent(cnew), cnew, 0);
-#endif
- total_reset = True;
- }
-
- if (old_src->multi_src.multi_length != src->multi_src.multi_length)
- src->multi_src.piece_size = src->multi_src.multi_length + 1;
-
- if ( !total_reset && old_src->multi_src.piece_size
- != src->multi_src.piece_size) {
- String mb_string = StorePiecesInString(old_src);
-
- if (mb_string != 0) {
- FreeAllPieces(old_src);
- LoadPieces(src, NULL, mb_string);
- XtFree(mb_string);
- }
- else {
- /* If the buffer holds bad chars, don't touch it... */
- XtAppWarningMsg(app_con,
- "convertError", "multiSource", "XawError",
- XtName(XtParent((Widget)old_src)), NULL, NULL);
- XtAppWarningMsg(app_con,
- "convertError", "multiSource", "XawError",
- "Non-character code(s) in buffer.", NULL, NULL);
- }
- }
-
- return (False);
-}
-
-static void
-XawMultiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
-{
- MultiSrcObject src = (MultiSrcObject)w;
- unsigned int i;
-
- if (src->multi_src.type == XawAsciiString) {
- for (i = 0; i < *num_args ; i++) {
- if (streq(args[i].name, XtNstring)) {
- if (src->multi_src.use_string_in_place)
- *((char **)args[i].value) = (char *)
- src->multi_src.first_piece->text;
- else if (_XawMultiSave(w)) /* If save sucessful */
- *((char **)args[i].value) = (char *)src->multi_src.string;
- break;
- }
- }
- }
-}
-
-static void
-XawMultiSrcDestroy(Widget w)
-{
- RemoveOldStringOrFile((MultiSrcObject) w, True);
-}
-
-/*
- * Public routines
- */
-/*
- * Function:
- * XawMultiSourceFreeString
- *
- * Parameters:
- * w - MultiSrc widget
- *
- * Description:
- * Frees the string returned by a get values call
- * on the string when the source is of type string.
- *
- * Note:
- * The public interface is XawAsciiSourceFreeString!
- */
-void
-_XawMultiSourceFreeString(Widget w)
-{
- MultiSrcObject src = (MultiSrcObject)w;
-
- if (src->multi_src.allocated_string) {
- XtFree((char *)src->multi_src.string);
- src->multi_src.allocated_string = False;
- src->multi_src.string = NULL;
- }
-}
-
-/*
- * Function:
- * _XawMultiSave
- *
- * Parameters:
- * w - multiSrc Widget
- *
- * Description:
- * Saves all the pieces into a file or string as required.
- *
- * Returns:
- * True if the save was successful
- *
- * Note:
- * The public interface is XawAsciiSave(w)!
- */
-Bool
-_XawMultiSave(Widget w)
-{
- MultiSrcObject src = (MultiSrcObject)w;
- XtAppContext app_con = XtWidgetToApplicationContext(w);
- char *mb_string;
-
- /*
- * If using the string in place then there is no need to play games
- * to get the internal info into a readable string
- */
- if (src->multi_src.use_string_in_place)
- return (True);
-
- if (src->multi_src.type == XawAsciiFile) {
-#ifdef OLDXAW
- if (!src->multi_src.changes)
-#else
- if (!src->text_src.changed) /* No changes to save */
-#endif
- return (True);
-
- mb_string = StorePiecesInString(src);
-
- if (mb_string != 0) {
- if (WriteToFile(mb_string, (String)src->multi_src.string) == False) {
- XtFree(mb_string);
- return (False);
- }
- XtFree(mb_string);
-#ifndef OLDXAW
- src->text_src.changed = False;
-#else
- src->multi_src.changes = False;
-#endif
- return (True);
- }
- else {
- /* If the buffer holds bad chars, don't touch it... */
- XtAppWarningMsg(app_con,
- "convertError", "multiSource", "XawError",
- "Due to illegal characters, file not saved.",
- NULL, NULL);
- return (False);
- }
- }
- else {
- /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED? The manual
- says this routine's only function is to save files to
- disk. -Sheeran */
- mb_string = StorePiecesInString(src);
-
- if (mb_string == 0) {
- /* If the buffer holds bad chars, don't touch it... */
- XtAppWarningMsg(app_con,
- "convertError", "multiSource", "XawError",
- XtName(XtParent((Widget)src)), NULL, NULL);
- return (False);
- }
-
- /* assert: mb_string holds good characters so the buffer is fine */
- if (src->multi_src.allocated_string == True)
- XtFree((char *)src->multi_src.string);
- else
- src->multi_src.allocated_string = True;
-
- src->multi_src.string = mb_string;
- }
-#ifdef OLDXAW
- src->multi_src.changes = False;
-#else
- src->text_src.changed = False;
-#endif
-
- return (True);
-}
-
-/*
- * Function:
- * XawMultiSaveAsFile
- *
- * Parameters:
- * w - MultiSrc widget
- * name - name of the file to save this file into
- *
- * Description:
- * Save the current buffer as a file.
- *
- * Returns:
- * True if the save was sucessful
- *
- * Note:
- * The public interface is XawAsciiSaveAsFile!
- */
-Bool
-_XawMultiSaveAsFile(Widget w, _Xconst char* name)
-{
- MultiSrcObject src = (MultiSrcObject)w;
- String mb_string;
- Bool ret;
-
- mb_string = StorePiecesInString(src);
-
- if (mb_string != 0) {
- ret = WriteToFile(mb_string, (char *)name);
- XtFree(mb_string);
-
- return (ret);
- }
-
- /* otherwise there was a conversion error. So print widget name too */
- XtAppWarningMsg(XtWidgetToApplicationContext(w),
- "convertError", "multiSource", "XawError",
- XtName(XtParent(w)), NULL, NULL);
-
- return (False);
-}
-
-/*
- * Private Functions
- */
-static void
-RemoveOldStringOrFile(MultiSrcObject src, Bool checkString)
-{
- FreeAllPieces(src);
-
- if (checkString && src->multi_src.allocated_string) {
- XtFree((char *)src->multi_src.string);
- src->multi_src.allocated_string = False;
- src->multi_src.string = NULL;
- }
-}
-
-/*
- * Function:
- * WriteToFile
- *
- * Parameters:
- * string - string to write
- * name - name of the file
- *
- * Description:
- * Write the string specified to the begining of the file specified.
- *
- * Returns:
- * Returns True if sucessful, False otherwise
- */
-static Bool
-WriteToFile(String string, String name)
-{
- int fd;
-
- if (((fd = creat(name, 0666)) == -1)
- || (write(fd, string, strlen(string)) == -1))
- return (False);
-
- if (close(fd) == -1)
- return (False);
-
- return (True);
-}
-
-
-/*
- * Function:
- * StorePiecesInString
- *
- * Parameters:
- * src - the multiSrc object to gather data from
- *
- * Description:
- * Store the pieces in memory into a char string.
- *
- * Returns:
- * mb_string: Caller must free
- * (or)
- * NULL: conversion error
- */
-static String
-StorePiecesInString(MultiSrcObject src)
-{
- wchar_t *wc_string;
- char *mb_string;
- int char_count = src->multi_src.length;
- XawTextPosition first;
- MultiPiece *piece;
-
- /* I believe the char_count + 1 and the NULL termination are unneeded! FS */
- wc_string = (wchar_t*)XtMalloc((char_count + 1) * sizeof(wchar_t));
-
- for (first = 0, piece = src->multi_src.first_piece ; piece != NULL;
- first += piece->used, piece = piece->next)
- (void)wcsncpy(wc_string + first, piece->text, piece->used);
-
- wc_string[char_count] = 0;
-
- /* This will refill all pieces to capacity */
- if (src->multi_src.data_compression) {
- FreeAllPieces(src);
- LoadPieces(src, NULL, (char *)wc_string);
- }
-
- /* Lastly, convert it to a MB format and send it back */
- mb_string = _XawTextWCToMB(XtDisplayOfObject((Widget)src),
- wc_string, &char_count);
-
- /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED */
- XtFree((char*)wc_string);
-
- return (mb_string);
-}
-
-/*
- * Function:
- * InitStringOrFile
- *
- * Parameters:
- * src - MultiSource
- *
- * Description:
- * Initializes the string or file.
- */
-static FILE *
-InitStringOrFile(MultiSrcObject src, Bool newString)
-{
- mode_t open_mode = 0;
- const char *fdopen_mode = NULL;
- int fd;
- FILE *file;
- Display *d = XtDisplayOfObject((Widget)src);
-
- if (src->multi_src.type == XawAsciiString) {
- if (src->multi_src.string == NULL)
- src->multi_src.length = 0;
-
- else if (!src->multi_src.use_string_in_place) {
- int length;
- String temp = XtNewString((char *)src->multi_src.string);
-
- if (src->multi_src.allocated_string)
- XtFree((char *)src->multi_src.string);
- src->multi_src.allocated_string = True;
- src->multi_src.string = temp;
-
- length = strlen((char *)src->multi_src.string);
-
- /* Wasteful, throwing away the WC string, but need side effect! */
- (void)_XawTextMBToWC(d, (char *)src->multi_src.string, &length);
- src->multi_src.length = (XawTextPosition)length;
- }
- else {
- src->multi_src.length = strlen((char *)src->multi_src.string);
- /* In case the length resource is incorrectly set */
- if (src->multi_src.length > src->multi_src.multi_length)
- src->multi_src.multi_length = src->multi_src.length;
-
- if (src->multi_src.multi_length == MAGIC_VALUE)
- src->multi_src.piece_size = src->multi_src.length;
- else
- src->multi_src.piece_size = src->multi_src.multi_length + 1;
- }
-
- return (NULL);
- }
-
- /*
- * type is XawAsciiFile
- */
- src->multi_src.is_tempfile = False;
-
- switch (src->text_src.edit_mode) {
- case XawtextRead:
- if (src->multi_src.string == NULL)
- XtErrorMsg("NoFile", "multiSourceCreate", "XawError",
- "Creating a read only disk widget and no file specified.",
- NULL, 0);
- open_mode = O_RDONLY;
- fdopen_mode = "r";
- break;
- case XawtextAppend:
- case XawtextEdit:
- if (src->multi_src.string == NULL) {
- src->multi_src.string = "*multi-src*";
- src->multi_src.is_tempfile = True;
- }
- else {
-/* O_NOFOLLOW is a BSD & Linux extension */
-#ifdef O_NOFOLLOW
- open_mode = O_RDWR | O_NOFOLLOW;
-#else
- open_mode = O_RDWR; /* unsafe; subject to race conditions */
-#endif
- fdopen_mode = "r+";
- }
- break;
- default:
- XtErrorMsg("badMode", "multiSourceCreate", "XawError",
- "Bad editMode for multi source; must be "
- "Read, Append or Edit.", NULL, NULL);
- }
-
- /* If is_tempfile, allocate a private copy of the text
- * Unlikely to be changed, just to set allocated_string */
- if (newString || src->multi_src.is_tempfile) {
- String temp = XtNewString((char *)src->multi_src.string);
-
- if (src->multi_src.allocated_string)
- XtFree((char *)src->multi_src.string);
- src->multi_src.string = temp;
- src->multi_src.allocated_string = True;
- }
-
- if (!src->multi_src.is_tempfile) {
- if ((fd = open((char *)src->multi_src.string, open_mode, 0666)) != -1) {
- if ((file = fdopen(fd, fdopen_mode)) != NULL) {
- (void)fseek(file, 0, SEEK_END);
- src->multi_src.length = (XawTextPosition)ftell(file);
- return(file);
- }
- }
- {
- String params[2];
- Cardinal num_params = 2;
-
- params[0] = (String)src->multi_src.string;
- params[1] = strerror(errno);
- XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
- "openError", "multiSourceCreate", "XawWarning",
- "Cannot open file %s; %s", params, &num_params);
- }
- }
- src->multi_src.length = 0;
- return (NULL);
-}
-
-/* LoadPieces: This routine takes either the MB contents of open file
- `file' or the MB contents of string or the MB contents of
- src->multi_src.string and places them in Pieces in WC format.
-
- CAUTION: You must have src->multi_src.length set to file length bytes
- when src->multi_src.type == XawAsciiFile. src->multi_src.length must be
- the length of the parameter string if string is non-NULL
-*/
-static void
-LoadPieces(MultiSrcObject src, FILE *file, char *string)
-{
- Display *d = XtDisplayOfObject((Widget)src);
- wchar_t* local_str, *ptr;
- MultiPiece* piece = NULL;
- XawTextPosition left;
- int bytes = sizeof(wchar_t);
- char* temp_mb_holder = NULL;
-
- /*
- * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg
- * in as MB length, out as WC length. We want local_length to be
- * WC count.
- */
- int local_length = src->multi_src.length;
-
- if (string != NULL) {
- /*
- * ASSERT: IF our caller passed a non-null string, THEN
- * src->multi_src.length is currently string's * byte count,
- * AND string is in a MB format
- */
- local_str = _XawTextMBToWC(d, (char *)string, &local_length);
- src->multi_src.length = (XawTextPosition) local_length;
- }
- else if (src->multi_src.type != XawAsciiFile) {
- /*
- * here, we are not changing the contents, just reloading,
- * so don't change len...
- */
- local_length = src->multi_src.string ?
- strlen((char *)src->multi_src.string) : 0;
- local_str = _XawTextMBToWC(d, (char *)src->multi_src.string,
- &local_length);
- }
- else {
- if (src->multi_src.length != 0) {
- temp_mb_holder =
- XtMalloc((src->multi_src.length + 1) * sizeof(unsigned char));
- fseek(file, 0, 0);
- src->multi_src.length = fread(temp_mb_holder,
- (Size_t)sizeof(unsigned char),
- (Size_t)src->multi_src.length, file);
- if (src->multi_src.length <= 0)
- XtAppErrorMsg(XtWidgetToApplicationContext ((Widget) src),
- "readError", "multiSource", "XawError",
- "fread returned error.", NULL, NULL);
- local_length = src->multi_src.length;
- local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length);
- src->multi_src.length = local_length;
-
- if (local_str == 0) {
- String params[2];
- Cardinal num_params;
- static char err_text[] =
- "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>";
-
- params[0] = XtName(XtParent((Widget)src));
- params[1] = src->multi_src.string;
- num_params = 2;
-
- XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
- "readLocaleError", "multiSource", "XawError",
- "%s: The file `%s' contains characters "
- "not representable in this locale.",
- params, &num_params);
- src->multi_src.length = sizeof err_text;
- local_length = src->multi_src.length;
- local_str = _XawTextMBToWC(d, err_text, &local_length);
- src->multi_src.length = local_length;
- }
- }
- else
- /* ASSERT that since following while loop looks at local_length
- this isn't needed. Sheeran, Omron KK, 1993/07/15
- temp_mb_holder[src->multi_src.length] = '\0'; */
- local_str = (wchar_t*)temp_mb_holder;
- }
-
- if (src->multi_src.use_string_in_place) {
- piece = AllocNewPiece(src, piece);
- piece->used = Min(src->multi_src.length, src->multi_src.piece_size);
- piece->text = (wchar_t*)src->multi_src.string;
- return;
- }
-
- ptr = local_str;
- left = local_length;
-
- do {
- piece = AllocNewPiece(src, piece);
-
- piece->text = (wchar_t*)XtMalloc((unsigned)(src->multi_src.piece_size
- * bytes));
- piece->used = Min(left, src->multi_src.piece_size);
- if (piece->used != 0)
- (void)wcsncpy(piece->text, ptr, piece->used);
-
- left -= piece->used;
- ptr += piece->used;
- } while (left > 0);
-
- if (temp_mb_holder)
- XtFree((char*)temp_mb_holder);
-}
-
-/*
- * Function:
- * AllocNewPiece
- *
- * Parameters:
- * src - MultiSrc Widget
- * prev - the piece just before this one, or NULL
- *
- * Description:
- * Allocates a new piece of memory.
- *
- * Returns:
- * The allocated piece
- */
-static MultiPiece *
-AllocNewPiece(MultiSrcObject src, MultiPiece *prev)
-{
- MultiPiece *piece = XtNew(MultiPiece);
-
- if (prev == NULL) {
- src->multi_src.first_piece = piece;
- piece->next = NULL;
- }
- else {
- if (prev->next != NULL)
- (prev->next)->prev = piece;
- piece->next = prev->next;
- prev->next = piece;
- }
-
- piece->prev = prev;
-
- return (piece);
-}
-
-/*
- * Function:
- * FreeAllPieces
- *
- * Parameters:
- * src - MultiSrc Widget
- *
- * Description:
- * Frees all the pieces
- */
-static void
-FreeAllPieces(MultiSrcObject src)
-{
- MultiPiece *next, *first = src->multi_src.first_piece;
-
-#ifdef DEBUG
- if (first->prev != NULL)
- printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n");
-#endif
-
- for (; first != NULL ; first = next) {
- next = first->next;
- RemovePiece(src, first);
- }
-}
-
-/*
- * Function:
- * RemovePiece
- *
- * Parameters:
- * piece - piece to remove
- *
- * Description:
- * Removes a piece from the list.
- */
-static void
-RemovePiece(MultiSrcObject src, MultiPiece *piece)
-{
- if (piece->prev == NULL)
- src->multi_src.first_piece = piece->next;
- else
- piece->prev->next = piece->next;
-
- if (piece->next != NULL)
- piece->next->prev = piece->prev;
-
- if (!src->multi_src.use_string_in_place)
- XtFree((char *)piece->text);
-
- XtFree((char *)piece);
-}
-
-/*
- * Function:
- * FindPiece
- *
- * Parameters:
- * src - MultiSrc Widget
- * position - position that we are searching for
- * first - position of the first character in this piece (return)
- *
- * Description:
- * Finds the piece containing the position indicated.
- *
- * Returns:
- * Piece that contains this position
- */
-static MultiPiece *
-FindPiece(MultiSrcObject src, XawTextPosition position, XawTextPosition *first)
-{
- MultiPiece *old_piece, *piece;
- XawTextPosition temp;
-
- for (old_piece = NULL, piece = src->multi_src.first_piece, temp = 0;
- piece; old_piece = piece, piece = piece->next)
- if ((temp += piece->used) > position) {
- *first = temp - piece->used;
- return (piece);
- }
-
- *first = temp - (old_piece ? old_piece->used : 0);
-
- return (old_piece); /* if we run off the end the return the last piece */
-}
-
-/*
- * Function:
- * BreakPiece
- *
- * Parameters:
- * src - MultiSrc Widget
- * piece - piece to break
- *
- * Description:
- * Breaks a full piece into two new pieces.
- */
-#define HALF_PIECE (src->multi_src.piece_size >> 1)
-static void
-BreakPiece(MultiSrcObject src, MultiPiece *piece)
-{
- MultiPiece *cnew = AllocNewPiece(src, piece);
-
- cnew->text = (wchar_t *)
- XtMalloc(src->multi_src.piece_size * sizeof(wchar_t));
- (void)wcsncpy(cnew->text, piece->text + HALF_PIECE,
- src->multi_src.piece_size - HALF_PIECE);
- piece->used = HALF_PIECE;
- cnew->used = src->multi_src.piece_size - HALF_PIECE;
-}
-
-/*ARGSUSED*/
-static void
-CvtStringToMultiType(XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal)
-{
- static XawAsciiType type = XawAsciiString;
- XrmQuark q;
- char name[7];
-
- XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
- q = XrmStringToQuark(name);
-
- if (q == Qstring)
- type = XawAsciiString;
- if (q == Qfile)
- type = XawAsciiFile;
- else {
- toVal->size = 0;
- toVal->addr = NULL;
- XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType);
- }
-
- toVal->size = sizeof(XawAsciiType);
- toVal->addr = (XPointer)&type;
-}
-
-/*ARGSUSED*/
-static Boolean
-CvtMultiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal,
- XtPointer *data)
-{
- static String buffer;
- Cardinal size;
-
- switch (*(XawAsciiType *)fromVal->addr) {
- case XawAsciiFile:
- buffer = XtEfile;
- break;
- case XawAsciiString:
- buffer = XtEstring;
- break;
- default:
- XawTypeToStringWarning(dpy, XtRAsciiType);
- toVal->addr = NULL;
- toVal->size = 0;
- return (False);
- }
-
- size = strlen(buffer) + 1;
- if (toVal->addr != NULL) {
- if (toVal->size < size) {
- toVal->size = size;
- return (False);
- }
- strcpy((char *)toVal->addr, buffer);
- }
- else
- toVal->addr = (XPointer)buffer;
- toVal->size = sizeof(String);
-
- return (True);
-}
-
-/*ARGSUSED*/
-static void
-GetDefaultPieceSize(Widget w, int offset, XrmValue *value)
-{
- static XPointer pagesize;
-
- if (pagesize == 0) {
- pagesize = (XPointer)((long)_XawGetPageSize());
- if (pagesize < (XPointer)BUFSIZ)
- pagesize = (XPointer)BUFSIZ;
- }
-
- value->addr = (XPointer)&pagesize;
-}
+/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name OMRON not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OMRON makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Chris Peterson MIT X Consortium + * Li Yuhong OMRON Corporation + * Frank Sheeran OMRON Corporation + * + * Much code taken from X11R3 String and Disk Sources. + */ + +/* + +Copyright 1991, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xfuncs.h> +#include <X11/Xos.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw/XawInit.h> +#include <X11/Xaw/MultiSrcP.h> +#include <X11/Xaw/XawImP.h> +#include "XawI18n.h" +#include "Private.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define MAGIC_VALUE ((XawTextPosition)-1) +#define streq(a, b) (strcmp((a), (b)) == 0) + +#ifdef X_NOT_POSIX +#define Off_t long +#define Size_t unsigned int +#else +#define Off_t off_t +#define Size_t size_t +#endif + + +/* + * Class Methods + */ +static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int); +static int ReplaceText(Widget, XawTextPosition, XawTextPosition, + XawTextBlock*); +static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, + XawTextScanDirection, int, Bool); +static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, + XawTextBlock*); +static void XawMultiSrcClassInitialize(void); +static void XawMultiSrcDestroy(Widget); +static void XawMultiSrcInitialize(Widget, Widget, ArgList, Cardinal*); +static Boolean XawMultiSrcSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static void XawMultiSrcGetValuesHook(Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +static MultiPiece *AllocNewPiece(MultiSrcObject, MultiPiece*); +static void BreakPiece(MultiSrcObject, MultiPiece*); +static Boolean CvtMultiTypeToString(Display*, XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr, XtPointer*); +static void CvtStringToMultiType(XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr); +static MultiPiece *FindPiece(MultiSrcObject, XawTextPosition, + XawTextPosition*); +static void FreeAllPieces(MultiSrcObject); +static FILE *InitStringOrFile(MultiSrcObject, Bool); +static void LoadPieces(MultiSrcObject, FILE*, char*); +static void RemovePiece(MultiSrcObject, MultiPiece*); +static void RemoveOldStringOrFile(MultiSrcObject, Bool); +static String StorePiecesInString(MultiSrcObject); +static Bool WriteToFile(String, String); +static void GetDefaultPieceSize(Widget, int, XrmValue*); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(MultiSrcRec, multi_src.field) +static XtResource resources[] = { + { + XtNstring, + XtCString, + XtRString, + sizeof(XtPointer), + offset(string), + XtRPointer, + NULL + }, + { + XtNtype, + XtCType, + XtRMultiType, + sizeof(XawAsciiType), + offset(type), + XtRImmediate, + (XtPointer)XawAsciiString + }, + { + XtNdataCompression, + XtCDataCompression, + XtRBoolean, + sizeof(Boolean), + offset(data_compression), + XtRImmediate, + (XtPointer)False + }, + { + XtNpieceSize, + XtCPieceSize, + XtRInt, + sizeof(XawTextPosition), + offset(piece_size), + XtRCallProc, + (XtPointer)GetDefaultPieceSize + }, +#ifdef OLDXAW + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(callback), + XtRCallback, + (XtPointer)NULL + }, +#endif + { + XtNuseStringInPlace, + XtCUseStringInPlace, + XtRBoolean, + sizeof(Boolean), + offset(use_string_in_place), + XtRImmediate, + (XtPointer)False + }, + { + XtNlength, + XtCLength, + XtRInt, + sizeof(int), + offset(multi_length), + XtRImmediate, + (XtPointer)MAGIC_VALUE + }, +}; +#undef offset + +#define superclass (&textSrcClassRec) +MultiSrcClassRec multiSrcClassRec = { + /* object */ + { + (WidgetClass)superclass, /* superclass */ + "MultiSrc", /* class_name */ + sizeof(MultiSrcRec), /* widget_size */ + XawMultiSrcClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawMultiSrcInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* obj1 */ + NULL, /* obj2 */ + 0, /* obj3 */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* obj4 */ + False, /* obj5 */ + False, /* obj6 */ + False, /* obj7 */ + XawMultiSrcDestroy, /* destroy */ + NULL, /* obj8 */ + NULL, /* obj9 */ + XawMultiSrcSetValues, /* set_values */ + NULL, /* set_values_hook */ + NULL, /* obj10 */ + XawMultiSrcGetValuesHook, /* get_values_hook */ + NULL, /* obj11 */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* obj12 */ + NULL, /* obj13 */ + NULL, /* obj14 */ + NULL, /* extension */ + }, + /* text_src */ + { + ReadText, /* Read */ + ReplaceText, /* Replace */ + Scan, /* Scan */ + Search, /* Search */ + XtInheritSetSelection, /* SetSelection */ + XtInheritConvertSelection, /* ConvertSelection */ + }, + /* multi_src */ + { + NULL, /* extension */ + }, +}; + +WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec; + +static XrmQuark Qstring, Qfile; + +/* + * Implementation + */ +static void +XawMultiSrcClassInitialize(void) +{ + XawInitializeWidgetSet(); + Qstring = XrmPermStringToQuark(XtEstring); + Qfile = XrmPermStringToQuark(XtEfile); + XtAddConverter(XtRString, XtRMultiType, CvtStringToMultiType, NULL, 0); + XtSetTypeConverter(XtRMultiType, XtRString, CvtMultiTypeToString, NULL, 0, + XtCacheNone, NULL); +} + +/* + * Function: + * XawMultiSrcInitialize + * + * Parameters: + * request - widget requested by the argument list + * cnew - the new widget with both resource and non resource values + * args - (unused) + * num_args - (unused) + * + * Description: + * Initializes the multi src object + */ +/*ARGSUSED*/ +static void +XawMultiSrcInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + MultiSrcObject src = (MultiSrcObject)cnew; + FILE *file; + + /* + * Set correct flags (override resources) depending upon widget class + */ +#ifdef OLDXAW + src->multi_src.changes = False; +#else + src->text_src.changed = False; +#endif + src->multi_src.allocated_string = False; + + if (src->multi_src.use_string_in_place && src->multi_src.string == NULL) + src->multi_src.use_string_in_place = False; + + file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile); + LoadPieces(src, file, NULL); + + if (file != NULL) + fclose(file); + src->text_src.text_format = XawFmtWide; +} + +/* + * Function: + * ReadText + * + * Parameters: + * w - MultiSource object + * pos - position of the text to retrieve + * text - text block that will contain returned text + * length - maximum number of characters to read + * + * Description: + * This function reads the source. + * + * Returns: + * The character position following the retrieved text. + */ +static XawTextPosition +ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length) +{ + MultiSrcObject src = (MultiSrcObject)w; + XawTextPosition count, start; + MultiPiece *piece = FindPiece(src, pos, &start); + + text->format = XawFmtWide; + text->firstPos = pos; + text->ptr = (char *)(piece->text + (pos - start)); + count = piece->used - (pos - start); + text->length = Max(0, (length > count) ? count : length); + + return (pos + text->length); +} + +/* + * Function: + * ReplaceText + * + * Parameters: + * w - MultiSource object + * startPos - ends of text that will be removed + * endPos - "" + * text - new text to be inserted into buffer at startPos + * + * Description: + * Replaces a block of text with new text. + * + * Returns: + * XawEditDone on success, XawEditError otherwise + */ +/*ARGSUSED*/ +static int +ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos, + XawTextBlock *u_text_p) +{ + MultiSrcObject src = (MultiSrcObject)w; + MultiPiece *start_piece, *end_piece, *temp_piece; + XawTextPosition start_first, end_first; + int length, firstPos; + wchar_t *wptr; + Bool local_artificial_block = False; + XawTextBlock text; + + /* STEP 1: The user handed me a text block called `u_text' that may be + * in either FMTWIDE or FMT8BIT (ie MB.) Later code needs the block + * `text' to hold FMTWIDE. So, this copies `u_text' to `text', and if + * `u_text' was MB, I knock it up to WIDE + */ + if (u_text_p->length == 0) /* if so, the block contents never ref'd */ + text.length = 0; + + else if (u_text_p->format == XawFmtWide) { + local_artificial_block = False; /* don't have to free it ourselves */ + text.firstPos = u_text_p->firstPos; + text.length = u_text_p->length; + text.ptr = u_text_p->ptr; + } + else { + /* + * WARNING! u_text->firstPos and length are in units of CHAR, + * not CHARACTERS! + */ + local_artificial_block = True; /* have to free it ourselves */ + text.firstPos = 0; + text.length = u_text_p->length; /* _XawTextMBToWC converts this + * to wchar len + */ + + text.ptr = (char*)_XawTextMBToWC(XtDisplay(XtParent(w)), + &u_text_p->ptr[u_text_p->firstPos], + &text.length); + + /* I assert the following assignment is not needed - since Step 4 + depends on length, it has no need of a terminating NULL. I think + the ASCII-version has the same needless NULL. */ + /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/ + } + + /* STEP 2: some initialization... */ + if (src->text_src.edit_mode == XawtextRead) + return (XawEditError); + + start_piece = FindPiece(src, startPos, &start_first); + end_piece = FindPiece(src, endPos, &end_first); + + /* STEP 3: remove the empty pieces... */ + if (start_piece != end_piece) { + temp_piece = start_piece->next; + + /* If empty and not the only piece then remove it */ + if (((start_piece->used = startPos - start_first) == 0) + && !(start_piece->next == NULL && start_piece->prev == NULL)) + RemovePiece(src, start_piece); + + while (temp_piece != end_piece) { + temp_piece = temp_piece->next; + RemovePiece(src, temp_piece->prev); + } + end_piece->used -= endPos - end_first; + if (end_piece->used != 0) + memmove(end_piece->text, end_piece->text + endPos - end_first, + end_piece->used * sizeof(wchar_t)); + } + else { /* We are fully in one piece */ + if ((start_piece->used -= endPos - startPos) == 0) { + if (!(start_piece->next == NULL && start_piece->prev == NULL)) + RemovePiece(src, start_piece); + } + else { + memmove(start_piece->text + (startPos - start_first), + start_piece->text + (endPos - start_first), + (start_piece->used - (startPos - start_first)) * + sizeof(wchar_t)); + if (src->multi_src.use_string_in_place && + ((src->multi_src.length - (endPos - startPos)) + < src->multi_src.piece_size - 1)) + start_piece->text[src->multi_src.length - (endPos - startPos)] = + (wchar_t)0; + } + } + + src->multi_src.length += text.length -(endPos - startPos); + + /* STEP 4: insert the new stuff */ + if ( text.length != 0) { + start_piece = FindPiece(src, startPos, &start_first); + length = text.length; + firstPos = text.firstPos; + + while (length > 0) { + wchar_t *ptr; + int fill; + + if (src->multi_src.use_string_in_place) { + if (start_piece->used == src->multi_src.piece_size - 1) { + + /* + * The string is used in place, then the string + * is not allowed to grow + */ + start_piece->used = src->multi_src.length = + src->multi_src.piece_size - 1; + + start_piece->text[src->multi_src.length] = (wchar_t)0; + return (XawEditError); + } + } + + if (start_piece->used == src->multi_src.piece_size) { + BreakPiece(src, start_piece); + start_piece = FindPiece(src, startPos, &start_first); + } + + fill = Min((int)(src->multi_src.piece_size - start_piece->used), length); + + ptr = start_piece->text + (startPos - start_first); + memmove(ptr + fill, ptr, (start_piece->used - + (startPos - start_first)) * sizeof(wchar_t)); + wptr =(wchar_t *)text.ptr; + (void)wcsncpy(ptr, wptr + firstPos, fill); + + startPos += fill; + firstPos += fill; + start_piece->used += fill; + length -= fill; + } + } + + if (local_artificial_block == True) + /* In other words, text is not the u_text that the user handed me but + one I made myself. I only care, because I need to free the string */ + XtFree(text.ptr); + + if (src->multi_src.use_string_in_place) + start_piece->text[start_piece->used] = (wchar_t)0; + +#ifdef OLDXAW + src->multi_src.changes = True; + XtCallCallbacks(w, XtNcallback, NULL); +#endif + + return (XawEditDone); +} + +/* + * Function: + * Scan + * + * Parameters: + * w - MultiSource widget + * position - position to start scanning + * type - type of thing to scan for + * dir - direction to scan + * count - which occurance if this thing to search for + * include - whether or not to include the character found in + * the position that is returned + * + * Description: + * Scans the text source for the number and type of item specified. + * + * Returns: + * The position of the item found + * + * Note: + * While there are only 'n' characters in the file there are n+1 + * possible cursor positions (one before the first character and + * one after the last character + */ +static XawTextPosition +Scan(Widget w, register XawTextPosition position, XawTextScanType type, + XawTextScanDirection dir, int count, Bool include) +{ + MultiSrcObject src = (MultiSrcObject)w; + register char inc; + MultiPiece *piece; + XawTextPosition first, first_eol_position = position; + register wchar_t *ptr; + int cnt = count; + + if (type == XawstAll) { + if (dir == XawsdRight) + return (src->multi_src.length); + return (0); + } + + /* STEP 1: basic sanity checks */ + if (position > src->multi_src.length) + position = src->multi_src.length; + + if (dir == XawsdRight) { + if (position == src->multi_src.length) + return (src->multi_src.length); + inc = 1; + } + else { + if (position == 0) + return (0); + inc = -1; + position--; + } + + piece = FindPiece(src, position, &first); + + if (piece->used == 0) + return (0); + + ptr = (position - first) + piece->text; + + switch (type) { + case XawstEOL: + case XawstParagraph: + case XawstWhiteSpace: + case XawstAlphaNumeric: + for (; cnt > 0 ; cnt--) { + Bool non_space = False, first_eol = True; + + /*CONSTCOND*/ + while (True) { + register wchar_t c; + + if (ptr < piece->text) { + piece = piece->prev; + if (piece == NULL) /* Begining of text */ + return (0); + ptr = piece->text + piece->used - 1; + c = *ptr; + } + else if (ptr >= piece->text + piece->used) { + piece = piece->next; + if (piece == NULL) /* End of text */ + return (src->multi_src.length); + ptr = piece->text; + } + + c = *ptr; + ptr += inc; + position += inc; + + if (type == XawstAlphaNumeric) { + if (!iswalnum(c)) { + if (non_space) + break; + } + else + non_space = True; + } + else if (type == XawstWhiteSpace) { + if (iswspace(c)) { + if (non_space) + break; + } + else + non_space = True; + } + else if (type == XawstEOL) { + if (c == _Xaw_atowc(XawLF)) + break; + } + else { /* XawstParagraph */ + if (first_eol) { + if (c == _Xaw_atowc(XawLF)) { + first_eol_position = position; + first_eol = False; + } + } + else + if (c == _Xaw_atowc(XawLF)) + break; + else if (!iswspace(c)) + first_eol = True; + } + } + } + if (!include) { + if (type == XawstParagraph) + position = first_eol_position; + if (count) + position -= inc; + } + break; + case XawstPositions: + position += count * inc; + break; + default: + break; + } + + if (dir == XawsdLeft) + position++; + + if (position >= src->multi_src.length) + return (src->multi_src.length); + if (position < 0) + return (0); + + return (position); +} + +/* + * Function: + * Search + * + * Parameters: + * w - MultiSource objecy + * position - position to start scanning + * dir - direction to scan + * text - text block to search for + * + * Description: + * Searchs the text source for the text block passed. + * + * Returns: + * The position of the item found + */ +static XawTextPosition +Search(Widget w, register XawTextPosition position, XawTextScanDirection dir, + XawTextBlock *text) +{ + MultiSrcObject src = (MultiSrcObject)w; + register int count = 0; + wchar_t *ptr; + wchar_t *wtarget; + int wtarget_len; + Display *d = XtDisplay(XtParent(w)); + MultiPiece *piece; + wchar_t *buf; + XawTextPosition first; + register char inc; + int cnt; + + /* STEP 1: First, a brief sanity check */ + if (dir == XawsdRight) + inc = 1; + else { + inc = -1; + if (position == 0) + return (XawTextSearchError); + position--; + } + + /* STEP 2: Ensure I have a local wide string.. */ + + /* Since this widget stores 32bit chars, I check here to see if + I'm being passed a string claiming to be 8bit chars (ie, MB text.) + If that is the case, naturally I convert to 32bit format */ + + /*if the block was FMT8BIT, length will convert to REAL wchar count bellow */ + wtarget_len = text->length; + + if (text->format == XawFmtWide) + wtarget = &(((wchar_t*)text->ptr) [text->firstPos]); + else { + /* The following converts wtarget_len from byte len to wchar count */ + wtarget = _XawTextMBToWC(d, &text->ptr[text->firstPos], &wtarget_len); + } + + /* OK, I can now assert that wtarget holds wide characters, wtarget_len + holds an accurate count of those characters, and that firstPos has been + effectively factored out of the following computations */ + + /* STEP 3: SEARCH! */ + buf = (wchar_t *)XtMalloc(sizeof(wchar_t) * wtarget_len); + (void)wcsncpy(buf, wtarget, wtarget_len); + piece = FindPiece(src, position, &first); + ptr = (position - first) + piece->text; + + /*CONSTCOND*/ + while (True) { + if (*ptr == (dir == XawsdRight ? *(buf + count) + : *(buf + wtarget_len - count - 1))) { + if (count == text->length - 1) + break; + else + count++; + } + else { + if (count != 0) { + position -=inc * count; + ptr -= inc * count; + } + count = 0; + } + + ptr += inc; + position += inc; + + while (ptr < piece->text) { + cnt = piece->text - ptr; + + piece = piece->prev; + if (piece == NULL) { /* Begining of text */ + XtFree((char *)buf); + return (XawTextSearchError); + } + ptr = piece->text + piece->used - cnt; + } + + while (ptr >= piece->text + piece->used) { + cnt = ptr - (piece->text + piece->used); + + piece = piece->next; + if (piece == NULL) { /* End of text */ + XtFree((char *)buf); + return (XawTextSearchError); + } + ptr = piece->text + cnt; + } + } + + XtFree((char *)buf); + if (dir == XawsdLeft) + return(position); + + return(position - (wtarget_len - 1)); +} + +/* + * Function: + * XawMultiSrcSetValues + * + * Parameters: + * current - current state of the widget + * request - what was requested + * cnew - what the widget will become + * args - representation of resources that have changed + * num_args - number of changed resources + * + * Description: + * Sets the values for the MultiSource. + * + * Returns: + * True if redisplay is needed + */ +static Boolean +XawMultiSrcSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + MultiSrcObject src = (MultiSrcObject)cnew; + MultiSrcObject old_src = (MultiSrcObject)current; + XtAppContext app_con = XtWidgetToApplicationContext(cnew); + Bool total_reset = False, string_set = False; + FILE *file; + unsigned int i; + + if (old_src->multi_src.use_string_in_place + != src->multi_src.use_string_in_place) { + XtAppWarning(app_con, + "MultiSrc: The XtNuseStringInPlace resources " + "may not be changed."); + src->multi_src.use_string_in_place = + old_src->multi_src.use_string_in_place; + } + + for (i = 0; i < *num_args ; i++) + if (streq(args[i].name, XtNstring)) { + string_set = True; + break; + } + + if (string_set || old_src->multi_src.type != src->multi_src.type) { + RemoveOldStringOrFile(old_src, string_set); + src->multi_src.allocated_string = old_src->multi_src.allocated_string; + file = InitStringOrFile(src, string_set); + + LoadPieces(src, file, NULL); + if (file != NULL) + fclose(file); +#ifndef OLDXAW + for (i = 0; i < src->text_src.num_text; i++) + /* Tell text widget what happened */ + XawTextSetSource(src->text_src.text[i], cnew, 0); +#else + XawTextSetSource(XtParent(cnew), cnew, 0); +#endif + total_reset = True; + } + + if (old_src->multi_src.multi_length != src->multi_src.multi_length) + src->multi_src.piece_size = src->multi_src.multi_length + 1; + + if ( !total_reset && old_src->multi_src.piece_size + != src->multi_src.piece_size) { + String mb_string = StorePiecesInString(old_src); + + if (mb_string != 0) { + FreeAllPieces(old_src); + LoadPieces(src, NULL, mb_string); + XtFree(mb_string); + } + else { + /* If the buffer holds bad chars, don't touch it... */ + XtAppWarningMsg(app_con, + "convertError", "multiSource", "XawError", + XtName(XtParent((Widget)old_src)), NULL, NULL); + XtAppWarningMsg(app_con, + "convertError", "multiSource", "XawError", + "Non-character code(s) in buffer.", NULL, NULL); + } + } + + return (False); +} + +static void +XawMultiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args) +{ + MultiSrcObject src = (MultiSrcObject)w; + unsigned int i; + + if (src->multi_src.type == XawAsciiString) { + for (i = 0; i < *num_args ; i++) { + if (streq(args[i].name, XtNstring)) { + if (src->multi_src.use_string_in_place) + *((char **)args[i].value) = (char *) + src->multi_src.first_piece->text; + else if (_XawMultiSave(w)) /* If save sucessful */ + *((char **)args[i].value) = (char *)src->multi_src.string; + break; + } + } + } +} + +static void +XawMultiSrcDestroy(Widget w) +{ + RemoveOldStringOrFile((MultiSrcObject) w, True); +} + +/* + * Public routines + */ +/* + * Function: + * XawMultiSourceFreeString + * + * Parameters: + * w - MultiSrc widget + * + * Description: + * Frees the string returned by a get values call + * on the string when the source is of type string. + * + * Note: + * The public interface is XawAsciiSourceFreeString! + */ +void +_XawMultiSourceFreeString(Widget w) +{ + MultiSrcObject src = (MultiSrcObject)w; + + if (src->multi_src.allocated_string) { + XtFree((char *)src->multi_src.string); + src->multi_src.allocated_string = False; + src->multi_src.string = NULL; + } +} + +/* + * Function: + * _XawMultiSave + * + * Parameters: + * w - multiSrc Widget + * + * Description: + * Saves all the pieces into a file or string as required. + * + * Returns: + * True if the save was successful + * + * Note: + * The public interface is XawAsciiSave(w)! + */ +Bool +_XawMultiSave(Widget w) +{ + MultiSrcObject src = (MultiSrcObject)w; + XtAppContext app_con = XtWidgetToApplicationContext(w); + char *mb_string; + + /* + * If using the string in place then there is no need to play games + * to get the internal info into a readable string + */ + if (src->multi_src.use_string_in_place) + return (True); + + if (src->multi_src.type == XawAsciiFile) { +#ifdef OLDXAW + if (!src->multi_src.changes) +#else + if (!src->text_src.changed) /* No changes to save */ +#endif + return (True); + + mb_string = StorePiecesInString(src); + + if (mb_string != 0) { + if (WriteToFile(mb_string, (String)src->multi_src.string) == False) { + XtFree(mb_string); + return (False); + } + XtFree(mb_string); +#ifndef OLDXAW + src->text_src.changed = False; +#else + src->multi_src.changes = False; +#endif + return (True); + } + else { + /* If the buffer holds bad chars, don't touch it... */ + XtAppWarningMsg(app_con, + "convertError", "multiSource", "XawError", + "Due to illegal characters, file not saved.", + NULL, NULL); + return (False); + } + } + else { + /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED? The manual + says this routine's only function is to save files to + disk. -Sheeran */ + mb_string = StorePiecesInString(src); + + if (mb_string == 0) { + /* If the buffer holds bad chars, don't touch it... */ + XtAppWarningMsg(app_con, + "convertError", "multiSource", "XawError", + XtName(XtParent((Widget)src)), NULL, NULL); + return (False); + } + + /* assert: mb_string holds good characters so the buffer is fine */ + if (src->multi_src.allocated_string == True) + XtFree((char *)src->multi_src.string); + else + src->multi_src.allocated_string = True; + + src->multi_src.string = mb_string; + } +#ifdef OLDXAW + src->multi_src.changes = False; +#else + src->text_src.changed = False; +#endif + + return (True); +} + +/* + * Function: + * XawMultiSaveAsFile + * + * Parameters: + * w - MultiSrc widget + * name - name of the file to save this file into + * + * Description: + * Save the current buffer as a file. + * + * Returns: + * True if the save was sucessful + * + * Note: + * The public interface is XawAsciiSaveAsFile! + */ +Bool +_XawMultiSaveAsFile(Widget w, _Xconst char* name) +{ + MultiSrcObject src = (MultiSrcObject)w; + String mb_string; + Bool ret; + + mb_string = StorePiecesInString(src); + + if (mb_string != 0) { + ret = WriteToFile(mb_string, (char *)name); + XtFree(mb_string); + + return (ret); + } + + /* otherwise there was a conversion error. So print widget name too */ + XtAppWarningMsg(XtWidgetToApplicationContext(w), + "convertError", "multiSource", "XawError", + XtName(XtParent(w)), NULL, NULL); + + return (False); +} + +/* + * Private Functions + */ +static void +RemoveOldStringOrFile(MultiSrcObject src, Bool checkString) +{ + FreeAllPieces(src); + + if (checkString && src->multi_src.allocated_string) { + XtFree((char *)src->multi_src.string); + src->multi_src.allocated_string = False; + src->multi_src.string = NULL; + } +} + +/* + * Function: + * WriteToFile + * + * Parameters: + * string - string to write + * name - name of the file + * + * Description: + * Write the string specified to the begining of the file specified. + * + * Returns: + * Returns True if sucessful, False otherwise + */ +static Bool +WriteToFile(String string, String name) +{ + int fd; + + if (((fd = creat(name, 0666)) == -1) + || (write(fd, string, strlen(string)) == -1)) + return (False); + + if (close(fd) == -1) + return (False); + + return (True); +} + + +/* + * Function: + * StorePiecesInString + * + * Parameters: + * src - the multiSrc object to gather data from + * + * Description: + * Store the pieces in memory into a char string. + * + * Returns: + * mb_string: Caller must free + * (or) + * NULL: conversion error + */ +static String +StorePiecesInString(MultiSrcObject src) +{ + wchar_t *wc_string; + char *mb_string; + int char_count = src->multi_src.length; + XawTextPosition first; + MultiPiece *piece; + + /* I believe the char_count + 1 and the NULL termination are unneeded! FS */ + wc_string = (wchar_t*)XtMalloc((char_count + 1) * sizeof(wchar_t)); + + for (first = 0, piece = src->multi_src.first_piece ; piece != NULL; + first += piece->used, piece = piece->next) + (void)wcsncpy(wc_string + first, piece->text, piece->used); + + wc_string[char_count] = 0; + + /* This will refill all pieces to capacity */ + if (src->multi_src.data_compression) { + FreeAllPieces(src); + LoadPieces(src, NULL, (char *)wc_string); + } + + /* Lastly, convert it to a MB format and send it back */ + mb_string = _XawTextWCToMB(XtDisplayOfObject((Widget)src), + wc_string, &char_count); + + /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED */ + XtFree((char*)wc_string); + + return (mb_string); +} + +/* + * Function: + * InitStringOrFile + * + * Parameters: + * src - MultiSource + * + * Description: + * Initializes the string or file. + */ +static FILE * +InitStringOrFile(MultiSrcObject src, Bool newString) +{ + mode_t open_mode = 0; + const char *fdopen_mode = NULL; + int fd; + FILE *file; + Display *d = XtDisplayOfObject((Widget)src); + + if (src->multi_src.type == XawAsciiString) { + if (src->multi_src.string == NULL) + src->multi_src.length = 0; + + else if (!src->multi_src.use_string_in_place) { + int length; + String temp = XtNewString((char *)src->multi_src.string); + + if (src->multi_src.allocated_string) + XtFree((char *)src->multi_src.string); + src->multi_src.allocated_string = True; + src->multi_src.string = temp; + + length = strlen((char *)src->multi_src.string); + + /* Wasteful, throwing away the WC string, but need side effect! */ + (void)_XawTextMBToWC(d, (char *)src->multi_src.string, &length); + src->multi_src.length = (XawTextPosition)length; + } + else { + src->multi_src.length = strlen((char *)src->multi_src.string); + /* In case the length resource is incorrectly set */ + if (src->multi_src.length > src->multi_src.multi_length) + src->multi_src.multi_length = src->multi_src.length; + + if (src->multi_src.multi_length == MAGIC_VALUE) + src->multi_src.piece_size = src->multi_src.length; + else + src->multi_src.piece_size = src->multi_src.multi_length + 1; + } + + return (NULL); + } + + /* + * type is XawAsciiFile + */ + src->multi_src.is_tempfile = False; + + switch (src->text_src.edit_mode) { + case XawtextRead: + if (src->multi_src.string == NULL) + XtErrorMsg("NoFile", "multiSourceCreate", "XawError", + "Creating a read only disk widget and no file specified.", + NULL, 0); + open_mode = O_RDONLY; + fdopen_mode = "r"; + break; + case XawtextAppend: + case XawtextEdit: + if (src->multi_src.string == NULL) { + src->multi_src.string = "*multi-src*"; + src->multi_src.is_tempfile = True; + } + else { +/* O_NOFOLLOW is a BSD & Linux extension */ +#ifdef O_NOFOLLOW + open_mode = O_RDWR | O_NOFOLLOW; +#else + open_mode = O_RDWR; /* unsafe; subject to race conditions */ +#endif + fdopen_mode = "r+"; + } + break; + default: + XtErrorMsg("badMode", "multiSourceCreate", "XawError", + "Bad editMode for multi source; must be " + "Read, Append or Edit.", NULL, NULL); + } + + /* If is_tempfile, allocate a private copy of the text + * Unlikely to be changed, just to set allocated_string */ + if (newString || src->multi_src.is_tempfile) { + String temp = XtNewString((char *)src->multi_src.string); + + if (src->multi_src.allocated_string) + XtFree((char *)src->multi_src.string); + src->multi_src.string = temp; + src->multi_src.allocated_string = True; + } + + if (!src->multi_src.is_tempfile) { + if ((fd = open((char *)src->multi_src.string, open_mode, 0666)) != -1) { + if ((file = fdopen(fd, fdopen_mode)) != NULL) { + (void)fseek(file, 0, SEEK_END); + src->multi_src.length = (XawTextPosition)ftell(file); + return(file); + } + } + { + String params[2]; + Cardinal num_params = 2; + + params[0] = (String)src->multi_src.string; + params[1] = strerror(errno); + XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), + "openError", "multiSourceCreate", "XawWarning", + "Cannot open file %s; %s", params, &num_params); + } + } + src->multi_src.length = 0; + return (NULL); +} + +/* LoadPieces: This routine takes either the MB contents of open file + `file' or the MB contents of string or the MB contents of + src->multi_src.string and places them in Pieces in WC format. + + CAUTION: You must have src->multi_src.length set to file length bytes + when src->multi_src.type == XawAsciiFile. src->multi_src.length must be + the length of the parameter string if string is non-NULL +*/ +static void +LoadPieces(MultiSrcObject src, FILE *file, char *string) +{ + Display *d = XtDisplayOfObject((Widget)src); + wchar_t* local_str, *ptr; + MultiPiece* piece = NULL; + XawTextPosition left; + int bytes = sizeof(wchar_t); + char* temp_mb_holder = NULL; + + /* + * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg + * in as MB length, out as WC length. We want local_length to be + * WC count. + */ + int local_length = src->multi_src.length; + + if (string != NULL) { + /* + * ASSERT: IF our caller passed a non-null string, THEN + * src->multi_src.length is currently string's * byte count, + * AND string is in a MB format + */ + local_str = _XawTextMBToWC(d, (char *)string, &local_length); + src->multi_src.length = (XawTextPosition) local_length; + } + else if (src->multi_src.type != XawAsciiFile) { + /* + * here, we are not changing the contents, just reloading, + * so don't change len... + */ + local_length = src->multi_src.string ? + strlen((char *)src->multi_src.string) : 0; + local_str = _XawTextMBToWC(d, (char *)src->multi_src.string, + &local_length); + } + else { + if (src->multi_src.length != 0) { + temp_mb_holder = + XtMalloc((src->multi_src.length + 1) * sizeof(unsigned char)); + fseek(file, 0, 0); + src->multi_src.length = fread(temp_mb_holder, + (Size_t)sizeof(unsigned char), + (Size_t)src->multi_src.length, file); + if (src->multi_src.length <= 0) + XtAppErrorMsg(XtWidgetToApplicationContext ((Widget) src), + "readError", "multiSource", "XawError", + "fread returned error.", NULL, NULL); + local_length = src->multi_src.length; + local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length); + src->multi_src.length = local_length; + + if (local_str == 0) { + String params[2]; + Cardinal num_params; + static char err_text[] = + "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>"; + + params[0] = XtName(XtParent((Widget)src)); + params[1] = src->multi_src.string; + num_params = 2; + + XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), + "readLocaleError", "multiSource", "XawError", + "%s: The file `%s' contains characters " + "not representable in this locale.", + params, &num_params); + src->multi_src.length = sizeof err_text; + local_length = src->multi_src.length; + local_str = _XawTextMBToWC(d, err_text, &local_length); + src->multi_src.length = local_length; + } + } + else + /* ASSERT that since following while loop looks at local_length + this isn't needed. Sheeran, Omron KK, 1993/07/15 + temp_mb_holder[src->multi_src.length] = '\0'; */ + local_str = (wchar_t*)temp_mb_holder; + } + + if (src->multi_src.use_string_in_place) { + piece = AllocNewPiece(src, piece); + piece->used = Min(src->multi_src.length, src->multi_src.piece_size); + piece->text = (wchar_t*)src->multi_src.string; + return; + } + + ptr = local_str; + left = local_length; + + do { + piece = AllocNewPiece(src, piece); + + piece->text = (wchar_t*)XtMalloc((unsigned)(src->multi_src.piece_size + * bytes)); + piece->used = Min(left, src->multi_src.piece_size); + if (piece->used != 0) + (void)wcsncpy(piece->text, ptr, piece->used); + + left -= piece->used; + ptr += piece->used; + } while (left > 0); + + if (temp_mb_holder) + XtFree((char*)temp_mb_holder); +} + +/* + * Function: + * AllocNewPiece + * + * Parameters: + * src - MultiSrc Widget + * prev - the piece just before this one, or NULL + * + * Description: + * Allocates a new piece of memory. + * + * Returns: + * The allocated piece + */ +static MultiPiece * +AllocNewPiece(MultiSrcObject src, MultiPiece *prev) +{ + MultiPiece *piece = XtNew(MultiPiece); + + if (prev == NULL) { + src->multi_src.first_piece = piece; + piece->next = NULL; + } + else { + if (prev->next != NULL) + (prev->next)->prev = piece; + piece->next = prev->next; + prev->next = piece; + } + + piece->prev = prev; + + return (piece); +} + +/* + * Function: + * FreeAllPieces + * + * Parameters: + * src - MultiSrc Widget + * + * Description: + * Frees all the pieces + */ +static void +FreeAllPieces(MultiSrcObject src) +{ + MultiPiece *next, *first = src->multi_src.first_piece; + +#ifdef DEBUG + if (first->prev != NULL) + printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n"); +#endif + + for (; first != NULL ; first = next) { + next = first->next; + RemovePiece(src, first); + } +} + +/* + * Function: + * RemovePiece + * + * Parameters: + * piece - piece to remove + * + * Description: + * Removes a piece from the list. + */ +static void +RemovePiece(MultiSrcObject src, MultiPiece *piece) +{ + if (piece->prev == NULL) + src->multi_src.first_piece = piece->next; + else + piece->prev->next = piece->next; + + if (piece->next != NULL) + piece->next->prev = piece->prev; + + if (!src->multi_src.use_string_in_place) + XtFree((char *)piece->text); + + XtFree((char *)piece); +} + +/* + * Function: + * FindPiece + * + * Parameters: + * src - MultiSrc Widget + * position - position that we are searching for + * first - position of the first character in this piece (return) + * + * Description: + * Finds the piece containing the position indicated. + * + * Returns: + * Piece that contains this position + */ +static MultiPiece * +FindPiece(MultiSrcObject src, XawTextPosition position, XawTextPosition *first) +{ + MultiPiece *old_piece, *piece; + XawTextPosition temp; + + for (old_piece = NULL, piece = src->multi_src.first_piece, temp = 0; + piece; old_piece = piece, piece = piece->next) + if ((temp += piece->used) > position) { + *first = temp - piece->used; + return (piece); + } + + *first = temp - (old_piece ? old_piece->used : 0); + + return (old_piece); /* if we run off the end the return the last piece */ +} + +/* + * Function: + * BreakPiece + * + * Parameters: + * src - MultiSrc Widget + * piece - piece to break + * + * Description: + * Breaks a full piece into two new pieces. + */ +#define HALF_PIECE (src->multi_src.piece_size >> 1) +static void +BreakPiece(MultiSrcObject src, MultiPiece *piece) +{ + MultiPiece *cnew = AllocNewPiece(src, piece); + + cnew->text = (wchar_t *) + XtMalloc(src->multi_src.piece_size * sizeof(wchar_t)); + (void)wcsncpy(cnew->text, piece->text + HALF_PIECE, + src->multi_src.piece_size - HALF_PIECE); + piece->used = HALF_PIECE; + cnew->used = src->multi_src.piece_size - HALF_PIECE; +} + +/*ARGSUSED*/ +static void +CvtStringToMultiType(XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal) +{ + static XawAsciiType type = XawAsciiString; + XrmQuark q; + char name[7]; + + XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); + q = XrmStringToQuark(name); + + if (q == Qstring) + type = XawAsciiString; + if (q == Qfile) + type = XawAsciiFile; + else { + toVal->size = 0; + toVal->addr = NULL; + XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType); + } + + toVal->size = sizeof(XawAsciiType); + toVal->addr = (XPointer)&type; +} + +/*ARGSUSED*/ +static Boolean +CvtMultiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal, + XtPointer *data) +{ + static String buffer; + Cardinal size; + + switch (*(XawAsciiType *)fromVal->addr) { + case XawAsciiFile: + buffer = XtEfile; + break; + case XawAsciiString: + buffer = XtEstring; + break; + default: + XawTypeToStringWarning(dpy, XtRAsciiType); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + + size = strlen(buffer) + 1; + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +/*ARGSUSED*/ +static void +GetDefaultPieceSize(Widget w, int offset, XrmValue *value) +{ + static XPointer pagesize; + + if (pagesize == 0) { + pagesize = (XPointer)((long)_XawGetPageSize()); + if (pagesize < (XPointer)BUFSIZ) + pagesize = (XPointer)BUFSIZ; + } + + value->addr = (XPointer)&pagesize; +} diff --git a/libXaw/src/OS.c b/libXaw/src/OS.c index ce8f0e801..8bc23ddf6 100644 --- a/libXaw/src/OS.c +++ b/libXaw/src/OS.c @@ -1,53 +1,53 @@ -/* Some OS-dependent utility code */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/Xosdefs.h>
-#include <X11/IntrinsicP.h>
-#include "Private.h"
-
-#ifndef X_NOT_POSIX
-#include <unistd.h> /* for sysconf(), and getpagesize() */
-#endif
-
-#if defined(linux)
-/* kernel header doesn't work with -ansi */
-/* #include <asm/page.h> *//* for PAGE_SIZE */
-#define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */
-#endif
-
-int
-_XawGetPageSize(void)
-{
- static int pagesize = -1;
-
- if (pagesize != -1)
- return pagesize;
-
- /* Try each supported method in the preferred order */
-
-#if defined(_SC_PAGESIZE) || defined(HAS_SC_PAGESIZE)
- pagesize = sysconf(_SC_PAGESIZE);
-#endif
-
-#ifdef _SC_PAGE_SIZE
- if (pagesize == -1)
- pagesize = sysconf(_SC_PAGE_SIZE);
-#endif
-
-#ifdef HAVE_GETPAGESIZE
- if (pagesize == -1)
- pagesize = getpagesize();
-#endif
-
-#ifdef PAGE_SIZE
- if (pagesize == -1)
- pagesize = PAGE_SIZE;
-#endif
-
- if (pagesize == -1)
- pagesize = 0;
-
- return pagesize;
-}
+/* Some OS-dependent utility code */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/Xosdefs.h> +#include <X11/IntrinsicP.h> +#include "Private.h" + +#ifndef X_NOT_POSIX +#include <unistd.h> /* for sysconf(), and getpagesize() */ +#endif + +#if defined(linux) +/* kernel header doesn't work with -ansi */ +/* #include <asm/page.h> *//* for PAGE_SIZE */ +#define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */ +#endif + +int +_XawGetPageSize(void) +{ + static int pagesize = -1; + + if (pagesize != -1) + return pagesize; + + /* Try each supported method in the preferred order */ + +#if defined(_SC_PAGESIZE) || defined(HAS_SC_PAGESIZE) + pagesize = sysconf(_SC_PAGESIZE); +#endif + +#ifdef _SC_PAGE_SIZE + if (pagesize == -1) + pagesize = sysconf(_SC_PAGE_SIZE); +#endif + +#ifdef HAVE_GETPAGESIZE + if (pagesize == -1) + pagesize = getpagesize(); +#endif + +#ifdef PAGE_SIZE + if (pagesize == -1) + pagesize = PAGE_SIZE; +#endif + + if (pagesize == -1) + pagesize = 0; + + return pagesize; +} diff --git a/libXaw/src/Paned.c b/libXaw/src/Paned.c index 842ea0e59..84999f717 100644 --- a/libXaw/src/Paned.c +++ b/libXaw/src/Paned.c @@ -1,2064 +1,2064 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
- * Updated and significantly modified from the Athena VPaned Widget.
- *
- * Date: March 1, 1989
- *
- * By: Chris D. Peterson
- * MIT X Consortium
- * kit@expo.lcs.mit.edu
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/cursorfont.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/Converters.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/Grip.h>
-#include <X11/Xaw/PanedP.h>
-#include <X11/Xaw/XawImP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-typedef enum {
- UpLeftPane = 'U',
- LowRightPane = 'L',
- ThisBorderOnly = 'T',
- AnyPane = 'A'
-} Direction;
-
-#define NO_INDEX -100
-#define IS_GRIP NULL
-
-#define PaneInfo(w) ((Pane)(w)->core.constraints)
-#define HasGrip(w) (PaneInfo(w)->grip != NULL)
-#define IsPane(w) ((w)->core.widget_class != gripWidgetClass)
-#define PaneIndex(w) (PaneInfo(w)->position)
-#define IsVert(w) ((w)->paned.orientation == XtorientVertical)
-
-#define ForAllPanes(pw, childP) \
-for ((childP) = (pw)->composite.children; \
- (childP) < (pw)->composite.children + (pw)->paned.num_panes; \
- (childP)++)
-
-#define ForAllChildren(pw, childP) \
-for ((childP) = (pw)->composite.children; \
- (childP) < (pw)->composite.children + (pw)->composite.num_children; \
- (childP)++)
-
-#define PaneSize(paned, vertical) \
- ((vertical) ? XtHeight(paned) : XtWidth(paned))
-
-#define GetRequestInfo(geo, vertical) \
- ((vertical) ? (geo)->height : (geo)->width)
-
-#define SatisfiesRule1(pane, shrink) \
- (((shrink) && ((pane)->size != (pane)->min)) \
- || (!(shrink) && ((pane)->size != (pane)->max)))
-
-#define SatisfiesRule2(pane) \
- (!(pane)->skip_adjust || (pane)->paned_adjusted_me)
-
-#define SatisfiesRule3(pane, shrink) \
- ((pane)->paned_adjusted_me \
- && (((shrink) && ((int)(pane)->wp_size <= (pane)->size)) \
- || (!(shrink) && ((int)(pane)->wp_size >= (pane)->size))))
-
-
-/*
- * Class Methods
- */
-static void XawPanedClassInitialize(void);
-static void XawPanedChangeManaged(Widget);
-static void XawPanedDeleteChild(Widget);
-static void XawPanedDestroy(Widget);
-static XtGeometryResult XawPanedGeometryManager(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawPanedInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawPanedInsertChild(Widget);
-static Boolean XawPanedPaneSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static void XawPanedRealize(Widget, Mask*, XSetWindowAttributes*);
-static void XawPanedRedisplay(Widget, XEvent*, Region);
-static void XawPanedResize(Widget);
-static Boolean XawPanedSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void _DrawInternalBorders(PanedWidget, GC);
-static void _DrawRect(PanedWidget, GC, int, int, unsigned int, unsigned int);
-static void _DrawTrackLines(PanedWidget, Bool);
-static void AdjustPanedSize(PanedWidget, unsigned int, XtGeometryResult*,
- Dimension*, Dimension*);
-static void ChangeAllGripCursors(PanedWidget);
-static Pane ChoosePaneToResize(PanedWidget, int, Direction, Bool);
-static void ClearPaneStack(PanedWidget);
-static void CommitGripAdjustment(PanedWidget);
-static void CreateGrip(Widget);
-static int GetEventLocation(PanedWidget, XEvent*);
-static void GetGCs(Widget);
-static void GetPaneStack(PanedWidget, Bool, Pane*, int*);
-static void HandleGrip(Widget, XtPointer, XtPointer);
-static void LoopAndRefigureChildren(PanedWidget, int, Direction, int*);
-static void ManageAndUnmanageGrips(PanedWidget);
-static void MoveGripAdjustment(PanedWidget, Widget, Direction, int);
-static Bool PopPaneStack(PanedWidget);
-static void PushPaneStack(PanedWidget, Pane);
-static void RefigureLocations(PanedWidget, int, Direction);
-static void RefigureLocationsAndCommit(Widget);
-static void ReleaseGCs(Widget);
-static void ResortChildren(PanedWidget);
-static void SetChildrenPrefSizes(PanedWidget, unsigned int);
-static void StartGripAdjustment(PanedWidget, Widget, Direction);
-
-/*
- * Initialization
- */
-static char defGripTranslations[] =
-"<Btn1Down>:" "GripAction(Start,UpLeftPane)\n"
-"<Btn2Down>:" "GripAction(Start,ThisBorderOnly)\n"
-"<Btn3Down>:" "GripAction(Start,LowRightPane)\n"
-"<Btn1Motion>:" "GripAction(Move,UpLeft)\n"
-"<Btn2Motion>:" "GripAction(Move,ThisBorder)\n"
-"<Btn3Motion>:" "GripAction(Move,LowRight)\n"
-"Any<BtnUp>:" "GripAction(Commit)\n"
-;
-
-#define offset(field) XtOffsetOf(PanedRec, paned.field)
-static XtResource resources[] = {
- {
- XtNinternalBorderColor,
- XtCBorderColor,
- XtRPixel,
- sizeof(Pixel),
- offset(internal_bp),
- XtRString,
- (XtPointer)XtDefaultForeground
- },
- {
- XtNinternalBorderWidth,
- XtCBorderWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(internal_bw),
- XtRImmediate,
- (XtPointer)1
- },
- {
- XtNgripIndent,
- XtCGripIndent,
- XtRPosition,
- sizeof(Position),
- offset(grip_indent),
- XtRImmediate,
- (XtPointer)10
- },
- {
- XtNrefigureMode,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(refiguremode),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNgripTranslations,
- XtCTranslations,
- XtRTranslationTable,
- sizeof(XtTranslations),
- offset(grip_translations),
- XtRString,
- (XtPointer)defGripTranslations
- },
- {
- XtNorientation,
- XtCOrientation,
- XtROrientation,
- sizeof(XtOrientation),
- offset(orientation),
- XtRImmediate,
- (XtPointer)XtorientVertical
- },
- {
- XtNcursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(cursor),
- XtRImmediate,
- NULL
- },
- {
- XtNgripCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(grip_cursor),
- XtRImmediate,
- NULL
- },
- {
- XtNverticalGripCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(v_grip_cursor),
- XtRString,
- "sb_v_double_arrow"
- },
- {
- XtNhorizontalGripCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(h_grip_cursor),
- XtRString,
- "sb_h_double_arrow"
- },
- {
- XtNbetweenCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(adjust_this_cursor),
- XtRString,
- NULL
- },
- {
- XtNverticalBetweenCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(v_adjust_this_cursor),
- XtRString,
- "sb_left_arrow"
- },
- {
- XtNhorizontalBetweenCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(h_adjust_this_cursor),
- XtRString,
- "sb_up_arrow"
- },
- {
- XtNupperCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(adjust_upper_cursor),
- XtRString,
- "sb_up_arrow"
- },
- {
- XtNlowerCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(adjust_lower_cursor),
- XtRString,
- "sb_down_arrow"
- },
- {
- XtNleftCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(adjust_left_cursor),
- XtRString,
- "sb_left_arrow"
- },
- {
- XtNrightCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(adjust_right_cursor),
- XtRString,
- "sb_right_arrow"
- },
-};
-#undef offset
-
-#define offset(field) XtOffsetOf(PanedConstraintsRec, paned.field)
-static XtResource subresources[] = {
- {
- XtNallowResize,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(allow_resize),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNposition,
- XtCPosition,
- XtRInt,
- sizeof(int),
- offset(position),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNmin,
- XtCMin,
- XtRDimension,
- sizeof(Dimension),
- offset(min),
- XtRImmediate,
- (XtPointer)PANED_GRIP_SIZE
- },
- {
- XtNmax,
- XtCMax,
- XtRDimension,
- sizeof(Dimension),
- offset(max),
- XtRImmediate,
- (XtPointer)~0
- },
- {
- XtNpreferredPaneSize,
- XtCPreferredPaneSize,
- XtRDimension,
- sizeof(Dimension),
- offset(preferred_size),
- XtRImmediate,
- (XtPointer)PANED_ASK_CHILD
- },
- {
- XtNresizeToPreferred,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(resize_to_pref),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNskipAdjust,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(skip_adjust),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNshowGrip,
- XtCShowGrip,
- XtRBoolean,
- sizeof(Boolean),
- offset(show_grip),
- XtRImmediate,
- (XtPointer)True
- },
-};
-#undef offset
-
-#define SuperClass ((ConstraintWidgetClass)&constraintClassRec)
-
-PanedClassRec panedClassRec = {
- /* core */
- {
- (WidgetClass)SuperClass, /* superclass */
- "Paned", /* class name */
- sizeof(PanedRec), /* size */
- XawPanedClassInitialize, /* class_initialize */
- NULL, /* class_part init */
- False, /* class_inited */
- XawPanedInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawPanedRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawPanedDestroy, /* destroy */
- XawPanedResize, /* resize */
- XawPanedRedisplay, /* expose */
- XawPanedSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* composite */
- {
- XawPanedGeometryManager, /* geometry_manager */
- XawPanedChangeManaged, /* change_managed */
- XawPanedInsertChild, /* insert_child */
- XawPanedDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- /* constraint */
- {
- subresources, /* subresources */
- XtNumber(subresources), /* subresource_count */
- sizeof(PanedConstraintsRec), /* constraint_size */
- NULL, /* initialize */
- NULL, /* destroy */
- XawPanedPaneSetValues, /* set_values */
- NULL, /* extension */
- },
-};
-
-WidgetClass panedWidgetClass = (WidgetClass)&panedClassRec;
-WidgetClass vPanedWidgetClass = (WidgetClass)&panedClassRec;
-
-/*
- * Implementation
- */
-/* Function:
- * AdjustPanedSize
- *
- * Parameters:
- * pw - paned widget to adjust
- * off_size - new off_size to use
- * result_ret - result of query (return)
- * on_size_ret - new on_size (return)
- * off_size_ret - new off_size (return)
- *
- * Description:
- * Adjusts the size of the pane.
- *
- * Returns:
- * amount of change in size
- */
-static void
-AdjustPanedSize(PanedWidget pw, unsigned int off_size,
- XtGeometryResult *result_ret,
- Dimension *on_size_ret, Dimension *off_size_ret)
-{
- Dimension old_size = PaneSize((Widget)pw, IsVert(pw));
- Dimension newsize = 0;
- Widget *childP;
- XtWidgetGeometry request, reply;
-
- request.request_mode = CWWidth | CWHeight;
-
- ForAllPanes(pw, childP) {
- int size = Max(PaneInfo(*childP)->size, (int)PaneInfo(*childP)->min);
-
- AssignMin(size, (int)PaneInfo(*childP)->max);
- newsize += size + pw->paned.internal_bw;
- }
- newsize -= pw->paned.internal_bw;
-
- if (newsize < 1)
- newsize = 1;
-
- if (IsVert(pw)) {
- request.width = off_size;
- request.height = newsize;
- }
- else {
- request.width = newsize;
- request.height = off_size;
- }
-
- if (result_ret != NULL) {
- request.request_mode |= XtCWQueryOnly;
-
- *result_ret = XtMakeGeometryRequest((Widget)pw, &request, &reply);
- _XawImCallVendorShellExtResize((Widget)pw);
-
- if (newsize == old_size || *result_ret == XtGeometryNo) {
- *on_size_ret = old_size;
- *off_size_ret = off_size;
- return;
- }
- if (*result_ret != XtGeometryAlmost) {
- *on_size_ret = GetRequestInfo(&request, IsVert(pw));
- *off_size_ret = GetRequestInfo(&request, !IsVert(pw));
- return;
- }
- *on_size_ret = GetRequestInfo(&reply, IsVert(pw));
- *off_size_ret = GetRequestInfo(&reply, !IsVert(pw));
- return;
- }
-
- if (newsize == old_size)
- return;
-
- if (XtMakeGeometryRequest((Widget)pw, &request, &reply) == XtGeometryAlmost)
- XtMakeGeometryRequest((Widget)pw, &reply, &request);
-}
-
-/*
- * Function:
- * ChoosePaneToResize.
- *
- * Parameters:
- * pw - paned widget
- * paneindex - index of the current pane
- * dir - direction to search first
- * shrink - True if we need to shrink a pane, False otherwise
- *
- * Description:
- * This function chooses a pane to resize.
- They are chosen using the following rules:
- *
- * 1) size < max && size > min
- * 2) skip adjust == False
- * 3) widget not its prefered height
- * && this change will bring it closer
- * && The user has not resized this pane.
- *
- * If no widgets are found that fits all the rules then
- * rule #3 is broken.
- * If there are still no widgets found than
- * rule #2 is broken.
- * Rule #1 is never broken.
- * If no widgets are found then NULL is returned.
- *
- * Returns:
- * pane to resize or NULL
- */
-static Pane
-ChoosePaneToResize(PanedWidget pw, int paneindex, Direction dir, Bool shrink)
-{
- Widget *childP;
- int rules = 3;
- Direction _dir = dir;
- int _index = paneindex;
-
- if (paneindex == NO_INDEX || dir == AnyPane) { /* Use defaults */
- _dir = LowRightPane; /* Go up - really */
- _index = pw->paned.num_panes - 1; /* Start the last pane, and work
- backwards */
- }
- childP = pw->composite.children + _index;
-
- /*CONSTCOND*/
- while(True) {
- Pane pane = PaneInfo(*childP);
-
- if ((rules < 3 || SatisfiesRule3(pane, shrink))
- && (rules < 2 || SatisfiesRule2(pane))
- && SatisfiesRule1(pane, shrink)
- && (paneindex != PaneIndex(*childP) || dir == AnyPane))
- return (pane);
-
- /*
- * This is counter-intuitive, but if we are resizing the pane
- * above the grip we want to choose a pane below the grip to lose,
- * and visa-versa
- */
- if (_dir == LowRightPane)
- --childP;
- else
- ++childP;
-
- /*
- * If we have come to and edge then reduce the rule set, and try again
- * If we are reduced the rules to none, then return NULL
- */
- if ((childP - pw->composite.children) < 0 ||
- (childP - pw->composite.children) >= pw->paned.num_panes) {
- if (--rules < 1) /* less strict rules */
- return (NULL);
- childP = pw->composite.children + _index;
- }
- }
-}
-
-/*
- * Function:
- * LoopAndRefigureChildren
- *
- * Parameters:
- * pw - paned widget
- * paneindex - number of the pane border we are moving
- * dir - pane to move (either UpLeftPane or LowRightPane)
- * sizeused - current amount of space used (used and returned)
- *
- * Description:
- * If we are resizing either the UpleftPane or LowRight Pane loop
- * through all the children to see if any will allow us to resize them.
- */
-static void
-LoopAndRefigureChildren(PanedWidget pw, int paneindex, Direction dir,
- int *sizeused)
-{
- int pane_size = (int)PaneSize((Widget)pw, IsVert(pw));
- Boolean shrink = (*sizeused > pane_size);
-
- if (dir == LowRightPane)
- paneindex++;
-
- /* While all panes do not fit properly */
- while (*sizeused != pane_size) {
- /*
- * Choose a pane to resize
- * First look on the Pane Stack, and then go hunting for another one
- * If we fail to find a pane to resize then give up
- */
- Pane pane;
- int start_size;
- Dimension old;
- Boolean rule3_ok = False, from_stack = True;
-
- GetPaneStack(pw, shrink, &pane, &start_size);
- if (pane == NULL) {
- pane = ChoosePaneToResize(pw, paneindex, dir, shrink);
- if (pane == NULL)
- return; /* no one to resize, give up */
-
- rule3_ok = SatisfiesRule3(pane, shrink);
- from_stack = False;
- PushPaneStack(pw, pane);
- }
-
- /*
- * Try to resize this pane so that all panes will fit, take min and max
- * into account
- */
- old = pane->size;
- pane->size += pane_size - *sizeused;
-
- if (from_stack) {
- if (shrink) {
- AssignMax(pane->size, start_size);
- } /* don't remove these braces */
- else
- AssignMin(pane->size, start_size);
-
- if (pane->size == start_size)
- (void)PopPaneStack(pw);
- }
- else if (rule3_ok) {
- if (shrink) {
- AssignMax(pane->size, (int)pane->wp_size);
- } /* don't remove these braces */
- else
- AssignMin(pane->size, (int)pane->wp_size);
- }
-
- pane->paned_adjusted_me = pane->size != pane->wp_size;
- AssignMax(pane->size, (int)pane->min);
- AssignMin(pane->size, (int)pane->max);
- *sizeused += (pane->size - old);
- }
-}
-
-/*
- * Function:
- * RefigureLocations
- *
- * Parameters:
- * pw - paned widget
- * paneindex - child to start refiguring at
- * dir - direction to move from child
- *
- * Description:
- * Refigures all locations of children.
- * There are special arguments to paneindex and dir, they are:
- * paneindex - NO_INDEX.
- * dir - AnyPane.
- *
- * If either of these is true then all panes may be resized and
- * the choosing of panes procedes in reverse order starting with the
- * last child.
- */
-static void
-RefigureLocations(PanedWidget pw, int paneindex, Direction dir)
-{
- Widget *childP;
- int pane_size = (int)PaneSize((Widget)pw, IsVert(pw));
- int sizeused = 0;
- Position loc = 0;
-
- if (pw->paned.num_panes == 0 || !pw->paned.refiguremode)
- return;
-
- /*
- * Get an initial estimate of the size we will use
- */
- ForAllPanes(pw, childP) {
- Pane pane = PaneInfo(*childP);
-
- AssignMax(pane->size, (int) pane->min);
- AssignMin(pane->size, (int) pane->max);
- sizeused += (int)pane->size + (int)pw->paned.internal_bw;
- }
- sizeused -= (int)pw->paned.internal_bw;
-
- if (dir != ThisBorderOnly && sizeused != pane_size)
- LoopAndRefigureChildren(pw, paneindex, dir, &sizeused);
-
- /*
- * If we still are not the right size, then tell the pane that
- * wanted to resize that it can't
- */
- if (paneindex != NO_INDEX && dir != AnyPane) {
- Pane pane = PaneInfo(*(pw->composite.children + paneindex));
- Dimension old = pane->size;
-
- pane->size += pane_size - sizeused;
- AssignMax(pane->size, (int) pane->min);
- AssignMin(pane->size, (int) pane->max);
- sizeused += pane->size - old;
- }
-
- /*
- * It is possible that the panes will not fit inside the vpaned widget, but
- * we have tried out best
- *
- * Assign each pane a location
- */
- ForAllPanes(pw, childP) {
- PaneInfo(*childP)->delta = loc;
- loc += PaneInfo(*childP)->size + pw->paned.internal_bw;
- }
-}
-
-/*
- * Function:
- * CommitNewLocations
- *
- * Parameters:
- * pw - paned widget
- *
- * Description:
- * Commits all of the previously figured locations.
- */
-static void
-CommitNewLocations(PanedWidget pw)
-{
- Widget *childP;
- XWindowChanges changes;
-
- changes.stack_mode = Above;
-
- ForAllPanes(pw, childP) {
- Pane pane = PaneInfo(*childP);
- Widget grip = pane->grip; /* may be NULL */
-
- if (IsVert(pw)) {
- XtMoveWidget(*childP, (Position) 0, pane->delta);
- XtResizeWidget(*childP, XtWidth(pw), pane->size, 0);
-
- if (HasGrip(*childP)) { /* Move and Display the Grip */
- changes.x = XtWidth(pw) - pw->paned.grip_indent -
- XtWidth(grip) - (XtBorderWidth(grip) << 1);
- changes.y = XtY(*childP) + XtHeight(*childP) -
- (XtHeight(grip) >> 1) - XtBorderWidth(grip) +
- (pw->paned.internal_bw >> 1);
- }
- }
- else {
- XtMoveWidget(*childP, pane->delta, 0);
- XtResizeWidget(*childP, pane->size, XtHeight(pw), 0);
-
- if (HasGrip(*childP)) { /* Move and Display the Grip */
- changes.x = XtX(*childP) + XtWidth(*childP) -
- (XtWidth(grip) >> 1) - XtBorderWidth(grip) +
- (pw->paned.internal_bw >> 1);
- changes.y = XtHeight(pw) - pw->paned.grip_indent -
- XtHeight(grip) - (XtBorderWidth(grip) << 1);
- }
- }
-
- /*
- * This should match XtMoveWidget, except that we're also insuring the
- * grip is Raised in the same request
- */
-
- if (HasGrip(*childP)) {
- XtX(grip) = changes.x;
- XtY(grip) = changes.y;
-
- if (XtIsRealized(pane->grip))
- XConfigureWindow(XtDisplay(pane->grip), XtWindow(pane->grip),
- CWX | CWY | CWStackMode, &changes);
- }
- }
- ClearPaneStack(pw);
-}
-
-/*
- * Function:
- * RefigureLocationsAndCommit
- *
- * Parameters:
- * pw - paned widget
- *
- * Description:
- * Refigures all locations in a paned widget and commits them immediately.
- *
- * This function does nothing if any of the following are true.
- * o refiguremode is false.
- * o The widget is unrealized.
- * o There are no panes is the paned widget.
- */
-static void
-RefigureLocationsAndCommit(Widget w)
-{
- PanedWidget pw = (PanedWidget)w;
-
- if (pw->paned.refiguremode && XtIsRealized(w) && pw->paned.num_panes > 0) {
- RefigureLocations(pw, NO_INDEX, AnyPane);
- CommitNewLocations(pw);
- }
-}
-
-/*
- * Function:
- * _DrawRect
- *
- * Parameters:
- * pw - paned widget
- * gc - gc to used for the draw
- * on_olc - location of upper left corner of rect
- * off_loc - ""
- * on_size - size of rectangle
- * off_size - ""
- *
- * Description:
- * Draws a rectangle in the proper orientation.
- */
-static void
-_DrawRect(PanedWidget pw, GC gc, int on_loc, int off_loc,
- unsigned int on_size, unsigned int off_size)
-{
- if (IsVert(pw))
- XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc,
- off_loc, on_loc, off_size, on_size);
- else
- XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc,
- on_loc, off_loc, on_size, off_size);
-}
-
-/*
- * Function:
- * _DrawInternalBorders
- *
- * Parameters:
- * pw - paned widget
- * gc - GC to use to draw the borders
- *
- * Description:
- * Draws the internal borders into the paned widget.
- */
-static void
-_DrawInternalBorders(PanedWidget pw, GC gc)
-{
- Widget *childP;
- int on_loc, off_loc;
- unsigned int on_size, off_size;
-
- /*
- * This is an optimization. Do not paint the internal borders if
- * they are the same color as the background
- */
- if (pw->core.background_pixel == pw->paned.internal_bp)
- return;
-
- off_loc = 0;
- off_size = (unsigned int) PaneSize((Widget)pw, !IsVert(pw));
- on_size = (unsigned int)pw->paned.internal_bw;
-
- ForAllPanes(pw, childP) {
- on_loc = IsVert(pw) ? XtY(*childP) : XtX(*childP);
- on_loc -= (int)on_size;
-
- _DrawRect(pw, gc, on_loc, off_loc, on_size, off_size);
- }
-}
-
-#define DrawInternalBorders(pw) \
- _DrawInternalBorders((pw), (pw)->paned.normgc)
-#define EraseInternalBorders(pw) \
- _DrawInternalBorders((pw), (pw)->paned.invgc)
-/*
- * Function Name:
- * _DrawTrackLines
- *
- * Parameters:
- * pw - Paned widget
- * erase - if True then just erase track lines, else draw them in
- *
- * Description:
- * Draws the lines that animate the pane borders when the grips are moved.
- */
-static void
-_DrawTrackLines(PanedWidget pw, Bool erase)
-{
- Widget *childP;
- Pane pane;
- int on_loc, off_loc;
- unsigned int on_size, off_size;
-
- off_loc = 0;
- off_size = PaneSize((Widget)pw, !IsVert(pw));
-
- ForAllPanes(pw, childP) {
- pane = PaneInfo(*childP);
- if (erase || pane->olddelta != pane->delta) {
- on_size = pw->paned.internal_bw;
- if (!erase) {
- on_loc = PaneInfo(*childP)->olddelta - (int) on_size;
- _DrawRect(pw, pw->paned.flipgc,
- on_loc, off_loc, on_size, off_size);
- }
-
- on_loc = PaneInfo(*childP)->delta - (int)on_size;
-
- _DrawRect(pw, pw->paned.flipgc,
- on_loc, off_loc, on_size, off_size);
-
- pane->olddelta = pane->delta;
- }
- }
-}
-
-#define DrawTrackLines(pw) _DrawTrackLines((pw), False);
-#define EraseTrackLines(pw) _DrawTrackLines((pw), True);
-/*
- * Function:
- * GetEventLocation
- *
- * Parameters:
- * pw - the paned widget
- * event - pointer to an event
- *
- * Description:
- * Converts and event to an x and y location.
- *
- * Returns:
- * if this is a vertical pane then (y) else (x)
- */
-static int
-GetEventLocation(PanedWidget pw, XEvent *event)
-{
- int x, y;
-
- switch (event->xany.type) {
- case ButtonPress:
- case ButtonRelease:
- x = event->xbutton.x_root;
- y = event->xbutton.y_root;
- break;
- case KeyPress:
- case KeyRelease:
- x = event->xkey.x_root;
- y = event->xkey.y_root;
- break;
- case MotionNotify:
- x = event->xmotion.x_root;
- y = event->xmotion.y_root;
- break;
- default:
- x = pw->paned.start_loc;
- y = pw->paned.start_loc;
- }
-
- if (IsVert(pw))
- return (y);
-
- return (x);
-}
-
-/*
- * Function:
- * StartGripAdjustment
- *
- * Parameters:
- * pw - paned widget
- * grip - grip widget selected
- * dir - direction that we are to be moving
- *
- * Description:
- * Starts the grip adjustment procedure.
- */
-static void
-StartGripAdjustment(PanedWidget pw, Widget grip, Direction dir)
-{
- Widget *childP;
- Cursor cursor;
-
- pw->paned.whichadd = pw->paned.whichsub = NULL;
-
- if (dir == ThisBorderOnly || dir == UpLeftPane)
- pw->paned.whichadd = pw->composite.children[PaneIndex(grip)];
- if (dir == ThisBorderOnly || dir == LowRightPane)
- pw->paned.whichsub = pw->composite.children[PaneIndex(grip) + 1];
-
- /*
- * Change the cursor
- */
- if (XtIsRealized(grip)) {
- if (IsVert(pw)) {
- if (dir == UpLeftPane)
- cursor = pw->paned.adjust_upper_cursor;
- else if (dir == LowRightPane)
- cursor = pw->paned.adjust_lower_cursor;
- else {
- if (pw->paned.adjust_this_cursor == None)
- cursor = pw->paned.v_adjust_this_cursor;
- else
- cursor = pw->paned.adjust_this_cursor;
- }
- }
- else {
- if (dir == UpLeftPane)
- cursor = pw->paned.adjust_left_cursor;
- else if (dir == LowRightPane)
- cursor = pw->paned.adjust_right_cursor;
- else {
- if (pw->paned.adjust_this_cursor == None)
- cursor = pw->paned.h_adjust_this_cursor;
- else
- cursor = pw->paned.adjust_this_cursor;
- }
- }
-
- XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor);
- }
-
- EraseInternalBorders(pw);
- ForAllPanes(pw, childP)
- PaneInfo(*childP)->olddelta = -99;
-
- EraseTrackLines(pw);
-}
-
-/*
- * Function:
- * MoveGripAdjustment
- *
- * Parameters:
- * pw - paned widget
- * grip - grip that we are moving
- * dir - direction the pane we are interested is w.r.t the grip
- * loc - location of pointer in proper direction
- *
- * Description:
- * This routine moves all panes around when a grip is moved.
- */
-static void
-MoveGripAdjustment(PanedWidget pw, Widget grip, Direction dir, int loc)
-{
- int diff, add_size = 0, sub_size = 0;
-
- diff = loc - pw->paned.start_loc;
-
- if (pw->paned.whichadd)
- add_size = PaneSize(pw->paned.whichadd, IsVert(pw)) + diff;
-
- if (pw->paned.whichsub)
- sub_size = PaneSize(pw->paned.whichsub, IsVert(pw)) - diff;
-
- /*
- * If moving this border only then do not allow either of the borders
- * to go beyond the min or max size allowed
- */
- if (dir == ThisBorderOnly) {
- int old_add_size = add_size, old_sub_size;
-
- AssignMax(add_size, (int)PaneInfo(pw->paned.whichadd)->min);
- AssignMin(add_size, (int)PaneInfo(pw->paned.whichadd)->max);
- if (add_size != old_add_size)
- sub_size += old_add_size - add_size;
-
- old_sub_size = sub_size;
- AssignMax(sub_size, (int)PaneInfo(pw->paned.whichsub)->min);
- AssignMin(sub_size, (int)PaneInfo(pw->paned.whichsub)->max);
- if (sub_size != old_sub_size)
- return; /* Abort to current sizes */
- }
-
- if (add_size != 0)
- PaneInfo(pw->paned.whichadd)->size = add_size;
- if (sub_size != 0)
- PaneInfo(pw->paned.whichsub)->size = sub_size;
- RefigureLocations(pw, PaneIndex(grip), dir);
- DrawTrackLines(pw);
-}
-
-/*
- * Function:
- * CommitGripAdjustment
- *
- * Parameters:
- * pw - paned widget
- *
- * Description:
- * Commits the grip adjustment.
- */
-static void
-CommitGripAdjustment(PanedWidget pw)
-{
- EraseTrackLines(pw);
- CommitNewLocations(pw);
- DrawInternalBorders(pw);
-
- /*
- * Since the user selected this size then use it as the preferred size
- */
- if (pw->paned.whichadd) {
- Pane pane = PaneInfo(pw->paned.whichadd);
-
- pane->wp_size = pane->size;
- }
- if (pw->paned.whichsub) {
- Pane pane = PaneInfo(pw->paned.whichsub);
-
- pane->wp_size = pane->size;
- }
-}
-
-/*
- * Function:
- * HandleGrip
- *
- * Parameters:
- * grip - grip widget that has been moved
- * temp - (not used)
- * call_data - data passed to us from the grip widget
- *
- * Description:
- * Handles the grip manipulations.
- */
-/*ARGSUSED*/
-static void
-HandleGrip(Widget grip, XtPointer temp, XtPointer callData)
-{
- XawGripCallData call_data = (XawGripCallData)callData;
- PanedWidget pw = (PanedWidget) XtParent(grip);
- int loc;
- char action_type[2], direction[2];
- Cursor cursor;
- Arg arglist[1];
-
- if (call_data->num_params)
- XmuNCopyISOLatin1Uppered(action_type, call_data->params[0],
- sizeof(action_type));
-
- if (call_data->num_params == 0
- || (action_type[0] == 'C' && call_data->num_params != 1)
- || (action_type[0] != 'C' && call_data->num_params != 2))
- XtAppError(XtWidgetToApplicationContext(grip),
- "Paned GripAction has been passed incorrect parameters.");
-
- loc = GetEventLocation(pw, (XEvent *)call_data->event);
-
- if (action_type[0] != 'C')
- XmuNCopyISOLatin1Uppered(direction, call_data->params[1],
- sizeof(direction));
-
- switch (action_type[0]) {
- case 'S': /* Start adjustment */
- pw->paned.resize_children_to_pref = False;
- StartGripAdjustment(pw, grip, (Direction)direction[0]);
- pw->paned.start_loc = loc;
- break;
- case 'M':
- MoveGripAdjustment(pw, grip, (Direction)direction[0], loc);
- break;
- case 'C':
- XtSetArg(arglist[0], XtNcursor, &cursor);
- XtGetValues(grip, arglist, 1);
- XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor);
- CommitGripAdjustment(pw);
- break;
- default:
- XtAppError(XtWidgetToApplicationContext(grip),
- "Paned GripAction(); 1st parameter invalid");
- break;
- }
-}
-
-/*
- * Function:
- * ResortChildren
- *
- * Arguments:
- * pw - paned widget
- *
- * Description:
- * Resorts the children so that all managed children are first.
- */
-static void
-ResortChildren(PanedWidget pw)
-{
- Widget *unmanagedP, *childP;
-
- unmanagedP = NULL;
- ForAllChildren(pw, childP) {
- if (!IsPane(*childP) || !XtIsManaged(*childP)) {
- /*
- * We only keep track of the first unmanaged pane
- */
- if (unmanagedP == NULL)
- unmanagedP = childP;
- }
- else { /* must be a managed pane */
- /*
- * If an earlier widget was not a managed pane, then swap
- */
- if (unmanagedP != NULL) {
- Widget child = *unmanagedP;
-
- *unmanagedP = *childP;
- *childP = child;
- childP = unmanagedP; /* easiest to just back-track */
- unmanagedP = NULL; /* in case there is another managed */
- }
- }
- }
-}
-
-/*
- * Function:
- * ManageAndUnmanageGrips
- *
- * Parameters:
- * pw - paned widget
- *
- * Description:
- * This function manages and unmanages the grips so that
- * the managed state of each grip matches that of its pane.
- */
-static void
-ManageAndUnmanageGrips(PanedWidget pw)
-{
- WidgetList managed_grips, unmanaged_grips;
- Widget *managedP, *unmanagedP, *childP;
- Cardinal alloc_size;
-
- alloc_size = sizeof(Widget) * (pw->composite.num_children >> 1);
- managedP = managed_grips = (WidgetList)XtMalloc(alloc_size);
- unmanagedP = unmanaged_grips = (WidgetList)XtMalloc(alloc_size);
-
- ForAllChildren(pw, childP)
- if (IsPane(*childP) && HasGrip(*childP)) {
- if (XtIsManaged(*childP))
- *managedP++ = PaneInfo(*childP)->grip;
- else
- *unmanagedP++ = PaneInfo(*childP)->grip;
- }
-
- if (managedP != managed_grips) {
- *unmanagedP++ = *--managedP; /* Last grip is never managed */
- XtManageChildren(managed_grips, managedP - managed_grips);
- }
-
- if (unmanagedP != unmanaged_grips)
- XtUnmanageChildren(unmanaged_grips, unmanagedP - unmanaged_grips);
-
- XtFree((char *)managed_grips);
- XtFree((char *)unmanaged_grips);
-}
-
-/*
- * Function:
- * CreateGrip
- *
- * Parameters:
- * child - child that wants a grip to be created for it
- *
- * Description:
- * Creates a grip widget.
- */
-static void
-CreateGrip(Widget child)
-{
- PanedWidget pw = (PanedWidget)XtParent(child);
- Arg arglist[2];
- Cardinal num_args = 0;
- Cursor cursor;
-
- XtSetArg(arglist[num_args], XtNtranslations, pw->paned.grip_translations);
- num_args++;
- if ((cursor = pw->paned.grip_cursor) == None) {
- if (IsVert(pw))
- cursor = pw->paned.v_grip_cursor;
- else
- cursor = pw->paned.h_grip_cursor;
- }
-
- XtSetArg(arglist[num_args], XtNcursor, cursor);
- num_args++;
- PaneInfo(child)->grip = XtCreateWidget("grip", gripWidgetClass, (Widget)pw,
- arglist, num_args);
-
- XtAddCallback(PaneInfo(child)->grip, XtNcallback,
- HandleGrip, (XtPointer)child);
-}
-
-/*
- * Function:
- * GetGCs
- *
- * Parameters:
- * w - paned widget
- */
-static void
-GetGCs(Widget w)
-{
- PanedWidget pw = (PanedWidget)w;
- XtGCMask valuemask;
- XGCValues values;
-
- /*
- * Draw pane borders in internal border color
- */
- values.foreground = pw->paned.internal_bp;
- valuemask = GCForeground;
- pw->paned.normgc = XtGetGC(w, valuemask, &values);
-
- /*
- * Erase pane borders with background color
- */
- values.foreground = pw->core.background_pixel;
- valuemask = GCForeground;
- pw->paned.invgc = XtGetGC(w, valuemask, &values);
-
- /*
- * Draw Track lines (animate pane borders) in
- * internal border color ^ bg color
- */
- values.function = GXinvert;
- values.plane_mask = pw->paned.internal_bp ^ pw->core.background_pixel;
- values.subwindow_mode = IncludeInferiors;
- valuemask = GCPlaneMask | GCFunction | GCSubwindowMode;
- pw->paned.flipgc = XtGetGC(w, valuemask, &values);
-}
-
-/*
- * Function:
- * SetChildrenPrefSizes
- *
- * Parameters:
- * pw - paned widget
- *
- * Description:
- * Sets the preferred sizes of the children.
- */
-static void
-SetChildrenPrefSizes(PanedWidget pw, unsigned int off_size)
-{
- Widget *childP;
- Boolean vert = IsVert(pw);
- XtWidgetGeometry request, reply;
-
- ForAllPanes(pw, childP)
- if (pw->paned.resize_children_to_pref || PaneInfo(*childP)->size == 0 ||
- PaneInfo(*childP)->resize_to_pref) {
- if (PaneInfo(*childP)->preferred_size != PANED_ASK_CHILD)
- PaneInfo(*childP)->wp_size = PaneInfo(*childP)->preferred_size;
- else {
- if(vert) {
- request.request_mode = CWWidth;
- request.width = off_size;
- }
- else {
- request.request_mode = CWHeight;
- request.height = off_size;
- }
-
- if ((XtQueryGeometry(*childP, &request, &reply)
- == XtGeometryAlmost)
- && (reply.request_mode = (vert ? CWHeight : CWWidth)))
- PaneInfo(*childP)->wp_size = GetRequestInfo(&reply, vert);
- else
- PaneInfo(*childP)->wp_size = PaneSize(*childP, vert);
- }
-
- PaneInfo(*childP)->size = PaneInfo(*childP)->wp_size;
- }
-}
-
-/*
- * Function:
- * ChangeAllGripCursors
- *
- * Parameters:
- * pw - paned widget
- *
- * Description:
- * Changes all the grip cursors.
- */
-static void
-ChangeAllGripCursors(PanedWidget pw)
-{
- Widget *childP;
-
- ForAllPanes(pw, childP) {
- Arg arglist[1];
- Cursor cursor;
-
- if ((cursor = pw->paned.grip_cursor) == None) {
- if (IsVert(pw))
- cursor = pw->paned.v_grip_cursor;
- else
- cursor = pw->paned.h_grip_cursor;
- }
-
- if (HasGrip(*childP)) {
- XtSetArg(arglist[0], XtNcursor, cursor);
- XtSetValues(PaneInfo(*childP)->grip, arglist, 1);
- }
- }
-}
-
-/*
- * Function:
- * PushPaneStack
- *
- * Parameters:
- * pw - paned widget
- * pane - pane that we are pushing
- *
- * Description:
- * Pushes a value onto the pane stack.
- */
-static void
-PushPaneStack(PanedWidget pw, Pane pane)
-{
- PaneStack *stack = (PaneStack *)XtMalloc(sizeof(PaneStack));
-
- stack->next = pw->paned.stack;
- stack->pane = pane;
- stack->start_size = pane->size;
-
- pw->paned.stack = stack;
-}
-
-/*
- * Function:
- * GetPaneStack
- *
- * Parameters:
- * pw - paned widget
- * shrink - True if we want to shrink this pane, False otherwise
- * pane - pane that we are popping (return)
- * start_size - size that this pane started at (return)
- *
- * Description:
- * Gets the top value from the pane stack.
- */
-static void
-GetPaneStack(PanedWidget pw, Bool shrink, Pane *pane, int *start_size)
-{
- if (pw->paned.stack == NULL) {
- *pane = NULL;
- return;
- }
-
- *pane = pw->paned.stack->pane;
- *start_size = pw->paned.stack->start_size;
-
- if (shrink != ((*pane)->size > *start_size))
- *pane = NULL;
-}
-
-/*
- * Function:
- * PopPaneStack
- *
- * Parameters:
- * pw - paned widget
- *
- * Description:
- * Pops the top item off the pane stack.
- *
- * Returns: True if this is not the last element on the stack
- */
-static Bool
-PopPaneStack(PanedWidget pw)
-{
- PaneStack *stack = pw->paned.stack;
-
- if (stack == NULL)
- return (False);
-
- pw->paned.stack = stack->next;
- XtFree((char *)stack);
-
- if (pw->paned.stack == NULL)
- return (False);
-
- return (True);
-}
-
-/*
- * Function:
- * ClearPaneStack
- *
- * Parameters:
- * pw - paned widget
- *
- * Description:
- * Removes all entries from the pane stack.
- */
-static void
-ClearPaneStack(PanedWidget pw)
-{
- while(PopPaneStack(pw))
- ;
-}
-
-static void
-XawPanedClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation,
- NULL, 0);
- XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-/* The Geometry Manager only allows changes after Realize if
- * allow_resize is True in the constraints record.
- *
- * For vertically paned widgets:
- *
- * It only allows height changes, but offers the requested height
- * as a compromise if both width and height changes were requested.
- *
- * For horizontal widgets the converse is true.
- * As all good Geometry Managers should, we will return No if the
- * request will have no effect; i.e. when the requestor is already
- * of the desired geometry.
- */
-static XtGeometryResult
-XawPanedGeometryManager(Widget w, XtWidgetGeometry *request,
- XtWidgetGeometry *reply)
-{
- PanedWidget pw = (PanedWidget)XtParent(w);
- XtGeometryMask mask = request->request_mode;
- Dimension old_size, old_wpsize, old_paned_size;
- Pane pane = PaneInfo(w);
- Boolean vert = IsVert(pw);
- Dimension on_size, off_size;
- XtGeometryResult result;
- Boolean almost = False;
-
- /*
- * If any of the following is true, disallow the geometry change
- *
- * o The paned widget is realized and allow_resize is false for the pane
- * o The child did not ask to change the on_size
- * o The request is not a width or height request
- * o The requested size is the same as the current size
- */
-
- if ((XtIsRealized((Widget)pw) && !pane->allow_resize)
- || !(mask & (vert ? CWHeight : CWWidth))
- ||(mask & ~(CWWidth | CWHeight))
- || GetRequestInfo(request, vert) == PaneSize(w, vert))
- return (XtGeometryNo);
-
- old_paned_size = PaneSize((Widget)pw, vert);
- old_wpsize = pane->wp_size;
- old_size = pane->size;
-
- pane->wp_size = pane->size = GetRequestInfo(request, vert);
-
- AdjustPanedSize(pw, PaneSize((Widget)pw, !vert), &result, &on_size,
- &off_size);
-
- /*
- * Fool the Refigure Locations proc to thinking that we are
- * a different on_size
- */
-
- if (result != XtGeometryNo) {
- if (vert)
- XtHeight(pw) = on_size;
- else
- XtWidth(pw) = on_size;
- }
-
- RefigureLocations(pw, PaneIndex(w), AnyPane);
-
- /*
- * Set up reply struct and reset core on_size
- */
- if (vert) {
- XtHeight(pw) = old_paned_size;
- reply->height = pane->size;
- reply->width = off_size;
- }
- else {
- XtWidth(pw) = old_paned_size;
- reply->height = off_size;
- reply->width = pane->size;
- }
-
- /*
- * IF either of the following is true
- *
- * o There was a "off_size" request and the new "off_size" is different
- * from that requested
- * o There was no "off_size" request and the new "off_size" is different
- *
- * o The "on_size" we will allow is different from that requested
- *
- * THEN: set almost
- */
- if (!((vert ? CWWidth : CWHeight) & mask)) {
- if (vert)
- request->width = XtWidth(w);
- else
- request->height = XtHeight(w);
- }
-
- almost = GetRequestInfo(request, !vert) != GetRequestInfo(reply, !vert);
- almost |= (GetRequestInfo(request, vert) != GetRequestInfo(reply, vert));
-
- if ((mask & XtCWQueryOnly) || almost) {
- pane->wp_size = old_wpsize;
- pane->size = old_size;
- RefigureLocations(pw, PaneIndex(w), AnyPane);
- reply->request_mode = CWWidth | CWHeight;
- if (almost)
- return (XtGeometryAlmost);
- }
- else {
- AdjustPanedSize(pw, PaneSize((Widget) pw, !vert), NULL, NULL, NULL);
- CommitNewLocations(pw); /* layout already refigured */
- }
-
- return (XtGeometryDone);
-}
-
-/*ARGSUSED*/
-static void
-XawPanedInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- PanedWidget pw = (PanedWidget)cnew;
-
- GetGCs((Widget)pw);
-
- pw->paned.recursively_called = False;
- pw->paned.stack = NULL;
- pw->paned.resize_children_to_pref = True;
- pw->paned.num_panes = 0;
-}
-
-static void
-XawPanedRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
-{
- PanedWidget pw = (PanedWidget)w;
- Widget *childP;
-
- if ((attributes->cursor = pw->paned.cursor) != None)
- *valueMask |= CWCursor;
-
- (*SuperClass->core_class.realize)(w, valueMask, attributes);
-
- /*
- * Before we commit the new locations we need to realize all the panes and
- * their grips
- */
- ForAllPanes(pw, childP) {
- XtRealizeWidget(*childP);
- if (HasGrip(*childP))
- XtRealizeWidget(PaneInfo(*childP)->grip);
- }
-
- RefigureLocationsAndCommit(w);
- pw->paned.resize_children_to_pref = False;
-}
-
-static void
-XawPanedDestroy(Widget w)
-{
- ReleaseGCs(w);
-}
-
-static void
-ReleaseGCs(Widget w)
-{
- PanedWidget pw = (PanedWidget)w;
-
- XtReleaseGC(w, pw->paned.normgc);
- XtReleaseGC(w, pw->paned.invgc);
- XtReleaseGC(w, pw->paned.flipgc);
-}
-
-static void
-XawPanedInsertChild(Widget w)
-{
- Pane pane = PaneInfo(w);
-
- /* insert the child widget in the composite children list with the
- superclass insert_child routine
- */
- (*SuperClass->composite_class.insert_child)(w);
-
- if (!IsPane(w))
- return;
-
- if (pane->show_grip == True) {
- CreateGrip(w);
- if (pane->min == PANED_GRIP_SIZE)
- pane->min = PaneSize(pane->grip, IsVert((PanedWidget)XtParent(w)));
- }
- else {
- if (pane->min == PANED_GRIP_SIZE)
- pane->min = 1;
- pane->grip = NULL;
- }
-
- pane->size = 0;
- pane->paned_adjusted_me = False;
-}
-
-static void
-XawPanedDeleteChild(Widget w)
-{
- /* remove the subwidget info and destroy the grip */
- if (IsPane(w) && HasGrip(w))
- XtDestroyWidget(PaneInfo(w)->grip);
-
- /* delete the child widget in the composite children list with the
- superclass delete_child routine
- */
- (*SuperClass->composite_class.delete_child)(w);
-}
-
-static void
-XawPanedChangeManaged(Widget w)
-{
- PanedWidget pw = (PanedWidget)w;
- Boolean vert = IsVert(pw);
- Dimension size;
- Widget *childP;
-
- if (pw->paned.recursively_called++)
- return;
-
- /*
- * If the size is zero then set it to the size of the widest or tallest pane
- */
-
- if ((size = PaneSize((Widget)pw, !vert)) == 0) {
- size = 1;
- ForAllChildren(pw, childP)
- if (XtIsManaged(*childP) && (PaneSize(*childP, !vert) > size))
- size = PaneSize(*childP, !vert);
- }
-
- ManageAndUnmanageGrips(pw);
- pw->paned.recursively_called = False;
- ResortChildren(pw);
-
- pw->paned.num_panes = 0;
- ForAllChildren(pw, childP)
- if (IsPane(*childP)) {
- if (XtIsManaged(*childP)) {
- Pane pane = PaneInfo(*childP);
-
- if (HasGrip(*childP))
- PaneInfo(pane->grip)->position = pw->paned.num_panes;
- pane->position = pw->paned.num_panes; /* TEMPORY -CDP 3/89 */
- pw->paned.num_panes++;
- }
- else
- break; /* This list is already sorted */
- }
-
- SetChildrenPrefSizes((PanedWidget) w, size);
-
- /*
- * ForAllPanes can now be used
- */
- if (PaneSize((Widget) pw, vert) == 0)
- AdjustPanedSize(pw, size, NULL, NULL, NULL);
-
- if (XtIsRealized((Widget)pw))
- RefigureLocationsAndCommit((Widget)pw);
-}
-
-static void
-XawPanedResize(Widget w)
-{
- SetChildrenPrefSizes((PanedWidget)w,
- PaneSize(w, !IsVert((PanedWidget)w)));
- RefigureLocationsAndCommit(w);
-}
-
-/*ARGSUSED*/
-static void
-XawPanedRedisplay(Widget w, XEvent *event, Region region)
-{
- DrawInternalBorders((PanedWidget)w);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawPanedSetValues(Widget old, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- PanedWidget old_pw = (PanedWidget)old;
- PanedWidget new_pw = (PanedWidget)cnew;
- Boolean redisplay = False;
-
- if ((old_pw->paned.cursor != new_pw->paned.cursor) && XtIsRealized(cnew))
- XDefineCursor(XtDisplay(cnew), XtWindow(cnew), new_pw->paned.cursor);
-
- if (old_pw->paned.internal_bp != new_pw->paned.internal_bp ||
- old_pw->core.background_pixel != new_pw->core.background_pixel) {
- ReleaseGCs(old);
- GetGCs(cnew);
- redisplay = True;
- }
-
- if (old_pw->paned.grip_cursor != new_pw->paned.grip_cursor ||
- old_pw->paned.v_grip_cursor != new_pw->paned.v_grip_cursor ||
- old_pw->paned.h_grip_cursor != new_pw->paned.h_grip_cursor)
- ChangeAllGripCursors(new_pw);
-
- if (IsVert(old_pw) != IsVert(new_pw)) {
- /*
- * We are fooling the paned widget into thinking that is needs to
- * fully refigure everything, which is what we want
- */
- if (IsVert(new_pw))
- XtWidth(new_pw) = 0;
- else
- XtHeight(new_pw) = 0;
-
- new_pw->paned.resize_children_to_pref = True;
- XawPanedChangeManaged(cnew); /* Seems weird, but does the right thing */
- new_pw->paned.resize_children_to_pref = False;
- if (new_pw->paned.grip_cursor == None)
- ChangeAllGripCursors(new_pw);
- return (True);
- }
-
- if (old_pw->paned.internal_bw != new_pw->paned.internal_bw) {
- AdjustPanedSize(new_pw, PaneSize(cnew, !IsVert(old_pw)),
- NULL, NULL, NULL);
- RefigureLocationsAndCommit(cnew);
- return (True); /* We have done a full configuration, return */
- }
-
- if (old_pw->paned.grip_indent != new_pw->paned.grip_indent &&
- XtIsRealized(cnew)) {
- CommitNewLocations(new_pw);
- redisplay = True;
- }
-
- return (redisplay);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawPanedPaneSetValues(Widget old, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- Pane old_pane = PaneInfo(old);
- Pane new_pane = PaneInfo(cnew);
- Boolean redisplay = False;
-
- /* Check for new min and max */
- if (old_pane->min != new_pane->min || old_pane->max != new_pane->max)
- XawPanedSetMinMax(cnew, (int)new_pane->min, (int)new_pane->max);
-
- /* Check for change in XtNshowGrip */
- if (old_pane->show_grip != new_pane->show_grip) {
- if (new_pane->show_grip == True) {
- CreateGrip(cnew);
- if (XtIsRealized(XtParent(cnew))) {
- if (XtIsManaged(cnew)) /* if paned is unrealized this will
- happen automatically at realize time
- */
- XtManageChild(PaneInfo(cnew)->grip); /* manage the grip */
- XtRealizeWidget(PaneInfo(cnew)->grip); /* realize the grip */
- CommitNewLocations((PanedWidget)XtParent(cnew));
- }
- }
- else if (HasGrip(old)) {
- XtDestroyWidget(old_pane->grip);
- new_pane->grip = NULL;
- redisplay = True;
- }
- }
-
- return (redisplay);
-}
-
-/*
- * Public routines
- */
-/*
- * Function:
- * XawPanedSetMinMax
- *
- * Parameters:
- * widget - widget that is a child of the Paned widget
- * min - new min and max size for the pane
- * max - ""
- *
- * Description:
- * Sets the min and max size for a pane.
- */
-void
-XawPanedSetMinMax(Widget widget, int min, int max)
-{
- Pane pane = PaneInfo(widget);
-
- pane->min = min;
- pane->max = max;
- RefigureLocationsAndCommit(widget->core.parent);
-}
-
-/*
- * Function:
- * XawPanedGetMinMax
- *
- * Parameters:
- * widget - widget that is a child of the Paned widget
- * min - current min and max size for the pane (return)
- * max - ""
- *
- * Description:
- * Gets the min and max size for a pane.
- */
-void
-XawPanedGetMinMax(Widget widget, int *min, int *max)
-{
- Pane pane = PaneInfo(widget);
-
- *min = pane->min;
- *max = pane->max;
-}
-
-/*
- * Function:
- * XawPanedSetRefigureMode
- *
- * Parameters:
- * w - paned widget
- * mode - if False then inhibit refigure
- *
- * Description:
- * Allows a flag to be set the will inhibit
- * the paned widgets relayout routine.
- */
-void
-XawPanedSetRefigureMode(Widget w,
-#if NeedWidePrototypes
- int mode
-#else
- Boolean mode
-#endif
-)
-{
- ((PanedWidget)w)->paned.refiguremode = mode;
- RefigureLocationsAndCommit(w);
-}
-
-/*
- * Function:
- * XawPanedGetNumSub
- *
- * Parameters:
- * w - paned widget
- *
- * Description:
- * Returns the number of panes in the paned widget.
- * Returns:
- * the number of panes in the paned widget
- */
-int
-XawPanedGetNumSub(Widget w)
-{
- return (((PanedWidget)w)->paned.num_panes);
-}
-
-/*
- * Function:
- * XawPanedAllowResize
- *
- * Parameters:
- * widget - child of the paned widget
- *
- * Description:
- * Allows a flag to be set that determines if the paned
- * widget will allow geometry requests from this child.
- */
-void
-XawPanedAllowResize(Widget widget,
-#if NeedWidePrototypes
- int allow_resize
-#else
- Boolean allow_resize
-#endif
-)
-{
- PaneInfo(widget)->allow_resize = allow_resize;
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Updated and significantly modified from the Athena VPaned Widget. + * + * Date: March 1, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/cursorfont.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/Grip.h> +#include <X11/Xaw/PanedP.h> +#include <X11/Xaw/XawImP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +typedef enum { + UpLeftPane = 'U', + LowRightPane = 'L', + ThisBorderOnly = 'T', + AnyPane = 'A' +} Direction; + +#define NO_INDEX -100 +#define IS_GRIP NULL + +#define PaneInfo(w) ((Pane)(w)->core.constraints) +#define HasGrip(w) (PaneInfo(w)->grip != NULL) +#define IsPane(w) ((w)->core.widget_class != gripWidgetClass) +#define PaneIndex(w) (PaneInfo(w)->position) +#define IsVert(w) ((w)->paned.orientation == XtorientVertical) + +#define ForAllPanes(pw, childP) \ +for ((childP) = (pw)->composite.children; \ + (childP) < (pw)->composite.children + (pw)->paned.num_panes; \ + (childP)++) + +#define ForAllChildren(pw, childP) \ +for ((childP) = (pw)->composite.children; \ + (childP) < (pw)->composite.children + (pw)->composite.num_children; \ + (childP)++) + +#define PaneSize(paned, vertical) \ + ((vertical) ? XtHeight(paned) : XtWidth(paned)) + +#define GetRequestInfo(geo, vertical) \ + ((vertical) ? (geo)->height : (geo)->width) + +#define SatisfiesRule1(pane, shrink) \ + (((shrink) && ((pane)->size != (pane)->min)) \ + || (!(shrink) && ((pane)->size != (pane)->max))) + +#define SatisfiesRule2(pane) \ + (!(pane)->skip_adjust || (pane)->paned_adjusted_me) + +#define SatisfiesRule3(pane, shrink) \ + ((pane)->paned_adjusted_me \ + && (((shrink) && ((int)(pane)->wp_size <= (pane)->size)) \ + || (!(shrink) && ((int)(pane)->wp_size >= (pane)->size)))) + + +/* + * Class Methods + */ +static void XawPanedClassInitialize(void); +static void XawPanedChangeManaged(Widget); +static void XawPanedDeleteChild(Widget); +static void XawPanedDestroy(Widget); +static XtGeometryResult XawPanedGeometryManager(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawPanedInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawPanedInsertChild(Widget); +static Boolean XawPanedPaneSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static void XawPanedRealize(Widget, Mask*, XSetWindowAttributes*); +static void XawPanedRedisplay(Widget, XEvent*, Region); +static void XawPanedResize(Widget); +static Boolean XawPanedSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +static void _DrawInternalBorders(PanedWidget, GC); +static void _DrawRect(PanedWidget, GC, int, int, unsigned int, unsigned int); +static void _DrawTrackLines(PanedWidget, Bool); +static void AdjustPanedSize(PanedWidget, unsigned int, XtGeometryResult*, + Dimension*, Dimension*); +static void ChangeAllGripCursors(PanedWidget); +static Pane ChoosePaneToResize(PanedWidget, int, Direction, Bool); +static void ClearPaneStack(PanedWidget); +static void CommitGripAdjustment(PanedWidget); +static void CreateGrip(Widget); +static int GetEventLocation(PanedWidget, XEvent*); +static void GetGCs(Widget); +static void GetPaneStack(PanedWidget, Bool, Pane*, int*); +static void HandleGrip(Widget, XtPointer, XtPointer); +static void LoopAndRefigureChildren(PanedWidget, int, Direction, int*); +static void ManageAndUnmanageGrips(PanedWidget); +static void MoveGripAdjustment(PanedWidget, Widget, Direction, int); +static Bool PopPaneStack(PanedWidget); +static void PushPaneStack(PanedWidget, Pane); +static void RefigureLocations(PanedWidget, int, Direction); +static void RefigureLocationsAndCommit(Widget); +static void ReleaseGCs(Widget); +static void ResortChildren(PanedWidget); +static void SetChildrenPrefSizes(PanedWidget, unsigned int); +static void StartGripAdjustment(PanedWidget, Widget, Direction); + +/* + * Initialization + */ +static char defGripTranslations[] = +"<Btn1Down>:" "GripAction(Start,UpLeftPane)\n" +"<Btn2Down>:" "GripAction(Start,ThisBorderOnly)\n" +"<Btn3Down>:" "GripAction(Start,LowRightPane)\n" +"<Btn1Motion>:" "GripAction(Move,UpLeft)\n" +"<Btn2Motion>:" "GripAction(Move,ThisBorder)\n" +"<Btn3Motion>:" "GripAction(Move,LowRight)\n" +"Any<BtnUp>:" "GripAction(Commit)\n" +; + +#define offset(field) XtOffsetOf(PanedRec, paned.field) +static XtResource resources[] = { + { + XtNinternalBorderColor, + XtCBorderColor, + XtRPixel, + sizeof(Pixel), + offset(internal_bp), + XtRString, + (XtPointer)XtDefaultForeground + }, + { + XtNinternalBorderWidth, + XtCBorderWidth, + XtRDimension, + sizeof(Dimension), + offset(internal_bw), + XtRImmediate, + (XtPointer)1 + }, + { + XtNgripIndent, + XtCGripIndent, + XtRPosition, + sizeof(Position), + offset(grip_indent), + XtRImmediate, + (XtPointer)10 + }, + { + XtNrefigureMode, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(refiguremode), + XtRImmediate, + (XtPointer)True + }, + { + XtNgripTranslations, + XtCTranslations, + XtRTranslationTable, + sizeof(XtTranslations), + offset(grip_translations), + XtRString, + (XtPointer)defGripTranslations + }, + { + XtNorientation, + XtCOrientation, + XtROrientation, + sizeof(XtOrientation), + offset(orientation), + XtRImmediate, + (XtPointer)XtorientVertical + }, + { + XtNcursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(cursor), + XtRImmediate, + NULL + }, + { + XtNgripCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(grip_cursor), + XtRImmediate, + NULL + }, + { + XtNverticalGripCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(v_grip_cursor), + XtRString, + "sb_v_double_arrow" + }, + { + XtNhorizontalGripCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(h_grip_cursor), + XtRString, + "sb_h_double_arrow" + }, + { + XtNbetweenCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(adjust_this_cursor), + XtRString, + NULL + }, + { + XtNverticalBetweenCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(v_adjust_this_cursor), + XtRString, + "sb_left_arrow" + }, + { + XtNhorizontalBetweenCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(h_adjust_this_cursor), + XtRString, + "sb_up_arrow" + }, + { + XtNupperCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(adjust_upper_cursor), + XtRString, + "sb_up_arrow" + }, + { + XtNlowerCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(adjust_lower_cursor), + XtRString, + "sb_down_arrow" + }, + { + XtNleftCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(adjust_left_cursor), + XtRString, + "sb_left_arrow" + }, + { + XtNrightCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(adjust_right_cursor), + XtRString, + "sb_right_arrow" + }, +}; +#undef offset + +#define offset(field) XtOffsetOf(PanedConstraintsRec, paned.field) +static XtResource subresources[] = { + { + XtNallowResize, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(allow_resize), + XtRImmediate, + (XtPointer)False + }, + { + XtNposition, + XtCPosition, + XtRInt, + sizeof(int), + offset(position), + XtRImmediate, + (XtPointer)0 + }, + { + XtNmin, + XtCMin, + XtRDimension, + sizeof(Dimension), + offset(min), + XtRImmediate, + (XtPointer)PANED_GRIP_SIZE + }, + { + XtNmax, + XtCMax, + XtRDimension, + sizeof(Dimension), + offset(max), + XtRImmediate, + (XtPointer)~0 + }, + { + XtNpreferredPaneSize, + XtCPreferredPaneSize, + XtRDimension, + sizeof(Dimension), + offset(preferred_size), + XtRImmediate, + (XtPointer)PANED_ASK_CHILD + }, + { + XtNresizeToPreferred, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(resize_to_pref), + XtRImmediate, + (XtPointer)False + }, + { + XtNskipAdjust, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(skip_adjust), + XtRImmediate, + (XtPointer)False + }, + { + XtNshowGrip, + XtCShowGrip, + XtRBoolean, + sizeof(Boolean), + offset(show_grip), + XtRImmediate, + (XtPointer)True + }, +}; +#undef offset + +#define SuperClass ((ConstraintWidgetClass)&constraintClassRec) + +PanedClassRec panedClassRec = { + /* core */ + { + (WidgetClass)SuperClass, /* superclass */ + "Paned", /* class name */ + sizeof(PanedRec), /* size */ + XawPanedClassInitialize, /* class_initialize */ + NULL, /* class_part init */ + False, /* class_inited */ + XawPanedInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawPanedRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawPanedDestroy, /* destroy */ + XawPanedResize, /* resize */ + XawPanedRedisplay, /* expose */ + XawPanedSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* composite */ + { + XawPanedGeometryManager, /* geometry_manager */ + XawPanedChangeManaged, /* change_managed */ + XawPanedInsertChild, /* insert_child */ + XawPanedDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + /* constraint */ + { + subresources, /* subresources */ + XtNumber(subresources), /* subresource_count */ + sizeof(PanedConstraintsRec), /* constraint_size */ + NULL, /* initialize */ + NULL, /* destroy */ + XawPanedPaneSetValues, /* set_values */ + NULL, /* extension */ + }, +}; + +WidgetClass panedWidgetClass = (WidgetClass)&panedClassRec; +WidgetClass vPanedWidgetClass = (WidgetClass)&panedClassRec; + +/* + * Implementation + */ +/* Function: + * AdjustPanedSize + * + * Parameters: + * pw - paned widget to adjust + * off_size - new off_size to use + * result_ret - result of query (return) + * on_size_ret - new on_size (return) + * off_size_ret - new off_size (return) + * + * Description: + * Adjusts the size of the pane. + * + * Returns: + * amount of change in size + */ +static void +AdjustPanedSize(PanedWidget pw, unsigned int off_size, + XtGeometryResult *result_ret, + Dimension *on_size_ret, Dimension *off_size_ret) +{ + Dimension old_size = PaneSize((Widget)pw, IsVert(pw)); + Dimension newsize = 0; + Widget *childP; + XtWidgetGeometry request, reply; + + request.request_mode = CWWidth | CWHeight; + + ForAllPanes(pw, childP) { + int size = Max(PaneInfo(*childP)->size, (int)PaneInfo(*childP)->min); + + AssignMin(size, (int)PaneInfo(*childP)->max); + newsize += size + pw->paned.internal_bw; + } + newsize -= pw->paned.internal_bw; + + if (newsize < 1) + newsize = 1; + + if (IsVert(pw)) { + request.width = off_size; + request.height = newsize; + } + else { + request.width = newsize; + request.height = off_size; + } + + if (result_ret != NULL) { + request.request_mode |= XtCWQueryOnly; + + *result_ret = XtMakeGeometryRequest((Widget)pw, &request, &reply); + _XawImCallVendorShellExtResize((Widget)pw); + + if (newsize == old_size || *result_ret == XtGeometryNo) { + *on_size_ret = old_size; + *off_size_ret = off_size; + return; + } + if (*result_ret != XtGeometryAlmost) { + *on_size_ret = GetRequestInfo(&request, IsVert(pw)); + *off_size_ret = GetRequestInfo(&request, !IsVert(pw)); + return; + } + *on_size_ret = GetRequestInfo(&reply, IsVert(pw)); + *off_size_ret = GetRequestInfo(&reply, !IsVert(pw)); + return; + } + + if (newsize == old_size) + return; + + if (XtMakeGeometryRequest((Widget)pw, &request, &reply) == XtGeometryAlmost) + XtMakeGeometryRequest((Widget)pw, &reply, &request); +} + +/* + * Function: + * ChoosePaneToResize. + * + * Parameters: + * pw - paned widget + * paneindex - index of the current pane + * dir - direction to search first + * shrink - True if we need to shrink a pane, False otherwise + * + * Description: + * This function chooses a pane to resize. + They are chosen using the following rules: + * + * 1) size < max && size > min + * 2) skip adjust == False + * 3) widget not its prefered height + * && this change will bring it closer + * && The user has not resized this pane. + * + * If no widgets are found that fits all the rules then + * rule #3 is broken. + * If there are still no widgets found than + * rule #2 is broken. + * Rule #1 is never broken. + * If no widgets are found then NULL is returned. + * + * Returns: + * pane to resize or NULL + */ +static Pane +ChoosePaneToResize(PanedWidget pw, int paneindex, Direction dir, Bool shrink) +{ + Widget *childP; + int rules = 3; + Direction _dir = dir; + int _index = paneindex; + + if (paneindex == NO_INDEX || dir == AnyPane) { /* Use defaults */ + _dir = LowRightPane; /* Go up - really */ + _index = pw->paned.num_panes - 1; /* Start the last pane, and work + backwards */ + } + childP = pw->composite.children + _index; + + /*CONSTCOND*/ + while(True) { + Pane pane = PaneInfo(*childP); + + if ((rules < 3 || SatisfiesRule3(pane, shrink)) + && (rules < 2 || SatisfiesRule2(pane)) + && SatisfiesRule1(pane, shrink) + && (paneindex != PaneIndex(*childP) || dir == AnyPane)) + return (pane); + + /* + * This is counter-intuitive, but if we are resizing the pane + * above the grip we want to choose a pane below the grip to lose, + * and visa-versa + */ + if (_dir == LowRightPane) + --childP; + else + ++childP; + + /* + * If we have come to and edge then reduce the rule set, and try again + * If we are reduced the rules to none, then return NULL + */ + if ((childP - pw->composite.children) < 0 || + (childP - pw->composite.children) >= pw->paned.num_panes) { + if (--rules < 1) /* less strict rules */ + return (NULL); + childP = pw->composite.children + _index; + } + } +} + +/* + * Function: + * LoopAndRefigureChildren + * + * Parameters: + * pw - paned widget + * paneindex - number of the pane border we are moving + * dir - pane to move (either UpLeftPane or LowRightPane) + * sizeused - current amount of space used (used and returned) + * + * Description: + * If we are resizing either the UpleftPane or LowRight Pane loop + * through all the children to see if any will allow us to resize them. + */ +static void +LoopAndRefigureChildren(PanedWidget pw, int paneindex, Direction dir, + int *sizeused) +{ + int pane_size = (int)PaneSize((Widget)pw, IsVert(pw)); + Boolean shrink = (*sizeused > pane_size); + + if (dir == LowRightPane) + paneindex++; + + /* While all panes do not fit properly */ + while (*sizeused != pane_size) { + /* + * Choose a pane to resize + * First look on the Pane Stack, and then go hunting for another one + * If we fail to find a pane to resize then give up + */ + Pane pane; + int start_size; + Dimension old; + Boolean rule3_ok = False, from_stack = True; + + GetPaneStack(pw, shrink, &pane, &start_size); + if (pane == NULL) { + pane = ChoosePaneToResize(pw, paneindex, dir, shrink); + if (pane == NULL) + return; /* no one to resize, give up */ + + rule3_ok = SatisfiesRule3(pane, shrink); + from_stack = False; + PushPaneStack(pw, pane); + } + + /* + * Try to resize this pane so that all panes will fit, take min and max + * into account + */ + old = pane->size; + pane->size += pane_size - *sizeused; + + if (from_stack) { + if (shrink) { + AssignMax(pane->size, start_size); + } /* don't remove these braces */ + else + AssignMin(pane->size, start_size); + + if (pane->size == start_size) + (void)PopPaneStack(pw); + } + else if (rule3_ok) { + if (shrink) { + AssignMax(pane->size, (int)pane->wp_size); + } /* don't remove these braces */ + else + AssignMin(pane->size, (int)pane->wp_size); + } + + pane->paned_adjusted_me = pane->size != pane->wp_size; + AssignMax(pane->size, (int)pane->min); + AssignMin(pane->size, (int)pane->max); + *sizeused += (pane->size - old); + } +} + +/* + * Function: + * RefigureLocations + * + * Parameters: + * pw - paned widget + * paneindex - child to start refiguring at + * dir - direction to move from child + * + * Description: + * Refigures all locations of children. + * There are special arguments to paneindex and dir, they are: + * paneindex - NO_INDEX. + * dir - AnyPane. + * + * If either of these is true then all panes may be resized and + * the choosing of panes procedes in reverse order starting with the + * last child. + */ +static void +RefigureLocations(PanedWidget pw, int paneindex, Direction dir) +{ + Widget *childP; + int pane_size = (int)PaneSize((Widget)pw, IsVert(pw)); + int sizeused = 0; + Position loc = 0; + + if (pw->paned.num_panes == 0 || !pw->paned.refiguremode) + return; + + /* + * Get an initial estimate of the size we will use + */ + ForAllPanes(pw, childP) { + Pane pane = PaneInfo(*childP); + + AssignMax(pane->size, (int) pane->min); + AssignMin(pane->size, (int) pane->max); + sizeused += (int)pane->size + (int)pw->paned.internal_bw; + } + sizeused -= (int)pw->paned.internal_bw; + + if (dir != ThisBorderOnly && sizeused != pane_size) + LoopAndRefigureChildren(pw, paneindex, dir, &sizeused); + + /* + * If we still are not the right size, then tell the pane that + * wanted to resize that it can't + */ + if (paneindex != NO_INDEX && dir != AnyPane) { + Pane pane = PaneInfo(*(pw->composite.children + paneindex)); + Dimension old = pane->size; + + pane->size += pane_size - sizeused; + AssignMax(pane->size, (int) pane->min); + AssignMin(pane->size, (int) pane->max); + sizeused += pane->size - old; + } + + /* + * It is possible that the panes will not fit inside the vpaned widget, but + * we have tried out best + * + * Assign each pane a location + */ + ForAllPanes(pw, childP) { + PaneInfo(*childP)->delta = loc; + loc += PaneInfo(*childP)->size + pw->paned.internal_bw; + } +} + +/* + * Function: + * CommitNewLocations + * + * Parameters: + * pw - paned widget + * + * Description: + * Commits all of the previously figured locations. + */ +static void +CommitNewLocations(PanedWidget pw) +{ + Widget *childP; + XWindowChanges changes; + + changes.stack_mode = Above; + + ForAllPanes(pw, childP) { + Pane pane = PaneInfo(*childP); + Widget grip = pane->grip; /* may be NULL */ + + if (IsVert(pw)) { + XtMoveWidget(*childP, (Position) 0, pane->delta); + XtResizeWidget(*childP, XtWidth(pw), pane->size, 0); + + if (HasGrip(*childP)) { /* Move and Display the Grip */ + changes.x = XtWidth(pw) - pw->paned.grip_indent - + XtWidth(grip) - (XtBorderWidth(grip) << 1); + changes.y = XtY(*childP) + XtHeight(*childP) - + (XtHeight(grip) >> 1) - XtBorderWidth(grip) + + (pw->paned.internal_bw >> 1); + } + } + else { + XtMoveWidget(*childP, pane->delta, 0); + XtResizeWidget(*childP, pane->size, XtHeight(pw), 0); + + if (HasGrip(*childP)) { /* Move and Display the Grip */ + changes.x = XtX(*childP) + XtWidth(*childP) - + (XtWidth(grip) >> 1) - XtBorderWidth(grip) + + (pw->paned.internal_bw >> 1); + changes.y = XtHeight(pw) - pw->paned.grip_indent - + XtHeight(grip) - (XtBorderWidth(grip) << 1); + } + } + + /* + * This should match XtMoveWidget, except that we're also insuring the + * grip is Raised in the same request + */ + + if (HasGrip(*childP)) { + XtX(grip) = changes.x; + XtY(grip) = changes.y; + + if (XtIsRealized(pane->grip)) + XConfigureWindow(XtDisplay(pane->grip), XtWindow(pane->grip), + CWX | CWY | CWStackMode, &changes); + } + } + ClearPaneStack(pw); +} + +/* + * Function: + * RefigureLocationsAndCommit + * + * Parameters: + * pw - paned widget + * + * Description: + * Refigures all locations in a paned widget and commits them immediately. + * + * This function does nothing if any of the following are true. + * o refiguremode is false. + * o The widget is unrealized. + * o There are no panes is the paned widget. + */ +static void +RefigureLocationsAndCommit(Widget w) +{ + PanedWidget pw = (PanedWidget)w; + + if (pw->paned.refiguremode && XtIsRealized(w) && pw->paned.num_panes > 0) { + RefigureLocations(pw, NO_INDEX, AnyPane); + CommitNewLocations(pw); + } +} + +/* + * Function: + * _DrawRect + * + * Parameters: + * pw - paned widget + * gc - gc to used for the draw + * on_olc - location of upper left corner of rect + * off_loc - "" + * on_size - size of rectangle + * off_size - "" + * + * Description: + * Draws a rectangle in the proper orientation. + */ +static void +_DrawRect(PanedWidget pw, GC gc, int on_loc, int off_loc, + unsigned int on_size, unsigned int off_size) +{ + if (IsVert(pw)) + XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc, + off_loc, on_loc, off_size, on_size); + else + XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc, + on_loc, off_loc, on_size, off_size); +} + +/* + * Function: + * _DrawInternalBorders + * + * Parameters: + * pw - paned widget + * gc - GC to use to draw the borders + * + * Description: + * Draws the internal borders into the paned widget. + */ +static void +_DrawInternalBorders(PanedWidget pw, GC gc) +{ + Widget *childP; + int on_loc, off_loc; + unsigned int on_size, off_size; + + /* + * This is an optimization. Do not paint the internal borders if + * they are the same color as the background + */ + if (pw->core.background_pixel == pw->paned.internal_bp) + return; + + off_loc = 0; + off_size = (unsigned int) PaneSize((Widget)pw, !IsVert(pw)); + on_size = (unsigned int)pw->paned.internal_bw; + + ForAllPanes(pw, childP) { + on_loc = IsVert(pw) ? XtY(*childP) : XtX(*childP); + on_loc -= (int)on_size; + + _DrawRect(pw, gc, on_loc, off_loc, on_size, off_size); + } +} + +#define DrawInternalBorders(pw) \ + _DrawInternalBorders((pw), (pw)->paned.normgc) +#define EraseInternalBorders(pw) \ + _DrawInternalBorders((pw), (pw)->paned.invgc) +/* + * Function Name: + * _DrawTrackLines + * + * Parameters: + * pw - Paned widget + * erase - if True then just erase track lines, else draw them in + * + * Description: + * Draws the lines that animate the pane borders when the grips are moved. + */ +static void +_DrawTrackLines(PanedWidget pw, Bool erase) +{ + Widget *childP; + Pane pane; + int on_loc, off_loc; + unsigned int on_size, off_size; + + off_loc = 0; + off_size = PaneSize((Widget)pw, !IsVert(pw)); + + ForAllPanes(pw, childP) { + pane = PaneInfo(*childP); + if (erase || pane->olddelta != pane->delta) { + on_size = pw->paned.internal_bw; + if (!erase) { + on_loc = PaneInfo(*childP)->olddelta - (int) on_size; + _DrawRect(pw, pw->paned.flipgc, + on_loc, off_loc, on_size, off_size); + } + + on_loc = PaneInfo(*childP)->delta - (int)on_size; + + _DrawRect(pw, pw->paned.flipgc, + on_loc, off_loc, on_size, off_size); + + pane->olddelta = pane->delta; + } + } +} + +#define DrawTrackLines(pw) _DrawTrackLines((pw), False); +#define EraseTrackLines(pw) _DrawTrackLines((pw), True); +/* + * Function: + * GetEventLocation + * + * Parameters: + * pw - the paned widget + * event - pointer to an event + * + * Description: + * Converts and event to an x and y location. + * + * Returns: + * if this is a vertical pane then (y) else (x) + */ +static int +GetEventLocation(PanedWidget pw, XEvent *event) +{ + int x, y; + + switch (event->xany.type) { + case ButtonPress: + case ButtonRelease: + x = event->xbutton.x_root; + y = event->xbutton.y_root; + break; + case KeyPress: + case KeyRelease: + x = event->xkey.x_root; + y = event->xkey.y_root; + break; + case MotionNotify: + x = event->xmotion.x_root; + y = event->xmotion.y_root; + break; + default: + x = pw->paned.start_loc; + y = pw->paned.start_loc; + } + + if (IsVert(pw)) + return (y); + + return (x); +} + +/* + * Function: + * StartGripAdjustment + * + * Parameters: + * pw - paned widget + * grip - grip widget selected + * dir - direction that we are to be moving + * + * Description: + * Starts the grip adjustment procedure. + */ +static void +StartGripAdjustment(PanedWidget pw, Widget grip, Direction dir) +{ + Widget *childP; + Cursor cursor; + + pw->paned.whichadd = pw->paned.whichsub = NULL; + + if (dir == ThisBorderOnly || dir == UpLeftPane) + pw->paned.whichadd = pw->composite.children[PaneIndex(grip)]; + if (dir == ThisBorderOnly || dir == LowRightPane) + pw->paned.whichsub = pw->composite.children[PaneIndex(grip) + 1]; + + /* + * Change the cursor + */ + if (XtIsRealized(grip)) { + if (IsVert(pw)) { + if (dir == UpLeftPane) + cursor = pw->paned.adjust_upper_cursor; + else if (dir == LowRightPane) + cursor = pw->paned.adjust_lower_cursor; + else { + if (pw->paned.adjust_this_cursor == None) + cursor = pw->paned.v_adjust_this_cursor; + else + cursor = pw->paned.adjust_this_cursor; + } + } + else { + if (dir == UpLeftPane) + cursor = pw->paned.adjust_left_cursor; + else if (dir == LowRightPane) + cursor = pw->paned.adjust_right_cursor; + else { + if (pw->paned.adjust_this_cursor == None) + cursor = pw->paned.h_adjust_this_cursor; + else + cursor = pw->paned.adjust_this_cursor; + } + } + + XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor); + } + + EraseInternalBorders(pw); + ForAllPanes(pw, childP) + PaneInfo(*childP)->olddelta = -99; + + EraseTrackLines(pw); +} + +/* + * Function: + * MoveGripAdjustment + * + * Parameters: + * pw - paned widget + * grip - grip that we are moving + * dir - direction the pane we are interested is w.r.t the grip + * loc - location of pointer in proper direction + * + * Description: + * This routine moves all panes around when a grip is moved. + */ +static void +MoveGripAdjustment(PanedWidget pw, Widget grip, Direction dir, int loc) +{ + int diff, add_size = 0, sub_size = 0; + + diff = loc - pw->paned.start_loc; + + if (pw->paned.whichadd) + add_size = PaneSize(pw->paned.whichadd, IsVert(pw)) + diff; + + if (pw->paned.whichsub) + sub_size = PaneSize(pw->paned.whichsub, IsVert(pw)) - diff; + + /* + * If moving this border only then do not allow either of the borders + * to go beyond the min or max size allowed + */ + if (dir == ThisBorderOnly) { + int old_add_size = add_size, old_sub_size; + + AssignMax(add_size, (int)PaneInfo(pw->paned.whichadd)->min); + AssignMin(add_size, (int)PaneInfo(pw->paned.whichadd)->max); + if (add_size != old_add_size) + sub_size += old_add_size - add_size; + + old_sub_size = sub_size; + AssignMax(sub_size, (int)PaneInfo(pw->paned.whichsub)->min); + AssignMin(sub_size, (int)PaneInfo(pw->paned.whichsub)->max); + if (sub_size != old_sub_size) + return; /* Abort to current sizes */ + } + + if (add_size != 0) + PaneInfo(pw->paned.whichadd)->size = add_size; + if (sub_size != 0) + PaneInfo(pw->paned.whichsub)->size = sub_size; + RefigureLocations(pw, PaneIndex(grip), dir); + DrawTrackLines(pw); +} + +/* + * Function: + * CommitGripAdjustment + * + * Parameters: + * pw - paned widget + * + * Description: + * Commits the grip adjustment. + */ +static void +CommitGripAdjustment(PanedWidget pw) +{ + EraseTrackLines(pw); + CommitNewLocations(pw); + DrawInternalBorders(pw); + + /* + * Since the user selected this size then use it as the preferred size + */ + if (pw->paned.whichadd) { + Pane pane = PaneInfo(pw->paned.whichadd); + + pane->wp_size = pane->size; + } + if (pw->paned.whichsub) { + Pane pane = PaneInfo(pw->paned.whichsub); + + pane->wp_size = pane->size; + } +} + +/* + * Function: + * HandleGrip + * + * Parameters: + * grip - grip widget that has been moved + * temp - (not used) + * call_data - data passed to us from the grip widget + * + * Description: + * Handles the grip manipulations. + */ +/*ARGSUSED*/ +static void +HandleGrip(Widget grip, XtPointer temp, XtPointer callData) +{ + XawGripCallData call_data = (XawGripCallData)callData; + PanedWidget pw = (PanedWidget) XtParent(grip); + int loc; + char action_type[2], direction[2]; + Cursor cursor; + Arg arglist[1]; + + if (call_data->num_params) + XmuNCopyISOLatin1Uppered(action_type, call_data->params[0], + sizeof(action_type)); + + if (call_data->num_params == 0 + || (action_type[0] == 'C' && call_data->num_params != 1) + || (action_type[0] != 'C' && call_data->num_params != 2)) + XtAppError(XtWidgetToApplicationContext(grip), + "Paned GripAction has been passed incorrect parameters."); + + loc = GetEventLocation(pw, (XEvent *)call_data->event); + + if (action_type[0] != 'C') + XmuNCopyISOLatin1Uppered(direction, call_data->params[1], + sizeof(direction)); + + switch (action_type[0]) { + case 'S': /* Start adjustment */ + pw->paned.resize_children_to_pref = False; + StartGripAdjustment(pw, grip, (Direction)direction[0]); + pw->paned.start_loc = loc; + break; + case 'M': + MoveGripAdjustment(pw, grip, (Direction)direction[0], loc); + break; + case 'C': + XtSetArg(arglist[0], XtNcursor, &cursor); + XtGetValues(grip, arglist, 1); + XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor); + CommitGripAdjustment(pw); + break; + default: + XtAppError(XtWidgetToApplicationContext(grip), + "Paned GripAction(); 1st parameter invalid"); + break; + } +} + +/* + * Function: + * ResortChildren + * + * Arguments: + * pw - paned widget + * + * Description: + * Resorts the children so that all managed children are first. + */ +static void +ResortChildren(PanedWidget pw) +{ + Widget *unmanagedP, *childP; + + unmanagedP = NULL; + ForAllChildren(pw, childP) { + if (!IsPane(*childP) || !XtIsManaged(*childP)) { + /* + * We only keep track of the first unmanaged pane + */ + if (unmanagedP == NULL) + unmanagedP = childP; + } + else { /* must be a managed pane */ + /* + * If an earlier widget was not a managed pane, then swap + */ + if (unmanagedP != NULL) { + Widget child = *unmanagedP; + + *unmanagedP = *childP; + *childP = child; + childP = unmanagedP; /* easiest to just back-track */ + unmanagedP = NULL; /* in case there is another managed */ + } + } + } +} + +/* + * Function: + * ManageAndUnmanageGrips + * + * Parameters: + * pw - paned widget + * + * Description: + * This function manages and unmanages the grips so that + * the managed state of each grip matches that of its pane. + */ +static void +ManageAndUnmanageGrips(PanedWidget pw) +{ + WidgetList managed_grips, unmanaged_grips; + Widget *managedP, *unmanagedP, *childP; + Cardinal alloc_size; + + alloc_size = sizeof(Widget) * (pw->composite.num_children >> 1); + managedP = managed_grips = (WidgetList)XtMalloc(alloc_size); + unmanagedP = unmanaged_grips = (WidgetList)XtMalloc(alloc_size); + + ForAllChildren(pw, childP) + if (IsPane(*childP) && HasGrip(*childP)) { + if (XtIsManaged(*childP)) + *managedP++ = PaneInfo(*childP)->grip; + else + *unmanagedP++ = PaneInfo(*childP)->grip; + } + + if (managedP != managed_grips) { + *unmanagedP++ = *--managedP; /* Last grip is never managed */ + XtManageChildren(managed_grips, managedP - managed_grips); + } + + if (unmanagedP != unmanaged_grips) + XtUnmanageChildren(unmanaged_grips, unmanagedP - unmanaged_grips); + + XtFree((char *)managed_grips); + XtFree((char *)unmanaged_grips); +} + +/* + * Function: + * CreateGrip + * + * Parameters: + * child - child that wants a grip to be created for it + * + * Description: + * Creates a grip widget. + */ +static void +CreateGrip(Widget child) +{ + PanedWidget pw = (PanedWidget)XtParent(child); + Arg arglist[2]; + Cardinal num_args = 0; + Cursor cursor; + + XtSetArg(arglist[num_args], XtNtranslations, pw->paned.grip_translations); + num_args++; + if ((cursor = pw->paned.grip_cursor) == None) { + if (IsVert(pw)) + cursor = pw->paned.v_grip_cursor; + else + cursor = pw->paned.h_grip_cursor; + } + + XtSetArg(arglist[num_args], XtNcursor, cursor); + num_args++; + PaneInfo(child)->grip = XtCreateWidget("grip", gripWidgetClass, (Widget)pw, + arglist, num_args); + + XtAddCallback(PaneInfo(child)->grip, XtNcallback, + HandleGrip, (XtPointer)child); +} + +/* + * Function: + * GetGCs + * + * Parameters: + * w - paned widget + */ +static void +GetGCs(Widget w) +{ + PanedWidget pw = (PanedWidget)w; + XtGCMask valuemask; + XGCValues values; + + /* + * Draw pane borders in internal border color + */ + values.foreground = pw->paned.internal_bp; + valuemask = GCForeground; + pw->paned.normgc = XtGetGC(w, valuemask, &values); + + /* + * Erase pane borders with background color + */ + values.foreground = pw->core.background_pixel; + valuemask = GCForeground; + pw->paned.invgc = XtGetGC(w, valuemask, &values); + + /* + * Draw Track lines (animate pane borders) in + * internal border color ^ bg color + */ + values.function = GXinvert; + values.plane_mask = pw->paned.internal_bp ^ pw->core.background_pixel; + values.subwindow_mode = IncludeInferiors; + valuemask = GCPlaneMask | GCFunction | GCSubwindowMode; + pw->paned.flipgc = XtGetGC(w, valuemask, &values); +} + +/* + * Function: + * SetChildrenPrefSizes + * + * Parameters: + * pw - paned widget + * + * Description: + * Sets the preferred sizes of the children. + */ +static void +SetChildrenPrefSizes(PanedWidget pw, unsigned int off_size) +{ + Widget *childP; + Boolean vert = IsVert(pw); + XtWidgetGeometry request, reply; + + ForAllPanes(pw, childP) + if (pw->paned.resize_children_to_pref || PaneInfo(*childP)->size == 0 || + PaneInfo(*childP)->resize_to_pref) { + if (PaneInfo(*childP)->preferred_size != PANED_ASK_CHILD) + PaneInfo(*childP)->wp_size = PaneInfo(*childP)->preferred_size; + else { + if(vert) { + request.request_mode = CWWidth; + request.width = off_size; + } + else { + request.request_mode = CWHeight; + request.height = off_size; + } + + if ((XtQueryGeometry(*childP, &request, &reply) + == XtGeometryAlmost) + && (reply.request_mode = (vert ? CWHeight : CWWidth))) + PaneInfo(*childP)->wp_size = GetRequestInfo(&reply, vert); + else + PaneInfo(*childP)->wp_size = PaneSize(*childP, vert); + } + + PaneInfo(*childP)->size = PaneInfo(*childP)->wp_size; + } +} + +/* + * Function: + * ChangeAllGripCursors + * + * Parameters: + * pw - paned widget + * + * Description: + * Changes all the grip cursors. + */ +static void +ChangeAllGripCursors(PanedWidget pw) +{ + Widget *childP; + + ForAllPanes(pw, childP) { + Arg arglist[1]; + Cursor cursor; + + if ((cursor = pw->paned.grip_cursor) == None) { + if (IsVert(pw)) + cursor = pw->paned.v_grip_cursor; + else + cursor = pw->paned.h_grip_cursor; + } + + if (HasGrip(*childP)) { + XtSetArg(arglist[0], XtNcursor, cursor); + XtSetValues(PaneInfo(*childP)->grip, arglist, 1); + } + } +} + +/* + * Function: + * PushPaneStack + * + * Parameters: + * pw - paned widget + * pane - pane that we are pushing + * + * Description: + * Pushes a value onto the pane stack. + */ +static void +PushPaneStack(PanedWidget pw, Pane pane) +{ + PaneStack *stack = (PaneStack *)XtMalloc(sizeof(PaneStack)); + + stack->next = pw->paned.stack; + stack->pane = pane; + stack->start_size = pane->size; + + pw->paned.stack = stack; +} + +/* + * Function: + * GetPaneStack + * + * Parameters: + * pw - paned widget + * shrink - True if we want to shrink this pane, False otherwise + * pane - pane that we are popping (return) + * start_size - size that this pane started at (return) + * + * Description: + * Gets the top value from the pane stack. + */ +static void +GetPaneStack(PanedWidget pw, Bool shrink, Pane *pane, int *start_size) +{ + if (pw->paned.stack == NULL) { + *pane = NULL; + return; + } + + *pane = pw->paned.stack->pane; + *start_size = pw->paned.stack->start_size; + + if (shrink != ((*pane)->size > *start_size)) + *pane = NULL; +} + +/* + * Function: + * PopPaneStack + * + * Parameters: + * pw - paned widget + * + * Description: + * Pops the top item off the pane stack. + * + * Returns: True if this is not the last element on the stack + */ +static Bool +PopPaneStack(PanedWidget pw) +{ + PaneStack *stack = pw->paned.stack; + + if (stack == NULL) + return (False); + + pw->paned.stack = stack->next; + XtFree((char *)stack); + + if (pw->paned.stack == NULL) + return (False); + + return (True); +} + +/* + * Function: + * ClearPaneStack + * + * Parameters: + * pw - paned widget + * + * Description: + * Removes all entries from the pane stack. + */ +static void +ClearPaneStack(PanedWidget pw) +{ + while(PopPaneStack(pw)) + ; +} + +static void +XawPanedClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation, + NULL, 0); + XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString, + NULL, 0, XtCacheNone, NULL); +} + +/* The Geometry Manager only allows changes after Realize if + * allow_resize is True in the constraints record. + * + * For vertically paned widgets: + * + * It only allows height changes, but offers the requested height + * as a compromise if both width and height changes were requested. + * + * For horizontal widgets the converse is true. + * As all good Geometry Managers should, we will return No if the + * request will have no effect; i.e. when the requestor is already + * of the desired geometry. + */ +static XtGeometryResult +XawPanedGeometryManager(Widget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + PanedWidget pw = (PanedWidget)XtParent(w); + XtGeometryMask mask = request->request_mode; + Dimension old_size, old_wpsize, old_paned_size; + Pane pane = PaneInfo(w); + Boolean vert = IsVert(pw); + Dimension on_size, off_size; + XtGeometryResult result; + Boolean almost = False; + + /* + * If any of the following is true, disallow the geometry change + * + * o The paned widget is realized and allow_resize is false for the pane + * o The child did not ask to change the on_size + * o The request is not a width or height request + * o The requested size is the same as the current size + */ + + if ((XtIsRealized((Widget)pw) && !pane->allow_resize) + || !(mask & (vert ? CWHeight : CWWidth)) + ||(mask & ~(CWWidth | CWHeight)) + || GetRequestInfo(request, vert) == PaneSize(w, vert)) + return (XtGeometryNo); + + old_paned_size = PaneSize((Widget)pw, vert); + old_wpsize = pane->wp_size; + old_size = pane->size; + + pane->wp_size = pane->size = GetRequestInfo(request, vert); + + AdjustPanedSize(pw, PaneSize((Widget)pw, !vert), &result, &on_size, + &off_size); + + /* + * Fool the Refigure Locations proc to thinking that we are + * a different on_size + */ + + if (result != XtGeometryNo) { + if (vert) + XtHeight(pw) = on_size; + else + XtWidth(pw) = on_size; + } + + RefigureLocations(pw, PaneIndex(w), AnyPane); + + /* + * Set up reply struct and reset core on_size + */ + if (vert) { + XtHeight(pw) = old_paned_size; + reply->height = pane->size; + reply->width = off_size; + } + else { + XtWidth(pw) = old_paned_size; + reply->height = off_size; + reply->width = pane->size; + } + + /* + * IF either of the following is true + * + * o There was a "off_size" request and the new "off_size" is different + * from that requested + * o There was no "off_size" request and the new "off_size" is different + * + * o The "on_size" we will allow is different from that requested + * + * THEN: set almost + */ + if (!((vert ? CWWidth : CWHeight) & mask)) { + if (vert) + request->width = XtWidth(w); + else + request->height = XtHeight(w); + } + + almost = GetRequestInfo(request, !vert) != GetRequestInfo(reply, !vert); + almost |= (GetRequestInfo(request, vert) != GetRequestInfo(reply, vert)); + + if ((mask & XtCWQueryOnly) || almost) { + pane->wp_size = old_wpsize; + pane->size = old_size; + RefigureLocations(pw, PaneIndex(w), AnyPane); + reply->request_mode = CWWidth | CWHeight; + if (almost) + return (XtGeometryAlmost); + } + else { + AdjustPanedSize(pw, PaneSize((Widget) pw, !vert), NULL, NULL, NULL); + CommitNewLocations(pw); /* layout already refigured */ + } + + return (XtGeometryDone); +} + +/*ARGSUSED*/ +static void +XawPanedInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + PanedWidget pw = (PanedWidget)cnew; + + GetGCs((Widget)pw); + + pw->paned.recursively_called = False; + pw->paned.stack = NULL; + pw->paned.resize_children_to_pref = True; + pw->paned.num_panes = 0; +} + +static void +XawPanedRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) +{ + PanedWidget pw = (PanedWidget)w; + Widget *childP; + + if ((attributes->cursor = pw->paned.cursor) != None) + *valueMask |= CWCursor; + + (*SuperClass->core_class.realize)(w, valueMask, attributes); + + /* + * Before we commit the new locations we need to realize all the panes and + * their grips + */ + ForAllPanes(pw, childP) { + XtRealizeWidget(*childP); + if (HasGrip(*childP)) + XtRealizeWidget(PaneInfo(*childP)->grip); + } + + RefigureLocationsAndCommit(w); + pw->paned.resize_children_to_pref = False; +} + +static void +XawPanedDestroy(Widget w) +{ + ReleaseGCs(w); +} + +static void +ReleaseGCs(Widget w) +{ + PanedWidget pw = (PanedWidget)w; + + XtReleaseGC(w, pw->paned.normgc); + XtReleaseGC(w, pw->paned.invgc); + XtReleaseGC(w, pw->paned.flipgc); +} + +static void +XawPanedInsertChild(Widget w) +{ + Pane pane = PaneInfo(w); + + /* insert the child widget in the composite children list with the + superclass insert_child routine + */ + (*SuperClass->composite_class.insert_child)(w); + + if (!IsPane(w)) + return; + + if (pane->show_grip == True) { + CreateGrip(w); + if (pane->min == PANED_GRIP_SIZE) + pane->min = PaneSize(pane->grip, IsVert((PanedWidget)XtParent(w))); + } + else { + if (pane->min == PANED_GRIP_SIZE) + pane->min = 1; + pane->grip = NULL; + } + + pane->size = 0; + pane->paned_adjusted_me = False; +} + +static void +XawPanedDeleteChild(Widget w) +{ + /* remove the subwidget info and destroy the grip */ + if (IsPane(w) && HasGrip(w)) + XtDestroyWidget(PaneInfo(w)->grip); + + /* delete the child widget in the composite children list with the + superclass delete_child routine + */ + (*SuperClass->composite_class.delete_child)(w); +} + +static void +XawPanedChangeManaged(Widget w) +{ + PanedWidget pw = (PanedWidget)w; + Boolean vert = IsVert(pw); + Dimension size; + Widget *childP; + + if (pw->paned.recursively_called++) + return; + + /* + * If the size is zero then set it to the size of the widest or tallest pane + */ + + if ((size = PaneSize((Widget)pw, !vert)) == 0) { + size = 1; + ForAllChildren(pw, childP) + if (XtIsManaged(*childP) && (PaneSize(*childP, !vert) > size)) + size = PaneSize(*childP, !vert); + } + + ManageAndUnmanageGrips(pw); + pw->paned.recursively_called = False; + ResortChildren(pw); + + pw->paned.num_panes = 0; + ForAllChildren(pw, childP) + if (IsPane(*childP)) { + if (XtIsManaged(*childP)) { + Pane pane = PaneInfo(*childP); + + if (HasGrip(*childP)) + PaneInfo(pane->grip)->position = pw->paned.num_panes; + pane->position = pw->paned.num_panes; /* TEMPORY -CDP 3/89 */ + pw->paned.num_panes++; + } + else + break; /* This list is already sorted */ + } + + SetChildrenPrefSizes((PanedWidget) w, size); + + /* + * ForAllPanes can now be used + */ + if (PaneSize((Widget) pw, vert) == 0) + AdjustPanedSize(pw, size, NULL, NULL, NULL); + + if (XtIsRealized((Widget)pw)) + RefigureLocationsAndCommit((Widget)pw); +} + +static void +XawPanedResize(Widget w) +{ + SetChildrenPrefSizes((PanedWidget)w, + PaneSize(w, !IsVert((PanedWidget)w))); + RefigureLocationsAndCommit(w); +} + +/*ARGSUSED*/ +static void +XawPanedRedisplay(Widget w, XEvent *event, Region region) +{ + DrawInternalBorders((PanedWidget)w); +} + +/*ARGSUSED*/ +static Boolean +XawPanedSetValues(Widget old, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + PanedWidget old_pw = (PanedWidget)old; + PanedWidget new_pw = (PanedWidget)cnew; + Boolean redisplay = False; + + if ((old_pw->paned.cursor != new_pw->paned.cursor) && XtIsRealized(cnew)) + XDefineCursor(XtDisplay(cnew), XtWindow(cnew), new_pw->paned.cursor); + + if (old_pw->paned.internal_bp != new_pw->paned.internal_bp || + old_pw->core.background_pixel != new_pw->core.background_pixel) { + ReleaseGCs(old); + GetGCs(cnew); + redisplay = True; + } + + if (old_pw->paned.grip_cursor != new_pw->paned.grip_cursor || + old_pw->paned.v_grip_cursor != new_pw->paned.v_grip_cursor || + old_pw->paned.h_grip_cursor != new_pw->paned.h_grip_cursor) + ChangeAllGripCursors(new_pw); + + if (IsVert(old_pw) != IsVert(new_pw)) { + /* + * We are fooling the paned widget into thinking that is needs to + * fully refigure everything, which is what we want + */ + if (IsVert(new_pw)) + XtWidth(new_pw) = 0; + else + XtHeight(new_pw) = 0; + + new_pw->paned.resize_children_to_pref = True; + XawPanedChangeManaged(cnew); /* Seems weird, but does the right thing */ + new_pw->paned.resize_children_to_pref = False; + if (new_pw->paned.grip_cursor == None) + ChangeAllGripCursors(new_pw); + return (True); + } + + if (old_pw->paned.internal_bw != new_pw->paned.internal_bw) { + AdjustPanedSize(new_pw, PaneSize(cnew, !IsVert(old_pw)), + NULL, NULL, NULL); + RefigureLocationsAndCommit(cnew); + return (True); /* We have done a full configuration, return */ + } + + if (old_pw->paned.grip_indent != new_pw->paned.grip_indent && + XtIsRealized(cnew)) { + CommitNewLocations(new_pw); + redisplay = True; + } + + return (redisplay); +} + +/*ARGSUSED*/ +static Boolean +XawPanedPaneSetValues(Widget old, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + Pane old_pane = PaneInfo(old); + Pane new_pane = PaneInfo(cnew); + Boolean redisplay = False; + + /* Check for new min and max */ + if (old_pane->min != new_pane->min || old_pane->max != new_pane->max) + XawPanedSetMinMax(cnew, (int)new_pane->min, (int)new_pane->max); + + /* Check for change in XtNshowGrip */ + if (old_pane->show_grip != new_pane->show_grip) { + if (new_pane->show_grip == True) { + CreateGrip(cnew); + if (XtIsRealized(XtParent(cnew))) { + if (XtIsManaged(cnew)) /* if paned is unrealized this will + happen automatically at realize time + */ + XtManageChild(PaneInfo(cnew)->grip); /* manage the grip */ + XtRealizeWidget(PaneInfo(cnew)->grip); /* realize the grip */ + CommitNewLocations((PanedWidget)XtParent(cnew)); + } + } + else if (HasGrip(old)) { + XtDestroyWidget(old_pane->grip); + new_pane->grip = NULL; + redisplay = True; + } + } + + return (redisplay); +} + +/* + * Public routines + */ +/* + * Function: + * XawPanedSetMinMax + * + * Parameters: + * widget - widget that is a child of the Paned widget + * min - new min and max size for the pane + * max - "" + * + * Description: + * Sets the min and max size for a pane. + */ +void +XawPanedSetMinMax(Widget widget, int min, int max) +{ + Pane pane = PaneInfo(widget); + + pane->min = min; + pane->max = max; + RefigureLocationsAndCommit(widget->core.parent); +} + +/* + * Function: + * XawPanedGetMinMax + * + * Parameters: + * widget - widget that is a child of the Paned widget + * min - current min and max size for the pane (return) + * max - "" + * + * Description: + * Gets the min and max size for a pane. + */ +void +XawPanedGetMinMax(Widget widget, int *min, int *max) +{ + Pane pane = PaneInfo(widget); + + *min = pane->min; + *max = pane->max; +} + +/* + * Function: + * XawPanedSetRefigureMode + * + * Parameters: + * w - paned widget + * mode - if False then inhibit refigure + * + * Description: + * Allows a flag to be set the will inhibit + * the paned widgets relayout routine. + */ +void +XawPanedSetRefigureMode(Widget w, +#if NeedWidePrototypes + int mode +#else + Boolean mode +#endif +) +{ + ((PanedWidget)w)->paned.refiguremode = mode; + RefigureLocationsAndCommit(w); +} + +/* + * Function: + * XawPanedGetNumSub + * + * Parameters: + * w - paned widget + * + * Description: + * Returns the number of panes in the paned widget. + * Returns: + * the number of panes in the paned widget + */ +int +XawPanedGetNumSub(Widget w) +{ + return (((PanedWidget)w)->paned.num_panes); +} + +/* + * Function: + * XawPanedAllowResize + * + * Parameters: + * widget - child of the paned widget + * + * Description: + * Allows a flag to be set that determines if the paned + * widget will allow geometry requests from this child. + */ +void +XawPanedAllowResize(Widget widget, +#if NeedWidePrototypes + int allow_resize +#else + Boolean allow_resize +#endif +) +{ + PaneInfo(widget)->allow_resize = allow_resize; +} diff --git a/libXaw/src/Panner.c b/libXaw/src/Panner.c index 04c3b4ce1..2ab88f5ed 100644 --- a/libXaw/src/Panner.c +++ b/libXaw/src/Panner.c @@ -1,1079 +1,1079 @@ -/*
- *
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- * Author: Jim Fulton, MIT X Consortium
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <ctype.h>
-#include <math.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xos.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/Drawing.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xaw/PannerP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#if defined(ISC) && __STDC__ && !defined(ISC30)
-extern double atof(char *);
-#else
-#include <stdlib.h> /* for atof() */
-#endif
-
-/*
- * Class Methods
- */
-static void XawPannerDestroy(Widget);
-static void XawPannerInitialize(Widget, Widget, ArgList, Cardinal*);
-static XtGeometryResult XawPannerQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawPannerRealize(Widget, XtValueMask*, XSetWindowAttributes*);
-static void XawPannerRedisplay(Widget, XEvent*, Region);
-static void XawPannerResize(Widget);
-static Boolean XawPannerSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-static void XawPannerSetValuesAlmost(Widget, Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-
-/*
- * Prototypes
- */
-static void check_knob(PannerWidget, Bool);
-static void get_default_size(PannerWidget, Dimension*, Dimension*);
-static Bool get_event_xy(PannerWidget, XEvent*, int*, int*);
-static void move_shadow(PannerWidget);
-static int parse_page_string(char*, int, int, Bool*);
-static void rescale(PannerWidget);
-static void reset_shadow_gc(PannerWidget);
-static void reset_slider_gc(PannerWidget);
-static void reset_xor_gc(PannerWidget);
-static void scale_knob(PannerWidget, Bool, Bool);
-
-/*
- * Actions
- */
-static void ActionAbort(Widget, XEvent*, String*, Cardinal*);
-static void ActionMove(Widget, XEvent*, String*, Cardinal*);
-static void ActionNotify(Widget, XEvent*, String*, Cardinal*);
-static void ActionPage(Widget, XEvent*, String*, Cardinal*);
-static void ActionSet(Widget, XEvent*, String*, Cardinal*);
-static void ActionStart(Widget, XEvent*, String*, Cardinal*);
-static void ActionStop(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * From Xmu/Distinct.c
- */
-Bool XmuDistinguishablePixels(Display*, Colormap, unsigned long*, int);
-
-/*
- * Initialization
- */
-static char defaultTranslations[] =
-"<Btn1Down>:" "start()\n"
-"<Btn1Motion>:" "move()\n"
-"<Btn1Up>:" "notify() stop()\n"
-"<Btn2Down>:" "abort()\n"
-":<Key>KP_Enter:" "set(rubberband,toggle)\n"
-"<Key>space:" "page(+1p,+1p)\n"
-"<Key>Delete:" "page(-1p,-1p)\n"
-":<Key>KP_Delete:" "page(-1p,-1p)\n"
-"<Key>BackSpace:" "page(-1p,-1p)\n"
-"<Key>Left:" "page(-.5p,+0)\n"
-":<Key>KP_Left:" "page(-.5p,+0)\n"
-"<Key>Right:" "page(+.5p,+0)\n"
-":<Key>KP_Right:" "page(+.5p,+0)\n"
-"<Key>Up:" "page(+0,-.5p)\n"
-":<Key>KP_Up:" "page(+0,-.5p)\n"
-"<Key>Down:" "page(+0,+.5p)\n"
-":<Key>KP_Down:" "page(+0,+.5p)\n"
-"<Key>Home:" "page(0,0)\n"
-":<Key>KP_Home:" "page(0,0)\n"
-;
-
-static XtActionsRec actions[] = {
- {"start", ActionStart}, /* start tmp graphics */
- {"stop", ActionStop}, /* stop tmp graphics */
- {"abort", ActionAbort}, /* punt */
- {"move", ActionMove}, /* move tmp graphics on Motion event */
- {"page", ActionPage}, /* page around usually from keyboard */
- {"notify", ActionNotify}, /* callback new position */
- {"set", ActionSet}, /* set various parameters */
-};
-
-#define offset(field) XtOffsetOf(PannerRec, panner.field)
-static XtResource resources[] = {
- {
- XtNallowOff,
- XtCAllowOff,
- XtRBoolean,
- sizeof(Boolean),
- offset(allow_off),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNresize,
- XtCResize,
- XtRBoolean,
- sizeof(Boolean),
- offset(resize_to_pref),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNreportCallback,
- XtCReportCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(report_callbacks),
- XtRCallback,
- NULL
- },
- {
- XtNdefaultScale,
- XtCDefaultScale,
- XtRDimension,
- sizeof(Dimension),
- offset(default_scale),
- XtRImmediate,
- (XtPointer)PANNER_DEFAULT_SCALE
- },
- {
- XtNrubberBand,
- XtCRubberBand,
- XtRBoolean,
- sizeof(Boolean),
- offset(rubber_band),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(foreground),
- XtRString,
- (XtPointer)XtDefaultBackground
- },
- {
- XtNinternalSpace,
- XtCInternalSpace,
- XtRDimension,
- sizeof(Dimension),
- offset(internal_border),
- XtRImmediate,
- (XtPointer)4
- },
- {
- XtNlineWidth,
- XtCLineWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(line_width),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNcanvasWidth,
- XtCCanvasWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(canvas_width),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNcanvasHeight,
- XtCCanvasHeight,
- XtRDimension,
- sizeof(Dimension),
- offset(canvas_height),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNsliderX,
- XtCSliderX,
- XtRPosition,
- sizeof(Position),
- offset(slider_x),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNsliderY,
- XtCSliderY,
- XtRPosition,
- sizeof(Position),
- offset(slider_y),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNsliderWidth,
- XtCSliderWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(slider_width),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNsliderHeight,
- XtCSliderHeight,
- XtRDimension,
- sizeof(Dimension),
- offset(slider_height),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNshadowColor,
- XtCShadowColor,
- XtRPixel,
- sizeof(Pixel),
- offset(shadow_color),
- XtRString,
- (XtPointer)XtDefaultForeground
- },
- {
- XtNshadowThickness,
- XtCShadowThickness,
- XtRDimension,
- sizeof(Dimension),
- offset(shadow_thickness),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNbackgroundStipple,
- XtCBackgroundStipple,
- XtRString,
- sizeof(String),
- offset(stipple_name),
- XtRImmediate,
- NULL
- },
-};
-#undef offset
-
-#define Superclass (&simpleClassRec)
-PannerClassRec pannerClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "Panner", /* class_name */
- sizeof(PannerRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawPannerInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawPannerRealize, /* realize */
- actions, /* actions */
- XtNumber(actions), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawPannerDestroy, /* destroy */
- XawPannerResize, /* resize */
- XawPannerRedisplay, /* expose */
- XawPannerSetValues, /* set_values */
- NULL, /* set_values_hook */
- XawPannerSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- defaultTranslations, /* tm_table */
- XawPannerQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* panner */
- {
- NULL, /* extension */
- }
-};
-
-WidgetClass pannerWidgetClass = (WidgetClass) &pannerClassRec;
-
-
-/*
- * Implementation
- */
-static void
-reset_shadow_gc(PannerWidget pw)
-{
- XtGCMask valuemask = GCForeground;
- XGCValues values;
- unsigned long pixels[3];
-
- if (pw->panner.shadow_gc)
- XtReleaseGC((Widget)pw, pw->panner.shadow_gc);
-
- pixels[0] = pw->panner.foreground;
- pixels[1] = pw->core.background_pixel;
- pixels[2] = pw->panner.shadow_color;
-
- if (!pw->panner.stipple_name &&
- !XmuDistinguishablePixels(XtDisplay(pw), pw->core.colormap,
- pixels, 3) &&
- XmuDistinguishablePixels(XtDisplay(pw), pw->core.colormap,
- pixels, 2)) {
- valuemask = GCTile | GCFillStyle;
- values.fill_style = FillTiled;
- values.tile = XmuCreateStippledPixmap(XtScreen((Widget)pw),
- pw->panner.foreground,
- pw->core.background_pixel,
- pw->core.depth);
- }
- else {
- if (!pw->panner.line_width &&
- !XmuDistinguishablePixels(XtDisplay(pw), pw->core.colormap,
- pixels, 2))
- pw->panner.line_width = 1;
- valuemask = GCForeground;
- values.foreground = pw->panner.shadow_color;
- }
- if (pw->panner.line_width > 0) {
- values.line_width = pw->panner.line_width;
- valuemask |= GCLineWidth;
- }
-
- pw->panner.shadow_gc = XtGetGC((Widget)pw, valuemask, &values);
-}
-
-static void
-reset_slider_gc(PannerWidget pw)
-{
- XtGCMask valuemask = GCForeground;
- XGCValues values;
-
- if (pw->panner.slider_gc)
- XtReleaseGC((Widget)pw, pw->panner.slider_gc);
-
- values.foreground = pw->panner.foreground;
-
- pw->panner.slider_gc = XtGetGC((Widget)pw, valuemask, &values);
-}
-
-static void
-reset_xor_gc(PannerWidget pw)
-{
- if (pw->panner.xor_gc)
- XtReleaseGC((Widget)pw, pw->panner.xor_gc);
-
- if (pw->panner.rubber_band) {
- XtGCMask valuemask = (GCForeground | GCFunction);
- XGCValues values;
- Pixel tmp;
-
- tmp = (pw->panner.foreground == pw->core.background_pixel ?
- pw->panner.shadow_color : pw->panner.foreground);
- values.foreground = tmp ^ pw->core.background_pixel;
- values.function = GXxor;
- if (pw->panner.line_width > 0) {
- valuemask |= GCLineWidth;
- values.line_width = pw->panner.line_width;
- }
- pw->panner.xor_gc = XtGetGC((Widget)pw, valuemask, &values);
- }
- else
- pw->panner.xor_gc = NULL;
-}
-
-static void
-check_knob(PannerWidget pw, Bool knob)
-{
- Position pad = pw->panner.internal_border << 1;
- Position maxx = (Position)XtWidth(pw) - pad -
- (Position)pw->panner.knob_width;
- Position maxy = (Position)XtHeight(pw) - pad -
- (Position)pw->panner.knob_height;
- Position *x = knob ? &pw->panner.knob_x : &pw->panner.tmp.x;
- Position *y = knob ? &pw->panner.knob_y : &pw->panner.tmp.y;
-
- /*
- * note that positions are already normalized (i.e. internal_border
- * has been subtracted out)
- */
- if (*x < 0)
- *x = 0;
- if (*x > maxx)
- *x = maxx;
-
- if (*y < 0)
- *y = 0;
- if (*y > maxy)
- *y = maxy;
-
- if (knob) {
- pw->panner.slider_x = (Position)((double)pw->panner.knob_x
- / pw->panner.haspect + 0.5);
- pw->panner.slider_y = (Position)((double)pw->panner.knob_y
- / pw->panner.vaspect + 0.5);
- pw->panner.last_x = pw->panner.last_y = PANNER_OUTOFRANGE;
- }
-}
-
-static void
-move_shadow(PannerWidget pw)
-{
- if (pw->panner.shadow_thickness > 0) {
- int lw = pw->panner.shadow_thickness + (pw->panner.line_width << 1);
- int pad = pw->panner.internal_border;
-
- if (pw->panner.knob_height > lw && pw->panner.knob_width > lw) {
- XRectangle *r = pw->panner.shadow_rects;
-
- r->x = pw->panner.knob_x + pad + pw->panner.knob_width;
- r->y = pw->panner.knob_y + pad + lw;
- r->width = pw->panner.shadow_thickness;
- r->height = pw->panner.knob_height - lw;
- r++;
- r->x = pw->panner.knob_x + pad + lw;
- r->y = pw->panner.knob_y + pad + pw->panner.knob_height;
- r->width = pw->panner.knob_width - lw + pw->panner.shadow_thickness;
- r->height = pw->panner.shadow_thickness;
- pw->panner.shadow_valid = True;
- return;
- }
- }
- pw->panner.shadow_valid = False;
-}
-
-static void
-scale_knob(PannerWidget pw, Bool location, Bool size)
-{
- if (location) {
- pw->panner.knob_x = (Position)PANNER_HSCALE(pw, pw->panner.slider_x);
- pw->panner.knob_y = (Position)PANNER_VSCALE(pw, pw->panner.slider_y);
- }
- if (size) {
- Dimension width, height;
-
- if (pw->panner.slider_width < 1)
- pw->panner.slider_width = pw->panner.canvas_width;
- if (pw->panner.slider_height < 1)
- pw->panner.slider_height = pw->panner.canvas_height;
- width = Min(pw->panner.slider_width, pw->panner.canvas_width);
- height = Min(pw->panner.slider_height, pw->panner.canvas_height);
-
- pw->panner.knob_width = (Dimension)PANNER_HSCALE(pw, width);
- pw->panner.knob_height = (Dimension)PANNER_VSCALE(pw, height);
- }
- if (!pw->panner.allow_off)
- check_knob(pw, True);
- move_shadow(pw);
-}
-
-static void
-rescale(PannerWidget pw)
-{
- int hpad = pw->panner.internal_border << 1;
- int vpad = hpad;
-
- if (pw->panner.canvas_width < 1)
- pw->panner.canvas_width = XtWidth(pw);
- if (pw->panner.canvas_height < 1)
- pw->panner.canvas_height = XtHeight(pw);
-
- if (XtWidth(pw) <= hpad)
- hpad = 0;
- if (XtHeight(pw) <= vpad)
- vpad = 0;
-
- pw->panner.haspect = ((double)XtWidth(pw) - hpad + .5)
- / (double)pw->panner.canvas_width;
- pw->panner.vaspect = ((double)XtHeight(pw) - vpad + .5)
- / (double)pw->panner.canvas_height;
- scale_knob(pw, True, True);
-}
-
-static void
-get_default_size(PannerWidget pw, Dimension *wp, Dimension *hp)
-{
- Dimension pad = pw->panner.internal_border << 1;
-
- *wp = PANNER_DSCALE(pw, pw->panner.canvas_width) + pad;
- *hp = PANNER_DSCALE(pw, pw->panner.canvas_height) + pad;
-}
-
-static Bool
-get_event_xy(PannerWidget pw, XEvent *event, int *x, int *y)
-{
- int pad = pw->panner.internal_border;
-
- switch (event->type) {
- case ButtonPress:
- case ButtonRelease:
- *x = event->xbutton.x - pad;
- *y = event->xbutton.y - pad;
- return (True);
- case KeyPress:
- case KeyRelease:
- *x = event->xkey.x - pad;
- *y = event->xkey.y - pad;
- return (True);
- case EnterNotify:
- case LeaveNotify:
- *x = event->xcrossing.x - pad;
- *y = event->xcrossing.y - pad;
- return (True);
- case MotionNotify:
- *x = event->xmotion.x - pad;
- *y = event->xmotion.y - pad;
- return (True);
- }
-
- return (False);
-}
-
-static int
-parse_page_string(char *s, int pagesize, int canvassize, Bool *relative)
-{
- char *cp;
- double val = 1.0;
- Bool rel = False;
-
- /*
- * syntax: spaces [+-] number spaces [pc\0] spaces
- */
- for (; isascii(*s) && isspace(*s); s++) /* skip white space */
- ;
-
- if (*s == '+' || *s == '-') { /* deal with signs */
- rel = True;
- if (*s == '-')
- val = -1.0;
- s++;
- }
- if (!*s) { /* if null then return nothing */
- *relative = True;
- return (0);
- }
-
- /* skip over numbers */
- for (cp = s; isascii(*s) && (isdigit(*s) || *s == '.'); s++)
- ;
- val *= atof(cp);
-
- /* skip blanks */
- for (; isascii(*s) && isspace(*s); s++)
- ;
-
- if (*s) { /* if units */
- switch (s[0]) {
- case 'p':
- case 'P':
- val *= (double)pagesize;
- break;
- case 'c':
- case 'C':
- val *= (double)canvassize;
- break;
- }
- }
- *relative = rel;
-
- return ((int)val);
-}
-
-#define DRAW_TMP(pw) \
-{ \
- XDrawRectangle(XtDisplay(pw), XtWindow(pw), \
- pw->panner.xor_gc, \
- pw->panner.tmp.x + pw->panner.internal_border, \
- pw->panner.tmp.y + pw->panner.internal_border, \
- pw->panner.knob_width - 1, \
- pw->panner.knob_height - 1); \
- pw->panner.tmp.showing = !pw->panner.tmp.showing; \
-}
-
-#define UNDRAW_TMP(pw) \
-{ \
- if (pw->panner.tmp.showing) \
- DRAW_TMP(pw); \
-}
-
-#define BACKGROUND_STIPPLE(pw) \
-XmuLocatePixmapFile(pw->core.screen, pw->panner.stipple_name, \
- pw->panner.shadow_color, pw->core.background_pixel, \
- pw->core.depth, NULL, 0, NULL, NULL, NULL, NULL)
-
-#define PIXMAP_OKAY(pm) ((pm) != None && (pm) != XtUnspecifiedPixmap)
-
-/*ARGSUSED*/
-static void
-XawPannerInitialize(Widget greq, Widget gnew, ArgList args, Cardinal *num_args)
-{
- PannerWidget req = (PannerWidget)greq, cnew = (PannerWidget)gnew;
- Dimension defwidth, defheight;
-
- if (req->panner.canvas_width < 1)
- cnew->panner.canvas_width = 1;
- if (req->panner.canvas_height < 1)
- cnew->panner.canvas_height = 1;
- if (req->panner.default_scale < 1)
- cnew->panner.default_scale = PANNER_DEFAULT_SCALE;
-
- get_default_size(req, &defwidth, &defheight);
- if (XtWidth(req) < 1)
- XtWidth(cnew) = defwidth;
- if (XtHeight(req) < 1)
- XtHeight(cnew) = defheight;
-
- cnew->panner.shadow_gc = NULL;
- reset_shadow_gc(cnew); /* shadowColor */
- cnew->panner.slider_gc = NULL;
- reset_slider_gc(cnew); /* foreground */
- cnew->panner.xor_gc = NULL;
- reset_xor_gc(cnew); /* foreground ^ background */
-
- rescale(cnew); /* does a position check */
- cnew->panner.shadow_valid = False;
- cnew->panner.tmp.doing = False;
- cnew->panner.tmp.showing = False;
- }
-
-static void
-XawPannerRealize(Widget gw, XtValueMask *valuemaskp,
- XSetWindowAttributes *attr)
-{
- PannerWidget pw = (PannerWidget)gw;
- Pixmap pm = XtUnspecifiedPixmap;
- Bool gotpm = False;
-
- if (pw->core.background_pixmap == XtUnspecifiedPixmap) {
- if (pw->panner.stipple_name)
- pm = BACKGROUND_STIPPLE(pw);
-
- if (PIXMAP_OKAY(pm)) {
- attr->background_pixmap = pm;
- *valuemaskp |= CWBackPixmap;
- *valuemaskp &= ~CWBackPixel;
- gotpm = True;
- }
- }
- (*pannerWidgetClass->core_class.superclass->core_class.realize)
- (gw, valuemaskp, attr);
-
- if (gotpm)
- XFreePixmap(XtDisplay(gw), pm);
-}
-
-static void
-XawPannerDestroy(Widget gw)
-{
- PannerWidget pw = (PannerWidget)gw;
-
- XtReleaseGC(gw, pw->panner.shadow_gc);
- XtReleaseGC(gw, pw->panner.slider_gc);
- XtReleaseGC(gw, pw->panner.xor_gc);
-}
-
-static void
-XawPannerResize(Widget gw)
-{
- rescale((PannerWidget)gw);
-}
-
-static void
-XawPannerRedisplay(Widget gw, XEvent *event, Region region)
-{
- PannerWidget pw = (PannerWidget)gw;
- Display *dpy = XtDisplay(gw);
- Window w = XtWindow(gw);
- int pad = pw->panner.internal_border;
- Dimension lw = pw->panner.line_width;
- Dimension extra = pw->panner.shadow_thickness + (lw << 1);
- int kx = pw->panner.knob_x + pad, ky = pw->panner.knob_y + pad;
-
- if (Superclass->core_class.expose)
- (Superclass->core_class.expose)(gw, event, region);
-
- pw->panner.tmp.showing = False;
- XClearArea(XtDisplay(pw), XtWindow(pw),
- (int)pw->panner.last_x - ((int)lw) + pad,
- (int)pw->panner.last_y - ((int)lw) + pad,
- pw->panner.knob_width + extra,
- pw->panner.knob_height + extra,
- False);
- pw->panner.last_x = pw->panner.knob_x;
- pw->panner.last_y = pw->panner.knob_y;
-
- XFillRectangle(dpy, w, pw->panner.slider_gc, kx, ky,
- pw->panner.knob_width - 1, pw->panner.knob_height - 1);
-
- if (lw)
- XDrawRectangle(dpy, w, pw->panner.shadow_gc, kx, ky,
- pw->panner.knob_width - 1, pw->panner.knob_height - 1);
-
- if (pw->panner.shadow_valid)
- XFillRectangles(dpy, w, pw->panner.shadow_gc, pw->panner.shadow_rects, 2);
-
- if (pw->panner.tmp.doing && pw->panner.rubber_band)
- DRAW_TMP(pw);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawPannerSetValues(Widget gcur, Widget greq, Widget gnew,
- ArgList args, Cardinal *num_args)
-{
- PannerWidget cur = (PannerWidget)gcur;
- PannerWidget cnew = (PannerWidget)gnew;
- Bool redisplay = False;
-
- if (cur->panner.foreground != cnew->panner.foreground) {
- reset_slider_gc(cnew);
- if (cur->panner.foreground != cur->core.background_pixel)
- reset_xor_gc(cnew);
- redisplay = True;
- }
- else if (cur->panner.line_width != cnew->panner.line_width ||
- cur->core.background_pixel != cnew->core.background_pixel) {
- reset_xor_gc(cnew);
- redisplay = True;
- }
- if (cur->panner.shadow_color != cnew->panner.shadow_color) {
- reset_shadow_gc(cnew);
- if (cur->panner.foreground == cur->core.background_pixel)
- reset_xor_gc(cnew);
- redisplay = True;
- }
- if (cur->panner.shadow_thickness != cnew->panner.shadow_thickness) {
- move_shadow(cnew);
- redisplay = True;
- }
- if (cur->panner.rubber_band != cnew->panner.rubber_band) {
- reset_xor_gc(cnew);
- if (cnew->panner.tmp.doing)
- redisplay = True;
- }
-
- if ((cur->panner.stipple_name != cnew->panner.stipple_name
- || cur->panner.shadow_color != cnew->panner.shadow_color
- || cur->core.background_pixel != cnew->core.background_pixel)
- && XtIsRealized(gnew)) {
- Pixmap pm = cnew->panner.stipple_name ?
- BACKGROUND_STIPPLE(cnew) : XtUnspecifiedPixmap;
-
- if (PIXMAP_OKAY(pm)) {
- XSetWindowBackgroundPixmap(XtDisplay(cnew), XtWindow(cnew), pm);
- XFreePixmap(XtDisplay(cnew), pm);
- }
- else
- XSetWindowBackground(XtDisplay(cnew), XtWindow(cnew),
- cnew->core.background_pixel);
-
- redisplay = True;
- }
-
- if (cnew->panner.resize_to_pref &&
- (cur->panner.canvas_width != cnew->panner.canvas_width
- || cur->panner.canvas_height != cnew->panner.canvas_height
- || cur->panner.resize_to_pref != cnew->panner.resize_to_pref)) {
- get_default_size(cnew, &cnew->core.width, &cnew->core.height);
- redisplay = True;
- }
- else if (cur->panner.canvas_width != cnew->panner.canvas_width
- || cur->panner.canvas_height != cnew->panner.canvas_height
- || cur->panner.internal_border != cnew->panner.internal_border) {
- rescale(cnew); /* does a scale_knob as well */
- redisplay = True;
- }
- else {
- Bool loc = cur->panner.slider_x != cnew->panner.slider_x ||
- cur->panner.slider_y != cnew->panner.slider_y;
- Bool siz = cur->panner.slider_width != cnew->panner.slider_width ||
- cur->panner.slider_height != cnew->panner.slider_height;
- if (loc || siz || (cur->panner.allow_off != cnew->panner.allow_off
- && cnew->panner.allow_off)) {
- scale_knob(cnew, loc, siz);
- redisplay = True;
- }
- }
-
- return (redisplay);
-}
-
-static void
-XawPannerSetValuesAlmost(Widget gold, Widget gnew, XtWidgetGeometry *req,
- XtWidgetGeometry *reply)
-{
- if (reply->request_mode == 0) /* got turned down, so cope */
- XawPannerResize(gnew);
-
- (*pannerWidgetClass->core_class.superclass->core_class.set_values_almost)
- (gold, gnew, req, reply);
-}
-
-static XtGeometryResult
-XawPannerQueryGeometry(Widget gw, XtWidgetGeometry *intended,
- XtWidgetGeometry *pref)
-{
- PannerWidget pw = (PannerWidget)gw;
-
- pref->request_mode = (CWWidth | CWHeight);
- get_default_size(pw, &pref->width, &pref->height);
-
- if (((intended->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight))
- && intended->width == pref->width && intended->height == pref->height)
- return (XtGeometryYes);
- else if (pref->width == XtWidth(pw) && pref->height == XtHeight(pw))
- return (XtGeometryNo);
-
- return (XtGeometryAlmost);
-}
-
-
-/*ARGSUSED*/
-static void
-ActionStart(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- PannerWidget pw = (PannerWidget)gw;
- int x, y;
-
- if (!get_event_xy(pw, event, &x, &y)) {
- XBell(XtDisplay(gw), 0);
- return;
- }
-
- pw->panner.tmp.doing = True;
- pw->panner.tmp.startx = pw->panner.knob_x;
- pw->panner.tmp.starty = pw->panner.knob_y;
- pw->panner.tmp.dx = x - pw->panner.knob_x;
- pw->panner.tmp.dy = y - pw->panner.knob_y;
- pw->panner.tmp.x = pw->panner.knob_x;
- pw->panner.tmp.y = pw->panner.knob_y;
- if (pw->panner.rubber_band)
- DRAW_TMP(pw);
-}
-
-/*ARGSUSED*/
-static void
-ActionStop(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- PannerWidget pw = (PannerWidget)gw;
- int x, y;
-
- if (get_event_xy(pw, event, &x, &y)) {
- pw->panner.tmp.x = x - pw->panner.tmp.dx;
- pw->panner.tmp.y = y - pw->panner.tmp.dy;
- if (!pw->panner.allow_off)
- check_knob(pw, False);
- }
- if (pw->panner.rubber_band)
- DRAW_TMP(pw);
- pw->panner.tmp.doing = False;
-}
-
-static void
-ActionAbort(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- PannerWidget pw = (PannerWidget)gw;
-
- if (!pw->panner.tmp.doing)
- return;
-
- if (pw->panner.rubber_band)
- UNDRAW_TMP(pw);
-
- if (!pw->panner.rubber_band) { /* restore old position */
- pw->panner.tmp.x = pw->panner.tmp.startx;
- pw->panner.tmp.y = pw->panner.tmp.starty;
- ActionNotify(gw, event, params, num_params);
- }
- pw->panner.tmp.doing = False;
-}
-
-static void
-ActionMove(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- PannerWidget pw = (PannerWidget)gw;
- int x, y;
-
- if (!pw->panner.tmp.doing)
- return;
-
- if (!get_event_xy(pw, event, &x, &y)) {
- XBell(XtDisplay(gw), 0); /* should do error message */
- return;
- }
-
- if (pw->panner.rubber_band)
- UNDRAW_TMP(pw);
- pw->panner.tmp.x = x - pw->panner.tmp.dx;
- pw->panner.tmp.y = y - pw->panner.tmp.dy;
-
- if (!pw->panner.rubber_band)
- ActionNotify(gw, event, params, num_params);
- else {
- if (!pw->panner.allow_off)
- check_knob(pw, False);
- DRAW_TMP(pw);
- }
-}
-
-
-static void
-ActionPage(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- PannerWidget pw = (PannerWidget)gw;
- Cardinal zero = 0;
- Bool isin = pw->panner.tmp.doing;
- int x, y;
- Bool relx, rely;
- int pad = pw->panner.internal_border << 1;
-
- if (*num_params != 2) {
- XBell(XtDisplay(gw), 0);
- return;
- }
-
- x = parse_page_string(params[0], pw->panner.knob_width,
- (int)XtWidth(pw) - pad, &relx);
- y = parse_page_string(params[1], pw->panner.knob_height,
- (int)XtHeight(pw) - pad, &rely);
-
- if (relx)
- x += pw->panner.knob_x;
- if (rely)
- y += pw->panner.knob_y;
-
- if (isin) { /* if in, then use move */
- XEvent ev;
-
- ev.xbutton.type = ButtonPress;
- ev.xbutton.x = x;
- ev.xbutton.y = y;
- ActionMove(gw, &ev, NULL, &zero);
- }
- else {
- pw->panner.tmp.doing = True;
- pw->panner.tmp.x = x;
- pw->panner.tmp.y = y;
- ActionNotify(gw, event, NULL, &zero);
- pw->panner.tmp.doing = False;
- }
-}
-
-/*ARGSUSED*/
-static void
-ActionNotify(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- PannerWidget pw = (PannerWidget)gw;
-
- if (!pw->panner.tmp.doing)
- return;
-
- if (!pw->panner.allow_off)
- check_knob(pw, False);
- pw->panner.knob_x = pw->panner.tmp.x;
- pw->panner.knob_y = pw->panner.tmp.y;
- move_shadow(pw);
-
- pw->panner.slider_x = (Position)((double)pw->panner.knob_x
- / pw->panner.haspect + 0.5);
- pw->panner.slider_y = (Position)((double) pw->panner.knob_y
- / pw->panner.vaspect + 0.5);
- if (!pw->panner.allow_off) {
- Position tmp;
-
- if (pw->panner.slider_x
- > (tmp = (Position)pw->panner.canvas_width -
- (Position)pw->panner.slider_width))
- pw->panner.slider_x = tmp;
- if (pw->panner.slider_x < 0)
- pw->panner.slider_x = 0;
- if (pw->panner.slider_y
- > (tmp = (Position)pw->panner.canvas_height -
- (Position)pw->panner.slider_height))
- pw->panner.slider_y = tmp;
- if (pw->panner.slider_y < 0)
- pw->panner.slider_y = 0;
- }
-
- if (pw->panner.last_x != pw->panner.knob_x ||
- pw->panner.last_y != pw->panner.knob_y) {
- XawPannerReport rep;
-
- XawPannerRedisplay(gw, NULL, NULL);
- rep.changed = XawPRSliderX | XawPRSliderY;
- rep.slider_x = pw->panner.slider_x;
- rep.slider_y = pw->panner.slider_y;
- rep.slider_width = pw->panner.slider_width;
- rep.slider_height = pw->panner.slider_height;
- rep.canvas_width = pw->panner.canvas_width;
- rep.canvas_height = pw->panner.canvas_height;
- XtCallCallbackList(gw, pw->panner.report_callbacks, (XtPointer)&rep);
- }
-}
-
-/*ARGSUSED*/
-static void
-ActionSet(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- PannerWidget pw = (PannerWidget)gw;
- Bool rb;
-
- if (*num_params < 2 ||
- XmuCompareISOLatin1(params[0], "rubberband") != 0) {
- XBell(XtDisplay(gw), 0);
- return;
- }
-
- if (XmuCompareISOLatin1(params[1], "on") == 0)
- rb = True;
- else if (XmuCompareISOLatin1(params[1], "off") == 0)
- rb = False;
- else if (XmuCompareISOLatin1(params[1], "toggle") == 0)
- rb = !pw->panner.rubber_band;
- else {
- XBell(XtDisplay(gw), 0);
- return;
- }
-
- if (rb != pw->panner.rubber_band) {
- Arg args[1];
-
- XtSetArg(args[0], XtNrubberBand, rb);
- XtSetValues(gw, args, 1);
- }
-}
+/* + * +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Jim Fulton, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <ctype.h> +#include <math.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw/PannerP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#if defined(ISC) && __STDC__ && !defined(ISC30) +extern double atof(char *); +#else +#include <stdlib.h> /* for atof() */ +#endif + +/* + * Class Methods + */ +static void XawPannerDestroy(Widget); +static void XawPannerInitialize(Widget, Widget, ArgList, Cardinal*); +static XtGeometryResult XawPannerQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawPannerRealize(Widget, XtValueMask*, XSetWindowAttributes*); +static void XawPannerRedisplay(Widget, XEvent*, Region); +static void XawPannerResize(Widget); +static Boolean XawPannerSetValues(Widget, Widget, Widget, ArgList, Cardinal*); +static void XawPannerSetValuesAlmost(Widget, Widget, XtWidgetGeometry*, + XtWidgetGeometry*); + +/* + * Prototypes + */ +static void check_knob(PannerWidget, Bool); +static void get_default_size(PannerWidget, Dimension*, Dimension*); +static Bool get_event_xy(PannerWidget, XEvent*, int*, int*); +static void move_shadow(PannerWidget); +static int parse_page_string(char*, int, int, Bool*); +static void rescale(PannerWidget); +static void reset_shadow_gc(PannerWidget); +static void reset_slider_gc(PannerWidget); +static void reset_xor_gc(PannerWidget); +static void scale_knob(PannerWidget, Bool, Bool); + +/* + * Actions + */ +static void ActionAbort(Widget, XEvent*, String*, Cardinal*); +static void ActionMove(Widget, XEvent*, String*, Cardinal*); +static void ActionNotify(Widget, XEvent*, String*, Cardinal*); +static void ActionPage(Widget, XEvent*, String*, Cardinal*); +static void ActionSet(Widget, XEvent*, String*, Cardinal*); +static void ActionStart(Widget, XEvent*, String*, Cardinal*); +static void ActionStop(Widget, XEvent*, String*, Cardinal*); + +/* + * From Xmu/Distinct.c + */ +Bool XmuDistinguishablePixels(Display*, Colormap, unsigned long*, int); + +/* + * Initialization + */ +static char defaultTranslations[] = +"<Btn1Down>:" "start()\n" +"<Btn1Motion>:" "move()\n" +"<Btn1Up>:" "notify() stop()\n" +"<Btn2Down>:" "abort()\n" +":<Key>KP_Enter:" "set(rubberband,toggle)\n" +"<Key>space:" "page(+1p,+1p)\n" +"<Key>Delete:" "page(-1p,-1p)\n" +":<Key>KP_Delete:" "page(-1p,-1p)\n" +"<Key>BackSpace:" "page(-1p,-1p)\n" +"<Key>Left:" "page(-.5p,+0)\n" +":<Key>KP_Left:" "page(-.5p,+0)\n" +"<Key>Right:" "page(+.5p,+0)\n" +":<Key>KP_Right:" "page(+.5p,+0)\n" +"<Key>Up:" "page(+0,-.5p)\n" +":<Key>KP_Up:" "page(+0,-.5p)\n" +"<Key>Down:" "page(+0,+.5p)\n" +":<Key>KP_Down:" "page(+0,+.5p)\n" +"<Key>Home:" "page(0,0)\n" +":<Key>KP_Home:" "page(0,0)\n" +; + +static XtActionsRec actions[] = { + {"start", ActionStart}, /* start tmp graphics */ + {"stop", ActionStop}, /* stop tmp graphics */ + {"abort", ActionAbort}, /* punt */ + {"move", ActionMove}, /* move tmp graphics on Motion event */ + {"page", ActionPage}, /* page around usually from keyboard */ + {"notify", ActionNotify}, /* callback new position */ + {"set", ActionSet}, /* set various parameters */ +}; + +#define offset(field) XtOffsetOf(PannerRec, panner.field) +static XtResource resources[] = { + { + XtNallowOff, + XtCAllowOff, + XtRBoolean, + sizeof(Boolean), + offset(allow_off), + XtRImmediate, + (XtPointer)False + }, + { + XtNresize, + XtCResize, + XtRBoolean, + sizeof(Boolean), + offset(resize_to_pref), + XtRImmediate, + (XtPointer)True + }, + { + XtNreportCallback, + XtCReportCallback, + XtRCallback, + sizeof(XtPointer), + offset(report_callbacks), + XtRCallback, + NULL + }, + { + XtNdefaultScale, + XtCDefaultScale, + XtRDimension, + sizeof(Dimension), + offset(default_scale), + XtRImmediate, + (XtPointer)PANNER_DEFAULT_SCALE + }, + { + XtNrubberBand, + XtCRubberBand, + XtRBoolean, + sizeof(Boolean), + offset(rubber_band), + XtRImmediate, + (XtPointer)False + }, + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(foreground), + XtRString, + (XtPointer)XtDefaultBackground + }, + { + XtNinternalSpace, + XtCInternalSpace, + XtRDimension, + sizeof(Dimension), + offset(internal_border), + XtRImmediate, + (XtPointer)4 + }, + { + XtNlineWidth, + XtCLineWidth, + XtRDimension, + sizeof(Dimension), + offset(line_width), + XtRImmediate, + (XtPointer)0 + }, + { + XtNcanvasWidth, + XtCCanvasWidth, + XtRDimension, + sizeof(Dimension), + offset(canvas_width), + XtRImmediate, + (XtPointer)0 + }, + { + XtNcanvasHeight, + XtCCanvasHeight, + XtRDimension, + sizeof(Dimension), + offset(canvas_height), + XtRImmediate, + (XtPointer)0 + }, + { + XtNsliderX, + XtCSliderX, + XtRPosition, + sizeof(Position), + offset(slider_x), + XtRImmediate, + (XtPointer)0 + }, + { + XtNsliderY, + XtCSliderY, + XtRPosition, + sizeof(Position), + offset(slider_y), + XtRImmediate, + (XtPointer)0 + }, + { + XtNsliderWidth, + XtCSliderWidth, + XtRDimension, + sizeof(Dimension), + offset(slider_width), + XtRImmediate, + (XtPointer)0 + }, + { + XtNsliderHeight, + XtCSliderHeight, + XtRDimension, + sizeof(Dimension), + offset(slider_height), + XtRImmediate, + (XtPointer)0 + }, + { + XtNshadowColor, + XtCShadowColor, + XtRPixel, + sizeof(Pixel), + offset(shadow_color), + XtRString, + (XtPointer)XtDefaultForeground + }, + { + XtNshadowThickness, + XtCShadowThickness, + XtRDimension, + sizeof(Dimension), + offset(shadow_thickness), + XtRImmediate, + (XtPointer)2 + }, + { + XtNbackgroundStipple, + XtCBackgroundStipple, + XtRString, + sizeof(String), + offset(stipple_name), + XtRImmediate, + NULL + }, +}; +#undef offset + +#define Superclass (&simpleClassRec) +PannerClassRec pannerClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Panner", /* class_name */ + sizeof(PannerRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawPannerInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawPannerRealize, /* realize */ + actions, /* actions */ + XtNumber(actions), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawPannerDestroy, /* destroy */ + XawPannerResize, /* resize */ + XawPannerRedisplay, /* expose */ + XawPannerSetValues, /* set_values */ + NULL, /* set_values_hook */ + XawPannerSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XawPannerQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* panner */ + { + NULL, /* extension */ + } +}; + +WidgetClass pannerWidgetClass = (WidgetClass) &pannerClassRec; + + +/* + * Implementation + */ +static void +reset_shadow_gc(PannerWidget pw) +{ + XtGCMask valuemask = GCForeground; + XGCValues values; + unsigned long pixels[3]; + + if (pw->panner.shadow_gc) + XtReleaseGC((Widget)pw, pw->panner.shadow_gc); + + pixels[0] = pw->panner.foreground; + pixels[1] = pw->core.background_pixel; + pixels[2] = pw->panner.shadow_color; + + if (!pw->panner.stipple_name && + !XmuDistinguishablePixels(XtDisplay(pw), pw->core.colormap, + pixels, 3) && + XmuDistinguishablePixels(XtDisplay(pw), pw->core.colormap, + pixels, 2)) { + valuemask = GCTile | GCFillStyle; + values.fill_style = FillTiled; + values.tile = XmuCreateStippledPixmap(XtScreen((Widget)pw), + pw->panner.foreground, + pw->core.background_pixel, + pw->core.depth); + } + else { + if (!pw->panner.line_width && + !XmuDistinguishablePixels(XtDisplay(pw), pw->core.colormap, + pixels, 2)) + pw->panner.line_width = 1; + valuemask = GCForeground; + values.foreground = pw->panner.shadow_color; + } + if (pw->panner.line_width > 0) { + values.line_width = pw->panner.line_width; + valuemask |= GCLineWidth; + } + + pw->panner.shadow_gc = XtGetGC((Widget)pw, valuemask, &values); +} + +static void +reset_slider_gc(PannerWidget pw) +{ + XtGCMask valuemask = GCForeground; + XGCValues values; + + if (pw->panner.slider_gc) + XtReleaseGC((Widget)pw, pw->panner.slider_gc); + + values.foreground = pw->panner.foreground; + + pw->panner.slider_gc = XtGetGC((Widget)pw, valuemask, &values); +} + +static void +reset_xor_gc(PannerWidget pw) +{ + if (pw->panner.xor_gc) + XtReleaseGC((Widget)pw, pw->panner.xor_gc); + + if (pw->panner.rubber_band) { + XtGCMask valuemask = (GCForeground | GCFunction); + XGCValues values; + Pixel tmp; + + tmp = (pw->panner.foreground == pw->core.background_pixel ? + pw->panner.shadow_color : pw->panner.foreground); + values.foreground = tmp ^ pw->core.background_pixel; + values.function = GXxor; + if (pw->panner.line_width > 0) { + valuemask |= GCLineWidth; + values.line_width = pw->panner.line_width; + } + pw->panner.xor_gc = XtGetGC((Widget)pw, valuemask, &values); + } + else + pw->panner.xor_gc = NULL; +} + +static void +check_knob(PannerWidget pw, Bool knob) +{ + Position pad = pw->panner.internal_border << 1; + Position maxx = (Position)XtWidth(pw) - pad - + (Position)pw->panner.knob_width; + Position maxy = (Position)XtHeight(pw) - pad - + (Position)pw->panner.knob_height; + Position *x = knob ? &pw->panner.knob_x : &pw->panner.tmp.x; + Position *y = knob ? &pw->panner.knob_y : &pw->panner.tmp.y; + + /* + * note that positions are already normalized (i.e. internal_border + * has been subtracted out) + */ + if (*x < 0) + *x = 0; + if (*x > maxx) + *x = maxx; + + if (*y < 0) + *y = 0; + if (*y > maxy) + *y = maxy; + + if (knob) { + pw->panner.slider_x = (Position)((double)pw->panner.knob_x + / pw->panner.haspect + 0.5); + pw->panner.slider_y = (Position)((double)pw->panner.knob_y + / pw->panner.vaspect + 0.5); + pw->panner.last_x = pw->panner.last_y = PANNER_OUTOFRANGE; + } +} + +static void +move_shadow(PannerWidget pw) +{ + if (pw->panner.shadow_thickness > 0) { + int lw = pw->panner.shadow_thickness + (pw->panner.line_width << 1); + int pad = pw->panner.internal_border; + + if (pw->panner.knob_height > lw && pw->panner.knob_width > lw) { + XRectangle *r = pw->panner.shadow_rects; + + r->x = pw->panner.knob_x + pad + pw->panner.knob_width; + r->y = pw->panner.knob_y + pad + lw; + r->width = pw->panner.shadow_thickness; + r->height = pw->panner.knob_height - lw; + r++; + r->x = pw->panner.knob_x + pad + lw; + r->y = pw->panner.knob_y + pad + pw->panner.knob_height; + r->width = pw->panner.knob_width - lw + pw->panner.shadow_thickness; + r->height = pw->panner.shadow_thickness; + pw->panner.shadow_valid = True; + return; + } + } + pw->panner.shadow_valid = False; +} + +static void +scale_knob(PannerWidget pw, Bool location, Bool size) +{ + if (location) { + pw->panner.knob_x = (Position)PANNER_HSCALE(pw, pw->panner.slider_x); + pw->panner.knob_y = (Position)PANNER_VSCALE(pw, pw->panner.slider_y); + } + if (size) { + Dimension width, height; + + if (pw->panner.slider_width < 1) + pw->panner.slider_width = pw->panner.canvas_width; + if (pw->panner.slider_height < 1) + pw->panner.slider_height = pw->panner.canvas_height; + width = Min(pw->panner.slider_width, pw->panner.canvas_width); + height = Min(pw->panner.slider_height, pw->panner.canvas_height); + + pw->panner.knob_width = (Dimension)PANNER_HSCALE(pw, width); + pw->panner.knob_height = (Dimension)PANNER_VSCALE(pw, height); + } + if (!pw->panner.allow_off) + check_knob(pw, True); + move_shadow(pw); +} + +static void +rescale(PannerWidget pw) +{ + int hpad = pw->panner.internal_border << 1; + int vpad = hpad; + + if (pw->panner.canvas_width < 1) + pw->panner.canvas_width = XtWidth(pw); + if (pw->panner.canvas_height < 1) + pw->panner.canvas_height = XtHeight(pw); + + if (XtWidth(pw) <= hpad) + hpad = 0; + if (XtHeight(pw) <= vpad) + vpad = 0; + + pw->panner.haspect = ((double)XtWidth(pw) - hpad + .5) + / (double)pw->panner.canvas_width; + pw->panner.vaspect = ((double)XtHeight(pw) - vpad + .5) + / (double)pw->panner.canvas_height; + scale_knob(pw, True, True); +} + +static void +get_default_size(PannerWidget pw, Dimension *wp, Dimension *hp) +{ + Dimension pad = pw->panner.internal_border << 1; + + *wp = PANNER_DSCALE(pw, pw->panner.canvas_width) + pad; + *hp = PANNER_DSCALE(pw, pw->panner.canvas_height) + pad; +} + +static Bool +get_event_xy(PannerWidget pw, XEvent *event, int *x, int *y) +{ + int pad = pw->panner.internal_border; + + switch (event->type) { + case ButtonPress: + case ButtonRelease: + *x = event->xbutton.x - pad; + *y = event->xbutton.y - pad; + return (True); + case KeyPress: + case KeyRelease: + *x = event->xkey.x - pad; + *y = event->xkey.y - pad; + return (True); + case EnterNotify: + case LeaveNotify: + *x = event->xcrossing.x - pad; + *y = event->xcrossing.y - pad; + return (True); + case MotionNotify: + *x = event->xmotion.x - pad; + *y = event->xmotion.y - pad; + return (True); + } + + return (False); +} + +static int +parse_page_string(char *s, int pagesize, int canvassize, Bool *relative) +{ + char *cp; + double val = 1.0; + Bool rel = False; + + /* + * syntax: spaces [+-] number spaces [pc\0] spaces + */ + for (; isascii(*s) && isspace(*s); s++) /* skip white space */ + ; + + if (*s == '+' || *s == '-') { /* deal with signs */ + rel = True; + if (*s == '-') + val = -1.0; + s++; + } + if (!*s) { /* if null then return nothing */ + *relative = True; + return (0); + } + + /* skip over numbers */ + for (cp = s; isascii(*s) && (isdigit(*s) || *s == '.'); s++) + ; + val *= atof(cp); + + /* skip blanks */ + for (; isascii(*s) && isspace(*s); s++) + ; + + if (*s) { /* if units */ + switch (s[0]) { + case 'p': + case 'P': + val *= (double)pagesize; + break; + case 'c': + case 'C': + val *= (double)canvassize; + break; + } + } + *relative = rel; + + return ((int)val); +} + +#define DRAW_TMP(pw) \ +{ \ + XDrawRectangle(XtDisplay(pw), XtWindow(pw), \ + pw->panner.xor_gc, \ + pw->panner.tmp.x + pw->panner.internal_border, \ + pw->panner.tmp.y + pw->panner.internal_border, \ + pw->panner.knob_width - 1, \ + pw->panner.knob_height - 1); \ + pw->panner.tmp.showing = !pw->panner.tmp.showing; \ +} + +#define UNDRAW_TMP(pw) \ +{ \ + if (pw->panner.tmp.showing) \ + DRAW_TMP(pw); \ +} + +#define BACKGROUND_STIPPLE(pw) \ +XmuLocatePixmapFile(pw->core.screen, pw->panner.stipple_name, \ + pw->panner.shadow_color, pw->core.background_pixel, \ + pw->core.depth, NULL, 0, NULL, NULL, NULL, NULL) + +#define PIXMAP_OKAY(pm) ((pm) != None && (pm) != XtUnspecifiedPixmap) + +/*ARGSUSED*/ +static void +XawPannerInitialize(Widget greq, Widget gnew, ArgList args, Cardinal *num_args) +{ + PannerWidget req = (PannerWidget)greq, cnew = (PannerWidget)gnew; + Dimension defwidth, defheight; + + if (req->panner.canvas_width < 1) + cnew->panner.canvas_width = 1; + if (req->panner.canvas_height < 1) + cnew->panner.canvas_height = 1; + if (req->panner.default_scale < 1) + cnew->panner.default_scale = PANNER_DEFAULT_SCALE; + + get_default_size(req, &defwidth, &defheight); + if (XtWidth(req) < 1) + XtWidth(cnew) = defwidth; + if (XtHeight(req) < 1) + XtHeight(cnew) = defheight; + + cnew->panner.shadow_gc = NULL; + reset_shadow_gc(cnew); /* shadowColor */ + cnew->panner.slider_gc = NULL; + reset_slider_gc(cnew); /* foreground */ + cnew->panner.xor_gc = NULL; + reset_xor_gc(cnew); /* foreground ^ background */ + + rescale(cnew); /* does a position check */ + cnew->panner.shadow_valid = False; + cnew->panner.tmp.doing = False; + cnew->panner.tmp.showing = False; + } + +static void +XawPannerRealize(Widget gw, XtValueMask *valuemaskp, + XSetWindowAttributes *attr) +{ + PannerWidget pw = (PannerWidget)gw; + Pixmap pm = XtUnspecifiedPixmap; + Bool gotpm = False; + + if (pw->core.background_pixmap == XtUnspecifiedPixmap) { + if (pw->panner.stipple_name) + pm = BACKGROUND_STIPPLE(pw); + + if (PIXMAP_OKAY(pm)) { + attr->background_pixmap = pm; + *valuemaskp |= CWBackPixmap; + *valuemaskp &= ~CWBackPixel; + gotpm = True; + } + } + (*pannerWidgetClass->core_class.superclass->core_class.realize) + (gw, valuemaskp, attr); + + if (gotpm) + XFreePixmap(XtDisplay(gw), pm); +} + +static void +XawPannerDestroy(Widget gw) +{ + PannerWidget pw = (PannerWidget)gw; + + XtReleaseGC(gw, pw->panner.shadow_gc); + XtReleaseGC(gw, pw->panner.slider_gc); + XtReleaseGC(gw, pw->panner.xor_gc); +} + +static void +XawPannerResize(Widget gw) +{ + rescale((PannerWidget)gw); +} + +static void +XawPannerRedisplay(Widget gw, XEvent *event, Region region) +{ + PannerWidget pw = (PannerWidget)gw; + Display *dpy = XtDisplay(gw); + Window w = XtWindow(gw); + int pad = pw->panner.internal_border; + Dimension lw = pw->panner.line_width; + Dimension extra = pw->panner.shadow_thickness + (lw << 1); + int kx = pw->panner.knob_x + pad, ky = pw->panner.knob_y + pad; + + if (Superclass->core_class.expose) + (Superclass->core_class.expose)(gw, event, region); + + pw->panner.tmp.showing = False; + XClearArea(XtDisplay(pw), XtWindow(pw), + (int)pw->panner.last_x - ((int)lw) + pad, + (int)pw->panner.last_y - ((int)lw) + pad, + pw->panner.knob_width + extra, + pw->panner.knob_height + extra, + False); + pw->panner.last_x = pw->panner.knob_x; + pw->panner.last_y = pw->panner.knob_y; + + XFillRectangle(dpy, w, pw->panner.slider_gc, kx, ky, + pw->panner.knob_width - 1, pw->panner.knob_height - 1); + + if (lw) + XDrawRectangle(dpy, w, pw->panner.shadow_gc, kx, ky, + pw->panner.knob_width - 1, pw->panner.knob_height - 1); + + if (pw->panner.shadow_valid) + XFillRectangles(dpy, w, pw->panner.shadow_gc, pw->panner.shadow_rects, 2); + + if (pw->panner.tmp.doing && pw->panner.rubber_band) + DRAW_TMP(pw); +} + +/*ARGSUSED*/ +static Boolean +XawPannerSetValues(Widget gcur, Widget greq, Widget gnew, + ArgList args, Cardinal *num_args) +{ + PannerWidget cur = (PannerWidget)gcur; + PannerWidget cnew = (PannerWidget)gnew; + Bool redisplay = False; + + if (cur->panner.foreground != cnew->panner.foreground) { + reset_slider_gc(cnew); + if (cur->panner.foreground != cur->core.background_pixel) + reset_xor_gc(cnew); + redisplay = True; + } + else if (cur->panner.line_width != cnew->panner.line_width || + cur->core.background_pixel != cnew->core.background_pixel) { + reset_xor_gc(cnew); + redisplay = True; + } + if (cur->panner.shadow_color != cnew->panner.shadow_color) { + reset_shadow_gc(cnew); + if (cur->panner.foreground == cur->core.background_pixel) + reset_xor_gc(cnew); + redisplay = True; + } + if (cur->panner.shadow_thickness != cnew->panner.shadow_thickness) { + move_shadow(cnew); + redisplay = True; + } + if (cur->panner.rubber_band != cnew->panner.rubber_band) { + reset_xor_gc(cnew); + if (cnew->panner.tmp.doing) + redisplay = True; + } + + if ((cur->panner.stipple_name != cnew->panner.stipple_name + || cur->panner.shadow_color != cnew->panner.shadow_color + || cur->core.background_pixel != cnew->core.background_pixel) + && XtIsRealized(gnew)) { + Pixmap pm = cnew->panner.stipple_name ? + BACKGROUND_STIPPLE(cnew) : XtUnspecifiedPixmap; + + if (PIXMAP_OKAY(pm)) { + XSetWindowBackgroundPixmap(XtDisplay(cnew), XtWindow(cnew), pm); + XFreePixmap(XtDisplay(cnew), pm); + } + else + XSetWindowBackground(XtDisplay(cnew), XtWindow(cnew), + cnew->core.background_pixel); + + redisplay = True; + } + + if (cnew->panner.resize_to_pref && + (cur->panner.canvas_width != cnew->panner.canvas_width + || cur->panner.canvas_height != cnew->panner.canvas_height + || cur->panner.resize_to_pref != cnew->panner.resize_to_pref)) { + get_default_size(cnew, &cnew->core.width, &cnew->core.height); + redisplay = True; + } + else if (cur->panner.canvas_width != cnew->panner.canvas_width + || cur->panner.canvas_height != cnew->panner.canvas_height + || cur->panner.internal_border != cnew->panner.internal_border) { + rescale(cnew); /* does a scale_knob as well */ + redisplay = True; + } + else { + Bool loc = cur->panner.slider_x != cnew->panner.slider_x || + cur->panner.slider_y != cnew->panner.slider_y; + Bool siz = cur->panner.slider_width != cnew->panner.slider_width || + cur->panner.slider_height != cnew->panner.slider_height; + if (loc || siz || (cur->panner.allow_off != cnew->panner.allow_off + && cnew->panner.allow_off)) { + scale_knob(cnew, loc, siz); + redisplay = True; + } + } + + return (redisplay); +} + +static void +XawPannerSetValuesAlmost(Widget gold, Widget gnew, XtWidgetGeometry *req, + XtWidgetGeometry *reply) +{ + if (reply->request_mode == 0) /* got turned down, so cope */ + XawPannerResize(gnew); + + (*pannerWidgetClass->core_class.superclass->core_class.set_values_almost) + (gold, gnew, req, reply); +} + +static XtGeometryResult +XawPannerQueryGeometry(Widget gw, XtWidgetGeometry *intended, + XtWidgetGeometry *pref) +{ + PannerWidget pw = (PannerWidget)gw; + + pref->request_mode = (CWWidth | CWHeight); + get_default_size(pw, &pref->width, &pref->height); + + if (((intended->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight)) + && intended->width == pref->width && intended->height == pref->height) + return (XtGeometryYes); + else if (pref->width == XtWidth(pw) && pref->height == XtHeight(pw)) + return (XtGeometryNo); + + return (XtGeometryAlmost); +} + + +/*ARGSUSED*/ +static void +ActionStart(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + PannerWidget pw = (PannerWidget)gw; + int x, y; + + if (!get_event_xy(pw, event, &x, &y)) { + XBell(XtDisplay(gw), 0); + return; + } + + pw->panner.tmp.doing = True; + pw->panner.tmp.startx = pw->panner.knob_x; + pw->panner.tmp.starty = pw->panner.knob_y; + pw->panner.tmp.dx = x - pw->panner.knob_x; + pw->panner.tmp.dy = y - pw->panner.knob_y; + pw->panner.tmp.x = pw->panner.knob_x; + pw->panner.tmp.y = pw->panner.knob_y; + if (pw->panner.rubber_band) + DRAW_TMP(pw); +} + +/*ARGSUSED*/ +static void +ActionStop(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + PannerWidget pw = (PannerWidget)gw; + int x, y; + + if (get_event_xy(pw, event, &x, &y)) { + pw->panner.tmp.x = x - pw->panner.tmp.dx; + pw->panner.tmp.y = y - pw->panner.tmp.dy; + if (!pw->panner.allow_off) + check_knob(pw, False); + } + if (pw->panner.rubber_band) + DRAW_TMP(pw); + pw->panner.tmp.doing = False; +} + +static void +ActionAbort(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + PannerWidget pw = (PannerWidget)gw; + + if (!pw->panner.tmp.doing) + return; + + if (pw->panner.rubber_band) + UNDRAW_TMP(pw); + + if (!pw->panner.rubber_band) { /* restore old position */ + pw->panner.tmp.x = pw->panner.tmp.startx; + pw->panner.tmp.y = pw->panner.tmp.starty; + ActionNotify(gw, event, params, num_params); + } + pw->panner.tmp.doing = False; +} + +static void +ActionMove(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + PannerWidget pw = (PannerWidget)gw; + int x, y; + + if (!pw->panner.tmp.doing) + return; + + if (!get_event_xy(pw, event, &x, &y)) { + XBell(XtDisplay(gw), 0); /* should do error message */ + return; + } + + if (pw->panner.rubber_band) + UNDRAW_TMP(pw); + pw->panner.tmp.x = x - pw->panner.tmp.dx; + pw->panner.tmp.y = y - pw->panner.tmp.dy; + + if (!pw->panner.rubber_band) + ActionNotify(gw, event, params, num_params); + else { + if (!pw->panner.allow_off) + check_knob(pw, False); + DRAW_TMP(pw); + } +} + + +static void +ActionPage(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + PannerWidget pw = (PannerWidget)gw; + Cardinal zero = 0; + Bool isin = pw->panner.tmp.doing; + int x, y; + Bool relx, rely; + int pad = pw->panner.internal_border << 1; + + if (*num_params != 2) { + XBell(XtDisplay(gw), 0); + return; + } + + x = parse_page_string(params[0], pw->panner.knob_width, + (int)XtWidth(pw) - pad, &relx); + y = parse_page_string(params[1], pw->panner.knob_height, + (int)XtHeight(pw) - pad, &rely); + + if (relx) + x += pw->panner.knob_x; + if (rely) + y += pw->panner.knob_y; + + if (isin) { /* if in, then use move */ + XEvent ev; + + ev.xbutton.type = ButtonPress; + ev.xbutton.x = x; + ev.xbutton.y = y; + ActionMove(gw, &ev, NULL, &zero); + } + else { + pw->panner.tmp.doing = True; + pw->panner.tmp.x = x; + pw->panner.tmp.y = y; + ActionNotify(gw, event, NULL, &zero); + pw->panner.tmp.doing = False; + } +} + +/*ARGSUSED*/ +static void +ActionNotify(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + PannerWidget pw = (PannerWidget)gw; + + if (!pw->panner.tmp.doing) + return; + + if (!pw->panner.allow_off) + check_knob(pw, False); + pw->panner.knob_x = pw->panner.tmp.x; + pw->panner.knob_y = pw->panner.tmp.y; + move_shadow(pw); + + pw->panner.slider_x = (Position)((double)pw->panner.knob_x + / pw->panner.haspect + 0.5); + pw->panner.slider_y = (Position)((double) pw->panner.knob_y + / pw->panner.vaspect + 0.5); + if (!pw->panner.allow_off) { + Position tmp; + + if (pw->panner.slider_x + > (tmp = (Position)pw->panner.canvas_width - + (Position)pw->panner.slider_width)) + pw->panner.slider_x = tmp; + if (pw->panner.slider_x < 0) + pw->panner.slider_x = 0; + if (pw->panner.slider_y + > (tmp = (Position)pw->panner.canvas_height - + (Position)pw->panner.slider_height)) + pw->panner.slider_y = tmp; + if (pw->panner.slider_y < 0) + pw->panner.slider_y = 0; + } + + if (pw->panner.last_x != pw->panner.knob_x || + pw->panner.last_y != pw->panner.knob_y) { + XawPannerReport rep; + + XawPannerRedisplay(gw, NULL, NULL); + rep.changed = XawPRSliderX | XawPRSliderY; + rep.slider_x = pw->panner.slider_x; + rep.slider_y = pw->panner.slider_y; + rep.slider_width = pw->panner.slider_width; + rep.slider_height = pw->panner.slider_height; + rep.canvas_width = pw->panner.canvas_width; + rep.canvas_height = pw->panner.canvas_height; + XtCallCallbackList(gw, pw->panner.report_callbacks, (XtPointer)&rep); + } +} + +/*ARGSUSED*/ +static void +ActionSet(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + PannerWidget pw = (PannerWidget)gw; + Bool rb; + + if (*num_params < 2 || + XmuCompareISOLatin1(params[0], "rubberband") != 0) { + XBell(XtDisplay(gw), 0); + return; + } + + if (XmuCompareISOLatin1(params[1], "on") == 0) + rb = True; + else if (XmuCompareISOLatin1(params[1], "off") == 0) + rb = False; + else if (XmuCompareISOLatin1(params[1], "toggle") == 0) + rb = !pw->panner.rubber_band; + else { + XBell(XtDisplay(gw), 0); + return; + } + + if (rb != pw->panner.rubber_band) { + Arg args[1]; + + XtSetArg(args[0], XtNrubberBand, rb); + XtSetValues(gw, args, 1); + } +} diff --git a/libXaw/src/Pixmap.c b/libXaw/src/Pixmap.c index 92880c247..b1718b50f 100644 --- a/libXaw/src/Pixmap.c +++ b/libXaw/src/Pixmap.c @@ -1,995 +1,995 @@ -/*
- * Copyright (c) 1998 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the XFree86 Project shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from the
- * XFree86 Project.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <X11/IntrinsicP.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xfuncs.h>
-#include <X11/extensions/shape.h>
-#ifndef OLDXAW
-#include <X11/xpm.h>
-#endif
-#include "Private.h"
-
-#ifdef __UNIXOS2__
-static char dummy;
-#endif
-
-#ifndef OLDXAW
-
-/*
- * Types
- */
-typedef struct _XawCache {
- long value;
- XtPointer *elems;
- unsigned int num_elems;
-} XawCache;
-
-typedef struct _XawPixmapLoaderInfo {
- XawPixmapLoader loader;
- String type;
- String ext;
-} XawPixmapLoaderInfo;
-
-/*
- * Private Methods
- */
-static Bool BitmapLoader(XawParams*, Screen*, Colormap, int,
- Pixmap*, Pixmap*, Dimension*, Dimension*);
-static Bool GradientLoader(XawParams*, Screen*, Colormap, int,
- Pixmap*, Pixmap*, Dimension*, Dimension*);
-static Bool XPixmapLoader(XawParams*, Screen*, Colormap, int,
- Pixmap*, Pixmap*, Dimension*, Dimension*);
-static XawPixmap *_XawFindPixmap(String, Screen*, Colormap, int);
-static void _XawCachePixmap(XawPixmap*, Screen*, Colormap, int);
-static int _XawFindPixmapLoaderIndex(String, String);
-static int qcmp_long(register _Xconst void*, register _Xconst void *);
-static int bcmp_long(register _Xconst void*, register _Xconst void *);
-static int qcmp_string(register _Xconst void*, register _Xconst void *);
-static int bcmp_string(register _Xconst void*, register _Xconst void *);
-static void GetResourcePixmapPath(Display*);
-
-/*
- * Initialization
- */
-static XawCache xaw_pixmaps;
-static XawCache x_pixmaps; /* for fast reverse search */
-static XawPixmapLoaderInfo **loader_info;
-static Cardinal num_loader_info;
-
-/*
- * Implementation
- */
-Bool
-XawPixmapsInitialize(void)
-{
- static Boolean first_time = True;
-
- if (!first_time)
- return (False);
-
- (void)XawAddPixmapLoader(NULL, NULL, BitmapLoader);
- (void)XawAddPixmapLoader("bitmap", NULL, BitmapLoader);
- (void)XawAddPixmapLoader("gradient", NULL, GradientLoader);
- (void)XawAddPixmapLoader("xpm", "xpm", XPixmapLoader);
-
- return (True);
-}
-
-XawParams *
-XawParseParamsString(String name)
-{
- XawParams *xaw_params;
- char *tok, *str, *type = NULL, *ext = NULL, *params = NULL;
-
- if (!name)
- return (NULL);
-
- xaw_params = (XawParams *)XtMalloc(sizeof(XawParams));
-
- str = XtNewString(name);
-
- /* Find type */
- tok = str;
- while (tok = strchr(tok, ':'), tok)
- {
- if (tok == str || tok[-1] != '\\')
- break;
- memmove(&tok[-1], tok, strlen(tok) + 1);
- }
- if (tok)
- {
- *tok = '\0';
- if (strchr(str, '?'))
- {
- *tok = ':';
- }
- else
- {
- ++tok;
- type = XtNewString(str);
- memmove(str, tok, strlen(tok) + 1);
- }
- }
-
- /* Find params */
- tok = str;
- while (tok = strchr(tok, '?'), tok)
- {
- if (tok == str || tok[-1] != '\\')
- params = tok;
- if (tok != str && tok[-1] == '\\')
- memmove(&tok[-1], tok, strlen(tok) + 1);
- else
- break;
- }
- if (params)
- {
- *params = '\0';
- ++params;
- }
-
- /* Find ext */
- tok = str;
- while (tok = strchr(tok, '.'), tok)
- {
- if (tok == str || tok[-1] != '\\')
- ext = tok;
- if (tok != str && tok[-1] == '\\')
- memmove(&tok[-1], tok, strlen(tok) + 1);
- else
- break;
- }
- if (ext)
- {
- ++ext;
- if (strchr(ext, '/'))
- ext = NULL;
- }
-
- xaw_params->name = XtNewString(str);
- xaw_params->type = type;
- xaw_params->ext = ext ? XtNewString(ext) : ext;
- xaw_params->args = NULL;
- xaw_params->num_args = 0;
-
- /* Parse params */
- if (params)
- {
- char *arg, *val;
- XawArgVal *xaw_arg;
-
- for (tok = strtok(params, "&"); tok; tok = strtok(NULL, "&"))
- {
- val = strchr(tok, '=');
- if (val)
- {
- *val = '\0';
- ++val;
- if (*val != '\0')
- val = XtNewString(val);
- else
- val = NULL;
- }
- arg = XtNewString(tok);
- xaw_arg = (XawArgVal *)XtMalloc(sizeof(XawArgVal));
- xaw_arg->name = arg;
- xaw_arg->value = val;
- if (!xaw_params->num_args)
- {
- xaw_params->num_args = 1;
- xaw_params->args = (XawArgVal **)
- XtMalloc(sizeof(XawArgVal*));
- }
- else
- {
- ++xaw_params->num_args;
- xaw_params->args = (XawArgVal **)
- XtRealloc((char *)xaw_params->args,
- sizeof(XawArgVal*) * xaw_params->num_args);
- }
- xaw_params->args[xaw_params->num_args - 1] = xaw_arg;
- }
- }
-
- if (xaw_params->num_args > 1)
- qsort(xaw_params->args, xaw_params->num_args, sizeof(XtPointer),
- qcmp_string);
-
- XtFree(str);
-
- return (xaw_params);
-}
-
-void
-XawFreeParamsStruct(XawParams *params)
-{
- unsigned int i;
-
- if (!params)
- return;
-
- for (i = 0; i < params->num_args; i++)
- {
- XtFree(params->args[i]->name);
- if (params->args[i]->value)
- XtFree(params->args[i]->value);
- XtFree((char *)params->args[i]);
- }
-
- if (params->args)
- XtFree((char *)params->args);
- XtFree((char *)params);
-}
-
-XawArgVal *
-XawFindArgVal(XawParams *params, String name)
-{
- XawArgVal **arg_val;
-
- if (!params->args)
- return (NULL);
-
- arg_val = (XawArgVal **)bsearch((void *)name, params->args,
- params->num_args, sizeof(XtPointer*),
- bcmp_string);
- if (!arg_val)
- return (NULL);
-
- return (*arg_val);
-}
-
-XawPixmap *
-XawLoadPixmap(String name, Screen *screen, Colormap colormap, int depth)
-{
- int idx;
- Bool success;
- XawPixmap *xaw_pixmap;
- Pixmap pixmap, mask;
- Dimension width, height;
- XawParams *xaw_params;
-
- if (!name)
- return (NULL);
-
- xaw_pixmap = _XawFindPixmap(name, screen, colormap, depth);
-
- if (xaw_pixmap)
- return (xaw_pixmap);
-
- if ((xaw_params = XawParseParamsString(name)) == NULL)
- return (NULL);
-
- idx = _XawFindPixmapLoaderIndex(xaw_params->type, xaw_params->ext);
- if (idx < 0)
- return (NULL);
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "(*) Loading pixmap \"%s\": ", name);
-#endif
-
- success = loader_info[idx]->loader(xaw_params, screen, colormap, depth,
- &pixmap, &mask, &width, &height);
- if (success)
- {
- xaw_pixmap = (XawPixmap *)XtMalloc(sizeof(XawPixmap));
- xaw_pixmap->name = XtNewString(name);
- xaw_pixmap->pixmap = pixmap;
- xaw_pixmap->mask = mask;
- xaw_pixmap->width = width;
- xaw_pixmap->height = height;
- _XawCachePixmap(xaw_pixmap, screen, colormap, depth);
- }
-
- XawFreeParamsStruct(xaw_params);
-
-#ifdef DIAGNOSTIC
- fprintf(stderr, "%s", success ? "success\n" : "failed\n");
-#endif
-
- return (success ? xaw_pixmap : NULL);
-}
-
-Bool
-XawAddPixmapLoader(String type, String ext, XawPixmapLoader loader)
-{
- XawPixmapLoaderInfo *info;
- int i;
-
- if (!loader)
- return (False);
-
- i = _XawFindPixmapLoaderIndex(type, ext);
-
- if (i >= 0)
- {
- loader_info[i]->loader = loader;
- if (loader_info[i]->type)
- XtFree(loader_info[i]->type);
- if (loader_info[i]->ext)
- XtFree(loader_info[i]->ext);
- loader_info[i]->type = type ? XtNewString(type) : NULL;
- loader_info[i]->ext = ext ? XtNewString(ext) : NULL;
- return (True);
- }
-
- if ((info = (XawPixmapLoaderInfo *)XtMalloc(sizeof(XawPixmapLoaderInfo)))
- == NULL)
- return (False);
-
- info->loader = loader;
- info->type = type ? XtNewString(type) : NULL;
- info->ext = ext ? XtNewString(ext) : NULL;
-
- if (!loader_info)
- {
- num_loader_info = 1;
- loader_info = (XawPixmapLoaderInfo**)
- XtMalloc(sizeof(XawPixmapLoaderInfo*));
- }
- else
- {
- ++num_loader_info;
- loader_info = (XawPixmapLoaderInfo**)
- XtRealloc((char *)loader_info,
- sizeof(XawPixmapLoaderInfo) * num_loader_info);
- }
- loader_info[num_loader_info - 1] = info;
-
- return (True);
-}
-
-static int
-_XawFindPixmapLoaderIndex(String type, String ext)
-{
- Cardinal i;
-
- if (!loader_info)
- return (-1);
-
- for (i = 0; i < num_loader_info; i++)
- if ((type && loader_info[i]->type && strcmp(type, loader_info[i]->type) == 0)
- || (ext && loader_info[i]->ext && strcmp(ext, loader_info[i]->ext) == 0))
- return ((int)i);
-
- if (!type)
- return (0); /* try a bitmap */
-
- return (-1);
-}
-
-static int
-qcmp_x_cache(register _Xconst void *left, register _Xconst void *right)
-{
- return ((int)((*(XawPixmap **)left)->pixmap) -
- (int)((*(XawPixmap **)right)->pixmap));
-}
-
-static int
-bcmp_x_cache(register _Xconst void *pixmap, register _Xconst void *xaw)
-{
- return (int)((long)pixmap - (long)((*(XawPixmap **)xaw)->pixmap));
-}
-
-static int
-qcmp_long(register _Xconst void *left, register _Xconst void *right)
-{
- return ((long)((*(XawCache **)left)->value) -
- (long)((*(XawCache **)right)->value));
-}
-
-static int
-qcmp_string(register _Xconst void *left, register _Xconst void *right)
-{
- return (strcmp((String)((*(XawCache **)left)->value),
- (String)((*(XawCache **)right)->value)));
-}
-
-static int
-bcmp_long(register _Xconst void *value, register _Xconst void *cache)
-{
- return ((long)value - (long)((*(XawCache **)cache)->value));
-}
-
-static int
-bcmp_string(register _Xconst void *string,
- register _Xconst void *cache)
-{
- return (strcmp((String)string, (String)((*(XawCache **)cache)->value)));
-}
-
-#define FIND_ALL 0
-#define FIND_SCREEN 1
-#define FIND_COLORMAP 2
-#define FIND_DEPTH 3
-static XawCache *
-_XawFindCache(XawCache *xaw,
- Screen *screen, Colormap colormap, int depth, int flags)
-{
- XawCache **cache;
-
- if (!xaw->num_elems)
- return (NULL);
-
- /* Screen */
- cache = (XawCache **)bsearch(screen, xaw->elems,
- xaw->num_elems, sizeof(XtPointer),
- bcmp_long);
- if (!cache || !(*cache)->num_elems)
- return (NULL);
- if (flags == FIND_SCREEN)
- return (*cache);
-
- /* Colormap */
- cache = (XawCache **)bsearch((void *)colormap, (*cache)->elems,
- (*cache)->num_elems, sizeof(XtPointer),
- bcmp_long);
- if (!cache || !(*cache)->num_elems)
- return (NULL);
- if (flags == FIND_COLORMAP)
- return (*cache);
-
- /* Depth */
- cache = (XawCache **)bsearch((void *)(long)depth, (*cache)->elems,
- (*cache)->num_elems, sizeof(XtPointer),
- bcmp_long);
-
- if (!cache || !(*cache)->num_elems)
- return (NULL);
- return (*cache);
-}
-
-static XawCache *
-_XawGetCache(XawCache *xaw, Screen *screen, Colormap colormap, int depth)
-{
- XawCache *s_cache, *c_cache, *d_cache, *cache, *pcache;
-
- cache = _XawFindCache(xaw, screen, colormap, depth, FIND_ALL);
-
- if (!cache)
- {
- s_cache = _XawFindCache(xaw,
- screen, colormap, depth, FIND_SCREEN);
- if (!s_cache)
- {
- pcache = (XawCache *)XtMalloc(sizeof(XawCache));
- if (!xaw->num_elems)
- {
- xaw->num_elems = 1;
- xaw->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
- }
- else
- {
- ++xaw->num_elems;
- xaw->elems = (XtPointer*)
- XtRealloc((char *)xaw->elems,
- sizeof(XtPointer) * xaw->num_elems);
- }
- pcache->value = (long)screen;
- pcache->elems = NULL;
- pcache->num_elems = 0;
- xaw->elems[xaw->num_elems - 1] = (XtPointer)pcache;
- s_cache = (XawCache *)xaw->elems[xaw->num_elems - 1];
- if (xaw->num_elems > 1)
- qsort(xaw->elems, xaw->num_elems, sizeof(XtPointer), qcmp_long);
- }
-
- c_cache = _XawFindCache(xaw,
- screen, colormap, depth, FIND_COLORMAP);
- if (!c_cache)
- {
- pcache = (XawCache *)XtMalloc(sizeof(XawCache));
- if (!s_cache->num_elems)
- {
- s_cache->num_elems = 1;
- s_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
- }
- else
- {
- ++s_cache->num_elems;
- s_cache->elems = (XtPointer*)
- XtRealloc((char *)s_cache->elems,
- sizeof(XtPointer) * s_cache->num_elems);
- }
- pcache->value = (long)colormap;
- pcache->elems = NULL;
- pcache->num_elems = 0;
- s_cache->elems[s_cache->num_elems - 1] = (XtPointer)pcache;
- c_cache = (XawCache *)s_cache->elems[s_cache->num_elems - 1];
- if (s_cache->num_elems > 1)
- qsort(s_cache->elems, s_cache->num_elems,
- sizeof(XtPointer), qcmp_long);
- }
-
- d_cache = _XawFindCache(xaw,
- screen, colormap, depth, FIND_DEPTH);
- if (!d_cache)
- {
- pcache = (XawCache *)XtMalloc(sizeof(XawCache));
- if (!c_cache->num_elems)
- {
- c_cache->num_elems = 1;
- c_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
- }
- else
- {
- ++c_cache->num_elems;
- c_cache->elems = (XtPointer*)
- XtRealloc((char *)c_cache->elems,
- sizeof(XtPointer) * c_cache->num_elems);
- }
- pcache->value = (long)depth;
- pcache->elems = NULL;
- pcache->num_elems = 0;
- c_cache->elems[c_cache->num_elems - 1] = (XtPointer)pcache;
- d_cache = (XawCache *)c_cache->elems[c_cache->num_elems - 1];
- if (c_cache->num_elems > 1)
- qsort(c_cache->elems, c_cache->num_elems,
- sizeof(XtPointer), qcmp_long);
- }
-
- cache = d_cache;
- }
-
- return (cache);
-}
-
-static XawPixmap *
-_XawFindPixmap(String name, Screen *screen, Colormap colormap, int depth)
-{
- XawCache *cache;
- XawPixmap **pixmap;
-
- cache = _XawFindCache(&xaw_pixmaps, screen, colormap, depth, FIND_ALL);
-
- if (!cache)
- return (NULL);
-
- /* Name */
- pixmap = (XawPixmap **)bsearch((void *)name, cache->elems,
- cache->num_elems, sizeof(XtPointer),
- bcmp_string);
- if (!pixmap)
- return (NULL);
-
- return (*pixmap);
-}
-
-XawPixmap *
-XawPixmapFromXPixmap(Pixmap pixmap,
- Screen *screen, Colormap colormap, int depth)
-{
- XawCache *cache;
- XawPixmap **x_pixmap;
-
- cache = _XawFindCache(&x_pixmaps, screen, colormap, depth, FIND_ALL);
-
- if (!cache)
- return (NULL);
-
- /* Pixmap */
- x_pixmap = (XawPixmap **)bsearch((void *)pixmap, cache->elems,
- cache->num_elems, sizeof(XtPointer),
- bcmp_x_cache);
- if (!x_pixmap)
- return (NULL);
-
- return (*x_pixmap);
-}
-
-static void
-_XawCachePixmap(XawPixmap *pixmap,
- Screen *screen, Colormap colormap, int depth)
-{
- XawCache *xaw_cache, *x_cache;
-
- xaw_cache = _XawGetCache(&xaw_pixmaps, screen, colormap, depth);
- x_cache = _XawGetCache(&x_pixmaps, screen, colormap, depth);
-
- if (!xaw_cache->num_elems)
- {
- xaw_cache->num_elems = 1;
- xaw_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
- }
- else
- {
- ++xaw_cache->num_elems;
- xaw_cache->elems = (XtPointer*)XtRealloc((char *)xaw_cache->elems,
- sizeof(XtPointer) *
- xaw_cache->num_elems);
- }
-
- xaw_cache->elems[xaw_cache->num_elems - 1] = (XtPointer)pixmap;
- if (xaw_cache->num_elems > 1)
- qsort(xaw_cache->elems, xaw_cache->num_elems,
- sizeof(XtPointer), qcmp_string);
-
-
- if (!x_cache->num_elems)
- {
- x_cache->num_elems = 1;
- x_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
- }
- else
- {
- ++x_cache->num_elems;
- x_cache->elems = (XtPointer*)XtRealloc((char *)x_cache->elems,
- sizeof(XtPointer) *
- x_cache->num_elems);
- }
-
- x_cache->elems[x_cache->num_elems - 1] = (XtPointer)pixmap;
- if (x_cache->num_elems > 1)
- qsort(x_cache->elems, x_cache->num_elems, sizeof(XtPointer), qcmp_x_cache);
-}
-
-#ifndef PROJECT_ROOT
-#define PROJECT_ROOT "/usr/X11R6"
-#endif
-
-static char *pixmap_path = NULL;
-
-static void
-GetResourcePixmapPath(Display *display)
-{
- XrmName xrm_name[2];
- XrmClass xrm_class[2];
- XrmRepresentation rep_type;
- XrmValue value;
- static char *default_path =
- "%H/%T/%N:%P/include/X11/%T/%N:/usr/X11R6/include/X11/%T/%N:/usr/include/X11/%T/%N:%N";
-
- xrm_name[0] = XrmPermStringToQuark("pixmapFilePath");
- xrm_name[1] = NULLQUARK;
- xrm_class[0] = XrmPermStringToQuark("PixmapFilePath");
- xrm_class[1] = NULLQUARK;
- if (!XrmGetDatabase(display))
- (void) XGetDefault(display, "", "");
- if (XrmQGetResource(XrmGetDatabase(display), xrm_name, xrm_class,
- &rep_type, &value) &&
- rep_type == XrmPermStringToQuark("String")) {
- int length = 0;
- char *tok, *buffer = XtNewString(value.addr);
-
- for (tok = strtok(buffer, ":"); tok; tok = strtok(NULL, ":")) {
- int toklen = strlen(tok);
-
- if (toklen) {
- pixmap_path = XtRealloc(pixmap_path, length + toklen + 5);
- strcpy(pixmap_path + length, tok);
- if (length)
- pixmap_path[length++] = ':';
- sprintf(pixmap_path + length, "%s/%%N", tok);
- length += strlen(tok) + 3;
- }
- }
- pixmap_path = XtRealloc(pixmap_path, length + strlen(default_path) + 2);
- if (length)
- pixmap_path[length++] = ':';
- strcpy(pixmap_path + length, default_path);
- }
- else
- pixmap_path = default_path;
-}
-
-static Bool
-BitmapLoader(XawParams *params, Screen *screen, Colormap colormap, int depth,
- Pixmap *pixmap_return, Pixmap *mask_return,
- Dimension *width_return, Dimension *height_return)
-{
- Pixel fg, bg;
- XColor color, exact;
- Pixmap pixmap;
- unsigned int width, height;
- unsigned char *data = NULL;
- int hotX, hotY;
- XawArgVal *argval;
- Bool retval = False;
- static SubstitutionRec sub[] = {
- {'H', NULL},
- {'N', NULL},
- {'T', "bitmaps"},
- {'P', PROJECT_ROOT},
- };
- char *filename;
-
- fg = BlackPixelOfScreen(screen);
- bg = WhitePixelOfScreen(screen);
-
- if ((argval = XawFindArgVal(params, "foreground")) != NULL
- && argval->value)
- {
- if (XAllocNamedColor(DisplayOfScreen(screen), colormap, argval->value,
- &color, &exact))
- fg = color.pixel;
- else
- return (False);
- }
- if ((argval = XawFindArgVal(params, "background")) != NULL
- && argval->value)
- {
- if (XAllocNamedColor(DisplayOfScreen(screen), colormap, argval->value,
- &color, &exact))
- bg = color.pixel;
- else
- return (False);
- }
-
- if (params->name[0] != '/' && params->name[0] != '.')
- {
- if (!sub[0].substitution)
- #ifdef _MSC_VER
- sub[0].substitution = ".";
- #else
- sub[0].substitution = getenv("HOME");
- #endif
- sub[1].substitution = params->name;
- if (pixmap_path == NULL)
- GetResourcePixmapPath(DisplayOfScreen(screen));
- filename = XtFindFile(pixmap_path, sub, XtNumber(sub), NULL);
- if (!filename)
- return (FALSE);
- }
- else
- filename = params->name;
-
- if (XReadBitmapFileData(filename, &width, &height, &data,
- &hotX, &hotY) == BitmapSuccess)
- {
- pixmap = XCreatePixmapFromBitmapData(DisplayOfScreen(screen),
- RootWindowOfScreen(screen),
- (char *)data,
- width, height, fg, bg, depth);
- if (data)
- XFree(data);
- *pixmap_return = pixmap;
- *mask_return = None;
- *width_return = width;
- *height_return = height;
-
- retval = True;
- }
-
- if (filename != params->name)
- XtFree(filename);
-
- return (retval);
-}
-
-#define VERTICAL 1
-#define HORIZONTAL 2
-static Bool
-GradientLoader(XawParams *params, Screen *screen, Colormap colormap, int depth,
- Pixmap *pixmap_return, Pixmap *mask_return,
- Dimension *width_return, Dimension *height_return)
-{
- double ired, igreen, iblue, red, green, blue;
- XColor start, end, color;
- XGCValues values;
- GC gc;
- double i, inc, x, y, xend, yend;
- Pixmap pixmap;
- XawArgVal *argval;
- int orientation, dimension, steps;
- char *value;
-
- if (XmuCompareISOLatin1(params->name, "vertical") == 0)
- orientation = VERTICAL;
- else if (XmuCompareISOLatin1(params->name, "horizontal") == 0)
- orientation = HORIZONTAL;
- else
- return (False);
-
- if ((argval = XawFindArgVal(params, "dimension")) != NULL
- && argval->value)
- {
- dimension = atoi(argval->value);
- if (dimension <= 0)
- return (False);
- }
- else
- dimension = 50;
-
- if ((argval = XawFindArgVal(params, "steps")) != NULL
- && argval->value)
- {
- steps = atoi(argval->value);
- if (steps <= 0)
- return (False);
- }
- else
- steps = dimension;
-
- steps = XawMin(steps, dimension);
-
- value = NULL;
- if ((argval = XawFindArgVal(params, "start")) != NULL)
- value = argval->value;
- if (value && !XAllocNamedColor(DisplayOfScreen(screen), colormap, value,
- &start, &color))
- return (False);
- else if (!value)
- {
- start.pixel = WhitePixelOfScreen(screen);
- XQueryColor(DisplayOfScreen(screen), colormap, &start);
- }
- value = NULL;
- if ((argval = XawFindArgVal(params, "end")) != NULL)
- value = argval->value;
- if (value && !XAllocNamedColor(DisplayOfScreen(screen), colormap, value,
- &end, &color))
- return (False);
- else if (!value)
- {
- end.pixel = BlackPixelOfScreen(screen);
- XQueryColor(DisplayOfScreen(screen), colormap, &end);
- }
-
- if ((pixmap = XCreatePixmap(DisplayOfScreen(screen),
- RootWindowOfScreen(screen),
- orientation == VERTICAL ? 1 : dimension,
- orientation == VERTICAL ? dimension : 1, depth))
- == 0)
- return (False);
-
- ired = (double)(end.red - start.red) / (double)steps;
- igreen = (double)(end.green - start.green) / (double)steps;
- iblue = (double)(end.blue - start.blue) / (double)steps;
-
- red = color.red = start.red;
- green = color.green = start.green;
- blue = color.blue = start.blue;
-
- inc = (double)dimension / (double)steps;
-
- gc = XCreateGC(DisplayOfScreen(screen), pixmap, 0, &values);
-
- x = y = 0.0;
- if (orientation == VERTICAL)
- {
- xend = 1;
- yend = 0;
- }
- else
- {
- xend = 0;
- yend = 1;
- }
-
- color.flags = DoRed | DoGreen | DoBlue;
-
- XSetForeground(DisplayOfScreen(screen), gc, start.pixel);
- for (i = 0.0; i < dimension; i += inc)
- {
- if ((int)color.red != (int)red || (int)color.green != (int)green
- || (int)color.blue != (int)blue)
- {
- XFillRectangle(DisplayOfScreen(screen), pixmap, gc, (int)x, (int)y,
- (unsigned int)xend, (unsigned int)yend);
- color.red = (unsigned short)red;
- color.green = (unsigned short)green;
- color.blue = (unsigned short)blue;
- if (!XAllocColor(DisplayOfScreen(screen), colormap, &color))
- {
- XFreePixmap(DisplayOfScreen(screen), pixmap);
- return (False);
- }
- XSetForeground(DisplayOfScreen(screen), gc, color.pixel);
- if (orientation == VERTICAL)
- y = yend;
- else
- x = xend;
- }
- red += ired;
- green += igreen;
- blue += iblue;
- if (orientation == VERTICAL)
- yend += inc;
- else
- xend += inc;
- }
- XFillRectangle(DisplayOfScreen(screen), pixmap, gc, (int)x, (int)y,
- (unsigned int)xend, (unsigned int)yend);
-
- *pixmap_return = pixmap;
- *mask_return = None;
- *width_return = orientation == VERTICAL ? 1 : dimension;
- *height_return = orientation == VERTICAL ? dimension : 1;
-
- XFreeGC(DisplayOfScreen(screen), gc);
-
- return (True);
-}
-
-static Bool
-XPixmapLoader(XawParams *params, Screen *screen, Colormap colormap, int depth,
- Pixmap *pixmap_return, Pixmap *mask_return,
- Dimension *width_return, Dimension *height_return)
-{
- XpmAttributes xpm_attributes;
- XawArgVal *argval;
- unsigned int closeness = 4000;
- static SubstitutionRec sub[] = {
- {'H', NULL},
- {'N', NULL},
- {'T', "pixmaps"},
- {'P', PROJECT_ROOT},
- };
- char *filename;
-
- if ((argval = XawFindArgVal(params, "closeness")) != NULL
- && argval->value)
- closeness = atoi(argval->value);
-
- if (params->name[0] != '/' && params->name[0] != '.')
- {
- if (!sub[0].substitution)
- sub[0].substitution = getenv("HOME");
- sub[1].substitution = params->name;
- if (pixmap_path == NULL)
- GetResourcePixmapPath(DisplayOfScreen(screen));
- filename = XtFindFile(pixmap_path, sub, XtNumber(sub), NULL);
- if (!filename)
- return (False);
- }
- else
- filename = params->name;
-
- xpm_attributes.colormap = colormap;
- xpm_attributes.closeness = closeness;
- xpm_attributes.valuemask = XpmSize | XpmColormap | XpmCloseness;
- if (XpmReadFileToPixmap(DisplayOfScreen(screen),
- RootWindowOfScreen(screen), filename, pixmap_return,
- mask_return, &xpm_attributes) == XpmSuccess)
- {
- *width_return = xpm_attributes.width;
- *height_return = xpm_attributes.height;
-
- return (True);
- }
-
- return (False);
-}
-
-void
-XawReshapeWidget(Widget w, XawPixmap *pixmap)
-{
- if (!pixmap || pixmap->mask == None)
- XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 0, 0,
- None, ShapeSet);
- else
- XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 0, 0,
- pixmap->mask, ShapeSet);
-}
-
-#endif /* OLDXAW */
+/* + * Copyright (c) 1998 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <X11/IntrinsicP.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xfuncs.h> +#include <X11/extensions/shape.h> +#ifndef OLDXAW +#include <X11/xpm.h> +#endif +#include "Private.h" + +#ifdef __UNIXOS2__ +static char dummy; +#endif + +#ifndef OLDXAW + +/* + * Types + */ +typedef struct _XawCache { + long value; + XtPointer *elems; + unsigned int num_elems; +} XawCache; + +typedef struct _XawPixmapLoaderInfo { + XawPixmapLoader loader; + String type; + String ext; +} XawPixmapLoaderInfo; + +/* + * Private Methods + */ +static Bool BitmapLoader(XawParams*, Screen*, Colormap, int, + Pixmap*, Pixmap*, Dimension*, Dimension*); +static Bool GradientLoader(XawParams*, Screen*, Colormap, int, + Pixmap*, Pixmap*, Dimension*, Dimension*); +static Bool XPixmapLoader(XawParams*, Screen*, Colormap, int, + Pixmap*, Pixmap*, Dimension*, Dimension*); +static XawPixmap *_XawFindPixmap(String, Screen*, Colormap, int); +static void _XawCachePixmap(XawPixmap*, Screen*, Colormap, int); +static int _XawFindPixmapLoaderIndex(String, String); +static int qcmp_long(register _Xconst void*, register _Xconst void *); +static int bcmp_long(register _Xconst void*, register _Xconst void *); +static int qcmp_string(register _Xconst void*, register _Xconst void *); +static int bcmp_string(register _Xconst void*, register _Xconst void *); +static void GetResourcePixmapPath(Display*); + +/* + * Initialization + */ +static XawCache xaw_pixmaps; +static XawCache x_pixmaps; /* for fast reverse search */ +static XawPixmapLoaderInfo **loader_info; +static Cardinal num_loader_info; + +/* + * Implementation + */ +Bool +XawPixmapsInitialize(void) +{ + static Boolean first_time = True; + + if (!first_time) + return (False); + + (void)XawAddPixmapLoader(NULL, NULL, BitmapLoader); + (void)XawAddPixmapLoader("bitmap", NULL, BitmapLoader); + (void)XawAddPixmapLoader("gradient", NULL, GradientLoader); + (void)XawAddPixmapLoader("xpm", "xpm", XPixmapLoader); + + return (True); +} + +XawParams * +XawParseParamsString(String name) +{ + XawParams *xaw_params; + char *tok, *str, *type = NULL, *ext = NULL, *params = NULL; + + if (!name) + return (NULL); + + xaw_params = (XawParams *)XtMalloc(sizeof(XawParams)); + + str = XtNewString(name); + + /* Find type */ + tok = str; + while (tok = strchr(tok, ':'), tok) + { + if (tok == str || tok[-1] != '\\') + break; + memmove(&tok[-1], tok, strlen(tok) + 1); + } + if (tok) + { + *tok = '\0'; + if (strchr(str, '?')) + { + *tok = ':'; + } + else + { + ++tok; + type = XtNewString(str); + memmove(str, tok, strlen(tok) + 1); + } + } + + /* Find params */ + tok = str; + while (tok = strchr(tok, '?'), tok) + { + if (tok == str || tok[-1] != '\\') + params = tok; + if (tok != str && tok[-1] == '\\') + memmove(&tok[-1], tok, strlen(tok) + 1); + else + break; + } + if (params) + { + *params = '\0'; + ++params; + } + + /* Find ext */ + tok = str; + while (tok = strchr(tok, '.'), tok) + { + if (tok == str || tok[-1] != '\\') + ext = tok; + if (tok != str && tok[-1] == '\\') + memmove(&tok[-1], tok, strlen(tok) + 1); + else + break; + } + if (ext) + { + ++ext; + if (strchr(ext, '/')) + ext = NULL; + } + + xaw_params->name = XtNewString(str); + xaw_params->type = type; + xaw_params->ext = ext ? XtNewString(ext) : ext; + xaw_params->args = NULL; + xaw_params->num_args = 0; + + /* Parse params */ + if (params) + { + char *arg, *val; + XawArgVal *xaw_arg; + + for (tok = strtok(params, "&"); tok; tok = strtok(NULL, "&")) + { + val = strchr(tok, '='); + if (val) + { + *val = '\0'; + ++val; + if (*val != '\0') + val = XtNewString(val); + else + val = NULL; + } + arg = XtNewString(tok); + xaw_arg = (XawArgVal *)XtMalloc(sizeof(XawArgVal)); + xaw_arg->name = arg; + xaw_arg->value = val; + if (!xaw_params->num_args) + { + xaw_params->num_args = 1; + xaw_params->args = (XawArgVal **) + XtMalloc(sizeof(XawArgVal*)); + } + else + { + ++xaw_params->num_args; + xaw_params->args = (XawArgVal **) + XtRealloc((char *)xaw_params->args, + sizeof(XawArgVal*) * xaw_params->num_args); + } + xaw_params->args[xaw_params->num_args - 1] = xaw_arg; + } + } + + if (xaw_params->num_args > 1) + qsort(xaw_params->args, xaw_params->num_args, sizeof(XtPointer), + qcmp_string); + + XtFree(str); + + return (xaw_params); +} + +void +XawFreeParamsStruct(XawParams *params) +{ + unsigned int i; + + if (!params) + return; + + for (i = 0; i < params->num_args; i++) + { + XtFree(params->args[i]->name); + if (params->args[i]->value) + XtFree(params->args[i]->value); + XtFree((char *)params->args[i]); + } + + if (params->args) + XtFree((char *)params->args); + XtFree((char *)params); +} + +XawArgVal * +XawFindArgVal(XawParams *params, String name) +{ + XawArgVal **arg_val; + + if (!params->args) + return (NULL); + + arg_val = (XawArgVal **)bsearch((void *)name, params->args, + params->num_args, sizeof(XtPointer*), + bcmp_string); + if (!arg_val) + return (NULL); + + return (*arg_val); +} + +XawPixmap * +XawLoadPixmap(String name, Screen *screen, Colormap colormap, int depth) +{ + int idx; + Bool success; + XawPixmap *xaw_pixmap; + Pixmap pixmap, mask; + Dimension width, height; + XawParams *xaw_params; + + if (!name) + return (NULL); + + xaw_pixmap = _XawFindPixmap(name, screen, colormap, depth); + + if (xaw_pixmap) + return (xaw_pixmap); + + if ((xaw_params = XawParseParamsString(name)) == NULL) + return (NULL); + + idx = _XawFindPixmapLoaderIndex(xaw_params->type, xaw_params->ext); + if (idx < 0) + return (NULL); + +#ifdef DIAGNOSTIC + fprintf(stderr, "(*) Loading pixmap \"%s\": ", name); +#endif + + success = loader_info[idx]->loader(xaw_params, screen, colormap, depth, + &pixmap, &mask, &width, &height); + if (success) + { + xaw_pixmap = (XawPixmap *)XtMalloc(sizeof(XawPixmap)); + xaw_pixmap->name = XtNewString(name); + xaw_pixmap->pixmap = pixmap; + xaw_pixmap->mask = mask; + xaw_pixmap->width = width; + xaw_pixmap->height = height; + _XawCachePixmap(xaw_pixmap, screen, colormap, depth); + } + + XawFreeParamsStruct(xaw_params); + +#ifdef DIAGNOSTIC + fprintf(stderr, "%s", success ? "success\n" : "failed\n"); +#endif + + return (success ? xaw_pixmap : NULL); +} + +Bool +XawAddPixmapLoader(String type, String ext, XawPixmapLoader loader) +{ + XawPixmapLoaderInfo *info; + int i; + + if (!loader) + return (False); + + i = _XawFindPixmapLoaderIndex(type, ext); + + if (i >= 0) + { + loader_info[i]->loader = loader; + if (loader_info[i]->type) + XtFree(loader_info[i]->type); + if (loader_info[i]->ext) + XtFree(loader_info[i]->ext); + loader_info[i]->type = type ? XtNewString(type) : NULL; + loader_info[i]->ext = ext ? XtNewString(ext) : NULL; + return (True); + } + + if ((info = (XawPixmapLoaderInfo *)XtMalloc(sizeof(XawPixmapLoaderInfo))) + == NULL) + return (False); + + info->loader = loader; + info->type = type ? XtNewString(type) : NULL; + info->ext = ext ? XtNewString(ext) : NULL; + + if (!loader_info) + { + num_loader_info = 1; + loader_info = (XawPixmapLoaderInfo**) + XtMalloc(sizeof(XawPixmapLoaderInfo*)); + } + else + { + ++num_loader_info; + loader_info = (XawPixmapLoaderInfo**) + XtRealloc((char *)loader_info, + sizeof(XawPixmapLoaderInfo) * num_loader_info); + } + loader_info[num_loader_info - 1] = info; + + return (True); +} + +static int +_XawFindPixmapLoaderIndex(String type, String ext) +{ + Cardinal i; + + if (!loader_info) + return (-1); + + for (i = 0; i < num_loader_info; i++) + if ((type && loader_info[i]->type && strcmp(type, loader_info[i]->type) == 0) + || (ext && loader_info[i]->ext && strcmp(ext, loader_info[i]->ext) == 0)) + return ((int)i); + + if (!type) + return (0); /* try a bitmap */ + + return (-1); +} + +static int +qcmp_x_cache(register _Xconst void *left, register _Xconst void *right) +{ + return ((int)((*(XawPixmap **)left)->pixmap) - + (int)((*(XawPixmap **)right)->pixmap)); +} + +static int +bcmp_x_cache(register _Xconst void *pixmap, register _Xconst void *xaw) +{ + return (int)((long)pixmap - (long)((*(XawPixmap **)xaw)->pixmap)); +} + +static int +qcmp_long(register _Xconst void *left, register _Xconst void *right) +{ + return ((long)((*(XawCache **)left)->value) - + (long)((*(XawCache **)right)->value)); +} + +static int +qcmp_string(register _Xconst void *left, register _Xconst void *right) +{ + return (strcmp((String)((*(XawCache **)left)->value), + (String)((*(XawCache **)right)->value))); +} + +static int +bcmp_long(register _Xconst void *value, register _Xconst void *cache) +{ + return ((long)value - (long)((*(XawCache **)cache)->value)); +} + +static int +bcmp_string(register _Xconst void *string, + register _Xconst void *cache) +{ + return (strcmp((String)string, (String)((*(XawCache **)cache)->value))); +} + +#define FIND_ALL 0 +#define FIND_SCREEN 1 +#define FIND_COLORMAP 2 +#define FIND_DEPTH 3 +static XawCache * +_XawFindCache(XawCache *xaw, + Screen *screen, Colormap colormap, int depth, int flags) +{ + XawCache **cache; + + if (!xaw->num_elems) + return (NULL); + + /* Screen */ + cache = (XawCache **)bsearch(screen, xaw->elems, + xaw->num_elems, sizeof(XtPointer), + bcmp_long); + if (!cache || !(*cache)->num_elems) + return (NULL); + if (flags == FIND_SCREEN) + return (*cache); + + /* Colormap */ + cache = (XawCache **)bsearch((void *)colormap, (*cache)->elems, + (*cache)->num_elems, sizeof(XtPointer), + bcmp_long); + if (!cache || !(*cache)->num_elems) + return (NULL); + if (flags == FIND_COLORMAP) + return (*cache); + + /* Depth */ + cache = (XawCache **)bsearch((void *)(long)depth, (*cache)->elems, + (*cache)->num_elems, sizeof(XtPointer), + bcmp_long); + + if (!cache || !(*cache)->num_elems) + return (NULL); + return (*cache); +} + +static XawCache * +_XawGetCache(XawCache *xaw, Screen *screen, Colormap colormap, int depth) +{ + XawCache *s_cache, *c_cache, *d_cache, *cache, *pcache; + + cache = _XawFindCache(xaw, screen, colormap, depth, FIND_ALL); + + if (!cache) + { + s_cache = _XawFindCache(xaw, + screen, colormap, depth, FIND_SCREEN); + if (!s_cache) + { + pcache = (XawCache *)XtMalloc(sizeof(XawCache)); + if (!xaw->num_elems) + { + xaw->num_elems = 1; + xaw->elems = (XtPointer*)XtMalloc(sizeof(XtPointer)); + } + else + { + ++xaw->num_elems; + xaw->elems = (XtPointer*) + XtRealloc((char *)xaw->elems, + sizeof(XtPointer) * xaw->num_elems); + } + pcache->value = (long)screen; + pcache->elems = NULL; + pcache->num_elems = 0; + xaw->elems[xaw->num_elems - 1] = (XtPointer)pcache; + s_cache = (XawCache *)xaw->elems[xaw->num_elems - 1]; + if (xaw->num_elems > 1) + qsort(xaw->elems, xaw->num_elems, sizeof(XtPointer), qcmp_long); + } + + c_cache = _XawFindCache(xaw, + screen, colormap, depth, FIND_COLORMAP); + if (!c_cache) + { + pcache = (XawCache *)XtMalloc(sizeof(XawCache)); + if (!s_cache->num_elems) + { + s_cache->num_elems = 1; + s_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer)); + } + else + { + ++s_cache->num_elems; + s_cache->elems = (XtPointer*) + XtRealloc((char *)s_cache->elems, + sizeof(XtPointer) * s_cache->num_elems); + } + pcache->value = (long)colormap; + pcache->elems = NULL; + pcache->num_elems = 0; + s_cache->elems[s_cache->num_elems - 1] = (XtPointer)pcache; + c_cache = (XawCache *)s_cache->elems[s_cache->num_elems - 1]; + if (s_cache->num_elems > 1) + qsort(s_cache->elems, s_cache->num_elems, + sizeof(XtPointer), qcmp_long); + } + + d_cache = _XawFindCache(xaw, + screen, colormap, depth, FIND_DEPTH); + if (!d_cache) + { + pcache = (XawCache *)XtMalloc(sizeof(XawCache)); + if (!c_cache->num_elems) + { + c_cache->num_elems = 1; + c_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer)); + } + else + { + ++c_cache->num_elems; + c_cache->elems = (XtPointer*) + XtRealloc((char *)c_cache->elems, + sizeof(XtPointer) * c_cache->num_elems); + } + pcache->value = (long)depth; + pcache->elems = NULL; + pcache->num_elems = 0; + c_cache->elems[c_cache->num_elems - 1] = (XtPointer)pcache; + d_cache = (XawCache *)c_cache->elems[c_cache->num_elems - 1]; + if (c_cache->num_elems > 1) + qsort(c_cache->elems, c_cache->num_elems, + sizeof(XtPointer), qcmp_long); + } + + cache = d_cache; + } + + return (cache); +} + +static XawPixmap * +_XawFindPixmap(String name, Screen *screen, Colormap colormap, int depth) +{ + XawCache *cache; + XawPixmap **pixmap; + + cache = _XawFindCache(&xaw_pixmaps, screen, colormap, depth, FIND_ALL); + + if (!cache) + return (NULL); + + /* Name */ + pixmap = (XawPixmap **)bsearch((void *)name, cache->elems, + cache->num_elems, sizeof(XtPointer), + bcmp_string); + if (!pixmap) + return (NULL); + + return (*pixmap); +} + +XawPixmap * +XawPixmapFromXPixmap(Pixmap pixmap, + Screen *screen, Colormap colormap, int depth) +{ + XawCache *cache; + XawPixmap **x_pixmap; + + cache = _XawFindCache(&x_pixmaps, screen, colormap, depth, FIND_ALL); + + if (!cache) + return (NULL); + + /* Pixmap */ + x_pixmap = (XawPixmap **)bsearch((void *)pixmap, cache->elems, + cache->num_elems, sizeof(XtPointer), + bcmp_x_cache); + if (!x_pixmap) + return (NULL); + + return (*x_pixmap); +} + +static void +_XawCachePixmap(XawPixmap *pixmap, + Screen *screen, Colormap colormap, int depth) +{ + XawCache *xaw_cache, *x_cache; + + xaw_cache = _XawGetCache(&xaw_pixmaps, screen, colormap, depth); + x_cache = _XawGetCache(&x_pixmaps, screen, colormap, depth); + + if (!xaw_cache->num_elems) + { + xaw_cache->num_elems = 1; + xaw_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer)); + } + else + { + ++xaw_cache->num_elems; + xaw_cache->elems = (XtPointer*)XtRealloc((char *)xaw_cache->elems, + sizeof(XtPointer) * + xaw_cache->num_elems); + } + + xaw_cache->elems[xaw_cache->num_elems - 1] = (XtPointer)pixmap; + if (xaw_cache->num_elems > 1) + qsort(xaw_cache->elems, xaw_cache->num_elems, + sizeof(XtPointer), qcmp_string); + + + if (!x_cache->num_elems) + { + x_cache->num_elems = 1; + x_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer)); + } + else + { + ++x_cache->num_elems; + x_cache->elems = (XtPointer*)XtRealloc((char *)x_cache->elems, + sizeof(XtPointer) * + x_cache->num_elems); + } + + x_cache->elems[x_cache->num_elems - 1] = (XtPointer)pixmap; + if (x_cache->num_elems > 1) + qsort(x_cache->elems, x_cache->num_elems, sizeof(XtPointer), qcmp_x_cache); +} + +#ifndef PROJECT_ROOT +#define PROJECT_ROOT "/usr/X11R6" +#endif + +static char *pixmap_path = NULL; + +static void +GetResourcePixmapPath(Display *display) +{ + XrmName xrm_name[2]; + XrmClass xrm_class[2]; + XrmRepresentation rep_type; + XrmValue value; + static char *default_path = + "%H/%T/%N:%P/include/X11/%T/%N:/usr/X11R6/include/X11/%T/%N:/usr/include/X11/%T/%N:%N"; + + xrm_name[0] = XrmPermStringToQuark("pixmapFilePath"); + xrm_name[1] = NULLQUARK; + xrm_class[0] = XrmPermStringToQuark("PixmapFilePath"); + xrm_class[1] = NULLQUARK; + if (!XrmGetDatabase(display)) + (void) XGetDefault(display, "", ""); + if (XrmQGetResource(XrmGetDatabase(display), xrm_name, xrm_class, + &rep_type, &value) && + rep_type == XrmPermStringToQuark("String")) { + int length = 0; + char *tok, *buffer = XtNewString(value.addr); + + for (tok = strtok(buffer, ":"); tok; tok = strtok(NULL, ":")) { + int toklen = strlen(tok); + + if (toklen) { + pixmap_path = XtRealloc(pixmap_path, length + toklen + 5); + strcpy(pixmap_path + length, tok); + if (length) + pixmap_path[length++] = ':'; + sprintf(pixmap_path + length, "%s/%%N", tok); + length += strlen(tok) + 3; + } + } + pixmap_path = XtRealloc(pixmap_path, length + strlen(default_path) + 2); + if (length) + pixmap_path[length++] = ':'; + strcpy(pixmap_path + length, default_path); + } + else + pixmap_path = default_path; +} + +static Bool +BitmapLoader(XawParams *params, Screen *screen, Colormap colormap, int depth, + Pixmap *pixmap_return, Pixmap *mask_return, + Dimension *width_return, Dimension *height_return) +{ + Pixel fg, bg; + XColor color, exact; + Pixmap pixmap; + unsigned int width, height; + unsigned char *data = NULL; + int hotX, hotY; + XawArgVal *argval; + Bool retval = False; + static SubstitutionRec sub[] = { + {'H', NULL}, + {'N', NULL}, + {'T', "bitmaps"}, + {'P', PROJECT_ROOT}, + }; + char *filename; + + fg = BlackPixelOfScreen(screen); + bg = WhitePixelOfScreen(screen); + + if ((argval = XawFindArgVal(params, "foreground")) != NULL + && argval->value) + { + if (XAllocNamedColor(DisplayOfScreen(screen), colormap, argval->value, + &color, &exact)) + fg = color.pixel; + else + return (False); + } + if ((argval = XawFindArgVal(params, "background")) != NULL + && argval->value) + { + if (XAllocNamedColor(DisplayOfScreen(screen), colormap, argval->value, + &color, &exact)) + bg = color.pixel; + else + return (False); + } + + if (params->name[0] != '/' && params->name[0] != '.') + { + if (!sub[0].substitution) + #ifdef _MSC_VER + sub[0].substitution = "."; + #else + sub[0].substitution = getenv("HOME"); + #endif + sub[1].substitution = params->name; + if (pixmap_path == NULL) + GetResourcePixmapPath(DisplayOfScreen(screen)); + filename = XtFindFile(pixmap_path, sub, XtNumber(sub), NULL); + if (!filename) + return (FALSE); + } + else + filename = params->name; + + if (XReadBitmapFileData(filename, &width, &height, &data, + &hotX, &hotY) == BitmapSuccess) + { + pixmap = XCreatePixmapFromBitmapData(DisplayOfScreen(screen), + RootWindowOfScreen(screen), + (char *)data, + width, height, fg, bg, depth); + if (data) + XFree(data); + *pixmap_return = pixmap; + *mask_return = None; + *width_return = width; + *height_return = height; + + retval = True; + } + + if (filename != params->name) + XtFree(filename); + + return (retval); +} + +#define VERTICAL 1 +#define HORIZONTAL 2 +static Bool +GradientLoader(XawParams *params, Screen *screen, Colormap colormap, int depth, + Pixmap *pixmap_return, Pixmap *mask_return, + Dimension *width_return, Dimension *height_return) +{ + double ired, igreen, iblue, red, green, blue; + XColor start, end, color; + XGCValues values; + GC gc; + double i, inc, x, y, xend, yend; + Pixmap pixmap; + XawArgVal *argval; + int orientation, dimension, steps; + char *value; + + if (XmuCompareISOLatin1(params->name, "vertical") == 0) + orientation = VERTICAL; + else if (XmuCompareISOLatin1(params->name, "horizontal") == 0) + orientation = HORIZONTAL; + else + return (False); + + if ((argval = XawFindArgVal(params, "dimension")) != NULL + && argval->value) + { + dimension = atoi(argval->value); + if (dimension <= 0) + return (False); + } + else + dimension = 50; + + if ((argval = XawFindArgVal(params, "steps")) != NULL + && argval->value) + { + steps = atoi(argval->value); + if (steps <= 0) + return (False); + } + else + steps = dimension; + + steps = XawMin(steps, dimension); + + value = NULL; + if ((argval = XawFindArgVal(params, "start")) != NULL) + value = argval->value; + if (value && !XAllocNamedColor(DisplayOfScreen(screen), colormap, value, + &start, &color)) + return (False); + else if (!value) + { + start.pixel = WhitePixelOfScreen(screen); + XQueryColor(DisplayOfScreen(screen), colormap, &start); + } + value = NULL; + if ((argval = XawFindArgVal(params, "end")) != NULL) + value = argval->value; + if (value && !XAllocNamedColor(DisplayOfScreen(screen), colormap, value, + &end, &color)) + return (False); + else if (!value) + { + end.pixel = BlackPixelOfScreen(screen); + XQueryColor(DisplayOfScreen(screen), colormap, &end); + } + + if ((pixmap = XCreatePixmap(DisplayOfScreen(screen), + RootWindowOfScreen(screen), + orientation == VERTICAL ? 1 : dimension, + orientation == VERTICAL ? dimension : 1, depth)) + == 0) + return (False); + + ired = (double)(end.red - start.red) / (double)steps; + igreen = (double)(end.green - start.green) / (double)steps; + iblue = (double)(end.blue - start.blue) / (double)steps; + + red = color.red = start.red; + green = color.green = start.green; + blue = color.blue = start.blue; + + inc = (double)dimension / (double)steps; + + gc = XCreateGC(DisplayOfScreen(screen), pixmap, 0, &values); + + x = y = 0.0; + if (orientation == VERTICAL) + { + xend = 1; + yend = 0; + } + else + { + xend = 0; + yend = 1; + } + + color.flags = DoRed | DoGreen | DoBlue; + + XSetForeground(DisplayOfScreen(screen), gc, start.pixel); + for (i = 0.0; i < dimension; i += inc) + { + if ((int)color.red != (int)red || (int)color.green != (int)green + || (int)color.blue != (int)blue) + { + XFillRectangle(DisplayOfScreen(screen), pixmap, gc, (int)x, (int)y, + (unsigned int)xend, (unsigned int)yend); + color.red = (unsigned short)red; + color.green = (unsigned short)green; + color.blue = (unsigned short)blue; + if (!XAllocColor(DisplayOfScreen(screen), colormap, &color)) + { + XFreePixmap(DisplayOfScreen(screen), pixmap); + return (False); + } + XSetForeground(DisplayOfScreen(screen), gc, color.pixel); + if (orientation == VERTICAL) + y = yend; + else + x = xend; + } + red += ired; + green += igreen; + blue += iblue; + if (orientation == VERTICAL) + yend += inc; + else + xend += inc; + } + XFillRectangle(DisplayOfScreen(screen), pixmap, gc, (int)x, (int)y, + (unsigned int)xend, (unsigned int)yend); + + *pixmap_return = pixmap; + *mask_return = None; + *width_return = orientation == VERTICAL ? 1 : dimension; + *height_return = orientation == VERTICAL ? dimension : 1; + + XFreeGC(DisplayOfScreen(screen), gc); + + return (True); +} + +static Bool +XPixmapLoader(XawParams *params, Screen *screen, Colormap colormap, int depth, + Pixmap *pixmap_return, Pixmap *mask_return, + Dimension *width_return, Dimension *height_return) +{ + XpmAttributes xpm_attributes; + XawArgVal *argval; + unsigned int closeness = 4000; + static SubstitutionRec sub[] = { + {'H', NULL}, + {'N', NULL}, + {'T', "pixmaps"}, + {'P', PROJECT_ROOT}, + }; + char *filename; + + if ((argval = XawFindArgVal(params, "closeness")) != NULL + && argval->value) + closeness = atoi(argval->value); + + if (params->name[0] != '/' && params->name[0] != '.') + { + if (!sub[0].substitution) + sub[0].substitution = getenv("HOME"); + sub[1].substitution = params->name; + if (pixmap_path == NULL) + GetResourcePixmapPath(DisplayOfScreen(screen)); + filename = XtFindFile(pixmap_path, sub, XtNumber(sub), NULL); + if (!filename) + return (False); + } + else + filename = params->name; + + xpm_attributes.colormap = colormap; + xpm_attributes.closeness = closeness; + xpm_attributes.valuemask = XpmSize | XpmColormap | XpmCloseness; + if (XpmReadFileToPixmap(DisplayOfScreen(screen), + RootWindowOfScreen(screen), filename, pixmap_return, + mask_return, &xpm_attributes) == XpmSuccess) + { + *width_return = xpm_attributes.width; + *height_return = xpm_attributes.height; + + return (True); + } + + return (False); +} + +void +XawReshapeWidget(Widget w, XawPixmap *pixmap) +{ + if (!pixmap || pixmap->mask == None) + XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 0, 0, + None, ShapeSet); + else + XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 0, 0, + pixmap->mask, ShapeSet); +} + +#endif /* OLDXAW */ diff --git a/libXaw/src/Porthole.c b/libXaw/src/Porthole.c index 082e98a12..e94d21360 100644 --- a/libXaw/src/Porthole.c +++ b/libXaw/src/Porthole.c @@ -1,376 +1,376 @@ -/*
- *
-Copyright 1990, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- * Author: Jim Fulton, MIT X Consortium
- *
- * This widget is a trivial clipping widget. It is typically used with a
- * panner or scrollbar to navigate.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xaw/PortholeP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * Class Methods
- */
-static void XawPortholeChangeManaged(Widget);
-static XtGeometryResult XawPortholeGeometryManager(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static XtGeometryResult XawPortholeQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawPortholeRealize(Widget, Mask*, XSetWindowAttributes*);
-static void XawPortholeResize(Widget);
-
-/*
- * Prototypes
- */
-static Widget find_child(PortholeWidget);
-static void layout_child(PortholeWidget, Widget, XtWidgetGeometry*,
- Position*, Position*, Dimension*, Dimension*);
-static void SendReport(PortholeWidget, unsigned int);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(PortholeRec, porthole.field)
-static XtResource resources[] = {
- {
- XtNreportCallback,
- XtCReportCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(report_callbacks),
- XtRCallback,
- NULL
- },
-};
-#undef offset
-
-#define Superclass (&compositeClassRec)
-PortholeClassRec portholeClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "Porthole", /* class_name */
- sizeof(PortholeRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- NULL, /* initialize */
- NULL, /* initialize_hook */
- XawPortholeRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- XawPortholeResize, /* resize */
- NULL, /* expose */
- NULL, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XawPortholeQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* composite */
- {
- XawPortholeGeometryManager, /* geometry_manager */
- XawPortholeChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- { /* porthole */
- NULL, /* extension */
- },
-};
-
-WidgetClass portholeWidgetClass = (WidgetClass)&portholeClassRec;
-
-/*
- * Implementation
- */
-static Widget
-find_child(PortholeWidget pw)
-{
- Widget *children;
- unsigned int i;
-
- /*
- * Find the managed child on which we should operate. Ignore multiple
- * managed children
- */
- for (i = 0, children = pw->composite.children;
- i < pw->composite.num_children; i++, children++)
- if (XtIsManaged(*children))
- return (*children);
-
- return (NULL);
-}
-
-static void
-SendReport(PortholeWidget pw, unsigned int changed)
-{
- Widget child = find_child(pw);
-
- if (pw->porthole.report_callbacks && child) {
- XawPannerReport prep;
-
- prep.changed = changed;
- prep.slider_x = -XtX(child); /* porthole is "inner" */
- prep.slider_y = -XtY(child); /* child is outer since it is larger */
- prep.slider_width = XtWidth(pw);
- prep.slider_height = XtHeight(pw);
- prep.canvas_width = XtWidth(child);
- prep.canvas_height = XtHeight(child);
- XtCallCallbackList((Widget)pw, pw->porthole.report_callbacks,
- (XtPointer)&prep);
- }
-}
-
-static void
-layout_child(PortholeWidget pw, Widget child, XtWidgetGeometry *geomp,
- Position *xp, Position *yp, Dimension *widthp, Dimension *heightp)
-{
- Position minx, miny;
-
- *xp = XtX(child); /* default to current values */
- *yp = XtY(child);
- *widthp = XtWidth(child);
- *heightp = XtHeight(child);
- if (geomp) { /* mix in any requested changes */
- if (geomp->request_mode & CWX)
- *xp = geomp->x;
- if (geomp->request_mode & CWY)
- *yp = geomp->y;
- if (geomp->request_mode & CWWidth)
- *widthp = geomp->width;
- if (geomp->request_mode & CWHeight)
- *heightp = geomp->height;
- }
-
- /*
- * Make sure that the child is at least as large as the porthole; there
- * is no maximum size
- */
- if (*widthp < XtWidth(pw)) *widthp = XtWidth(pw);
- if (*heightp < XtHeight(pw)) *heightp = XtHeight(pw);
-
- /*
- * Make sure that the child is still on the screen. Note that this must
- * be done *after* the size computation so that we know where to put it
- */
- minx = (Position)XtWidth(pw) - (Position)*widthp;
- miny = (Position)XtHeight(pw) - (Position)*heightp;
-
- if (*xp < minx)
- *xp = minx;
- if (*yp < miny)
- *yp = miny;
-
- if (*xp > 0)
- *xp = 0;
- if (*yp > 0)
- *yp = 0;
-}
-
-static void
-XawPortholeRealize(Widget gw, Mask *valueMask, XSetWindowAttributes *attr)
-{
- attr->bit_gravity = NorthWestGravity;
- *valueMask |= CWBitGravity;
-
- if (XtWidth(gw) < 1)
- XtWidth(gw) = 1;
- if (XtHeight(gw) < 1)
- XtHeight(gw) = 1;
- (*portholeWidgetClass->core_class.superclass->core_class.realize)
- (gw, valueMask, attr);
-}
-
-static void
-XawPortholeResize(Widget gw)
-{
- PortholeWidget pw = (PortholeWidget)gw;
- Widget child = find_child(pw);
-
- /*
- * If we have a child, we need to make sure that it is at least as big
- * as we are and in the right place
- */
- if (child) {
- Position x, y;
- Dimension width, height;
-
- layout_child(pw, child, NULL, &x, &y, &width, &height);
- XtConfigureWidget(child, x, y, width, height, 0);
- }
-
- SendReport(pw, XawPRCanvasWidth | XawPRCanvasHeight);
-}
-
-static XtGeometryResult
-XawPortholeQueryGeometry(Widget gw, XtWidgetGeometry *intended,
- XtWidgetGeometry *preferred)
-{
- PortholeWidget pw = (PortholeWidget)gw;
- Widget child = find_child(pw);
-
- if (child) {
-#define SIZEONLY (CWWidth | CWHeight)
- preferred->request_mode = SIZEONLY;
- preferred->width = XtWidth(child);
- preferred->height = XtHeight(child);
-
- if ((intended->request_mode & SIZEONLY) == SIZEONLY &&
- intended->width == preferred->width &&
- intended->height == preferred->height)
- return (XtGeometryYes);
- else if (preferred->width == XtWidth(pw) &&
- preferred->height == XtHeight(pw))
- return (XtGeometryNo);
-
- return (XtGeometryAlmost);
-#undef SIZEONLY
- }
-
- return (XtGeometryNo);
-}
-
-static XtGeometryResult
-XawPortholeGeometryManager(Widget w, XtWidgetGeometry *req,
- XtWidgetGeometry *reply)
-{
- PortholeWidget pw = (PortholeWidget) w->core.parent;
- Widget child = find_child(pw);
- Bool okay = True;
-
- if (child != w)
- return (XtGeometryNo);
-
- *reply = *req; /* assume we'll grant everything */
-
- if ((req->request_mode & CWBorderWidth) && req->border_width != 0) {
- reply->border_width = 0;
- okay = False;
- }
-
- layout_child(pw, child, req, &reply->x, &reply->y,
- &reply->width, &reply->height);
-
- if ((req->request_mode & CWX) && req->x != reply->x)
- okay = False;
- if ((req->request_mode & CWY) && req->x != reply->x)
- okay = False;
- if ((req->request_mode & CWWidth) && req->width != reply->width)
- okay = False;
- if ((req->request_mode & CWHeight) && req->height != reply->height)
- okay = False;
-
- /*
- * If we failed on anything, simply return without touching widget
- */
- if (!okay)
- return (XtGeometryAlmost);
-
- /*
- * If not just doing a query, update widget and send report. Note that
- * we will often set fields that weren't requested because we want to keep
- * the child visible
- */
- if (!(req->request_mode & XtCWQueryOnly)) {
- unsigned int changed = 0;
-
- if (XtX(child) != reply->x) {
- changed |= XawPRSliderX;
- XtX(child) = reply->x;
- }
- if (XtY(child) != reply->y) {
- changed |= XawPRSliderY;
- XtY(child) = reply->y;
- }
- if (XtWidth(child) != reply->width) {
- changed |= XawPRSliderWidth;
- XtWidth(child) = reply->width;
- }
- if (XtHeight(child) != reply->height) {
- changed |= XawPRSliderHeight;
- XtHeight(child) = reply->height;
- }
- if (changed)
- SendReport(pw, changed);
- }
-
- return (XtGeometryYes); /* success! */
-}
-
-static void
-XawPortholeChangeManaged(Widget gw)
-{
- PortholeWidget pw = (PortholeWidget)gw;
- Widget child = find_child (pw); /* ignore extra children */
-
- if (child) {
- if (!XtIsRealized (gw)) {
- XtWidgetGeometry geom, retgeom;
-
- geom.request_mode = 0;
- if (XtWidth(pw) == 0) {
- geom.width = XtWidth(child);
- geom.request_mode |= CWWidth;
- }
- if (XtHeight(pw) == 0) {
- geom.height = XtHeight(child);
- geom.request_mode |= CWHeight;
- }
- if (geom.request_mode &&
- XtMakeGeometryRequest (gw, &geom, &retgeom)
- == XtGeometryAlmost)
- (void)XtMakeGeometryRequest(gw, &retgeom, NULL);
- }
-
- XtResizeWidget(child, Max(XtWidth(child), XtWidth(pw)),
- Max(XtHeight(child), XtHeight(pw)), 0);
-
- SendReport(pw, XawPRAll);
- }
-}
+/* + * +Copyright 1990, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Jim Fulton, MIT X Consortium + * + * This widget is a trivial clipping widget. It is typically used with a + * panner or scrollbar to navigate. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw/PortholeP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * Class Methods + */ +static void XawPortholeChangeManaged(Widget); +static XtGeometryResult XawPortholeGeometryManager(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static XtGeometryResult XawPortholeQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawPortholeRealize(Widget, Mask*, XSetWindowAttributes*); +static void XawPortholeResize(Widget); + +/* + * Prototypes + */ +static Widget find_child(PortholeWidget); +static void layout_child(PortholeWidget, Widget, XtWidgetGeometry*, + Position*, Position*, Dimension*, Dimension*); +static void SendReport(PortholeWidget, unsigned int); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(PortholeRec, porthole.field) +static XtResource resources[] = { + { + XtNreportCallback, + XtCReportCallback, + XtRCallback, + sizeof(XtPointer), + offset(report_callbacks), + XtRCallback, + NULL + }, +}; +#undef offset + +#define Superclass (&compositeClassRec) +PortholeClassRec portholeClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Porthole", /* class_name */ + sizeof(PortholeRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + NULL, /* initialize */ + NULL, /* initialize_hook */ + XawPortholeRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XawPortholeResize, /* resize */ + NULL, /* expose */ + NULL, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XawPortholeQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* composite */ + { + XawPortholeGeometryManager, /* geometry_manager */ + XawPortholeChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + { /* porthole */ + NULL, /* extension */ + }, +}; + +WidgetClass portholeWidgetClass = (WidgetClass)&portholeClassRec; + +/* + * Implementation + */ +static Widget +find_child(PortholeWidget pw) +{ + Widget *children; + unsigned int i; + + /* + * Find the managed child on which we should operate. Ignore multiple + * managed children + */ + for (i = 0, children = pw->composite.children; + i < pw->composite.num_children; i++, children++) + if (XtIsManaged(*children)) + return (*children); + + return (NULL); +} + +static void +SendReport(PortholeWidget pw, unsigned int changed) +{ + Widget child = find_child(pw); + + if (pw->porthole.report_callbacks && child) { + XawPannerReport prep; + + prep.changed = changed; + prep.slider_x = -XtX(child); /* porthole is "inner" */ + prep.slider_y = -XtY(child); /* child is outer since it is larger */ + prep.slider_width = XtWidth(pw); + prep.slider_height = XtHeight(pw); + prep.canvas_width = XtWidth(child); + prep.canvas_height = XtHeight(child); + XtCallCallbackList((Widget)pw, pw->porthole.report_callbacks, + (XtPointer)&prep); + } +} + +static void +layout_child(PortholeWidget pw, Widget child, XtWidgetGeometry *geomp, + Position *xp, Position *yp, Dimension *widthp, Dimension *heightp) +{ + Position minx, miny; + + *xp = XtX(child); /* default to current values */ + *yp = XtY(child); + *widthp = XtWidth(child); + *heightp = XtHeight(child); + if (geomp) { /* mix in any requested changes */ + if (geomp->request_mode & CWX) + *xp = geomp->x; + if (geomp->request_mode & CWY) + *yp = geomp->y; + if (geomp->request_mode & CWWidth) + *widthp = geomp->width; + if (geomp->request_mode & CWHeight) + *heightp = geomp->height; + } + + /* + * Make sure that the child is at least as large as the porthole; there + * is no maximum size + */ + if (*widthp < XtWidth(pw)) *widthp = XtWidth(pw); + if (*heightp < XtHeight(pw)) *heightp = XtHeight(pw); + + /* + * Make sure that the child is still on the screen. Note that this must + * be done *after* the size computation so that we know where to put it + */ + minx = (Position)XtWidth(pw) - (Position)*widthp; + miny = (Position)XtHeight(pw) - (Position)*heightp; + + if (*xp < minx) + *xp = minx; + if (*yp < miny) + *yp = miny; + + if (*xp > 0) + *xp = 0; + if (*yp > 0) + *yp = 0; +} + +static void +XawPortholeRealize(Widget gw, Mask *valueMask, XSetWindowAttributes *attr) +{ + attr->bit_gravity = NorthWestGravity; + *valueMask |= CWBitGravity; + + if (XtWidth(gw) < 1) + XtWidth(gw) = 1; + if (XtHeight(gw) < 1) + XtHeight(gw) = 1; + (*portholeWidgetClass->core_class.superclass->core_class.realize) + (gw, valueMask, attr); +} + +static void +XawPortholeResize(Widget gw) +{ + PortholeWidget pw = (PortholeWidget)gw; + Widget child = find_child(pw); + + /* + * If we have a child, we need to make sure that it is at least as big + * as we are and in the right place + */ + if (child) { + Position x, y; + Dimension width, height; + + layout_child(pw, child, NULL, &x, &y, &width, &height); + XtConfigureWidget(child, x, y, width, height, 0); + } + + SendReport(pw, XawPRCanvasWidth | XawPRCanvasHeight); +} + +static XtGeometryResult +XawPortholeQueryGeometry(Widget gw, XtWidgetGeometry *intended, + XtWidgetGeometry *preferred) +{ + PortholeWidget pw = (PortholeWidget)gw; + Widget child = find_child(pw); + + if (child) { +#define SIZEONLY (CWWidth | CWHeight) + preferred->request_mode = SIZEONLY; + preferred->width = XtWidth(child); + preferred->height = XtHeight(child); + + if ((intended->request_mode & SIZEONLY) == SIZEONLY && + intended->width == preferred->width && + intended->height == preferred->height) + return (XtGeometryYes); + else if (preferred->width == XtWidth(pw) && + preferred->height == XtHeight(pw)) + return (XtGeometryNo); + + return (XtGeometryAlmost); +#undef SIZEONLY + } + + return (XtGeometryNo); +} + +static XtGeometryResult +XawPortholeGeometryManager(Widget w, XtWidgetGeometry *req, + XtWidgetGeometry *reply) +{ + PortholeWidget pw = (PortholeWidget) w->core.parent; + Widget child = find_child(pw); + Bool okay = True; + + if (child != w) + return (XtGeometryNo); + + *reply = *req; /* assume we'll grant everything */ + + if ((req->request_mode & CWBorderWidth) && req->border_width != 0) { + reply->border_width = 0; + okay = False; + } + + layout_child(pw, child, req, &reply->x, &reply->y, + &reply->width, &reply->height); + + if ((req->request_mode & CWX) && req->x != reply->x) + okay = False; + if ((req->request_mode & CWY) && req->x != reply->x) + okay = False; + if ((req->request_mode & CWWidth) && req->width != reply->width) + okay = False; + if ((req->request_mode & CWHeight) && req->height != reply->height) + okay = False; + + /* + * If we failed on anything, simply return without touching widget + */ + if (!okay) + return (XtGeometryAlmost); + + /* + * If not just doing a query, update widget and send report. Note that + * we will often set fields that weren't requested because we want to keep + * the child visible + */ + if (!(req->request_mode & XtCWQueryOnly)) { + unsigned int changed = 0; + + if (XtX(child) != reply->x) { + changed |= XawPRSliderX; + XtX(child) = reply->x; + } + if (XtY(child) != reply->y) { + changed |= XawPRSliderY; + XtY(child) = reply->y; + } + if (XtWidth(child) != reply->width) { + changed |= XawPRSliderWidth; + XtWidth(child) = reply->width; + } + if (XtHeight(child) != reply->height) { + changed |= XawPRSliderHeight; + XtHeight(child) = reply->height; + } + if (changed) + SendReport(pw, changed); + } + + return (XtGeometryYes); /* success! */ +} + +static void +XawPortholeChangeManaged(Widget gw) +{ + PortholeWidget pw = (PortholeWidget)gw; + Widget child = find_child (pw); /* ignore extra children */ + + if (child) { + if (!XtIsRealized (gw)) { + XtWidgetGeometry geom, retgeom; + + geom.request_mode = 0; + if (XtWidth(pw) == 0) { + geom.width = XtWidth(child); + geom.request_mode |= CWWidth; + } + if (XtHeight(pw) == 0) { + geom.height = XtHeight(child); + geom.request_mode |= CWHeight; + } + if (geom.request_mode && + XtMakeGeometryRequest (gw, &geom, &retgeom) + == XtGeometryAlmost) + (void)XtMakeGeometryRequest(gw, &retgeom, NULL); + } + + XtResizeWidget(child, Max(XtWidth(child), XtWidth(pw)), + Max(XtHeight(child), XtHeight(pw)), 0); + + SendReport(pw, XawPRAll); + } +} diff --git a/libXaw/src/Private.h b/libXaw/src/Private.h index 672062aeb..3a91b7a43 100644 --- a/libXaw/src/Private.h +++ b/libXaw/src/Private.h @@ -1,152 +1,152 @@ -/*
- * Copyright (c) 1998 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the XFree86 Project shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from the
- * XFree86 Project.
- */
-
-#ifndef _XawPrivate_h
-#define _XawPrivate_h
-
-#define XawMax(a, b) ((a) > (b) ? (a) : (b))
-#define XawMin(a, b) ((a) < (b) ? (a) : (b))
-#define XawAbs(a) ((a) < 0 ? -(a) : (a))
-
-#define XawStackAlloc(size, stk_buffer) \
-((size) <= sizeof(stk_buffer) \
- ? (XtPointer)(stk_buffer) \
- : XtMalloc((unsigned)(size)))
-
-#define XawStackFree(pointer, stk_buffer) \
-do { \
- if ((pointer) != (XtPointer)(stk_buffer)) \
- XtFree((char *)pointer); \
-} while (0)
-
-#ifndef XtX
-#define XtX(w) (((RectObj)w)->rectangle.x)
-#endif
-#ifndef XtY
-#define XtY(w) (((RectObj)w)->rectangle.y)
-#endif
-#ifndef XtWidth
-#define XtWidth(w) (((RectObj)w)->rectangle.width)
-#endif
-#ifndef XtHeight
-#define XtHeight(w) (((RectObj)w)->rectangle.height)
-#endif
-#ifndef XtBorderWidth
-#define XtBorderWidth(w) (((RectObj)w)->rectangle.border_width)
-#endif
-
-#ifndef OLDXAW
-#define XAW_PRIV_VAR_PREFIX '$'
-
-typedef Bool (*XawParseBooleanProc)(Widget, String, XEvent*, Bool*);
-
-typedef struct _XawActionVarList XawActionVarList;
-typedef struct _XawActionResList XawActionResList;
-
-/* Boolean expressions */
-Bool XawParseBoolean(Widget, String, XEvent*, Bool*);
-Bool XawBooleanExpression(Widget, String, XEvent*);
-
-/* actions */
-void XawPrintActionErrorMsg(String, Widget, String*, Cardinal*);
-XawActionResList *XawGetActionResList(WidgetClass);
-XawActionVarList *XawGetActionVarList(Widget);
-
-void XawSetValuesAction(Widget, XEvent*, String*, Cardinal*);
-void XawGetValuesAction(Widget, XEvent*, String*, Cardinal*);
-void XawDeclareAction(Widget, XEvent*, String*, Cardinal*);
-void XawCallProcAction(Widget, XEvent*, String*, Cardinal*);
-
-/* display lists */
-#define XAWDL_CONVERT_ERROR (XtPointer)-1
-typedef struct _XawDL _XawDisplayList;
-typedef struct _XawDLClass XawDLClass, XawDisplayListClass;
-
-typedef void (*XawDisplayListProc)(Widget, XtPointer, XtPointer,
- XEvent*, Region);
-typedef void *(*XawDLArgsInitProc)(String, String*, Cardinal*,
- Screen*, Colormap, int);
-typedef void *(*XawDLDataInitProc)(String,
- Screen*, Colormap, int);
-typedef void (*XawDLArgsDestructor)(Display*, String, XtPointer,
- String*, Cardinal*);
-typedef void (*XawDLDataDestructor)(Display*, String, XtPointer);
-
-void XawRunDisplayList(Widget, _XawDisplayList*, XEvent*, Region);
-void XawDisplayListInitialize(void);
-
-_XawDisplayList *XawCreateDisplayList(String, Screen*, Colormap, int);
-void XawDestroyDisplayList(_XawDisplayList*);
-String XawDisplayListString(_XawDisplayList*);
-XawDLClass *XawGetDisplayListClass(String);
-XawDLClass *XawCreateDisplayListClass(String,
- XawDLArgsInitProc, XawDLArgsDestructor,
- XawDLDataInitProc, XawDLDataDestructor);
-Bool XawDeclareDisplayListProc(XawDLClass*, String, XawDisplayListProc);
-
-/* pixmaps */
-typedef struct _XawArgVal {
- String name;
- String value;
-} XawArgVal;
-
-typedef struct _XawParams {
- String name;
- String type;
- String ext;
- XawArgVal **args;
- Cardinal num_args;
-} XawParams;
-
-typedef struct _XawPixmap {
- String name;
- Pixmap pixmap;
- Pixmap mask;
- Dimension width;
- Dimension height;
-} XawPixmap;
-
-typedef Bool (*XawPixmapLoader)(XawParams*, Screen*, Colormap, int,
- Pixmap*, Pixmap*,
- Dimension*, Dimension*);
-Bool XawPixmapsInitialize(void);
-Bool XawAddPixmapLoader(String, String, XawPixmapLoader);
-XawPixmap *XawLoadPixmap(String, Screen*, Colormap, int);
-XawPixmap *XawPixmapFromXPixmap(Pixmap, Screen*, Colormap, int);
-XawParams *XawParseParamsString(String name);
-void XawFreeParamsStruct(XawParams *params);
-XawArgVal *XawFindArgVal(XawParams *params, String name);
-void XawReshapeWidget(Widget, XawPixmap*);
-#endif /* OLDXAW */
-
-/* misc */
-void XawTypeToStringWarning(Display*, String);
-
-/* OS.c */
-int _XawGetPageSize(void);
-
-#endif /* _XawPrivate_h */
+/* + * Copyright (c) 1998 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifndef _XawPrivate_h +#define _XawPrivate_h + +#define XawMax(a, b) ((a) > (b) ? (a) : (b)) +#define XawMin(a, b) ((a) < (b) ? (a) : (b)) +#define XawAbs(a) ((a) < 0 ? -(a) : (a)) + +#define XawStackAlloc(size, stk_buffer) \ +((size) <= sizeof(stk_buffer) \ + ? (XtPointer)(stk_buffer) \ + : XtMalloc((unsigned)(size))) + +#define XawStackFree(pointer, stk_buffer) \ +do { \ + if ((pointer) != (XtPointer)(stk_buffer)) \ + XtFree((char *)pointer); \ +} while (0) + +#ifndef XtX +#define XtX(w) (((RectObj)w)->rectangle.x) +#endif +#ifndef XtY +#define XtY(w) (((RectObj)w)->rectangle.y) +#endif +#ifndef XtWidth +#define XtWidth(w) (((RectObj)w)->rectangle.width) +#endif +#ifndef XtHeight +#define XtHeight(w) (((RectObj)w)->rectangle.height) +#endif +#ifndef XtBorderWidth +#define XtBorderWidth(w) (((RectObj)w)->rectangle.border_width) +#endif + +#ifndef OLDXAW +#define XAW_PRIV_VAR_PREFIX '$' + +typedef Bool (*XawParseBooleanProc)(Widget, String, XEvent*, Bool*); + +typedef struct _XawActionVarList XawActionVarList; +typedef struct _XawActionResList XawActionResList; + +/* Boolean expressions */ +Bool XawParseBoolean(Widget, String, XEvent*, Bool*); +Bool XawBooleanExpression(Widget, String, XEvent*); + +/* actions */ +void XawPrintActionErrorMsg(String, Widget, String*, Cardinal*); +XawActionResList *XawGetActionResList(WidgetClass); +XawActionVarList *XawGetActionVarList(Widget); + +void XawSetValuesAction(Widget, XEvent*, String*, Cardinal*); +void XawGetValuesAction(Widget, XEvent*, String*, Cardinal*); +void XawDeclareAction(Widget, XEvent*, String*, Cardinal*); +void XawCallProcAction(Widget, XEvent*, String*, Cardinal*); + +/* display lists */ +#define XAWDL_CONVERT_ERROR (XtPointer)-1 +typedef struct _XawDL _XawDisplayList; +typedef struct _XawDLClass XawDLClass, XawDisplayListClass; + +typedef void (*XawDisplayListProc)(Widget, XtPointer, XtPointer, + XEvent*, Region); +typedef void *(*XawDLArgsInitProc)(String, String*, Cardinal*, + Screen*, Colormap, int); +typedef void *(*XawDLDataInitProc)(String, + Screen*, Colormap, int); +typedef void (*XawDLArgsDestructor)(Display*, String, XtPointer, + String*, Cardinal*); +typedef void (*XawDLDataDestructor)(Display*, String, XtPointer); + +void XawRunDisplayList(Widget, _XawDisplayList*, XEvent*, Region); +void XawDisplayListInitialize(void); + +_XawDisplayList *XawCreateDisplayList(String, Screen*, Colormap, int); +void XawDestroyDisplayList(_XawDisplayList*); +String XawDisplayListString(_XawDisplayList*); +XawDLClass *XawGetDisplayListClass(String); +XawDLClass *XawCreateDisplayListClass(String, + XawDLArgsInitProc, XawDLArgsDestructor, + XawDLDataInitProc, XawDLDataDestructor); +Bool XawDeclareDisplayListProc(XawDLClass*, String, XawDisplayListProc); + +/* pixmaps */ +typedef struct _XawArgVal { + String name; + String value; +} XawArgVal; + +typedef struct _XawParams { + String name; + String type; + String ext; + XawArgVal **args; + Cardinal num_args; +} XawParams; + +typedef struct _XawPixmap { + String name; + Pixmap pixmap; + Pixmap mask; + Dimension width; + Dimension height; +} XawPixmap; + +typedef Bool (*XawPixmapLoader)(XawParams*, Screen*, Colormap, int, + Pixmap*, Pixmap*, + Dimension*, Dimension*); +Bool XawPixmapsInitialize(void); +Bool XawAddPixmapLoader(String, String, XawPixmapLoader); +XawPixmap *XawLoadPixmap(String, Screen*, Colormap, int); +XawPixmap *XawPixmapFromXPixmap(Pixmap, Screen*, Colormap, int); +XawParams *XawParseParamsString(String name); +void XawFreeParamsStruct(XawParams *params); +XawArgVal *XawFindArgVal(XawParams *params, String name); +void XawReshapeWidget(Widget, XawPixmap*); +#endif /* OLDXAW */ + +/* misc */ +void XawTypeToStringWarning(Display*, String); + +/* OS.c */ +int _XawGetPageSize(void); + +#endif /* _XawPrivate_h */ diff --git a/libXaw/src/Repeater.c b/libXaw/src/Repeater.c index b70fa67c0..e99a978f2 100644 --- a/libXaw/src/Repeater.c +++ b/libXaw/src/Repeater.c @@ -1,298 +1,298 @@ -/*
- *
-Copyright 1990, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- * Author: Jim Fulton, MIT X Consortium
- *
- * This widget is used for press-and-hold style buttons.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/RepeaterP.h>
-#include <X11/Xaw/XawInit.h>
-
-#define DO_CALLBACK(rw) \
-XtCallCallbackList((Widget)rw, rw->command.callbacks, NULL)
-
-#define ADD_TIMEOUT(rw, delay) \
-XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)rw), \
- delay, tic, (XtPointer)rw)
-
-#define CLEAR_TIMEOUT(rw) \
-if ((rw)->repeater.timer) { \
- XtRemoveTimeOut((rw)->repeater.timer); \
- (rw)->repeater.timer = 0; \
-}
-
-/*
- * Class Methods
- */
-static void XawRepeaterInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawRepeaterDestroy(Widget);
-static Boolean XawRepeaterSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void tic(XtPointer, XtIntervalId*);
-
-/*
- * Actions
- */
-static void ActionStart(Widget, XEvent*, String*, Cardinal*);
-static void ActionStop(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * Initialization
- */
-static char defaultTranslations[] =
-"<Enter>:" "highlight()\n"
-"<Leave>:" "unhighlight()\n"
-"<Btn1Down>:" "set() start()\n"
-"<Btn1Up>:" "stop() unset()\n"
-;
-
-static XtActionsRec actions[] = {
- {"start", ActionStart},
- {"stop", ActionStop},
-};
-
-#define offset(field) XtOffsetOf(RepeaterRec, repeater.field)
-static XtResource resources[] = {
- {
- XtNdecay,
- XtCDecay,
- XtRInt,
- sizeof(int),
- offset(decay),
- XtRImmediate,
- (XtPointer)REP_DEF_DECAY
- },
- {
- XtNinitialDelay,
- XtCDelay,
- XtRInt,
- sizeof(int),
- offset(initial_delay),
- XtRImmediate,
- (XtPointer)REP_DEF_INITIAL_DELAY
- },
- {
- XtNminimumDelay,
- XtCMinimumDelay,
- XtRInt,
- sizeof(int),
- offset(minimum_delay),
- XtRImmediate,
- (XtPointer)REP_DEF_MINIMUM_DELAY
- },
- {
- XtNrepeatDelay,
- XtCDelay,
- XtRInt,
- sizeof(int),
- offset(repeat_delay),
- XtRImmediate,
- (XtPointer)REP_DEF_REPEAT_DELAY
- },
- {
- XtNflash,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(flash),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNstartCallback,
- XtCStartCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(start_callbacks),
- XtRImmediate,
- NULL
- },
- {
- XtNstopCallback,
- XtCStopCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(stop_callbacks),
- XtRImmediate,
- NULL
- },
-};
-#undef offset
-
-#define Superclass (&commandClassRec)
-RepeaterClassRec repeaterClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "Repeater", /* class_name */
- sizeof(RepeaterRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawRepeaterInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- actions, /* actions */
- XtNumber(actions), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawRepeaterDestroy, /* destroy */
- XtInheritResize, /* resize */
- XtInheritExpose, /* expose */
- XawRepeaterSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- defaultTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* label */
- {
- NULL, /* extension */
- },
- /* command */
- {
- NULL, /* extension */
- },
- /* repeater */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass repeaterWidgetClass = (WidgetClass) &repeaterClassRec;
-
-
-/*
- * Implementation
- */
-/*ARGSUSED*/
-static void
-tic(XtPointer client_data, XtIntervalId *id)
-{
- RepeaterWidget rw = (RepeaterWidget)client_data;
-
- rw->repeater.timer = 0; /* timer is removed */
- if (rw->repeater.flash) {
- Widget w = (Widget)rw;
-
- XClearWindow(XtDisplay(w), XtWindow(w));
- XtCallActionProc(w, "reset", NULL, NULL, 0);
- XClearWindow(XtDisplay(w), XtWindow(w));
- XtCallActionProc(w, "set", NULL, NULL, 0);
- }
- DO_CALLBACK(rw);
-
- rw->repeater.timer = ADD_TIMEOUT(rw, rw->repeater.next_delay);
-
- if (rw->repeater.decay) {
- rw->repeater.next_delay -= rw->repeater.decay;
- if (rw->repeater.next_delay < rw->repeater.minimum_delay)
- rw->repeater.next_delay = rw->repeater.minimum_delay;
- }
-}
-
-/*ARGSUSED*/
-static void
-XawRepeaterInitialize(Widget greq, Widget gnew,
- ArgList args, Cardinal *num_args)
-{
- RepeaterWidget cnew = (RepeaterWidget)gnew;
-
- if (cnew->repeater.minimum_delay < 0)
- cnew->repeater.minimum_delay = 0;
- cnew->repeater.timer = 0;
-}
-
-static void
-XawRepeaterDestroy(Widget gw)
-{
- CLEAR_TIMEOUT((RepeaterWidget)gw);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawRepeaterSetValues(Widget gcur, Widget greq, Widget gnew,
- ArgList args, Cardinal *num_args)
-{
- RepeaterWidget cur = (RepeaterWidget)gcur;
- RepeaterWidget cnew = (RepeaterWidget)gnew;
-
- if (cur->repeater.minimum_delay != cnew->repeater.minimum_delay) {
- if (cnew->repeater.next_delay < cnew->repeater.minimum_delay)
- cnew->repeater.next_delay = cnew->repeater.minimum_delay;
- }
-
- return (False);
-}
-
-/*ARGSUSED*/
-static void
-ActionStart(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- RepeaterWidget rw = (RepeaterWidget)gw;
-
- CLEAR_TIMEOUT(rw);
- if (rw->repeater.start_callbacks)
- XtCallCallbackList(gw, rw->repeater.start_callbacks, NULL);
-
- DO_CALLBACK(rw);
- rw->repeater.timer = ADD_TIMEOUT(rw, rw->repeater.initial_delay);
- rw->repeater.next_delay = rw->repeater.repeat_delay;
-}
-
-/*ARGSUSED*/
-static void
-ActionStop(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- RepeaterWidget rw = (RepeaterWidget)gw;
-
- CLEAR_TIMEOUT((RepeaterWidget)gw);
- if (rw->repeater.stop_callbacks)
- XtCallCallbackList(gw, rw->repeater.stop_callbacks, NULL);
-}
+/* + * +Copyright 1990, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Jim Fulton, MIT X Consortium + * + * This widget is used for press-and-hold style buttons. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/RepeaterP.h> +#include <X11/Xaw/XawInit.h> + +#define DO_CALLBACK(rw) \ +XtCallCallbackList((Widget)rw, rw->command.callbacks, NULL) + +#define ADD_TIMEOUT(rw, delay) \ +XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)rw), \ + delay, tic, (XtPointer)rw) + +#define CLEAR_TIMEOUT(rw) \ +if ((rw)->repeater.timer) { \ + XtRemoveTimeOut((rw)->repeater.timer); \ + (rw)->repeater.timer = 0; \ +} + +/* + * Class Methods + */ +static void XawRepeaterInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawRepeaterDestroy(Widget); +static Boolean XawRepeaterSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void tic(XtPointer, XtIntervalId*); + +/* + * Actions + */ +static void ActionStart(Widget, XEvent*, String*, Cardinal*); +static void ActionStop(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +static char defaultTranslations[] = +"<Enter>:" "highlight()\n" +"<Leave>:" "unhighlight()\n" +"<Btn1Down>:" "set() start()\n" +"<Btn1Up>:" "stop() unset()\n" +; + +static XtActionsRec actions[] = { + {"start", ActionStart}, + {"stop", ActionStop}, +}; + +#define offset(field) XtOffsetOf(RepeaterRec, repeater.field) +static XtResource resources[] = { + { + XtNdecay, + XtCDecay, + XtRInt, + sizeof(int), + offset(decay), + XtRImmediate, + (XtPointer)REP_DEF_DECAY + }, + { + XtNinitialDelay, + XtCDelay, + XtRInt, + sizeof(int), + offset(initial_delay), + XtRImmediate, + (XtPointer)REP_DEF_INITIAL_DELAY + }, + { + XtNminimumDelay, + XtCMinimumDelay, + XtRInt, + sizeof(int), + offset(minimum_delay), + XtRImmediate, + (XtPointer)REP_DEF_MINIMUM_DELAY + }, + { + XtNrepeatDelay, + XtCDelay, + XtRInt, + sizeof(int), + offset(repeat_delay), + XtRImmediate, + (XtPointer)REP_DEF_REPEAT_DELAY + }, + { + XtNflash, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(flash), + XtRImmediate, + (XtPointer)False + }, + { + XtNstartCallback, + XtCStartCallback, + XtRCallback, + sizeof(XtPointer), + offset(start_callbacks), + XtRImmediate, + NULL + }, + { + XtNstopCallback, + XtCStopCallback, + XtRCallback, + sizeof(XtPointer), + offset(stop_callbacks), + XtRImmediate, + NULL + }, +}; +#undef offset + +#define Superclass (&commandClassRec) +RepeaterClassRec repeaterClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Repeater", /* class_name */ + sizeof(RepeaterRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawRepeaterInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + actions, /* actions */ + XtNumber(actions), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawRepeaterDestroy, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + XawRepeaterSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* label */ + { + NULL, /* extension */ + }, + /* command */ + { + NULL, /* extension */ + }, + /* repeater */ + { + NULL, /* extension */ + }, +}; + +WidgetClass repeaterWidgetClass = (WidgetClass) &repeaterClassRec; + + +/* + * Implementation + */ +/*ARGSUSED*/ +static void +tic(XtPointer client_data, XtIntervalId *id) +{ + RepeaterWidget rw = (RepeaterWidget)client_data; + + rw->repeater.timer = 0; /* timer is removed */ + if (rw->repeater.flash) { + Widget w = (Widget)rw; + + XClearWindow(XtDisplay(w), XtWindow(w)); + XtCallActionProc(w, "reset", NULL, NULL, 0); + XClearWindow(XtDisplay(w), XtWindow(w)); + XtCallActionProc(w, "set", NULL, NULL, 0); + } + DO_CALLBACK(rw); + + rw->repeater.timer = ADD_TIMEOUT(rw, rw->repeater.next_delay); + + if (rw->repeater.decay) { + rw->repeater.next_delay -= rw->repeater.decay; + if (rw->repeater.next_delay < rw->repeater.minimum_delay) + rw->repeater.next_delay = rw->repeater.minimum_delay; + } +} + +/*ARGSUSED*/ +static void +XawRepeaterInitialize(Widget greq, Widget gnew, + ArgList args, Cardinal *num_args) +{ + RepeaterWidget cnew = (RepeaterWidget)gnew; + + if (cnew->repeater.minimum_delay < 0) + cnew->repeater.minimum_delay = 0; + cnew->repeater.timer = 0; +} + +static void +XawRepeaterDestroy(Widget gw) +{ + CLEAR_TIMEOUT((RepeaterWidget)gw); +} + +/*ARGSUSED*/ +static Boolean +XawRepeaterSetValues(Widget gcur, Widget greq, Widget gnew, + ArgList args, Cardinal *num_args) +{ + RepeaterWidget cur = (RepeaterWidget)gcur; + RepeaterWidget cnew = (RepeaterWidget)gnew; + + if (cur->repeater.minimum_delay != cnew->repeater.minimum_delay) { + if (cnew->repeater.next_delay < cnew->repeater.minimum_delay) + cnew->repeater.next_delay = cnew->repeater.minimum_delay; + } + + return (False); +} + +/*ARGSUSED*/ +static void +ActionStart(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + RepeaterWidget rw = (RepeaterWidget)gw; + + CLEAR_TIMEOUT(rw); + if (rw->repeater.start_callbacks) + XtCallCallbackList(gw, rw->repeater.start_callbacks, NULL); + + DO_CALLBACK(rw); + rw->repeater.timer = ADD_TIMEOUT(rw, rw->repeater.initial_delay); + rw->repeater.next_delay = rw->repeater.repeat_delay; +} + +/*ARGSUSED*/ +static void +ActionStop(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + RepeaterWidget rw = (RepeaterWidget)gw; + + CLEAR_TIMEOUT((RepeaterWidget)gw); + if (rw->repeater.stop_callbacks) + XtCallCallbackList(gw, rw->repeater.stop_callbacks, NULL); +} diff --git a/libXaw/src/Scrollbar.c b/libXaw/src/Scrollbar.c index 777043063..6413f0bf6 100644 --- a/libXaw/src/Scrollbar.c +++ b/libXaw/src/Scrollbar.c @@ -1,882 +1,882 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/Drawing.h>
-#include <X11/Xaw/ScrollbarP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#define NoButton -1
-#define PICKLENGTH(widget, x, y) \
-(((widget)->scrollbar.orientation == XtorientHorizontal) ? (x) : (y))
-
-/*
- * Class Methods
- */
-static void XawScrollbarClassInitialize(void);
-static void XawScrollbarDestroy(Widget);
-static void XawScrollbarInitialize(Widget, Widget, ArgList, Cardinal*_args);
-static void XawScrollbarRealize(Widget, Mask*, XSetWindowAttributes*);
-static void XawScrollbarRedisplay(Widget, XEvent*, Region);
-static void XawScrollbarResize(Widget);
-static Boolean XawScrollbarSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static Boolean CompareEvents(XEvent*, XEvent*);
-static void CreateGC(Widget);
-static float FloatInRange(float, float, float);
-static float FractionLoc(ScrollbarWidget, int, int);
-static void ExtractPosition(XEvent*, Position*, Position*);
-static int InRange(int, int, int);
-static void FillArea(ScrollbarWidget, int, int, int);
-static Bool LookAhead(Widget, XEvent*);
-static void PaintThumb(ScrollbarWidget);
-static Bool PeekNotifyEvent(Display*, XEvent*, char*);
-static void SetDimensions(ScrollbarWidget);
-
-/*
- * Actions
- */
-static void EndScroll(Widget, XEvent*, String*, Cardinal*);
-static void MoveThumb(Widget, XEvent*, String*, Cardinal*);
-static void NotifyScroll(Widget, XEvent*, String*, Cardinal*);
-static void NotifyThumb(Widget, XEvent*, String*, Cardinal*);
-static void StartScroll(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * Initialization
- */
-static char defaultTranslations[] =
-"<Btn1Down>:" "StartScroll(Forward)\n"
-"<Btn2Down>:" "StartScroll(Continuous) MoveThumb() NotifyThumb()\n"
-"<Btn3Down>:" "StartScroll(Backward)\n"
-"<Btn2Motion>:" "MoveThumb() NotifyThumb()\n"
-"<BtnUp>:" "NotifyScroll(Proportional) EndScroll()\n";
-
-static float floatZero = 0.0;
-
-#define Offset(field) XtOffsetOf(ScrollbarRec, field)
-
-static XtResource resources[] = {
- {
- XtNlength,
- XtCLength,
- XtRDimension,
- sizeof(Dimension),
- Offset(scrollbar.length),
- XtRImmediate,
- (XtPointer)1
- },
- {
- XtNthickness,
- XtCThickness,
- XtRDimension,
- sizeof(Dimension),
- Offset(scrollbar.thickness),
- XtRImmediate,
- (XtPointer)14
- },
- {
- XtNorientation,
- XtCOrientation,
- XtROrientation,
- sizeof(XtOrientation),
- Offset(scrollbar.orientation),
- XtRImmediate,
- (XtPointer)XtorientVertical
- },
- {
- XtNscrollProc,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- Offset(scrollbar.scrollProc),
- XtRCallback,
- NULL
- },
- {
- XtNthumbProc,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- Offset(scrollbar.thumbProc),
- XtRCallback,
- NULL
- },
- {
- XtNjumpProc,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- Offset(scrollbar.jumpProc),
- XtRCallback,
- NULL
- },
- {
- XtNthumb,
- XtCThumb,
- XtRBitmap,
- sizeof(Pixmap),
- Offset(scrollbar.thumb),
- XtRImmediate,
- (XtPointer)XtUnspecifiedPixmap
- },
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- Offset(scrollbar.foreground),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNshown,
- XtCShown,
- XtRFloat,
- sizeof(float),
- Offset(scrollbar.shown),
- XtRFloat,
- (XtPointer)&floatZero
- },
- {
- XtNtopOfThumb,
- XtCTopOfThumb,
- XtRFloat,
- sizeof(float),
- Offset(scrollbar.top),
- XtRFloat,
- (XtPointer)&floatZero
- },
- {
- XtNscrollVCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- Offset(scrollbar.verCursor),
- XtRString,
- "sb_v_double_arrow"
- },
- {
- XtNscrollHCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- Offset(scrollbar.horCursor),
- XtRString,
- "sb_h_double_arrow"
- },
- {
- XtNscrollUCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- Offset(scrollbar.upCursor),
- XtRString,
- "sb_up_arrow"
- },
- {
- XtNscrollDCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- Offset(scrollbar.downCursor),
- XtRString,
- "sb_down_arrow"
- },
- {
- XtNscrollLCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- Offset(scrollbar.leftCursor),
- XtRString,
- "sb_left_arrow"
- },
- {
- XtNscrollRCursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- Offset(scrollbar.rightCursor),
- XtRString,
- "sb_right_arrow"
- },
- {
- XtNminimumThumb,
- XtCMinimumThumb,
- XtRDimension,
- sizeof(Dimension),
- Offset(scrollbar.min_thumb),
- XtRImmediate,
- (XtPointer)7
- },
-};
-#undef Offset
-
-static XtActionsRec actions[] = {
- {"StartScroll", StartScroll},
- {"MoveThumb", MoveThumb},
- {"NotifyThumb", NotifyThumb},
- {"NotifyScroll", NotifyScroll},
- {"EndScroll", EndScroll},
-};
-
-#define Superclass (&simpleClassRec)
-ScrollbarClassRec scrollbarClassRec = {
- /* core */
- {
- (WidgetClass)&simpleClassRec, /* superclass */
- "Scrollbar", /* class_name */
- sizeof(ScrollbarRec), /* widget_size */
- XawScrollbarClassInitialize, /* class_initialize */
- NULL, /* class_part_init */
- False, /* class_inited */
- XawScrollbarInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawScrollbarRealize, /* realize */
- actions, /* actions */
- XtNumber(actions), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawScrollbarDestroy, /* destroy */
- XawScrollbarResize, /* resize */
- XawScrollbarRedisplay, /* expose */
- XawScrollbarSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- defaultTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* scrollbar */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec;
-
-/*
- * Implementation
- */
-static void
-XawScrollbarClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation,
- NULL, 0);
- XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-/*
- * Make sure the first number is within the range specified by the other
- * two numbers.
- */
-static int
-InRange(int num, int small, int big)
-{
- return ((num < small) ? small : ((num > big) ? big : num));
-}
-
-/*
- * Same as above, but for floating numbers
- */
-static float
-FloatInRange(float num, float small, float big)
-{
- return ((num < small) ? small : ((num > big) ? big : num));
-}
-
-/* Fill the area specified by top and bottom with the given pattern */
-static float
-FractionLoc(ScrollbarWidget w, int x, int y)
-{
- float result;
-
- result = PICKLENGTH(w, x / (float)XtWidth(w), y / (float)XtHeight(w));
-
- return (FloatInRange(result, 0.0, 1.0));
-}
-
-static void
-FillArea(ScrollbarWidget w, int top, int bottom, int thumb)
-{
- Dimension length;
-
- top = XawMax(1, top);
- if (w->scrollbar.orientation == XtorientHorizontal)
- bottom = XawMin(bottom, XtWidth(w) - 1);
- else
- bottom = XawMin(bottom, XtHeight(w) - 1);
-
- if (bottom <= top)
- return;
-
- length = bottom - top;
-
- switch(thumb) {
- /* Fill the new Thumb location */
- case 1:
- if (w->scrollbar.orientation == XtorientHorizontal)
- XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc,
- top, 1, length, XtHeight(w) - 2);
- else
- XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc,
- 1, top, XtWidth(w) - 2, length);
- break;
- /* Clear the old Thumb location */
- case 0:
- if (w->scrollbar.orientation == XtorientHorizontal)
- XClearArea(XtDisplay(w), XtWindow(w),
- top, 1, length, XtHeight(w) - 2, False);
- else
- XClearArea(XtDisplay(w), XtWindow(w),
- 1, top, XtWidth(w) - 2, length, False);
- break;
- }
-}
-
-
-/* Paint the thumb in the area specified by w->top and
- w->shown. The old area is erased. The painting and
- erasing is done cleverly so that no flickering will occur. */
-static void
-PaintThumb(ScrollbarWidget w)
-{
- Position oldtop, oldbot, newtop, newbot;
-
- oldtop = w->scrollbar.topLoc;
- oldbot = oldtop + w->scrollbar.shownLength;
- newtop = w->scrollbar.length * w->scrollbar.top;
- newbot = newtop + (int)(w->scrollbar.length * w->scrollbar.shown);
- if (newbot < newtop + (int)w->scrollbar.min_thumb)
- newbot = newtop + w->scrollbar.min_thumb;
- w->scrollbar.topLoc = newtop;
- w->scrollbar.shownLength = newbot - newtop;
-
- if (XtIsRealized((Widget)w)) {
- if (newtop < oldtop)
- FillArea(w, newtop, XawMin(newbot, oldtop), 1);
- if (newtop > oldtop)
- FillArea(w, oldtop, XawMin(newtop, oldbot), 0);
- if (newbot < oldbot)
- FillArea(w, XawMax(newbot, oldtop), oldbot, 0);
- if (newbot > oldbot)
- FillArea(w, XawMax(newtop, oldbot), newbot, 1);
- }
-}
-
-static void
-SetDimensions(ScrollbarWidget w)
-{
- if (w->scrollbar.orientation == XtorientVertical) {
- w->scrollbar.length = XtHeight(w);
- w->scrollbar.thickness = XtWidth(w);
- }
- else {
- w->scrollbar.length = XtWidth(w);
- w->scrollbar.thickness = XtHeight(w);
- }
-}
-
-static void
-XawScrollbarDestroy(Widget w)
-{
- ScrollbarWidget sbw = (ScrollbarWidget)w;
-
- XtReleaseGC(w, sbw->scrollbar.gc);
-}
-
-static void
-CreateGC(Widget w)
-{
- ScrollbarWidget sbw = (ScrollbarWidget)w;
- XGCValues gcValues;
- XtGCMask mask;
- unsigned int depth = 1;
-
- if (sbw->scrollbar.thumb == XtUnspecifiedPixmap)
- sbw->scrollbar.thumb = XmuCreateStippledPixmap(XtScreen(w),
- (Pixel)1, (Pixel)0,
- depth);
- else if (sbw->scrollbar.thumb != None) {
- Window root;
- int x, y;
- unsigned int width, height, bw;
-
- XGetGeometry(XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y,
- &width, &height, &bw, &depth);
- }
-
- gcValues.foreground = sbw->scrollbar.foreground;
- gcValues.background = sbw->core.background_pixel;
- mask = GCForeground | GCBackground;
-
- if (sbw->scrollbar.thumb != None) {
- if (depth == 1) {
- gcValues.fill_style = FillOpaqueStippled;
- gcValues.stipple = sbw->scrollbar.thumb;
- mask |= GCFillStyle | GCStipple;
- }
- else {
- gcValues.fill_style = FillTiled;
- gcValues.tile = sbw->scrollbar.thumb;
- mask |= GCFillStyle | GCTile;
- }
- }
- sbw->scrollbar.gc = XtGetGC(w, mask, &gcValues);
-}
-
-/* ARGSUSED */
-static void
-XawScrollbarInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- ScrollbarWidget w = (ScrollbarWidget)cnew;
-
- CreateGC(cnew);
-
- if (XtWidth(w) == 0)
- XtWidth(w) = w->scrollbar.orientation == XtorientVertical ?
- w->scrollbar.thickness : w->scrollbar.length;
-
- if (XtHeight(w) == 0)
- XtHeight(w) = w->scrollbar.orientation == XtorientHorizontal ?
- w->scrollbar.thickness : w->scrollbar.length;
-
- SetDimensions(w);
- w->scrollbar.direction = 0;
- w->scrollbar.topLoc = 0;
- w->scrollbar.shownLength = w->scrollbar.min_thumb;
-}
-
-static void
-XawScrollbarRealize(Widget gw, Mask *valueMask,
- XSetWindowAttributes *attributes)
-{
- ScrollbarWidget w = (ScrollbarWidget)gw;
-
- w->scrollbar.inactiveCursor = w->scrollbar.orientation == XtorientVertical ?
- w->scrollbar.verCursor : w->scrollbar.horCursor;
-
- XtVaSetValues(gw, XtNcursor, w->scrollbar.inactiveCursor, NULL);
-
- /*
- * The Simple widget actually stuffs the value in the valuemask
- */
- (*scrollbarWidgetClass->core_class.superclass->core_class.realize)
- (gw, valueMask, attributes);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawScrollbarSetValues(Widget current, Widget request, Widget desired,
- ArgList args, Cardinal *num_args)
-{
- ScrollbarWidget w = (ScrollbarWidget)current;
- ScrollbarWidget dw = (ScrollbarWidget)desired;
- Boolean redraw = False;
-
- /*
- * If these values are outside the acceptable range ignore them...
- */
- if (dw->scrollbar.top < 0.0 || dw->scrollbar.top > 1.0)
- dw->scrollbar.top = w->scrollbar.top;
-
- if (dw->scrollbar.shown < 0.0 || dw->scrollbar.shown > 1.0)
- dw->scrollbar.shown = w->scrollbar.shown;
-
- if (XtIsRealized (desired)) {
- if (w->scrollbar.foreground != dw->scrollbar.foreground ||
- w->core.background_pixel != dw->core.background_pixel ||
- w->scrollbar.thumb != dw->scrollbar.thumb) {
- XtReleaseGC((Widget)dw, w->scrollbar.gc);
- CreateGC((Widget)dw);
- redraw = True;
- }
- if (w->scrollbar.top != dw->scrollbar.top ||
- w->scrollbar.shown != dw->scrollbar.shown)
- redraw = True;
- }
-
- return (redraw);
-}
-
-static void
-XawScrollbarResize(Widget gw)
-{
- /* ForgetGravity has taken care of background, but thumb may
- * have to move as a result of the new size. */
- SetDimensions((ScrollbarWidget)gw);
- XawScrollbarRedisplay(gw, NULL, NULL);
-}
-
-/*ARGSUSED*/
-static void
-XawScrollbarRedisplay(Widget gw, XEvent *event, Region region)
-{
- ScrollbarWidget w = (ScrollbarWidget)gw;
- int x, y;
- unsigned int width, height;
-
- if (Superclass->core_class.expose)
- (*Superclass->core_class.expose)(gw, event, region);
-
- if (w->scrollbar.orientation == XtorientHorizontal) {
- x = w->scrollbar.topLoc;
- y = 1;
- width = w->scrollbar.shownLength;
- height = XtHeight(w) - 2;
- }
- else {
- x = 1;
- y = w->scrollbar.topLoc;
- width = XtWidth(w) - 2;
- height = w->scrollbar.shownLength;
- }
-
- if (region == NULL ||
- XRectInRegion(region, x, y, width, height) != RectangleOut) {
- /* Forces entire thumb to be painted */
- w->scrollbar.topLoc = -(w->scrollbar.length + 1);
- PaintThumb(w);
- }
-}
-
-/*ARGSUSED*/
-static void
-StartScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- ScrollbarWidget w = (ScrollbarWidget)gw;
- Cursor cursor;
- char direction;
-
- if (w->scrollbar.direction != 0) /* if we're already scrolling */
- return;
- if (*num_params > 0)
- direction = *params[0];
- else
- direction = 'C';
-
- w->scrollbar.direction = direction;
-
- switch(direction) {
- case 'B':
- case 'b':
- cursor = w->scrollbar.orientation == XtorientVertical ?
- w->scrollbar.downCursor : w->scrollbar.rightCursor;
- break;
- case 'F':
- case 'f':
- cursor = w->scrollbar.orientation == XtorientVertical ?
- w->scrollbar.upCursor : w->scrollbar.leftCursor;
- break;
- case 'C':
- case 'c':
- cursor = w->scrollbar.orientation == XtorientVertical ?
- w->scrollbar.rightCursor : w->scrollbar.upCursor;
- break;
- default:
- return; /* invalid invocation */
- }
-
- XtVaSetValues(gw, XtNcursor, cursor, NULL);
-
- XFlush(XtDisplay(w));
-}
-
-static Boolean
-CompareEvents(XEvent *oldEvent, XEvent *newEvent)
-{
-#define Check(field) if (newEvent->field != oldEvent->field) return (False)
-
- Check(xany.display);
- Check(xany.type);
- Check(xany.window);
-
- switch(newEvent->type) {
- case MotionNotify:
- Check(xmotion.state);
- break;
- case ButtonPress:
- case ButtonRelease:
- Check(xbutton.state);
- Check(xbutton.button);
- break;
- case KeyPress:
- case KeyRelease:
- Check(xkey.state);
- Check(xkey.keycode);
- break;
- case EnterNotify:
- case LeaveNotify:
- Check(xcrossing.mode);
- Check(xcrossing.detail);
- Check(xcrossing.state);
- break;
- }
-#undef Check
-
- return (True);
-}
-
-struct EventData {
- XEvent *oldEvent;
- int count;
-};
-
-static Bool
-PeekNotifyEvent(Display *dpy, XEvent *event, char *args)
-{
- struct EventData *eventData = (struct EventData*)args;
-
- return (++eventData->count == QLength(dpy) /* since PeekIf blocks */
- || CompareEvents(event, eventData->oldEvent));
-}
-
-static Bool
-LookAhead(Widget w, XEvent *event)
-{
- XEvent newEvent;
- struct EventData eventData;
-
- if (QLength(XtDisplay(w)) == 0)
- return (False);
-
- eventData.count = 0;
- eventData.oldEvent = event;
-
- XPeekIfEvent(XtDisplay(w), &newEvent, PeekNotifyEvent, (char*)&eventData);
-
- if (CompareEvents(event, &newEvent))
- return (True);
-
- return (False);
-}
-
-static void
-ExtractPosition(XEvent *event, Position *x, Position *y)
-{
- switch(event->type) {
- case MotionNotify:
- *x = event->xmotion.x;
- *y = event->xmotion.y;
- break;
- case ButtonPress:
- case ButtonRelease:
- *x = event->xbutton.x;
- *y = event->xbutton.y;
- break;
- case KeyPress:
- case KeyRelease:
- *x = event->xkey.x;
- *y = event->xkey.y;
- break;
- case EnterNotify:
- case LeaveNotify:
- *x = event->xcrossing.x;
- *y = event->xcrossing.y;
- break;
- default:
- *x = 0;
- *y = 0;
- break;
- }
-}
-
-static void
-NotifyScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- ScrollbarWidget w = (ScrollbarWidget)gw;
- long call_data = 0;
- char style;
- Position x, y;
-
- if (w->scrollbar.direction == 0) /* if no StartScroll */
- return;
-
- if (LookAhead(gw, event))
- return;
-
- if (*num_params > 0)
- style = *params[0];
- else
- style = 'P';
-
- switch(style) {
- case 'P': /* Proportional */
- case 'p':
- ExtractPosition(event, &x, &y);
- call_data = InRange(PICKLENGTH(w, x, y), 0, (int)w->scrollbar.length);
- break;
- case 'F': /* FullLength */
- case 'f':
- call_data = w->scrollbar.length;
- break;
- }
-
- switch(w->scrollbar.direction) {
- case 'B':
- case 'b':
- call_data = -call_data;
- /*FALLTHROUGH*/
- case 'F':
- case 'f':
- XtCallCallbacks(gw, XtNscrollProc, (XtPointer)call_data);
- break;
- case 'C':
- case 'c': /* NotifyThumb has already called the thumbProc(s) */
- break;
- }
-}
-
-/*ARGSUSED*/
-static void
-EndScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- ScrollbarWidget w = (ScrollbarWidget)gw;
-
- XtVaSetValues(gw, XtNcursor, w->scrollbar.inactiveCursor, NULL);
- XFlush(XtDisplay(w)); /* make sure it get propogated */
-
- w->scrollbar.direction = 0;
-}
-
-/*ARGSUSED*/
-static void
-MoveThumb(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- ScrollbarWidget w = (ScrollbarWidget)gw;
- Position x, y;
-
- if (w->scrollbar.direction == 0) /* if no StartScroll */
- return;
-
- if (LookAhead(gw, event))
- return;
-
- if (!event->xmotion.same_screen)
- return;
-
- ExtractPosition(event, &x, &y);
- w->scrollbar.top = FractionLoc(w, x, y);
-}
-
-/*ARGSUSED*/
-static void
-NotifyThumb(Widget gw, XEvent *event, String *params, Cardinal *num_params)
-{
- ScrollbarWidget w = (ScrollbarWidget)gw;
- union {
- XtPointer xtp;
- float xtf;
- } xtpf;
-
- if (w->scrollbar.direction == 0) /* if no StartScroll */
- return;
-
- if (LookAhead(gw, event))
- return;
-
- /* thumbProc is not pretty, but is necessary for backwards
- compatibility on those architectures for which it work{s,ed};
- the intent is to pass a (truncated) float by value. */
- xtpf.xtf = w->scrollbar.top;
- XtCallCallbacks(gw, XtNthumbProc, xtpf.xtp);
- XtCallCallbacks(gw, XtNjumpProc, (XtPointer)&w->scrollbar.top);
-
- PaintThumb(w);
-}
-
-/*
- * Public routines
- */
-/* Set the scroll bar to the given location. */
-void
-XawScrollbarSetThumb(Widget gw,
-#if NeedWidePrototypes
- double top, double shown
-#else
- float top, float shown
-#endif
- )
-{
- ScrollbarWidget w = (ScrollbarWidget)gw;
-
- if (w->scrollbar.direction == 'c') /* if still thumbing */
- return;
-
- w->scrollbar.top = top > 1.0 ? 1.0 : top >= 0.0 ? top : w->scrollbar.top;
-
- w->scrollbar.shown = shown > 1.0 ? 1.0 : shown >= 0.0 ?
- shown : w->scrollbar.shown;
- PaintThumb(w);
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xaw/ScrollbarP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define NoButton -1 +#define PICKLENGTH(widget, x, y) \ +(((widget)->scrollbar.orientation == XtorientHorizontal) ? (x) : (y)) + +/* + * Class Methods + */ +static void XawScrollbarClassInitialize(void); +static void XawScrollbarDestroy(Widget); +static void XawScrollbarInitialize(Widget, Widget, ArgList, Cardinal*_args); +static void XawScrollbarRealize(Widget, Mask*, XSetWindowAttributes*); +static void XawScrollbarRedisplay(Widget, XEvent*, Region); +static void XawScrollbarResize(Widget); +static Boolean XawScrollbarSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static Boolean CompareEvents(XEvent*, XEvent*); +static void CreateGC(Widget); +static float FloatInRange(float, float, float); +static float FractionLoc(ScrollbarWidget, int, int); +static void ExtractPosition(XEvent*, Position*, Position*); +static int InRange(int, int, int); +static void FillArea(ScrollbarWidget, int, int, int); +static Bool LookAhead(Widget, XEvent*); +static void PaintThumb(ScrollbarWidget); +static Bool PeekNotifyEvent(Display*, XEvent*, char*); +static void SetDimensions(ScrollbarWidget); + +/* + * Actions + */ +static void EndScroll(Widget, XEvent*, String*, Cardinal*); +static void MoveThumb(Widget, XEvent*, String*, Cardinal*); +static void NotifyScroll(Widget, XEvent*, String*, Cardinal*); +static void NotifyThumb(Widget, XEvent*, String*, Cardinal*); +static void StartScroll(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +static char defaultTranslations[] = +"<Btn1Down>:" "StartScroll(Forward)\n" +"<Btn2Down>:" "StartScroll(Continuous) MoveThumb() NotifyThumb()\n" +"<Btn3Down>:" "StartScroll(Backward)\n" +"<Btn2Motion>:" "MoveThumb() NotifyThumb()\n" +"<BtnUp>:" "NotifyScroll(Proportional) EndScroll()\n"; + +static float floatZero = 0.0; + +#define Offset(field) XtOffsetOf(ScrollbarRec, field) + +static XtResource resources[] = { + { + XtNlength, + XtCLength, + XtRDimension, + sizeof(Dimension), + Offset(scrollbar.length), + XtRImmediate, + (XtPointer)1 + }, + { + XtNthickness, + XtCThickness, + XtRDimension, + sizeof(Dimension), + Offset(scrollbar.thickness), + XtRImmediate, + (XtPointer)14 + }, + { + XtNorientation, + XtCOrientation, + XtROrientation, + sizeof(XtOrientation), + Offset(scrollbar.orientation), + XtRImmediate, + (XtPointer)XtorientVertical + }, + { + XtNscrollProc, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + Offset(scrollbar.scrollProc), + XtRCallback, + NULL + }, + { + XtNthumbProc, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + Offset(scrollbar.thumbProc), + XtRCallback, + NULL + }, + { + XtNjumpProc, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + Offset(scrollbar.jumpProc), + XtRCallback, + NULL + }, + { + XtNthumb, + XtCThumb, + XtRBitmap, + sizeof(Pixmap), + Offset(scrollbar.thumb), + XtRImmediate, + (XtPointer)XtUnspecifiedPixmap + }, + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + Offset(scrollbar.foreground), + XtRString, + XtDefaultForeground + }, + { + XtNshown, + XtCShown, + XtRFloat, + sizeof(float), + Offset(scrollbar.shown), + XtRFloat, + (XtPointer)&floatZero + }, + { + XtNtopOfThumb, + XtCTopOfThumb, + XtRFloat, + sizeof(float), + Offset(scrollbar.top), + XtRFloat, + (XtPointer)&floatZero + }, + { + XtNscrollVCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.verCursor), + XtRString, + "sb_v_double_arrow" + }, + { + XtNscrollHCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.horCursor), + XtRString, + "sb_h_double_arrow" + }, + { + XtNscrollUCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.upCursor), + XtRString, + "sb_up_arrow" + }, + { + XtNscrollDCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.downCursor), + XtRString, + "sb_down_arrow" + }, + { + XtNscrollLCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.leftCursor), + XtRString, + "sb_left_arrow" + }, + { + XtNscrollRCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.rightCursor), + XtRString, + "sb_right_arrow" + }, + { + XtNminimumThumb, + XtCMinimumThumb, + XtRDimension, + sizeof(Dimension), + Offset(scrollbar.min_thumb), + XtRImmediate, + (XtPointer)7 + }, +}; +#undef Offset + +static XtActionsRec actions[] = { + {"StartScroll", StartScroll}, + {"MoveThumb", MoveThumb}, + {"NotifyThumb", NotifyThumb}, + {"NotifyScroll", NotifyScroll}, + {"EndScroll", EndScroll}, +}; + +#define Superclass (&simpleClassRec) +ScrollbarClassRec scrollbarClassRec = { + /* core */ + { + (WidgetClass)&simpleClassRec, /* superclass */ + "Scrollbar", /* class_name */ + sizeof(ScrollbarRec), /* widget_size */ + XawScrollbarClassInitialize, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + XawScrollbarInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawScrollbarRealize, /* realize */ + actions, /* actions */ + XtNumber(actions), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawScrollbarDestroy, /* destroy */ + XawScrollbarResize, /* resize */ + XawScrollbarRedisplay, /* expose */ + XawScrollbarSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* scrollbar */ + { + NULL, /* extension */ + }, +}; + +WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec; + +/* + * Implementation + */ +static void +XawScrollbarClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation, + NULL, 0); + XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString, + NULL, 0, XtCacheNone, NULL); +} + +/* + * Make sure the first number is within the range specified by the other + * two numbers. + */ +static int +InRange(int num, int small, int big) +{ + return ((num < small) ? small : ((num > big) ? big : num)); +} + +/* + * Same as above, but for floating numbers + */ +static float +FloatInRange(float num, float small, float big) +{ + return ((num < small) ? small : ((num > big) ? big : num)); +} + +/* Fill the area specified by top and bottom with the given pattern */ +static float +FractionLoc(ScrollbarWidget w, int x, int y) +{ + float result; + + result = PICKLENGTH(w, x / (float)XtWidth(w), y / (float)XtHeight(w)); + + return (FloatInRange(result, 0.0, 1.0)); +} + +static void +FillArea(ScrollbarWidget w, int top, int bottom, int thumb) +{ + Dimension length; + + top = XawMax(1, top); + if (w->scrollbar.orientation == XtorientHorizontal) + bottom = XawMin(bottom, XtWidth(w) - 1); + else + bottom = XawMin(bottom, XtHeight(w) - 1); + + if (bottom <= top) + return; + + length = bottom - top; + + switch(thumb) { + /* Fill the new Thumb location */ + case 1: + if (w->scrollbar.orientation == XtorientHorizontal) + XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc, + top, 1, length, XtHeight(w) - 2); + else + XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc, + 1, top, XtWidth(w) - 2, length); + break; + /* Clear the old Thumb location */ + case 0: + if (w->scrollbar.orientation == XtorientHorizontal) + XClearArea(XtDisplay(w), XtWindow(w), + top, 1, length, XtHeight(w) - 2, False); + else + XClearArea(XtDisplay(w), XtWindow(w), + 1, top, XtWidth(w) - 2, length, False); + break; + } +} + + +/* Paint the thumb in the area specified by w->top and + w->shown. The old area is erased. The painting and + erasing is done cleverly so that no flickering will occur. */ +static void +PaintThumb(ScrollbarWidget w) +{ + Position oldtop, oldbot, newtop, newbot; + + oldtop = w->scrollbar.topLoc; + oldbot = oldtop + w->scrollbar.shownLength; + newtop = w->scrollbar.length * w->scrollbar.top; + newbot = newtop + (int)(w->scrollbar.length * w->scrollbar.shown); + if (newbot < newtop + (int)w->scrollbar.min_thumb) + newbot = newtop + w->scrollbar.min_thumb; + w->scrollbar.topLoc = newtop; + w->scrollbar.shownLength = newbot - newtop; + + if (XtIsRealized((Widget)w)) { + if (newtop < oldtop) + FillArea(w, newtop, XawMin(newbot, oldtop), 1); + if (newtop > oldtop) + FillArea(w, oldtop, XawMin(newtop, oldbot), 0); + if (newbot < oldbot) + FillArea(w, XawMax(newbot, oldtop), oldbot, 0); + if (newbot > oldbot) + FillArea(w, XawMax(newtop, oldbot), newbot, 1); + } +} + +static void +SetDimensions(ScrollbarWidget w) +{ + if (w->scrollbar.orientation == XtorientVertical) { + w->scrollbar.length = XtHeight(w); + w->scrollbar.thickness = XtWidth(w); + } + else { + w->scrollbar.length = XtWidth(w); + w->scrollbar.thickness = XtHeight(w); + } +} + +static void +XawScrollbarDestroy(Widget w) +{ + ScrollbarWidget sbw = (ScrollbarWidget)w; + + XtReleaseGC(w, sbw->scrollbar.gc); +} + +static void +CreateGC(Widget w) +{ + ScrollbarWidget sbw = (ScrollbarWidget)w; + XGCValues gcValues; + XtGCMask mask; + unsigned int depth = 1; + + if (sbw->scrollbar.thumb == XtUnspecifiedPixmap) + sbw->scrollbar.thumb = XmuCreateStippledPixmap(XtScreen(w), + (Pixel)1, (Pixel)0, + depth); + else if (sbw->scrollbar.thumb != None) { + Window root; + int x, y; + unsigned int width, height, bw; + + XGetGeometry(XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y, + &width, &height, &bw, &depth); + } + + gcValues.foreground = sbw->scrollbar.foreground; + gcValues.background = sbw->core.background_pixel; + mask = GCForeground | GCBackground; + + if (sbw->scrollbar.thumb != None) { + if (depth == 1) { + gcValues.fill_style = FillOpaqueStippled; + gcValues.stipple = sbw->scrollbar.thumb; + mask |= GCFillStyle | GCStipple; + } + else { + gcValues.fill_style = FillTiled; + gcValues.tile = sbw->scrollbar.thumb; + mask |= GCFillStyle | GCTile; + } + } + sbw->scrollbar.gc = XtGetGC(w, mask, &gcValues); +} + +/* ARGSUSED */ +static void +XawScrollbarInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ScrollbarWidget w = (ScrollbarWidget)cnew; + + CreateGC(cnew); + + if (XtWidth(w) == 0) + XtWidth(w) = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.thickness : w->scrollbar.length; + + if (XtHeight(w) == 0) + XtHeight(w) = w->scrollbar.orientation == XtorientHorizontal ? + w->scrollbar.thickness : w->scrollbar.length; + + SetDimensions(w); + w->scrollbar.direction = 0; + w->scrollbar.topLoc = 0; + w->scrollbar.shownLength = w->scrollbar.min_thumb; +} + +static void +XawScrollbarRealize(Widget gw, Mask *valueMask, + XSetWindowAttributes *attributes) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + + w->scrollbar.inactiveCursor = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.verCursor : w->scrollbar.horCursor; + + XtVaSetValues(gw, XtNcursor, w->scrollbar.inactiveCursor, NULL); + + /* + * The Simple widget actually stuffs the value in the valuemask + */ + (*scrollbarWidgetClass->core_class.superclass->core_class.realize) + (gw, valueMask, attributes); +} + +/*ARGSUSED*/ +static Boolean +XawScrollbarSetValues(Widget current, Widget request, Widget desired, + ArgList args, Cardinal *num_args) +{ + ScrollbarWidget w = (ScrollbarWidget)current; + ScrollbarWidget dw = (ScrollbarWidget)desired; + Boolean redraw = False; + + /* + * If these values are outside the acceptable range ignore them... + */ + if (dw->scrollbar.top < 0.0 || dw->scrollbar.top > 1.0) + dw->scrollbar.top = w->scrollbar.top; + + if (dw->scrollbar.shown < 0.0 || dw->scrollbar.shown > 1.0) + dw->scrollbar.shown = w->scrollbar.shown; + + if (XtIsRealized (desired)) { + if (w->scrollbar.foreground != dw->scrollbar.foreground || + w->core.background_pixel != dw->core.background_pixel || + w->scrollbar.thumb != dw->scrollbar.thumb) { + XtReleaseGC((Widget)dw, w->scrollbar.gc); + CreateGC((Widget)dw); + redraw = True; + } + if (w->scrollbar.top != dw->scrollbar.top || + w->scrollbar.shown != dw->scrollbar.shown) + redraw = True; + } + + return (redraw); +} + +static void +XawScrollbarResize(Widget gw) +{ + /* ForgetGravity has taken care of background, but thumb may + * have to move as a result of the new size. */ + SetDimensions((ScrollbarWidget)gw); + XawScrollbarRedisplay(gw, NULL, NULL); +} + +/*ARGSUSED*/ +static void +XawScrollbarRedisplay(Widget gw, XEvent *event, Region region) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + int x, y; + unsigned int width, height; + + if (Superclass->core_class.expose) + (*Superclass->core_class.expose)(gw, event, region); + + if (w->scrollbar.orientation == XtorientHorizontal) { + x = w->scrollbar.topLoc; + y = 1; + width = w->scrollbar.shownLength; + height = XtHeight(w) - 2; + } + else { + x = 1; + y = w->scrollbar.topLoc; + width = XtWidth(w) - 2; + height = w->scrollbar.shownLength; + } + + if (region == NULL || + XRectInRegion(region, x, y, width, height) != RectangleOut) { + /* Forces entire thumb to be painted */ + w->scrollbar.topLoc = -(w->scrollbar.length + 1); + PaintThumb(w); + } +} + +/*ARGSUSED*/ +static void +StartScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + Cursor cursor; + char direction; + + if (w->scrollbar.direction != 0) /* if we're already scrolling */ + return; + if (*num_params > 0) + direction = *params[0]; + else + direction = 'C'; + + w->scrollbar.direction = direction; + + switch(direction) { + case 'B': + case 'b': + cursor = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.downCursor : w->scrollbar.rightCursor; + break; + case 'F': + case 'f': + cursor = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.upCursor : w->scrollbar.leftCursor; + break; + case 'C': + case 'c': + cursor = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.rightCursor : w->scrollbar.upCursor; + break; + default: + return; /* invalid invocation */ + } + + XtVaSetValues(gw, XtNcursor, cursor, NULL); + + XFlush(XtDisplay(w)); +} + +static Boolean +CompareEvents(XEvent *oldEvent, XEvent *newEvent) +{ +#define Check(field) if (newEvent->field != oldEvent->field) return (False) + + Check(xany.display); + Check(xany.type); + Check(xany.window); + + switch(newEvent->type) { + case MotionNotify: + Check(xmotion.state); + break; + case ButtonPress: + case ButtonRelease: + Check(xbutton.state); + Check(xbutton.button); + break; + case KeyPress: + case KeyRelease: + Check(xkey.state); + Check(xkey.keycode); + break; + case EnterNotify: + case LeaveNotify: + Check(xcrossing.mode); + Check(xcrossing.detail); + Check(xcrossing.state); + break; + } +#undef Check + + return (True); +} + +struct EventData { + XEvent *oldEvent; + int count; +}; + +static Bool +PeekNotifyEvent(Display *dpy, XEvent *event, char *args) +{ + struct EventData *eventData = (struct EventData*)args; + + return (++eventData->count == QLength(dpy) /* since PeekIf blocks */ + || CompareEvents(event, eventData->oldEvent)); +} + +static Bool +LookAhead(Widget w, XEvent *event) +{ + XEvent newEvent; + struct EventData eventData; + + if (QLength(XtDisplay(w)) == 0) + return (False); + + eventData.count = 0; + eventData.oldEvent = event; + + XPeekIfEvent(XtDisplay(w), &newEvent, PeekNotifyEvent, (char*)&eventData); + + if (CompareEvents(event, &newEvent)) + return (True); + + return (False); +} + +static void +ExtractPosition(XEvent *event, Position *x, Position *y) +{ + switch(event->type) { + case MotionNotify: + *x = event->xmotion.x; + *y = event->xmotion.y; + break; + case ButtonPress: + case ButtonRelease: + *x = event->xbutton.x; + *y = event->xbutton.y; + break; + case KeyPress: + case KeyRelease: + *x = event->xkey.x; + *y = event->xkey.y; + break; + case EnterNotify: + case LeaveNotify: + *x = event->xcrossing.x; + *y = event->xcrossing.y; + break; + default: + *x = 0; + *y = 0; + break; + } +} + +static void +NotifyScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + long call_data = 0; + char style; + Position x, y; + + if (w->scrollbar.direction == 0) /* if no StartScroll */ + return; + + if (LookAhead(gw, event)) + return; + + if (*num_params > 0) + style = *params[0]; + else + style = 'P'; + + switch(style) { + case 'P': /* Proportional */ + case 'p': + ExtractPosition(event, &x, &y); + call_data = InRange(PICKLENGTH(w, x, y), 0, (int)w->scrollbar.length); + break; + case 'F': /* FullLength */ + case 'f': + call_data = w->scrollbar.length; + break; + } + + switch(w->scrollbar.direction) { + case 'B': + case 'b': + call_data = -call_data; + /*FALLTHROUGH*/ + case 'F': + case 'f': + XtCallCallbacks(gw, XtNscrollProc, (XtPointer)call_data); + break; + case 'C': + case 'c': /* NotifyThumb has already called the thumbProc(s) */ + break; + } +} + +/*ARGSUSED*/ +static void +EndScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + + XtVaSetValues(gw, XtNcursor, w->scrollbar.inactiveCursor, NULL); + XFlush(XtDisplay(w)); /* make sure it get propogated */ + + w->scrollbar.direction = 0; +} + +/*ARGSUSED*/ +static void +MoveThumb(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + Position x, y; + + if (w->scrollbar.direction == 0) /* if no StartScroll */ + return; + + if (LookAhead(gw, event)) + return; + + if (!event->xmotion.same_screen) + return; + + ExtractPosition(event, &x, &y); + w->scrollbar.top = FractionLoc(w, x, y); +} + +/*ARGSUSED*/ +static void +NotifyThumb(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + union { + XtPointer xtp; + float xtf; + } xtpf; + + if (w->scrollbar.direction == 0) /* if no StartScroll */ + return; + + if (LookAhead(gw, event)) + return; + + /* thumbProc is not pretty, but is necessary for backwards + compatibility on those architectures for which it work{s,ed}; + the intent is to pass a (truncated) float by value. */ + xtpf.xtf = w->scrollbar.top; + XtCallCallbacks(gw, XtNthumbProc, xtpf.xtp); + XtCallCallbacks(gw, XtNjumpProc, (XtPointer)&w->scrollbar.top); + + PaintThumb(w); +} + +/* + * Public routines + */ +/* Set the scroll bar to the given location. */ +void +XawScrollbarSetThumb(Widget gw, +#if NeedWidePrototypes + double top, double shown +#else + float top, float shown +#endif + ) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + + if (w->scrollbar.direction == 'c') /* if still thumbing */ + return; + + w->scrollbar.top = top > 1.0 ? 1.0 : top >= 0.0 ? top : w->scrollbar.top; + + w->scrollbar.shown = shown > 1.0 ? 1.0 : shown >= 0.0 ? + shown : w->scrollbar.shown; + PaintThumb(w); +} diff --git a/libXaw/src/Simple.c b/libXaw/src/Simple.c index b5d2fddd8..711e9007a 100644 --- a/libXaw/src/Simple.c +++ b/libXaw/src/Simple.c @@ -1,500 +1,500 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/Drawing.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/SimpleP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-#ifndef OLDXAW
-#include <X11/Xaw/Tip.h>
-#endif
-
-/*
- * Class Methods
- */
-static Bool ChangeSensitive(Widget);
-static void XawSimpleClassInitialize(void);
-static void XawSimpleClassPartInitialize(WidgetClass);
-#ifndef OLDXAW
-static void XawSimpleInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawSimpleDestroy(Widget);
-static void XawSimpleExpose(Widget, XEvent*, Region);
-#endif
-static void XawSimpleRealize(Widget, Mask*, XSetWindowAttributes*);
-static Boolean XawSimpleSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void ConvertCursor(Widget);
-
-/*
- * Initialization
- */
-#ifndef OLDXAW
-static XtActionsRec actions[] = {
- {"set-values", XawSetValuesAction},
- {"get-values", XawGetValuesAction},
- {"declare", XawDeclareAction},
- {"call-proc", XawCallProcAction},
-};
-#endif
-
-#define offset(field) XtOffsetOf(SimpleRec, simple.field)
-static XtResource resources[] = {
- {
- XtNcursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(cursor),
- XtRImmediate,
- (XtPointer)None
- },
- {
- XtNinsensitiveBorder,
- XtCInsensitive,
- XtRPixmap,
- sizeof(Pixmap),
- offset(insensitive_border),
- XtRImmediate,
- NULL
- },
- {
- XtNpointerColor,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(pointer_fg),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNpointerColorBackground,
- XtCBackground,
- XtRPixel,
- sizeof(Pixel),
- offset(pointer_bg),
- XtRString,
- XtDefaultBackground
- },
- {
- XtNcursorName,
- XtCCursor,
- XtRString,
- sizeof(String),
- offset(cursor_name),
- XtRString,
- NULL
- },
- {
- XtNinternational,
- XtCInternational,
- XtRBoolean,
- sizeof(Boolean),
- offset(international),
- XtRImmediate,
- (XtPointer)False
- },
-#ifndef OLDXAW
- {
- XawNdisplayList,
- XawCDisplayList,
- XawRDisplayList,
- sizeof(XawDisplayList*),
- offset(display_list),
- XtRImmediate,
- NULL
- },
- {
- XtNtip,
- XtCTip,
- XtRString,
- sizeof(String),
- offset(tip),
- XtRImmediate,
- NULL
- },
-#endif
-#undef offset
-};
-
-SimpleClassRec simpleClassRec = {
- /* core */
- {
- (WidgetClass)&widgetClassRec, /* superclass */
- "Simple", /* class_name */
- sizeof(SimpleRec), /* widget_size */
- XawSimpleClassInitialize, /* class_initialize */
- XawSimpleClassPartInitialize, /* class_part_initialize */
- False, /* class_inited */
-#ifndef OLDXAW
- XawSimpleInitialize, /* initialize */
-#else
- NULL, /* initialize */
-#endif
- NULL, /* initialize_hook */
- XawSimpleRealize, /* realize */
-#ifndef OLDXAW
- actions, /* actions */
- XtNumber(actions), /* num_actions */
-#else
- NULL, /* actions */
- 0, /* num_actions */
-#endif
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
-#ifndef OLDXAW
- XawSimpleDestroy, /* destroy */
-#else
- NULL, /* destroy */
-#endif
- NULL, /* resize */
-#ifndef OLDXAW
- XawSimpleExpose, /* expose */
-#else
- NULL, /* expose */
-#endif
- XawSimpleSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- ChangeSensitive, /* change_sensitive */
- },
-};
-
-WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec;
-
-static void
-XawSimpleClassInitialize(void)
-{
- static XtConvertArgRec convertArg[] = {
- {
- XtWidgetBaseOffset,
- (XtPointer)XtOffsetOf(WidgetRec, core.screen),
- sizeof(Screen *)
- },
- {
- XtResourceString,
- (XtPointer)XtNpointerColor,
- sizeof(Pixel)
- },
- {
- XtResourceString,
- (XtPointer)XtNpointerColorBackground,
- sizeof(Pixel)
- },
- {
- XtWidgetBaseOffset,
- (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
- sizeof(Colormap)
- },
- };
-
- XawInitializeWidgetSet();
- XtSetTypeConverter(XtRString, XtRColorCursor, XmuCvtStringToColorCursor,
- convertArg, XtNumber(convertArg), XtCacheByDisplay, NULL);
-}
-
-static void
-XawSimpleClassPartInitialize(WidgetClass cclass)
-{
- SimpleWidgetClass c = (SimpleWidgetClass)cclass;
- SimpleWidgetClass super = (SimpleWidgetClass)c->core_class.superclass;
-
- if (c->simple_class.change_sensitive == NULL) {
- char buf[BUFSIZ];
-
- (void)XmuSnprintf(buf, sizeof(buf),
- "%s Widget: The Simple Widget class method "
- "'change_sensitive' is undefined.\nA function "
- "must be defined or inherited.",
- c->core_class.class_name);
- XtWarning(buf);
- c->simple_class.change_sensitive = ChangeSensitive;
- }
-
- if (c->simple_class.change_sensitive == XtInheritChangeSensitive)
- c->simple_class.change_sensitive = super->simple_class.change_sensitive;
-}
-
-#ifndef OLDXAW
-/*ARGSUSED*/
-static void
-XawSimpleInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SimpleWidget simple = (SimpleWidget)cnew;
-
- if (simple->simple.tip)
- simple->simple.tip = XtNewString(simple->simple.tip);
-}
-
-static void
-XawSimpleDestroy(Widget w)
-{
- SimpleWidget simple = (SimpleWidget)w;
-
- if (simple->simple.tip)
- XtFree((XtPointer)simple->simple.tip);
-}
-#endif
-
-static void
-XawSimpleRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
-{
-#ifndef OLDXAW
- XawPixmap *pixmap;
-#endif
- Pixmap border_pixmap = CopyFromParent;
-
- if (!XtIsSensitive(w))
- {
- /* change border to gray; have to remember the old one,
- * so XtDestroyWidget deletes the proper one */
- if (((SimpleWidget)w)->simple.insensitive_border == None)
- ((SimpleWidget)w)->simple.insensitive_border =
- XmuCreateStippledPixmap(XtScreen(w),
- w->core.border_pixel,
- w->core.background_pixel,
- w->core.depth);
- border_pixmap = w->core.border_pixmap;
- attributes->border_pixmap =
- w->core.border_pixmap = ((SimpleWidget)w)->simple.insensitive_border;
-
- *valueMask |= CWBorderPixmap;
- *valueMask &= ~CWBorderPixel;
- }
-
- ConvertCursor(w);
-
- if ((attributes->cursor = ((SimpleWidget)w)->simple.cursor) != None)
- *valueMask |= CWCursor;
-
- XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent,
- *valueMask, attributes);
-
- if (!XtIsSensitive(w))
- w->core.border_pixmap = border_pixmap;
-
-#ifndef OLDXAW
- if (w->core.background_pixmap > XtUnspecifiedPixmap) {
- pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
- w->core.colormap, w->core.depth);
- if (pixmap && pixmap->mask)
- XawReshapeWidget(w, pixmap);
- }
-
- if (((SimpleWidget)w)->simple.tip)
- XawTipEnable(w);
-#endif
-}
-
-/*
- * Function:
- * ConvertCursor
- *
- * Parameters:
- * w - simple widget
- *
- * Description:
- * Converts a name to a new cursor.
- */
-static void
-ConvertCursor(Widget w)
-{
- SimpleWidget simple = (SimpleWidget) w;
- XrmValue from, to;
- Cursor cursor = None;
-
- if (simple->simple.cursor_name == NULL)
- return;
-
- from.addr = (XPointer)simple->simple.cursor_name;
- from.size = strlen((char *)from.addr) + 1;
-
- to.size = sizeof(Cursor);
- to.addr = (XPointer)&cursor;
-
- if (XtConvertAndStore(w, XtRString, &from, XtRColorCursor, &to))
- simple->simple.cursor = cursor;
- else
- XtAppErrorMsg(XtWidgetToApplicationContext(w),
- "convertFailed","ConvertCursor","XawError",
- "Simple: ConvertCursor failed.",
- NULL, NULL);
-}
-
-
-/*ARGSUSED*/
-static Boolean
-XawSimpleSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SimpleWidget s_old = (SimpleWidget)current;
- SimpleWidget s_new = (SimpleWidget)cnew;
- Bool new_cursor = False;
-
- /* this disables user changes after creation */
- s_new->simple.international = s_old->simple.international;
-
- if (XtIsSensitive(current) != XtIsSensitive(cnew))
- (*((SimpleWidgetClass)XtClass(cnew))->simple_class.change_sensitive)
- (cnew);
-
- if (s_old->simple.cursor != s_new->simple.cursor)
- new_cursor = True;
-
- /*
- * We are not handling the string cursor_name correctly here
- */
-
- if (s_old->simple.pointer_fg != s_new->simple.pointer_fg ||
- s_old->simple.pointer_bg != s_new->simple.pointer_bg ||
- s_old->simple.cursor_name != s_new->simple.cursor_name) {
- ConvertCursor(cnew);
- new_cursor = True;
- }
-
- if (new_cursor && XtIsRealized(cnew)) {
- if (s_new->simple.cursor != None)
- XDefineCursor(XtDisplay(cnew), XtWindow(cnew), s_new->simple.cursor);
- else
- XUndefineCursor(XtDisplay(cnew), XtWindow(cnew));
- }
-
-#ifndef OLDXAW
- if (s_old->core.background_pixmap != s_new->core.background_pixmap) {
- XawPixmap *opix, *npix;
-
- opix = XawPixmapFromXPixmap(s_old->core.background_pixmap,
- XtScreen(s_old), s_old->core.colormap,
- s_old->core.depth);
- npix = XawPixmapFromXPixmap(s_new->core.background_pixmap,
- XtScreen(s_new), s_new->core.colormap,
- s_new->core.depth);
- if ((npix && npix->mask) || (opix && opix->mask))
- XawReshapeWidget(cnew, npix);
- }
-
- if (s_old->simple.tip != s_new->simple.tip) {
- if (s_old->simple.tip)
- XtFree((XtPointer)s_old->simple.tip);
- if (s_new->simple.tip)
- s_new->simple.tip = XtNewString(s_new->simple.tip);
- }
-
- if (s_old->simple.tip && !s_new->simple.tip)
- XawTipDisable(cnew);
- else if (!s_old->simple.tip && s_new->simple.tip)
- XawTipEnable(cnew);
-
- if (s_old->simple.display_list != s_new->simple.display_list)
- return (True);
-#endif /* OLDXAW */
-
- return (False);
-}
-
-#ifndef OLDXAW
-static void
-XawSimpleExpose(Widget w, XEvent *event, Region region)
-{
- SimpleWidget xaw = (SimpleWidget)w;
-
- if (xaw->simple.display_list)
- XawRunDisplayList(w, xaw->simple.display_list, event, region);
-}
-#endif
-
-static Bool
-ChangeSensitive(Widget w)
-{
- if (XtIsRealized(w)) {
- if (XtIsSensitive(w))
- if (w->core.border_pixmap != XtUnspecifiedPixmap)
- XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
- w->core.border_pixmap);
- else
- XSetWindowBorder(XtDisplay(w), XtWindow(w),
- w->core.border_pixel);
- else {
- if (((SimpleWidget)w)->simple.insensitive_border == None)
- ((SimpleWidget)w)->simple.insensitive_border =
- XmuCreateStippledPixmap(XtScreen(w),
- w->core.border_pixel,
- w->core.background_pixel,
- w->core.depth);
- XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
- ((SimpleWidget)w)->simple.insensitive_border);
- }
- }
-
- return (False);
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/SimpleP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" +#ifndef OLDXAW +#include <X11/Xaw/Tip.h> +#endif + +/* + * Class Methods + */ +static Bool ChangeSensitive(Widget); +static void XawSimpleClassInitialize(void); +static void XawSimpleClassPartInitialize(WidgetClass); +#ifndef OLDXAW +static void XawSimpleInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawSimpleDestroy(Widget); +static void XawSimpleExpose(Widget, XEvent*, Region); +#endif +static void XawSimpleRealize(Widget, Mask*, XSetWindowAttributes*); +static Boolean XawSimpleSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +static void ConvertCursor(Widget); + +/* + * Initialization + */ +#ifndef OLDXAW +static XtActionsRec actions[] = { + {"set-values", XawSetValuesAction}, + {"get-values", XawGetValuesAction}, + {"declare", XawDeclareAction}, + {"call-proc", XawCallProcAction}, +}; +#endif + +#define offset(field) XtOffsetOf(SimpleRec, simple.field) +static XtResource resources[] = { + { + XtNcursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(cursor), + XtRImmediate, + (XtPointer)None + }, + { + XtNinsensitiveBorder, + XtCInsensitive, + XtRPixmap, + sizeof(Pixmap), + offset(insensitive_border), + XtRImmediate, + NULL + }, + { + XtNpointerColor, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(pointer_fg), + XtRString, + XtDefaultForeground + }, + { + XtNpointerColorBackground, + XtCBackground, + XtRPixel, + sizeof(Pixel), + offset(pointer_bg), + XtRString, + XtDefaultBackground + }, + { + XtNcursorName, + XtCCursor, + XtRString, + sizeof(String), + offset(cursor_name), + XtRString, + NULL + }, + { + XtNinternational, + XtCInternational, + XtRBoolean, + sizeof(Boolean), + offset(international), + XtRImmediate, + (XtPointer)False + }, +#ifndef OLDXAW + { + XawNdisplayList, + XawCDisplayList, + XawRDisplayList, + sizeof(XawDisplayList*), + offset(display_list), + XtRImmediate, + NULL + }, + { + XtNtip, + XtCTip, + XtRString, + sizeof(String), + offset(tip), + XtRImmediate, + NULL + }, +#endif +#undef offset +}; + +SimpleClassRec simpleClassRec = { + /* core */ + { + (WidgetClass)&widgetClassRec, /* superclass */ + "Simple", /* class_name */ + sizeof(SimpleRec), /* widget_size */ + XawSimpleClassInitialize, /* class_initialize */ + XawSimpleClassPartInitialize, /* class_part_initialize */ + False, /* class_inited */ +#ifndef OLDXAW + XawSimpleInitialize, /* initialize */ +#else + NULL, /* initialize */ +#endif + NULL, /* initialize_hook */ + XawSimpleRealize, /* realize */ +#ifndef OLDXAW + actions, /* actions */ + XtNumber(actions), /* num_actions */ +#else + NULL, /* actions */ + 0, /* num_actions */ +#endif + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ +#ifndef OLDXAW + XawSimpleDestroy, /* destroy */ +#else + NULL, /* destroy */ +#endif + NULL, /* resize */ +#ifndef OLDXAW + XawSimpleExpose, /* expose */ +#else + NULL, /* expose */ +#endif + XawSimpleSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + ChangeSensitive, /* change_sensitive */ + }, +}; + +WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec; + +static void +XawSimpleClassInitialize(void) +{ + static XtConvertArgRec convertArg[] = { + { + XtWidgetBaseOffset, + (XtPointer)XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *) + }, + { + XtResourceString, + (XtPointer)XtNpointerColor, + sizeof(Pixel) + }, + { + XtResourceString, + (XtPointer)XtNpointerColorBackground, + sizeof(Pixel) + }, + { + XtWidgetBaseOffset, + (XtPointer)XtOffsetOf(WidgetRec, core.colormap), + sizeof(Colormap) + }, + }; + + XawInitializeWidgetSet(); + XtSetTypeConverter(XtRString, XtRColorCursor, XmuCvtStringToColorCursor, + convertArg, XtNumber(convertArg), XtCacheByDisplay, NULL); +} + +static void +XawSimpleClassPartInitialize(WidgetClass cclass) +{ + SimpleWidgetClass c = (SimpleWidgetClass)cclass; + SimpleWidgetClass super = (SimpleWidgetClass)c->core_class.superclass; + + if (c->simple_class.change_sensitive == NULL) { + char buf[BUFSIZ]; + + (void)XmuSnprintf(buf, sizeof(buf), + "%s Widget: The Simple Widget class method " + "'change_sensitive' is undefined.\nA function " + "must be defined or inherited.", + c->core_class.class_name); + XtWarning(buf); + c->simple_class.change_sensitive = ChangeSensitive; + } + + if (c->simple_class.change_sensitive == XtInheritChangeSensitive) + c->simple_class.change_sensitive = super->simple_class.change_sensitive; +} + +#ifndef OLDXAW +/*ARGSUSED*/ +static void +XawSimpleInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SimpleWidget simple = (SimpleWidget)cnew; + + if (simple->simple.tip) + simple->simple.tip = XtNewString(simple->simple.tip); +} + +static void +XawSimpleDestroy(Widget w) +{ + SimpleWidget simple = (SimpleWidget)w; + + if (simple->simple.tip) + XtFree((XtPointer)simple->simple.tip); +} +#endif + +static void +XawSimpleRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) +{ +#ifndef OLDXAW + XawPixmap *pixmap; +#endif + Pixmap border_pixmap = CopyFromParent; + + if (!XtIsSensitive(w)) + { + /* change border to gray; have to remember the old one, + * so XtDestroyWidget deletes the proper one */ + if (((SimpleWidget)w)->simple.insensitive_border == None) + ((SimpleWidget)w)->simple.insensitive_border = + XmuCreateStippledPixmap(XtScreen(w), + w->core.border_pixel, + w->core.background_pixel, + w->core.depth); + border_pixmap = w->core.border_pixmap; + attributes->border_pixmap = + w->core.border_pixmap = ((SimpleWidget)w)->simple.insensitive_border; + + *valueMask |= CWBorderPixmap; + *valueMask &= ~CWBorderPixel; + } + + ConvertCursor(w); + + if ((attributes->cursor = ((SimpleWidget)w)->simple.cursor) != None) + *valueMask |= CWCursor; + + XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent, + *valueMask, attributes); + + if (!XtIsSensitive(w)) + w->core.border_pixmap = border_pixmap; + +#ifndef OLDXAW + if (w->core.background_pixmap > XtUnspecifiedPixmap) { + pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w), + w->core.colormap, w->core.depth); + if (pixmap && pixmap->mask) + XawReshapeWidget(w, pixmap); + } + + if (((SimpleWidget)w)->simple.tip) + XawTipEnable(w); +#endif +} + +/* + * Function: + * ConvertCursor + * + * Parameters: + * w - simple widget + * + * Description: + * Converts a name to a new cursor. + */ +static void +ConvertCursor(Widget w) +{ + SimpleWidget simple = (SimpleWidget) w; + XrmValue from, to; + Cursor cursor = None; + + if (simple->simple.cursor_name == NULL) + return; + + from.addr = (XPointer)simple->simple.cursor_name; + from.size = strlen((char *)from.addr) + 1; + + to.size = sizeof(Cursor); + to.addr = (XPointer)&cursor; + + if (XtConvertAndStore(w, XtRString, &from, XtRColorCursor, &to)) + simple->simple.cursor = cursor; + else + XtAppErrorMsg(XtWidgetToApplicationContext(w), + "convertFailed","ConvertCursor","XawError", + "Simple: ConvertCursor failed.", + NULL, NULL); +} + + +/*ARGSUSED*/ +static Boolean +XawSimpleSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SimpleWidget s_old = (SimpleWidget)current; + SimpleWidget s_new = (SimpleWidget)cnew; + Bool new_cursor = False; + + /* this disables user changes after creation */ + s_new->simple.international = s_old->simple.international; + + if (XtIsSensitive(current) != XtIsSensitive(cnew)) + (*((SimpleWidgetClass)XtClass(cnew))->simple_class.change_sensitive) + (cnew); + + if (s_old->simple.cursor != s_new->simple.cursor) + new_cursor = True; + + /* + * We are not handling the string cursor_name correctly here + */ + + if (s_old->simple.pointer_fg != s_new->simple.pointer_fg || + s_old->simple.pointer_bg != s_new->simple.pointer_bg || + s_old->simple.cursor_name != s_new->simple.cursor_name) { + ConvertCursor(cnew); + new_cursor = True; + } + + if (new_cursor && XtIsRealized(cnew)) { + if (s_new->simple.cursor != None) + XDefineCursor(XtDisplay(cnew), XtWindow(cnew), s_new->simple.cursor); + else + XUndefineCursor(XtDisplay(cnew), XtWindow(cnew)); + } + +#ifndef OLDXAW + if (s_old->core.background_pixmap != s_new->core.background_pixmap) { + XawPixmap *opix, *npix; + + opix = XawPixmapFromXPixmap(s_old->core.background_pixmap, + XtScreen(s_old), s_old->core.colormap, + s_old->core.depth); + npix = XawPixmapFromXPixmap(s_new->core.background_pixmap, + XtScreen(s_new), s_new->core.colormap, + s_new->core.depth); + if ((npix && npix->mask) || (opix && opix->mask)) + XawReshapeWidget(cnew, npix); + } + + if (s_old->simple.tip != s_new->simple.tip) { + if (s_old->simple.tip) + XtFree((XtPointer)s_old->simple.tip); + if (s_new->simple.tip) + s_new->simple.tip = XtNewString(s_new->simple.tip); + } + + if (s_old->simple.tip && !s_new->simple.tip) + XawTipDisable(cnew); + else if (!s_old->simple.tip && s_new->simple.tip) + XawTipEnable(cnew); + + if (s_old->simple.display_list != s_new->simple.display_list) + return (True); +#endif /* OLDXAW */ + + return (False); +} + +#ifndef OLDXAW +static void +XawSimpleExpose(Widget w, XEvent *event, Region region) +{ + SimpleWidget xaw = (SimpleWidget)w; + + if (xaw->simple.display_list) + XawRunDisplayList(w, xaw->simple.display_list, event, region); +} +#endif + +static Bool +ChangeSensitive(Widget w) +{ + if (XtIsRealized(w)) { + if (XtIsSensitive(w)) + if (w->core.border_pixmap != XtUnspecifiedPixmap) + XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w), + w->core.border_pixmap); + else + XSetWindowBorder(XtDisplay(w), XtWindow(w), + w->core.border_pixel); + else { + if (((SimpleWidget)w)->simple.insensitive_border == None) + ((SimpleWidget)w)->simple.insensitive_border = + XmuCreateStippledPixmap(XtScreen(w), + w->core.border_pixel, + w->core.background_pixel, + w->core.depth); + XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w), + ((SimpleWidget)w)->simple.insensitive_border); + } + } + + return (False); +} diff --git a/libXaw/src/SimpleMenu.c b/libXaw/src/SimpleMenu.c index cfde9df29..0152a8560 100644 --- a/libXaw/src/SimpleMenu.c +++ b/libXaw/src/SimpleMenu.c @@ -1,1830 +1,1830 @@ -/*
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- */
-
-/*
- * SimpleMenu.c - Source code file for SimpleMenu widget.
- *
- * Date: April 3, 1989
- *
- * By: Chris D. Peterson
- * MIT X Consortium
- * kit@expo.lcs.mit.edu
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/Initer.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/SimpleMenP.h>
-#include <X11/Xaw/SmeBSBP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
-#define ForAllChildren(smw, childP) \
-for ((childP) = (SmeObject *)(smw)->composite.children; \
- (childP) < (SmeObject *)((smw)->composite.children \
- + (smw)->composite.num_children); \
- (childP)++)
-
-#ifndef OLDXAW
-#define SMW_UNMAPPING 0x01
-#define SMW_POPLEFT 0x02
-#endif
-
-/*
- * Class Methods
- */
-static void XawSimpleMenuChangeManaged(Widget);
-static void XawSimpleMenuClassInitialize(void);
-static void XawSimpleMenuClassPartInitialize(WidgetClass);
-static XtGeometryResult XawSimpleMenuGeometryManager(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawSimpleMenuInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawSimpleMenuRealize(Widget, XtValueMask*, XSetWindowAttributes*);
-static void XawSimpleMenuRedisplay(Widget, XEvent*, Region);
-static void XawSimpleMenuResize(Widget);
-static Boolean XawSimpleMenuSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static Boolean XawSimpleMenuSetValuesHook(Widget, ArgList, Cardinal*);
-#ifndef OLDXAW
-static void PopupSubMenu(SimpleMenuWidget);
-static void PopdownSubMenu(SimpleMenuWidget);
-static void PopupCB(Widget, XtPointer, XtPointer);
-#endif
-
-/*
- * Prototypes
- */
-static void AddPositionAction(XtAppContext, XPointer);
-static void CalculateNewSize(Widget, Dimension*, Dimension*);
-static void ChangeCursorOnGrab(Widget, XtPointer, XtPointer);
-static void CreateLabel(Widget);
-static SmeObject DoGetEventEntry(Widget, int, int);
-static Widget FindMenu(Widget, String);
-static SmeObject GetEventEntry(Widget, XEvent*);
-static void Layout(Widget, Dimension*, Dimension*);
-static void MakeResizeRequest(Widget);
-static void MakeSetValuesRequest(Widget, unsigned int, unsigned int);
-static void MoveMenu(Widget, int, int);
-static void PositionMenu(Widget, XPoint*);
-
-/*
- * Actions
- */
-static void Highlight(Widget, XEvent*, String*, Cardinal*);
-static void Notify(Widget, XEvent*, String*, Cardinal*);
-#ifndef OLDXAW
-static void Popdown(Widget, XEvent*, String*, Cardinal*);
-#endif
-static void PositionMenuAction(Widget, XEvent*, String*, Cardinal*);
-static void Unhighlight(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(SimpleMenuRec, simple_menu.field)
-
-static XtResource resources[] = {
- /* label */
- {
- XtNlabel,
- XtCLabel,
- XtRString,
- sizeof(String),
- offset(label_string),
- XtRString,
- NULL
- },
- {
- XtNlabelClass,
- XtCLabelClass,
- XtRPointer,
- sizeof(WidgetClass),
- offset(label_class),
- XtRImmediate,
- NULL
- },
-
- /* layout */
- {
- XtNrowHeight,
- XtCRowHeight,
- XtRDimension,
- sizeof(Dimension),
- offset(row_height),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNtopMargin,
- XtCVerticalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(top_margin),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNbottomMargin,
- XtCVerticalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(bottom_margin),
- XtRImmediate,
- (XtPointer)0
- },
-#ifndef OLDXAW
- {
- XtNleftMargin,
- XtCHorizontalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(left_margin),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNrightMargin,
- XtCHorizontalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(right_margin),
- XtRImmediate,
- (XtPointer)0
- },
-#endif
-
- /* misc */
- {
- XtNallowShellResize,
- XtCAllowShellResize,
- XtRBoolean,
- sizeof(Boolean),
- XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNcursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(cursor),
- XtRImmediate,
- (XtPointer)None
- },
- {
- XtNmenuOnScreen,
- XtCMenuOnScreen,
- XtRBoolean,
- sizeof(Boolean),
- offset(menu_on_screen),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNpopupOnEntry,
- XtCPopupOnEntry,
- XtRWidget,
- sizeof(Widget),
- offset(popup_entry),
- XtRWidget,
- NULL
- },
- {
- XtNbackingStore,
- XtCBackingStore,
- XtRBackingStore,
- sizeof(int),
- offset(backing_store),
- XtRImmediate,
- (XtPointer)(Always + WhenMapped + NotUseful)
- },
-#ifndef OLDXAW
- {
- XawNdisplayList,
- XawCDisplayList,
- XawRDisplayList,
- sizeof(XawDisplayList*),
- offset(display_list),
- XtRImmediate,
- NULL
- },
-#endif
-};
-#undef offset
-
-static char defaultTranslations[] =
-"<Enter>:" "highlight()\n"
-"<Leave>:" "unhighlight()\n"
-"<BtnMotion>:" "highlight()\n"
-#ifndef OLDXAW
-"<BtnUp>:" "popdown() notify() unhighlight()\n"
-#else
-"<BtnUp>:" "MenuPopdown() notify() unhighlight()\n"
-#endif
-;
-
-static XtActionsRec actionsList[] =
-{
- {"notify", Notify},
- {"highlight", Highlight},
- {"unhighlight", Unhighlight},
-#ifndef OLDXAW
- {"popdown", Popdown},
- {"set-values", XawSetValuesAction},
- {"get-values", XawGetValuesAction},
- {"declare", XawDeclareAction},
- {"call-proc", XawCallProcAction},
-#endif
-};
-
-static CompositeClassExtensionRec extension_rec = {
- NULL, /* next_extension */
- NULLQUARK, /* record_type */
- XtCompositeExtensionVersion, /* version */
- sizeof(CompositeClassExtensionRec), /* record_size */
- True, /* accepts_objects */
-};
-
-#define Superclass (&overrideShellClassRec)
-SimpleMenuClassRec simpleMenuClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "SimpleMenu", /* class_name */
- sizeof(SimpleMenuRec), /* size */
- XawSimpleMenuClassInitialize, /* class_initialize */
- XawSimpleMenuClassPartInitialize, /* class_part_initialize */
- False, /* class_inited */
- XawSimpleMenuInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawSimpleMenuRealize, /* realize */
- actionsList, /* actions */
- XtNumber(actionsList), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- XawSimpleMenuResize, /* resize */
- XawSimpleMenuRedisplay, /* expose */
- XawSimpleMenuSetValues, /* set_values */
- XawSimpleMenuSetValuesHook, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* intrinsics version */
- NULL, /* callback offsets */
- defaultTranslations, /* tm_table */
- NULL, /* query_geometry */
- NULL, /* display_accelerator */
- NULL, /* extension */
- },
- /* composite */
- {
- XawSimpleMenuGeometryManager, /* geometry_manager */
- XawSimpleMenuChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- /* shell */
- {
- NULL, /* extension */
- },
- /* override */
- {
- NULL, /* extension */
- },
- /* simple_menu */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec;
-
-/*
- * Implementation
- */
-/*
- * Function:
- * XawSimpleMenuClassInitialize
- *
- * Description:
- * Class Initialize routine, called only once.
- */
-static void
-XawSimpleMenuClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
- NULL, 0);
- XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString,
- NULL, 0, XtCacheNone, NULL);
- XmuAddInitializer(AddPositionAction, NULL);
-}
-
-/*
- * Function:
- * XawSimpleMenuClassPartInitialize
- * Arguments: wc - the widget class of the subclass.
- *
- * Description:
- * Class Part Initialize routine, called for every subclass. Makes
- * sure that the subclasses pick up the extension record.
- */
-static void
-XawSimpleMenuClassPartInitialize(WidgetClass wc)
-{
- SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass)wc;
-
- /*
- * Make sure that our subclass gets the extension rec too
- */
- extension_rec.next_extension = smwc->composite_class.extension;
- smwc->composite_class.extension = (XtPointer) &extension_rec;
-}
-
-/*
- * Function:
- * XawSimpleMenuInitialize
- *
- * Parameters:
- * request - widget requested by the argument list
- * cnew - new widget with both resource and non resource values
- *
- * Description:
- * Initializes the simple menu widget.
- */
-/*ARGSUSED*/
-static void
-XawSimpleMenuInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)cnew;
- Dimension width, height;
-
- XmuCallInitializers(XtWidgetToApplicationContext(cnew));
-
- if (smw->simple_menu.label_class == NULL)
- smw->simple_menu.label_class = smeBSBObjectClass;
-
- smw->simple_menu.label = NULL;
- smw->simple_menu.entry_set = NULL;
- smw->simple_menu.recursive_set_values = False;
-#ifndef OLDXAW
- smw->simple_menu.sub_menu = NULL;
- smw->simple_menu.state = 0;
-
- XtAddCallback(cnew, XtNpopupCallback, PopupCB, NULL);
-#endif
-
- if (smw->simple_menu.label_string != NULL)
- CreateLabel(cnew);
-
- width = height = 0;
- CalculateNewSize(cnew, &width, &height);
-
- smw->simple_menu.menu_width = True;
-
- if (XtWidth(smw) == 0) {
- smw->simple_menu.menu_width = False;
- XtWidth(smw) = width;
- }
-
- smw->simple_menu.menu_height = True;
-
- if (XtHeight(smw) == 0) {
- smw->simple_menu.menu_height = False;
- XtHeight(smw) = height;
- }
-
- /*
- * Add a popup_callback routine for changing the cursor
- */
- XtAddCallback(cnew, XtNpopupCallback, ChangeCursorOnGrab, NULL);
-}
-
-/*
- * Function:
- * XawSimpleMenuRedisplay
- *
- * Parameters:
- * w - simple menu widget
- * event - X event that caused this redisplay
- * region - region the needs to be repainted
- *
- * Description:
- * Redisplays the contents of the widget.
- */
-/*ARGSUSED*/
-static void
-XawSimpleMenuRedisplay(Widget w, XEvent *event, Region region)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
- SmeObject *entry;
- SmeObjectClass cclass;
-
- if (region == NULL)
- XClearWindow(XtDisplay(w), XtWindow(w));
-
-#ifndef OLDXAW
- if (smw->simple_menu.display_list)
- XawRunDisplayList(w, smw->simple_menu.display_list, event, region);
-#endif
-
- /*
- * Check and Paint each of the entries - including the label
- */
- ForAllChildren(smw, entry) {
- if (!XtIsManaged((Widget)*entry))
- continue;
-
- if (region != NULL)
- switch(XRectInRegion(region, XtX(*entry),XtY(*entry),
- XtWidth(*entry), XtHeight(*entry))) {
- case RectangleIn:
- case RectanglePart:
- break;
- default:
- continue;
- }
-
- cclass = (SmeObjectClass)(*entry)->object.widget_class;
-
- if (cclass->rect_class.expose != NULL)
- (cclass->rect_class.expose)((Widget)*entry, NULL, NULL);
- }
-}
-
-/*
- * Function:
- * XawSimpleMenuRealize
- *
- * Parameters:
- * w - simple menu widget
- * mask - value mask for the window to create
- * attrs - attributes for the window to create
- *
- * Description:
- * Realizes the widget.
- */
-static void
-XawSimpleMenuRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attrs)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
-#ifndef OLDXAW
- XawPixmap *pixmap;
-#endif
-
- attrs->cursor = smw->simple_menu.cursor;
- *mask |= CWCursor;
- if (smw->simple_menu.backing_store == Always ||
- smw->simple_menu.backing_store == NotUseful ||
- smw->simple_menu.backing_store == WhenMapped) {
- *mask |= CWBackingStore;
- attrs->backing_store = smw->simple_menu.backing_store;
- }
- else
- *mask &= ~CWBackingStore;
-
- (*Superclass->core_class.realize)(w, mask, attrs);
-
-#ifndef OLDXAW
- if (w->core.background_pixmap > XtUnspecifiedPixmap) {
- pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
- w->core.colormap, w->core.depth);
- if (pixmap && pixmap->mask)
- XawReshapeWidget(w, pixmap);
- }
-#endif
-}
-
-/*
- * Function:
- * XawSimpleMenuResize
- *
- * Parameters:
- * w - simple menu widget
- *
- * Description:
- * Handle the menu being resized.
- */
-static void
-XawSimpleMenuResize(Widget w)
-{
- if (!XtIsRealized(w))
- return;
-
- Layout(w, NULL, NULL);
-
- XawSimpleMenuRedisplay(w, NULL, NULL);
-}
-
-/*
- * Function:
- * XawSimpleMenuSetValues
- *
- * Parameters:
- * current - current state of the widget
- * request - what was requested
- * cnew - what the widget will become
- *
- * Description:
- * Relayout the menu when one of the resources is changed.
- */
-/*ARGSUSED*/
-static Boolean
-XawSimpleMenuSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SimpleMenuWidget smw_old = (SimpleMenuWidget)current;
- SimpleMenuWidget smw_new = (SimpleMenuWidget)cnew;
- Boolean ret_val = False, layout = False;
-
- if (!XtIsRealized(current))
- return (False);
-
- if (!smw_new->simple_menu.recursive_set_values) {
- if (XtWidth(smw_new) != XtWidth(smw_old)) {
- smw_new->simple_menu.menu_width = XtWidth(smw_new) != 0;
- layout = True;
- }
- if (XtHeight(smw_new) != XtHeight(smw_old)) {
- smw_new->simple_menu.menu_height = XtHeight(smw_new) != 0;
- layout = True;
- }
- }
-
- if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor)
- XDefineCursor(XtDisplay(cnew), XtWindow(cnew),
- smw_new->simple_menu.cursor);
-
- if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) {
- if (smw_new->simple_menu.label_string == NULL) /* Destroy */
- XtDestroyWidget((Widget)smw_old->simple_menu.label);
- else if (smw_old->simple_menu.label_string == NULL) /* Create */
- CreateLabel(cnew);
- else { /* Change */
- Arg arglist[1];
-
- XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string);
- XtSetValues((Widget)smw_new->simple_menu.label, arglist, ONE);
- }
- }
-
- if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class)
- XtAppWarning(XtWidgetToApplicationContext(cnew),
- "No Dynamic class change of the SimpleMenu Label.");
-
- if (smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin
- || smw_old->simple_menu.bottom_margin
- != smw_new->simple_menu.bottom_margin) {
- layout = True;
- ret_val = True;
- }
-
-#ifndef OLDXAW
- if (smw_old->core.background_pixmap != smw_new->core.background_pixmap) {
- XawPixmap *opix, *npix;
-
- opix = XawPixmapFromXPixmap(smw_old->core.background_pixmap,
- XtScreen(smw_old), smw_old->core.colormap,
- smw_old->core.depth);
- npix = XawPixmapFromXPixmap(smw_new->core.background_pixmap,
- XtScreen(smw_new), smw_new->core.colormap,
- smw_new->core.depth);
- if ((npix && npix->mask) || (opix && opix->mask))
- XawReshapeWidget(cnew, npix);
- }
-#endif
-
- if (layout)
- Layout(cnew, NULL, NULL);
-
- return (ret_val);
-}
-
-/*
- * Function:
- * XawSimpleMenuSetValuesHook
- *
- * Parameters:
- * w - menu widget
- * arglist - argument list passed to XtSetValues
- * num_args - number of args
- *
- * Description:
- * To handle a special case, this is passed the actual arguments.
- */
-static Boolean
-XawSimpleMenuSetValuesHook(Widget w, ArgList arglist, Cardinal *num_args)
-{
- Cardinal i;
- Dimension width, height;
-
- width = XtWidth(w);
- height = XtHeight(w);
-
- for (i = 0 ; i < *num_args ; i++) {
- if (streq(arglist[i].name, XtNwidth))
- width = (Dimension)arglist[i].value;
- if (streq(arglist[i].name, XtNheight))
- height = (Dimension) arglist[i].value;
- }
-
- if (width != XtWidth(w) || height != XtHeight(w))
- MakeSetValuesRequest(w, width, height);
-
- return (False);
-}
-
-/*
- * Geometry Management routines
- */
-/*
- * Function:
- * XawSimpleMenuGeometryManager
- *
- * Parameters:
- * w - Menu Entry making the request
- * request - requested new geometry
- * reply - the allowed geometry.
- *
- * Description:
- * This is the SimpleMenu Widget's Geometry Manager.
- *
- * Returns:
- * XtGeometry{Yes, No, Almost}
- */
-static XtGeometryResult
-XawSimpleMenuGeometryManager(Widget w, XtWidgetGeometry *request,
- XtWidgetGeometry *reply)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)XtParent(w);
- SmeObject entry = (SmeObject)w;
- XtGeometryMask mode = request->request_mode;
- XtGeometryResult answer;
- Dimension old_height, old_width;
-
- if (!(mode & CWWidth) && !(mode & CWHeight))
- return (XtGeometryNo);
-
- reply->width = request->width;
- reply->height = request->height;
-
- old_width = XtWidth(entry);
- old_height = XtHeight(entry);
-
- Layout(w, &reply->width, &reply->height);
-
- /*
- * Since we are an override shell and have no parent there is no one to
- * ask to see if this geom change is okay, so I am just going to assume
- * we can do whatever we want. If you subclass be very careful with this
- * assumption, it could bite you.
- *
- * Chris D. Peterson - Sept. 1989.
- */
- if ((!(mode & CWWidth) || reply->width == request->width)
- && (!(mode & CWHeight) || reply->height == request->height)) {
- if (mode & XtCWQueryOnly) { /* Actually perform the layout */
- XtWidth(entry) = old_width;
- XtHeight(entry) = old_height;
- }
- else
- Layout((Widget)smw, NULL, NULL);
- answer = XtGeometryDone;
- }
- else {
- XtWidth(entry) = old_width;
- XtHeight(entry) = old_height;
-
- if ((reply->width == request->width && !(mode & CWHeight))
- || (reply->height == request->height && !(mode & CWWidth))
- || (reply->width == request->width
- && reply->height == request->height))
- answer = XtGeometryNo;
- else {
- answer = XtGeometryAlmost;
- reply->request_mode = 0;
- if (reply->width != request->width)
- reply->request_mode |= CWWidth;
- if (reply->height != request->height)
- reply->request_mode |= CWHeight;
- }
- }
-
- return (answer);
-}
-
-/*
- * Function:
- * XawSimpleMenuChangeManaged
- *
- * Parameters:
- * w - simple menu widget
- *
- * Description:
- * Called whenever a new child is managed.
- */
-static void
-XawSimpleMenuChangeManaged(Widget w)
-{
- Layout(w, NULL, NULL);
-}
-
-/*
- * Global Action Routines
- *
- * These actions routines will be added to the application's
- * global action list
- */
-/*
- * Function:
- * PositionMenuAction
- *
- * Parameters:
- * w - a widget (no the simple menu widget)
- * event - the event that caused this action
- * params - parameters passed to the routine.
- * we expect the name of the menu here.
- * num_params - ""
- *
- * Description:
- * Positions the simple menu widget.
- */
-/*ARGSUSED*/
-static void
-PositionMenuAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- Widget menu;
- XPoint loc;
-
- if (*num_params != 1) {
- XtAppWarning(XtWidgetToApplicationContext(w),
- "SimpleMenuWidget: position menu action expects "
- "only one parameter which is the name of the menu.");
- return;
- }
-
- if ((menu = FindMenu(w, params[0])) == NULL) {
- char error_buf[BUFSIZ];
-
- (void)XmuSnprintf(error_buf, sizeof(error_buf),
- "SimpleMenuWidget: could not find menu named %s.",
- params[0]);
- XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
- return;
- }
-
- switch (event->type) {
- case ButtonPress:
- case ButtonRelease:
- loc.x = event->xbutton.x_root;
- loc.y = event->xbutton.y_root;
- PositionMenu(menu, &loc);
- break;
- case EnterNotify:
- case LeaveNotify:
- loc.x = event->xcrossing.x_root;
- loc.y = event->xcrossing.y_root;
- PositionMenu(menu, &loc);
- break;
- case MotionNotify:
- loc.x = event->xmotion.x_root;
- loc.y = event->xmotion.y_root;
- PositionMenu(menu, &loc);
- break;
- default:
- PositionMenu(menu, NULL);
- break;
- }
-}
-
-/*
- * Widget Action Routines
- */
-/*
- * Function:
- * Unhighlight
- *
- * Parameters:
- * w - simple menu widget
- * event - event that caused this action
- * params - not used
- * num_params - ""
- *
- * Description:
- * Unhighlights current entry.
- */
-/*ARGSUSED*/
-static void
-Unhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
- SmeObject entry = smw->simple_menu.entry_set;
-
- if (entry == NULL)
- return;
-
-#ifndef OLDXAW
- if (!smw->simple_menu.sub_menu)
-#endif
- {
- SmeObjectClass cclass;
-
- smw->simple_menu.entry_set = NULL;
- cclass = (SmeObjectClass)entry->object.widget_class;
- (cclass->sme_class.unhighlight)((Widget)entry);
- }
-}
-
-/*
- * Function:
- * Highlight
- *
- * Parameters:
- * w - simple menu widget
- * event - event that caused this action
- * params - not used
- * num_params - ""
- *
- * Description:
- * Highlights current entry.
- */
-/*ARGSUSED*/
-static void
-Highlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
- SmeObject entry;
-
- if (!XtIsSensitive(w))
- return;
-
- entry = GetEventEntry(w, event);
-
- if (entry == smw->simple_menu.entry_set)
- return;
-
-#ifndef OLDXAW
- if (!smw->simple_menu.sub_menu)
-#endif
- Unhighlight(w, event, params, num_params);
-
- if (entry == NULL)
- return;
-
- if (!XtIsSensitive((Widget)entry))
- return;
-
-#ifndef OLDXAW
- if (smw->simple_menu.sub_menu)
- PopdownSubMenu(smw);
-#endif
-
- Unhighlight(w, event, params, num_params);
-
-#ifndef OLDXAW
- if (!(smw->simple_menu.state & SMW_UNMAPPING))
-#endif
- {
- SmeObjectClass cclass;
-
- smw->simple_menu.entry_set = entry;
- cclass = (SmeObjectClass)entry->object.widget_class;
-
- (cclass->sme_class.highlight)((Widget)entry);
-
-#ifndef OLDXAW
- if (XtIsSubclass((Widget)entry, smeBSBObjectClass))
- PopupSubMenu(smw);
-#endif
- }
-}
-
-/*
- * Function:
- * Notify
- *
- * Parameters:
- * w - simple menu widget
- * event - event that caused this action
- * params - not used
- * num_params - ""
- *
- * Description:
- * Notify user of current entry.
- */
-/*ARGSUSED*/
-static void
-Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- SmeObject entry;
- SmeObjectClass cclass;
-
- /* may be a propagated event from a sub menu, need to check it */
- if (XtWindow(w) != event->xany.window)
- return;
- entry = GetEventEntry(w, event);
- if (entry == NULL || !XtIsSensitive((Widget)entry))
- return;
-
- cclass = (SmeObjectClass) entry->object.widget_class;
- (cclass->sme_class.notify)((Widget)entry);
-}
-
-/*
- * Public Functions
- */
-/*
- * Function:
- * XawSimpleMenuAddGlobalActions
- *
- * Arguments:
- * app_con - appcontext
- *
- * Description:
- * Adds the global actions to the simple menu widget.
- */
-void
-XawSimpleMenuAddGlobalActions(XtAppContext app_con)
-{
- XtInitializeWidgetClass(simpleMenuWidgetClass);
- XmuCallInitializers(app_con);
-}
-
-/*
- * Function:
- * XawSimpleMenuGetActiveEntry
- *
- * Parameters:
- * w - smw widget
- *
- * Description:
- * Gets the currently active (set) entry.
- *
- * Returns:
- * The currently set entry or NULL if none is set
- */
-Widget
-XawSimpleMenuGetActiveEntry(Widget w)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
-
- return ((Widget)smw->simple_menu.entry_set);
-}
-
-/*
- * Function:
- * XawSimpleMenuClearActiveEntry
- *
- * Parameters:
- * w - smw widget
- *
- * Description:
- * Unsets the currently active (set) entry.
- */
-void
-XawSimpleMenuClearActiveEntry(Widget w)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
-
- smw->simple_menu.entry_set = NULL;
-}
-
-/*
- * Private Functions
- */
-/*
- * Function:
- * CreateLabel
- *
- * Parameters:
- * w - smw widget
- *
- * Description:
- * Creates the label object and makes sure it is the first child in
- * in the list.
- */
-static void
-CreateLabel(Widget w)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
- Widget *child, *next_child;
- int i;
- Arg args[2];
-
- if (smw->simple_menu.label_string == NULL ||
- smw->simple_menu.label != NULL) {
- XtAppWarning(XtWidgetToApplicationContext(w),
- "Xaw Simple Menu Widget: label string is NULL or "
- "label already exists, no label is being created.");
- return;
- }
-
- XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string);
- XtSetArg(args[1], XtNjustify, XtJustifyCenter);
- smw->simple_menu.label = (SmeObject)
- XtCreateManagedWidget("menuLabel",
- smw->simple_menu.label_class, w, args, TWO);
-
- next_child = NULL;
- for (child = smw->composite.children + smw->composite.num_children,
- i = smw->composite.num_children; i > 0; i--, child--) {
- if (next_child != NULL)
- *next_child = *child;
- next_child = child;
- }
- *child = (Widget)smw->simple_menu.label;
-}
-
-/*
- * Function:
- * Layout
- *
- * Arguments:
- * w - See below
- * width_ret - returned width
- * height_ret - returned height
- *
- * Note:
- * if width == NULL || height == NULL then it assumes the you do not care
- * about the return values, and just want a relayout.
- *
- * if this is not the case then it will set width_ret and height_ret
- * to be width and height that the child would get if it were layed out
- * at this time.
- *
- * "w" can be the simple menu widget or any of its object children.
- */
-static void
-Layout(Widget w, Dimension *width_ret, Dimension *height_ret)
-{
- SmeObject current_entry;
- SimpleMenuWidget smw;
- Dimension width, height;
- Boolean allow_change_size;
- Widget kid;
- Cardinal i, count, n;
- int width_kid, height_kid, tmp_w, tmp_h;
- short vadd, hadd, x_ins, y_ins;
- Dimension *widths;
-
- height = 0;
-
- if (XtIsSubclass(w, simpleMenuWidgetClass)) {
- smw = (SimpleMenuWidget)w;
- current_entry = NULL;
- }
- else {
- smw = (SimpleMenuWidget)XtParent(w);
- current_entry = (SmeObject)w;
- }
-
- allow_change_size = (!XtIsRealized((Widget)smw)
- || smw->shell.allow_shell_resize);
-
- for (i = smw->simple_menu.label ? 1 : 0;
- i < smw->composite.num_children;
- i++) {
- XtWidgetGeometry preferred;
-
- kid = smw->composite.children[i];
- if (!XtIsManaged(kid))
- continue;
- if (smw->simple_menu.row_height != 0)
- XtHeight(kid) = smw->simple_menu.row_height;
- XtQueryGeometry(kid, NULL, &preferred);
- if (preferred.request_mode & CWWidth)
- XtWidth(kid) = preferred.width;
- }
-
- if (smw->simple_menu.label
- && XtIsManaged((Widget)smw->simple_menu.label)) {
- XtWidgetGeometry preferred;
-
- kid = (Widget)smw->simple_menu.label;
- XtQueryGeometry(kid, NULL, &preferred);
- if (preferred.request_mode & CWWidth)
- XtWidth(kid) = preferred.width;
- if (preferred.request_mode & CWHeight)
- XtHeight(kid) = preferred.height;
- }
-
- /* reset */
- if (!smw->simple_menu.menu_width)
- XtWidth(smw) = 0;
- if (!smw->simple_menu.menu_height)
- XtHeight(smw) = 0;
- if (!XtWidth(smw) || !XtHeight(smw))
- MakeResizeRequest((Widget)smw);
-
- widths = (Dimension *)XtMalloc(sizeof(Dimension));
-#ifndef OLDXAW
- hadd = smw->simple_menu.left_margin;
-#else
- hadd = 0;
-#endif
- vadd = smw->simple_menu.top_margin;
- if (smw->simple_menu.label)
- vadd += XtHeight(smw->simple_menu.label);
-
- count = 1;
- width = tmp_w = tmp_h = n = 0;
- height = vadd;
-
- for (i = smw->simple_menu.label ? 1 : 0;
- i < smw->composite.num_children;
- i++) {
- kid = smw->composite.children[i];
- if (!XtIsManaged(kid))
- continue;
- width_kid = XtWidth(kid);
- height_kid = XtHeight(kid);
-
- if (n && (height + height_kid + smw->simple_menu.bottom_margin
- > XtHeight(smw))) {
- ++count;
- widths = (Dimension *)XtRealloc((char *)widths,
- sizeof(Dimension) * count);
- widths[count - 1] = width_kid;
- width += tmp_w;
- tmp_w = width_kid;
- height = height_kid + vadd;
- }
- else
- height += height_kid;
- if (height > tmp_h)
- tmp_h = height;
- if (width_kid > tmp_w)
- widths[count - 1] = tmp_w = width_kid;
- ++n;
- }
-
- height = tmp_h + smw->simple_menu.bottom_margin;
- width += tmp_w;
-
- if (smw->simple_menu.label && width < XtWidth(smw->simple_menu.label)) {
- float inc;
-
- inc = (XtWidth(smw->simple_menu.label) - width) / (float)count;
- width = XtWidth(smw->simple_menu.label);
- for (n = 0; n < count; n++)
- widths[n] += inc;
- }
-
-#ifndef OLDXAW
- width += hadd + smw->simple_menu.right_margin;
-#endif
-
- x_ins = n = count = 0;
- tmp_w = widths[0];
- tmp_h = vadd;
-
- for (i = smw->simple_menu.label ? 1 : 0;
- i < smw->composite.num_children;
- i++) {
- kid = smw->composite.children[i];
- if (!XtIsManaged(kid))
- continue;
-
- height_kid = XtHeight(kid);
-
- if (n && (tmp_h + height_kid + smw->simple_menu.bottom_margin
- > XtHeight(smw))) {
- x_ins = tmp_w;
- y_ins = vadd;
- ++count;
- tmp_w += widths[count];
- tmp_h = height_kid + vadd;
- }
- else {
- y_ins = tmp_h;
- tmp_h += height_kid;
- }
- ++n;
-
- XtX(kid) = x_ins + hadd;
- XtY(kid) = y_ins;
- XtWidth(kid) = widths[count];
- }
-
- XtFree((char *)widths);
-
- if (allow_change_size)
- MakeSetValuesRequest((Widget) smw, width, height);
-
- if (smw->simple_menu.label) {
- XtX(smw->simple_menu.label) = 0;
- XtY(smw->simple_menu.label) = smw->simple_menu.top_margin;
- XtWidth(smw->simple_menu.label) = XtWidth(smw)
-#ifndef OLDXAW
- - (smw->simple_menu.left_margin + smw->simple_menu.right_margin)
-#endif
- ;
- }
- if (current_entry) {
- if (width_ret)
- *width_ret = XtWidth(current_entry);
- if (height_ret)
- *height_ret = XtHeight(current_entry);
- }
-}
-
-/*
- * Function:
- * AddPositionAction
- *
- * Parameters:
- * app_con - application context
- * data - (not used)
- *
- * Description:
- * Adds the XawPositionSimpleMenu action to the global
- * action list for this appcon.
- */
-/*ARGSUSED*/
-static void
-AddPositionAction(XtAppContext app_con, XPointer data)
-{
- static XtActionsRec pos_action[] = {
- {"XawPositionSimpleMenu", PositionMenuAction},
- };
-
- XtAppAddActions(app_con, pos_action, XtNumber(pos_action));
-}
-
-/*
- * Function:
- * FindMenu
- *
- * Parameters:
- * widget - reference widget
- * name - menu widget's name
- *
- * Description:
- * Find the menu give a name and reference widget
- *
- * Returns:
- * The menu widget or NULL.
- */
-static Widget
-FindMenu(Widget widget, String name)
-{
- Widget w, menu;
-
- for (w = widget; w != NULL; w = XtParent(w))
- if ((menu = XtNameToWidget(w, name)) != NULL)
- return (menu);
-
- return (NULL);
-}
-
-/*
- * Function:
- * PositionMenu
- *
- * Parameters:
- * w - simple menu widget
- * location - pointer the the position or NULL
- *
- * Description:
- * Places the menu
- */
-static void
-PositionMenu(Widget w, XPoint *location)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
- SmeObject entry;
- XPoint t_point;
-
- if (location == NULL) {
- Window temp1, temp2;
- int root_x, root_y, tempX, tempY;
- unsigned int tempM;
-
- location = &t_point;
- if (XQueryPointer(XtDisplay(w), XtWindow(w), &temp1, &temp2,
- &root_x, &root_y, &tempX, &tempY, &tempM) == False) {
- XtAppWarning(XtWidgetToApplicationContext(w),
- "Xaw Simple Menu Widget: "
- "Could not find location of mouse pointer");
- return;
- }
- location->x = (short) root_x;
- location->y = (short) root_y;
- }
-
- /*
- * The width will not be correct unless it is realized
- */
- XtRealizeWidget(w);
-
- location->x -= XtWidth(w) >> 1;
-
- if (smw->simple_menu.popup_entry == NULL)
- entry = smw->simple_menu.label;
- else
- entry = smw->simple_menu.popup_entry;
-
- if (entry != NULL)
- location->y -= XtY(entry) + (XtHeight(entry) >> 1);
-
- MoveMenu(w, location->x, location->y);
-}
-
-/*
- * Function:
- * MoveMenu
- *
- * Parameters:
- * w - simple menu widget
- * x - current location of the widget
- * y - ""
- *
- * Description:
- * Actually moves the menu, may force it to
- * to be fully visable if menu_on_screen is True.
- */
-static void
-MoveMenu(Widget w, int x, int y)
-{
- Arg arglist[2];
- Cardinal num_args = 0;
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
-
- if (smw->simple_menu.menu_on_screen) {
- int width = XtWidth(w) + (XtBorderWidth(w) << 1);
- int height = XtHeight(w) + (XtBorderWidth(w) << 1);
-
- if (x >= 0) {
- int scr_width = WidthOfScreen(XtScreen(w));
-
- if (x + width > scr_width)
- x = scr_width - width;
- }
- if (x < 0)
- x = 0;
-
- if (y >= 0) {
- int scr_height = HeightOfScreen(XtScreen(w));
-
- if (y + height > scr_height)
- y = scr_height - height;
- }
- if (y < 0)
- y = 0;
- }
-
- XtSetArg(arglist[num_args], XtNx, x); num_args++;
- XtSetArg(arglist[num_args], XtNy, y); num_args++;
- XtSetValues(w, arglist, num_args);
-}
-
-/*
- * Function:
- * ChangeCursorOnGrab
- *
- * Parameters:
- * w - menu widget
- * temp1 - not used
- * temp2 - ""
- *
- * Description:
- * Changes the cursor on the active grab to the one
- * specified in out resource list.
- */
-/*ARGSUSED*/
-static void
-ChangeCursorOnGrab(Widget w, XtPointer temp1, XtPointer temp2)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
-
- /*
- * The event mask here is what is currently in the MIT implementation.
- * There really needs to be a way to get the value of the mask out
- * of the toolkit (CDP 5/26/89).
- */
- XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask | ButtonReleaseMask,
- smw->simple_menu.cursor,
- XtLastTimestampProcessed(XtDisplay(w)));
-}
-
-/*
- * Function:
- * MakeSetValuesRequest
- *
- * Parameters:
- * w - simple menu widget
- * width - size requested
- * height - ""
- */
-static void
-MakeSetValuesRequest(Widget w, unsigned int width, unsigned int height)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
- Arg arglist[2];
- Cardinal num_args = 0;
-
- if (!smw->simple_menu.recursive_set_values) {
- if (XtWidth(smw) != width || XtHeight(smw) != height) {
- smw->simple_menu.recursive_set_values = True;
- XtSetArg(arglist[num_args], XtNwidth, width); num_args++;
- XtSetArg(arglist[num_args], XtNheight, height); num_args++;
- XtSetValues(w, arglist, num_args);
- }
- else if (XtIsRealized((Widget)smw))
- XawSimpleMenuRedisplay((Widget)smw, NULL, NULL);
- }
- smw->simple_menu.recursive_set_values = False;
-}
-
-static SmeObject
-DoGetEventEntry(Widget w, int x_loc, int y_loc)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
- SmeObject *entry;
-
- ForAllChildren(smw, entry) {
- if (!XtIsManaged((Widget)*entry))
- continue;
-
- if (x_loc > XtX(*entry)
- && x_loc <= XtX(*entry) + XtWidth(*entry)
- && y_loc > XtY(*entry)
- && y_loc <= XtY(*entry) + XtHeight(*entry)) {
- if (*entry == smw->simple_menu.label)
- return (NULL); /* cannot select the label */
- else
- return (*entry);
- }
- }
-
- return (NULL);
-}
-
-/*
- * Function:
- * GetEventEntry
- *
- * Parameters:
- * w - simple menu widget
- * event - X event
- *
- * Description:
- * Gets an entry given an event that has X and Y coords.
- *
- * Returns:
- * The entry that this point is in
- */
-static SmeObject
-GetEventEntry(Widget w, XEvent *event)
-{
- int x_loc, y_loc, x_root;
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
- SmeObject entry;
- int warp, move;
-
- switch (event->type) {
- case MotionNotify:
- x_loc = event->xmotion.x;
- y_loc = event->xmotion.y;
- x_root = event->xmotion.x_root;
- break;
- case EnterNotify:
- case LeaveNotify:
- x_loc = event->xcrossing.x;
- y_loc = event->xcrossing.y;
- x_root = event->xcrossing.x_root;
- break;
- case ButtonPress:
- case ButtonRelease:
- x_loc = event->xbutton.x;
- y_loc = event->xbutton.y;
- x_root = event->xbutton.x_root;
- break;
- default:
- XtAppError(XtWidgetToApplicationContext(w),
- "Unknown event type in GetEventEntry().");
- return (NULL);
- }
-
- if (x_loc < 0 || x_loc >= XtWidth(smw) ||
- y_loc < 0 || y_loc >= XtHeight(smw))
- return (NULL);
-
- /* Move the menu if it's outside the screen, does not check
- * smw->simple_menu.menu_on_screen because menus is bigger than screen
- */
- if (x_root == WidthOfScreen(XtScreen(w)) - 1 &&
- XtX(w) + XtWidth(w) + (XtBorderWidth(w)) > x_root) {
- warp = -8;
- if (smw->simple_menu.entry_set) {
- entry = DoGetEventEntry(w,
- XtX(smw->simple_menu.entry_set)
- + XtWidth(smw->simple_menu.entry_set) + 1,
- y_loc);
- Unhighlight(w, event, NULL, NULL);
- if (entry) {
- warp = -(int)XtWidth(entry) >> 1;
- move = x_loc - XtWidth(entry) - XtX(entry) + XtBorderWidth(w);
- }
- else {
- warp = 0;
- move = WidthOfScreen(XtScreen(w)) -
- (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1));
- }
- }
- else {
- warp = 0;
- move = WidthOfScreen(XtScreen(w)) -
- (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1));
- }
- }
- else if (x_root == 0 && XtX(w) < 0) {
- warp = 8;
- if (smw->simple_menu.entry_set) {
- entry = DoGetEventEntry(w, XtX(smw->simple_menu.entry_set) - 1,
- y_loc);
- Unhighlight(w, event, NULL, NULL);
- if (entry) {
- warp = XtWidth(entry) >> 1;
- move = x_loc - XtX(entry);
- }
- else
- move = x_loc + XtBorderWidth(w);
- }
- else
- move = x_loc + XtBorderWidth(w);
- }
- else
- move = warp = 0;
-
- if (move)
- XtMoveWidget(w, XtX(w) + move, XtY(w));
- if (warp)
- XWarpPointer(XtDisplay(w), None, None, 0, 0, 0, 0, warp, 0);
-
- return (DoGetEventEntry(w, x_loc, y_loc));
-}
-
-static void
-CalculateNewSize(Widget w, Dimension *width_return, Dimension *height_return)
-{
- SimpleMenuWidget xaw = (SimpleMenuWidget)w;
- Widget kid;
- Cardinal i;
- int width_kid, height_kid;
- int width, height, tmp_w, tmp_h, max_dim;
- short vadd, hadd;
- int n, columns, test_h, num_children = 0;
- Boolean try_layout = False;
-
-#ifndef OLDXAW
- hadd = xaw->simple_menu.left_margin + xaw->simple_menu.right_margin;
-#else
- hadd = 0;
-#endif
- vadd = xaw->simple_menu.top_margin + xaw->simple_menu.bottom_margin;
- if (xaw->simple_menu.label)
- vadd += XtHeight(xaw->simple_menu.label);
-
- if (*height_return)
- max_dim = *height_return;
- else if (!XtHeight(w)) {
- max_dim = HeightOfScreen(XtScreen(w));
- try_layout = True;
- }
- else
- max_dim = XtHeight(w);
- max_dim -= vadd;
-
- width = height = tmp_w = tmp_h = n = test_h = 0;
- columns = 1;
- for (i = xaw->simple_menu.label ? 1 : 0;
- i < xaw->composite.num_children;
- i++) {
- kid = xaw->composite.children[i];
- if (!XtIsManaged(kid))
- continue;
- ++num_children;
- width_kid = XtWidth(kid);
- height_kid = XtHeight(kid);
-
- if (try_layout) {
- if (!test_h)
- test_h = height_kid;
- else if (test_h != height_kid)
- try_layout = False;
- }
-
- if (n && (height + height_kid > max_dim)) {
- ++columns;
- width += tmp_w;
- tmp_w = width_kid;
- height = height_kid;
- }
- else
- height += height_kid;
- if (height > tmp_h)
- tmp_h = height;
- if (width_kid > tmp_w)
- tmp_w = width_kid;
- ++n;
- }
-
- height = tmp_h + vadd;
- width += tmp_w + hadd;
-
- if (xaw->simple_menu.label)
- width = XawMax(width, XtWidth(xaw->simple_menu.label) + hadd);
-
- *width_return = width;
- *height_return = height;
-
- if (try_layout && columns > 1 && num_children > 2) {
- int space;
-
- height = test_h * (xaw->simple_menu.label ?
- num_children - 1 :
- num_children);
-
- max_dim -= max_dim % test_h;
- space = max_dim - (height % max_dim);
- if (space >= test_h * columns) {
- height = max_dim - space / columns;
- if (height % test_h)
- height += test_h - (height % test_h);
- *height_return = height + vadd;
- CalculateNewSize(w, width_return, height_return);
- }
- }
-}
-
-static void
-MakeResizeRequest(Widget w)
-{
- int tries;
- Dimension width, height;
-
- width = XtWidth(w);
- height = XtHeight(w);
-
- for (tries = 0; tries < 100; tries++) {
- CalculateNewSize(w, &width, &height);
- if (width == XtWidth(w) && height == XtHeight(w))
- break;
- if (XtMakeResizeRequest(w, width, height, &width, &height) ==
- XtGeometryNo)
- break;
- }
-}
-
-#ifndef OLDXAW
-static void
-Popdown(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
-
- while (XtParent(w) &&
- XtIsSubclass(XtParent(w), simpleMenuWidgetClass)) {
- if (((SimpleMenuWidget)XtParent(w))->simple_menu.sub_menu == (Widget)w) {
- w = XtParent(w);
- smw = (SimpleMenuWidget)w;
- smw->simple_menu.entry_set = NULL;
- }
- else
- break;
- }
-
- smw->simple_menu.state |= SMW_UNMAPPING;
- if (smw->simple_menu.sub_menu)
- PopdownSubMenu(smw);
- XtCallActionProc(w, "XtMenuPopdown", event, params, *num_params);
-}
-
-static void
-PopupSubMenu(SimpleMenuWidget smw)
-{
- Arg args[2];
- Cardinal num_args;
- Widget menu;
- SmeBSBObject entry = (SmeBSBObject)smw->simple_menu.entry_set;
- Position menu_x, menu_y;
- Bool popleft;
-
- if (entry->sme_bsb.menu_name == NULL)
- return;
-
- if ((menu = FindMenu((Widget)smw, entry->sme_bsb.menu_name)) == NULL)
- return;
-
- smw->simple_menu.sub_menu = menu;
-
- if (!XtIsRealized(menu))
- XtRealizeWidget(menu);
-
- popleft = (smw->simple_menu.state & SMW_POPLEFT) != 0;
-
- if (popleft)
- XtTranslateCoords((Widget)smw, -(int)XtWidth(menu),
- XtY(entry) - XtBorderWidth(menu), &menu_x, &menu_y);
- else
- XtTranslateCoords((Widget)smw, XtWidth(smw), XtY(entry)
- - XtBorderWidth(menu), &menu_x, &menu_y);
-
- if (!popleft && menu_x >= 0) {
- int scr_width = WidthOfScreen(XtScreen(menu));
-
- if (menu_x + XtWidth(menu) > scr_width) {
- menu_x -= XtWidth(menu) + XtWidth(smw);
- popleft = True;
- }
- }
- else if (popleft && menu_x < 0) {
- menu_x = 0;
- popleft = False;
- }
- if (menu_y >= 0) {
- int scr_height = HeightOfScreen(XtScreen(menu));
-
- if (menu_y + XtHeight(menu) > scr_height)
- menu_y = scr_height - XtHeight(menu) - XtBorderWidth(menu);
- }
- if (menu_y < 0)
- menu_y = 0;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNx, menu_x); num_args++;
- XtSetArg(args[num_args], XtNy, menu_y); num_args++;
- XtSetValues(menu, args, num_args);
-
- if (popleft)
- ((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT;
- else
- ((SimpleMenuWidget)menu)->simple_menu.state &= ~SMW_POPLEFT;
-
- XtPopup(menu, XtGrabNone);
-}
-
-static void
-PopdownSubMenu(SimpleMenuWidget smw)
-{
- SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu;
-
- if (!menu)
- return;
-
- menu->simple_menu.state |= SMW_UNMAPPING;
- PopdownSubMenu(menu);
-
- XtPopdown((Widget)menu);
-
- smw->simple_menu.sub_menu = NULL;
-}
-
-/*ARGSUSED*/
-static void
-PopupCB(Widget w, XtPointer client_data, XtPointer call_data)
-{
- SimpleMenuWidget smw = (SimpleMenuWidget)w;
-
- smw->simple_menu.state &= ~(SMW_UNMAPPING | SMW_POPLEFT);
-}
-#endif /* OLDXAW */
+/* +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ + +/* + * SimpleMenu.c - Source code file for SimpleMenu widget. + * + * Date: April 3, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Initer.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/SimpleMenP.h> +#include <X11/Xaw/SmeBSBP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define streq(a, b) (strcmp((a), (b)) == 0) + +#define ForAllChildren(smw, childP) \ +for ((childP) = (SmeObject *)(smw)->composite.children; \ + (childP) < (SmeObject *)((smw)->composite.children \ + + (smw)->composite.num_children); \ + (childP)++) + +#ifndef OLDXAW +#define SMW_UNMAPPING 0x01 +#define SMW_POPLEFT 0x02 +#endif + +/* + * Class Methods + */ +static void XawSimpleMenuChangeManaged(Widget); +static void XawSimpleMenuClassInitialize(void); +static void XawSimpleMenuClassPartInitialize(WidgetClass); +static XtGeometryResult XawSimpleMenuGeometryManager(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawSimpleMenuInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawSimpleMenuRealize(Widget, XtValueMask*, XSetWindowAttributes*); +static void XawSimpleMenuRedisplay(Widget, XEvent*, Region); +static void XawSimpleMenuResize(Widget); +static Boolean XawSimpleMenuSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static Boolean XawSimpleMenuSetValuesHook(Widget, ArgList, Cardinal*); +#ifndef OLDXAW +static void PopupSubMenu(SimpleMenuWidget); +static void PopdownSubMenu(SimpleMenuWidget); +static void PopupCB(Widget, XtPointer, XtPointer); +#endif + +/* + * Prototypes + */ +static void AddPositionAction(XtAppContext, XPointer); +static void CalculateNewSize(Widget, Dimension*, Dimension*); +static void ChangeCursorOnGrab(Widget, XtPointer, XtPointer); +static void CreateLabel(Widget); +static SmeObject DoGetEventEntry(Widget, int, int); +static Widget FindMenu(Widget, String); +static SmeObject GetEventEntry(Widget, XEvent*); +static void Layout(Widget, Dimension*, Dimension*); +static void MakeResizeRequest(Widget); +static void MakeSetValuesRequest(Widget, unsigned int, unsigned int); +static void MoveMenu(Widget, int, int); +static void PositionMenu(Widget, XPoint*); + +/* + * Actions + */ +static void Highlight(Widget, XEvent*, String*, Cardinal*); +static void Notify(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void Popdown(Widget, XEvent*, String*, Cardinal*); +#endif +static void PositionMenuAction(Widget, XEvent*, String*, Cardinal*); +static void Unhighlight(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(SimpleMenuRec, simple_menu.field) + +static XtResource resources[] = { + /* label */ + { + XtNlabel, + XtCLabel, + XtRString, + sizeof(String), + offset(label_string), + XtRString, + NULL + }, + { + XtNlabelClass, + XtCLabelClass, + XtRPointer, + sizeof(WidgetClass), + offset(label_class), + XtRImmediate, + NULL + }, + + /* layout */ + { + XtNrowHeight, + XtCRowHeight, + XtRDimension, + sizeof(Dimension), + offset(row_height), + XtRImmediate, + (XtPointer)0 + }, + { + XtNtopMargin, + XtCVerticalMargins, + XtRDimension, + sizeof(Dimension), + offset(top_margin), + XtRImmediate, + (XtPointer)0 + }, + { + XtNbottomMargin, + XtCVerticalMargins, + XtRDimension, + sizeof(Dimension), + offset(bottom_margin), + XtRImmediate, + (XtPointer)0 + }, +#ifndef OLDXAW + { + XtNleftMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(left_margin), + XtRImmediate, + (XtPointer)0 + }, + { + XtNrightMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(right_margin), + XtRImmediate, + (XtPointer)0 + }, +#endif + + /* misc */ + { + XtNallowShellResize, + XtCAllowShellResize, + XtRBoolean, + sizeof(Boolean), + XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize), + XtRImmediate, + (XtPointer)True + }, + { + XtNcursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(cursor), + XtRImmediate, + (XtPointer)None + }, + { + XtNmenuOnScreen, + XtCMenuOnScreen, + XtRBoolean, + sizeof(Boolean), + offset(menu_on_screen), + XtRImmediate, + (XtPointer)True + }, + { + XtNpopupOnEntry, + XtCPopupOnEntry, + XtRWidget, + sizeof(Widget), + offset(popup_entry), + XtRWidget, + NULL + }, + { + XtNbackingStore, + XtCBackingStore, + XtRBackingStore, + sizeof(int), + offset(backing_store), + XtRImmediate, + (XtPointer)(Always + WhenMapped + NotUseful) + }, +#ifndef OLDXAW + { + XawNdisplayList, + XawCDisplayList, + XawRDisplayList, + sizeof(XawDisplayList*), + offset(display_list), + XtRImmediate, + NULL + }, +#endif +}; +#undef offset + +static char defaultTranslations[] = +"<Enter>:" "highlight()\n" +"<Leave>:" "unhighlight()\n" +"<BtnMotion>:" "highlight()\n" +#ifndef OLDXAW +"<BtnUp>:" "popdown() notify() unhighlight()\n" +#else +"<BtnUp>:" "MenuPopdown() notify() unhighlight()\n" +#endif +; + +static XtActionsRec actionsList[] = +{ + {"notify", Notify}, + {"highlight", Highlight}, + {"unhighlight", Unhighlight}, +#ifndef OLDXAW + {"popdown", Popdown}, + {"set-values", XawSetValuesAction}, + {"get-values", XawGetValuesAction}, + {"declare", XawDeclareAction}, + {"call-proc", XawCallProcAction}, +#endif +}; + +static CompositeClassExtensionRec extension_rec = { + NULL, /* next_extension */ + NULLQUARK, /* record_type */ + XtCompositeExtensionVersion, /* version */ + sizeof(CompositeClassExtensionRec), /* record_size */ + True, /* accepts_objects */ +}; + +#define Superclass (&overrideShellClassRec) +SimpleMenuClassRec simpleMenuClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "SimpleMenu", /* class_name */ + sizeof(SimpleMenuRec), /* size */ + XawSimpleMenuClassInitialize, /* class_initialize */ + XawSimpleMenuClassPartInitialize, /* class_part_initialize */ + False, /* class_inited */ + XawSimpleMenuInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawSimpleMenuRealize, /* realize */ + actionsList, /* actions */ + XtNumber(actionsList), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XawSimpleMenuResize, /* resize */ + XawSimpleMenuRedisplay, /* expose */ + XawSimpleMenuSetValues, /* set_values */ + XawSimpleMenuSetValuesHook, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* intrinsics version */ + NULL, /* callback offsets */ + defaultTranslations, /* tm_table */ + NULL, /* query_geometry */ + NULL, /* display_accelerator */ + NULL, /* extension */ + }, + /* composite */ + { + XawSimpleMenuGeometryManager, /* geometry_manager */ + XawSimpleMenuChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + /* shell */ + { + NULL, /* extension */ + }, + /* override */ + { + NULL, /* extension */ + }, + /* simple_menu */ + { + NULL, /* extension */ + }, +}; + +WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec; + +/* + * Implementation + */ +/* + * Function: + * XawSimpleMenuClassInitialize + * + * Description: + * Class Initialize routine, called only once. + */ +static void +XawSimpleMenuClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore, + NULL, 0); + XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString, + NULL, 0, XtCacheNone, NULL); + XmuAddInitializer(AddPositionAction, NULL); +} + +/* + * Function: + * XawSimpleMenuClassPartInitialize + * Arguments: wc - the widget class of the subclass. + * + * Description: + * Class Part Initialize routine, called for every subclass. Makes + * sure that the subclasses pick up the extension record. + */ +static void +XawSimpleMenuClassPartInitialize(WidgetClass wc) +{ + SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass)wc; + + /* + * Make sure that our subclass gets the extension rec too + */ + extension_rec.next_extension = smwc->composite_class.extension; + smwc->composite_class.extension = (XtPointer) &extension_rec; +} + +/* + * Function: + * XawSimpleMenuInitialize + * + * Parameters: + * request - widget requested by the argument list + * cnew - new widget with both resource and non resource values + * + * Description: + * Initializes the simple menu widget. + */ +/*ARGSUSED*/ +static void +XawSimpleMenuInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)cnew; + Dimension width, height; + + XmuCallInitializers(XtWidgetToApplicationContext(cnew)); + + if (smw->simple_menu.label_class == NULL) + smw->simple_menu.label_class = smeBSBObjectClass; + + smw->simple_menu.label = NULL; + smw->simple_menu.entry_set = NULL; + smw->simple_menu.recursive_set_values = False; +#ifndef OLDXAW + smw->simple_menu.sub_menu = NULL; + smw->simple_menu.state = 0; + + XtAddCallback(cnew, XtNpopupCallback, PopupCB, NULL); +#endif + + if (smw->simple_menu.label_string != NULL) + CreateLabel(cnew); + + width = height = 0; + CalculateNewSize(cnew, &width, &height); + + smw->simple_menu.menu_width = True; + + if (XtWidth(smw) == 0) { + smw->simple_menu.menu_width = False; + XtWidth(smw) = width; + } + + smw->simple_menu.menu_height = True; + + if (XtHeight(smw) == 0) { + smw->simple_menu.menu_height = False; + XtHeight(smw) = height; + } + + /* + * Add a popup_callback routine for changing the cursor + */ + XtAddCallback(cnew, XtNpopupCallback, ChangeCursorOnGrab, NULL); +} + +/* + * Function: + * XawSimpleMenuRedisplay + * + * Parameters: + * w - simple menu widget + * event - X event that caused this redisplay + * region - region the needs to be repainted + * + * Description: + * Redisplays the contents of the widget. + */ +/*ARGSUSED*/ +static void +XawSimpleMenuRedisplay(Widget w, XEvent *event, Region region) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject *entry; + SmeObjectClass cclass; + + if (region == NULL) + XClearWindow(XtDisplay(w), XtWindow(w)); + +#ifndef OLDXAW + if (smw->simple_menu.display_list) + XawRunDisplayList(w, smw->simple_menu.display_list, event, region); +#endif + + /* + * Check and Paint each of the entries - including the label + */ + ForAllChildren(smw, entry) { + if (!XtIsManaged((Widget)*entry)) + continue; + + if (region != NULL) + switch(XRectInRegion(region, XtX(*entry),XtY(*entry), + XtWidth(*entry), XtHeight(*entry))) { + case RectangleIn: + case RectanglePart: + break; + default: + continue; + } + + cclass = (SmeObjectClass)(*entry)->object.widget_class; + + if (cclass->rect_class.expose != NULL) + (cclass->rect_class.expose)((Widget)*entry, NULL, NULL); + } +} + +/* + * Function: + * XawSimpleMenuRealize + * + * Parameters: + * w - simple menu widget + * mask - value mask for the window to create + * attrs - attributes for the window to create + * + * Description: + * Realizes the widget. + */ +static void +XawSimpleMenuRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attrs) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; +#ifndef OLDXAW + XawPixmap *pixmap; +#endif + + attrs->cursor = smw->simple_menu.cursor; + *mask |= CWCursor; + if (smw->simple_menu.backing_store == Always || + smw->simple_menu.backing_store == NotUseful || + smw->simple_menu.backing_store == WhenMapped) { + *mask |= CWBackingStore; + attrs->backing_store = smw->simple_menu.backing_store; + } + else + *mask &= ~CWBackingStore; + + (*Superclass->core_class.realize)(w, mask, attrs); + +#ifndef OLDXAW + if (w->core.background_pixmap > XtUnspecifiedPixmap) { + pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w), + w->core.colormap, w->core.depth); + if (pixmap && pixmap->mask) + XawReshapeWidget(w, pixmap); + } +#endif +} + +/* + * Function: + * XawSimpleMenuResize + * + * Parameters: + * w - simple menu widget + * + * Description: + * Handle the menu being resized. + */ +static void +XawSimpleMenuResize(Widget w) +{ + if (!XtIsRealized(w)) + return; + + Layout(w, NULL, NULL); + + XawSimpleMenuRedisplay(w, NULL, NULL); +} + +/* + * Function: + * XawSimpleMenuSetValues + * + * Parameters: + * current - current state of the widget + * request - what was requested + * cnew - what the widget will become + * + * Description: + * Relayout the menu when one of the resources is changed. + */ +/*ARGSUSED*/ +static Boolean +XawSimpleMenuSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SimpleMenuWidget smw_old = (SimpleMenuWidget)current; + SimpleMenuWidget smw_new = (SimpleMenuWidget)cnew; + Boolean ret_val = False, layout = False; + + if (!XtIsRealized(current)) + return (False); + + if (!smw_new->simple_menu.recursive_set_values) { + if (XtWidth(smw_new) != XtWidth(smw_old)) { + smw_new->simple_menu.menu_width = XtWidth(smw_new) != 0; + layout = True; + } + if (XtHeight(smw_new) != XtHeight(smw_old)) { + smw_new->simple_menu.menu_height = XtHeight(smw_new) != 0; + layout = True; + } + } + + if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor) + XDefineCursor(XtDisplay(cnew), XtWindow(cnew), + smw_new->simple_menu.cursor); + + if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) { + if (smw_new->simple_menu.label_string == NULL) /* Destroy */ + XtDestroyWidget((Widget)smw_old->simple_menu.label); + else if (smw_old->simple_menu.label_string == NULL) /* Create */ + CreateLabel(cnew); + else { /* Change */ + Arg arglist[1]; + + XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string); + XtSetValues((Widget)smw_new->simple_menu.label, arglist, ONE); + } + } + + if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class) + XtAppWarning(XtWidgetToApplicationContext(cnew), + "No Dynamic class change of the SimpleMenu Label."); + + if (smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin + || smw_old->simple_menu.bottom_margin + != smw_new->simple_menu.bottom_margin) { + layout = True; + ret_val = True; + } + +#ifndef OLDXAW + if (smw_old->core.background_pixmap != smw_new->core.background_pixmap) { + XawPixmap *opix, *npix; + + opix = XawPixmapFromXPixmap(smw_old->core.background_pixmap, + XtScreen(smw_old), smw_old->core.colormap, + smw_old->core.depth); + npix = XawPixmapFromXPixmap(smw_new->core.background_pixmap, + XtScreen(smw_new), smw_new->core.colormap, + smw_new->core.depth); + if ((npix && npix->mask) || (opix && opix->mask)) + XawReshapeWidget(cnew, npix); + } +#endif + + if (layout) + Layout(cnew, NULL, NULL); + + return (ret_val); +} + +/* + * Function: + * XawSimpleMenuSetValuesHook + * + * Parameters: + * w - menu widget + * arglist - argument list passed to XtSetValues + * num_args - number of args + * + * Description: + * To handle a special case, this is passed the actual arguments. + */ +static Boolean +XawSimpleMenuSetValuesHook(Widget w, ArgList arglist, Cardinal *num_args) +{ + Cardinal i; + Dimension width, height; + + width = XtWidth(w); + height = XtHeight(w); + + for (i = 0 ; i < *num_args ; i++) { + if (streq(arglist[i].name, XtNwidth)) + width = (Dimension)arglist[i].value; + if (streq(arglist[i].name, XtNheight)) + height = (Dimension) arglist[i].value; + } + + if (width != XtWidth(w) || height != XtHeight(w)) + MakeSetValuesRequest(w, width, height); + + return (False); +} + +/* + * Geometry Management routines + */ +/* + * Function: + * XawSimpleMenuGeometryManager + * + * Parameters: + * w - Menu Entry making the request + * request - requested new geometry + * reply - the allowed geometry. + * + * Description: + * This is the SimpleMenu Widget's Geometry Manager. + * + * Returns: + * XtGeometry{Yes, No, Almost} + */ +static XtGeometryResult +XawSimpleMenuGeometryManager(Widget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)XtParent(w); + SmeObject entry = (SmeObject)w; + XtGeometryMask mode = request->request_mode; + XtGeometryResult answer; + Dimension old_height, old_width; + + if (!(mode & CWWidth) && !(mode & CWHeight)) + return (XtGeometryNo); + + reply->width = request->width; + reply->height = request->height; + + old_width = XtWidth(entry); + old_height = XtHeight(entry); + + Layout(w, &reply->width, &reply->height); + + /* + * Since we are an override shell and have no parent there is no one to + * ask to see if this geom change is okay, so I am just going to assume + * we can do whatever we want. If you subclass be very careful with this + * assumption, it could bite you. + * + * Chris D. Peterson - Sept. 1989. + */ + if ((!(mode & CWWidth) || reply->width == request->width) + && (!(mode & CWHeight) || reply->height == request->height)) { + if (mode & XtCWQueryOnly) { /* Actually perform the layout */ + XtWidth(entry) = old_width; + XtHeight(entry) = old_height; + } + else + Layout((Widget)smw, NULL, NULL); + answer = XtGeometryDone; + } + else { + XtWidth(entry) = old_width; + XtHeight(entry) = old_height; + + if ((reply->width == request->width && !(mode & CWHeight)) + || (reply->height == request->height && !(mode & CWWidth)) + || (reply->width == request->width + && reply->height == request->height)) + answer = XtGeometryNo; + else { + answer = XtGeometryAlmost; + reply->request_mode = 0; + if (reply->width != request->width) + reply->request_mode |= CWWidth; + if (reply->height != request->height) + reply->request_mode |= CWHeight; + } + } + + return (answer); +} + +/* + * Function: + * XawSimpleMenuChangeManaged + * + * Parameters: + * w - simple menu widget + * + * Description: + * Called whenever a new child is managed. + */ +static void +XawSimpleMenuChangeManaged(Widget w) +{ + Layout(w, NULL, NULL); +} + +/* + * Global Action Routines + * + * These actions routines will be added to the application's + * global action list + */ +/* + * Function: + * PositionMenuAction + * + * Parameters: + * w - a widget (no the simple menu widget) + * event - the event that caused this action + * params - parameters passed to the routine. + * we expect the name of the menu here. + * num_params - "" + * + * Description: + * Positions the simple menu widget. + */ +/*ARGSUSED*/ +static void +PositionMenuAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + Widget menu; + XPoint loc; + + if (*num_params != 1) { + XtAppWarning(XtWidgetToApplicationContext(w), + "SimpleMenuWidget: position menu action expects " + "only one parameter which is the name of the menu."); + return; + } + + if ((menu = FindMenu(w, params[0])) == NULL) { + char error_buf[BUFSIZ]; + + (void)XmuSnprintf(error_buf, sizeof(error_buf), + "SimpleMenuWidget: could not find menu named %s.", + params[0]); + XtAppWarning(XtWidgetToApplicationContext(w), error_buf); + return; + } + + switch (event->type) { + case ButtonPress: + case ButtonRelease: + loc.x = event->xbutton.x_root; + loc.y = event->xbutton.y_root; + PositionMenu(menu, &loc); + break; + case EnterNotify: + case LeaveNotify: + loc.x = event->xcrossing.x_root; + loc.y = event->xcrossing.y_root; + PositionMenu(menu, &loc); + break; + case MotionNotify: + loc.x = event->xmotion.x_root; + loc.y = event->xmotion.y_root; + PositionMenu(menu, &loc); + break; + default: + PositionMenu(menu, NULL); + break; + } +} + +/* + * Widget Action Routines + */ +/* + * Function: + * Unhighlight + * + * Parameters: + * w - simple menu widget + * event - event that caused this action + * params - not used + * num_params - "" + * + * Description: + * Unhighlights current entry. + */ +/*ARGSUSED*/ +static void +Unhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject entry = smw->simple_menu.entry_set; + + if (entry == NULL) + return; + +#ifndef OLDXAW + if (!smw->simple_menu.sub_menu) +#endif + { + SmeObjectClass cclass; + + smw->simple_menu.entry_set = NULL; + cclass = (SmeObjectClass)entry->object.widget_class; + (cclass->sme_class.unhighlight)((Widget)entry); + } +} + +/* + * Function: + * Highlight + * + * Parameters: + * w - simple menu widget + * event - event that caused this action + * params - not used + * num_params - "" + * + * Description: + * Highlights current entry. + */ +/*ARGSUSED*/ +static void +Highlight(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject entry; + + if (!XtIsSensitive(w)) + return; + + entry = GetEventEntry(w, event); + + if (entry == smw->simple_menu.entry_set) + return; + +#ifndef OLDXAW + if (!smw->simple_menu.sub_menu) +#endif + Unhighlight(w, event, params, num_params); + + if (entry == NULL) + return; + + if (!XtIsSensitive((Widget)entry)) + return; + +#ifndef OLDXAW + if (smw->simple_menu.sub_menu) + PopdownSubMenu(smw); +#endif + + Unhighlight(w, event, params, num_params); + +#ifndef OLDXAW + if (!(smw->simple_menu.state & SMW_UNMAPPING)) +#endif + { + SmeObjectClass cclass; + + smw->simple_menu.entry_set = entry; + cclass = (SmeObjectClass)entry->object.widget_class; + + (cclass->sme_class.highlight)((Widget)entry); + +#ifndef OLDXAW + if (XtIsSubclass((Widget)entry, smeBSBObjectClass)) + PopupSubMenu(smw); +#endif + } +} + +/* + * Function: + * Notify + * + * Parameters: + * w - simple menu widget + * event - event that caused this action + * params - not used + * num_params - "" + * + * Description: + * Notify user of current entry. + */ +/*ARGSUSED*/ +static void +Notify(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + SmeObject entry; + SmeObjectClass cclass; + + /* may be a propagated event from a sub menu, need to check it */ + if (XtWindow(w) != event->xany.window) + return; + entry = GetEventEntry(w, event); + if (entry == NULL || !XtIsSensitive((Widget)entry)) + return; + + cclass = (SmeObjectClass) entry->object.widget_class; + (cclass->sme_class.notify)((Widget)entry); +} + +/* + * Public Functions + */ +/* + * Function: + * XawSimpleMenuAddGlobalActions + * + * Arguments: + * app_con - appcontext + * + * Description: + * Adds the global actions to the simple menu widget. + */ +void +XawSimpleMenuAddGlobalActions(XtAppContext app_con) +{ + XtInitializeWidgetClass(simpleMenuWidgetClass); + XmuCallInitializers(app_con); +} + +/* + * Function: + * XawSimpleMenuGetActiveEntry + * + * Parameters: + * w - smw widget + * + * Description: + * Gets the currently active (set) entry. + * + * Returns: + * The currently set entry or NULL if none is set + */ +Widget +XawSimpleMenuGetActiveEntry(Widget w) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + + return ((Widget)smw->simple_menu.entry_set); +} + +/* + * Function: + * XawSimpleMenuClearActiveEntry + * + * Parameters: + * w - smw widget + * + * Description: + * Unsets the currently active (set) entry. + */ +void +XawSimpleMenuClearActiveEntry(Widget w) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + + smw->simple_menu.entry_set = NULL; +} + +/* + * Private Functions + */ +/* + * Function: + * CreateLabel + * + * Parameters: + * w - smw widget + * + * Description: + * Creates the label object and makes sure it is the first child in + * in the list. + */ +static void +CreateLabel(Widget w) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + Widget *child, *next_child; + int i; + Arg args[2]; + + if (smw->simple_menu.label_string == NULL || + smw->simple_menu.label != NULL) { + XtAppWarning(XtWidgetToApplicationContext(w), + "Xaw Simple Menu Widget: label string is NULL or " + "label already exists, no label is being created."); + return; + } + + XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string); + XtSetArg(args[1], XtNjustify, XtJustifyCenter); + smw->simple_menu.label = (SmeObject) + XtCreateManagedWidget("menuLabel", + smw->simple_menu.label_class, w, args, TWO); + + next_child = NULL; + for (child = smw->composite.children + smw->composite.num_children, + i = smw->composite.num_children; i > 0; i--, child--) { + if (next_child != NULL) + *next_child = *child; + next_child = child; + } + *child = (Widget)smw->simple_menu.label; +} + +/* + * Function: + * Layout + * + * Arguments: + * w - See below + * width_ret - returned width + * height_ret - returned height + * + * Note: + * if width == NULL || height == NULL then it assumes the you do not care + * about the return values, and just want a relayout. + * + * if this is not the case then it will set width_ret and height_ret + * to be width and height that the child would get if it were layed out + * at this time. + * + * "w" can be the simple menu widget or any of its object children. + */ +static void +Layout(Widget w, Dimension *width_ret, Dimension *height_ret) +{ + SmeObject current_entry; + SimpleMenuWidget smw; + Dimension width, height; + Boolean allow_change_size; + Widget kid; + Cardinal i, count, n; + int width_kid, height_kid, tmp_w, tmp_h; + short vadd, hadd, x_ins, y_ins; + Dimension *widths; + + height = 0; + + if (XtIsSubclass(w, simpleMenuWidgetClass)) { + smw = (SimpleMenuWidget)w; + current_entry = NULL; + } + else { + smw = (SimpleMenuWidget)XtParent(w); + current_entry = (SmeObject)w; + } + + allow_change_size = (!XtIsRealized((Widget)smw) + || smw->shell.allow_shell_resize); + + for (i = smw->simple_menu.label ? 1 : 0; + i < smw->composite.num_children; + i++) { + XtWidgetGeometry preferred; + + kid = smw->composite.children[i]; + if (!XtIsManaged(kid)) + continue; + if (smw->simple_menu.row_height != 0) + XtHeight(kid) = smw->simple_menu.row_height; + XtQueryGeometry(kid, NULL, &preferred); + if (preferred.request_mode & CWWidth) + XtWidth(kid) = preferred.width; + } + + if (smw->simple_menu.label + && XtIsManaged((Widget)smw->simple_menu.label)) { + XtWidgetGeometry preferred; + + kid = (Widget)smw->simple_menu.label; + XtQueryGeometry(kid, NULL, &preferred); + if (preferred.request_mode & CWWidth) + XtWidth(kid) = preferred.width; + if (preferred.request_mode & CWHeight) + XtHeight(kid) = preferred.height; + } + + /* reset */ + if (!smw->simple_menu.menu_width) + XtWidth(smw) = 0; + if (!smw->simple_menu.menu_height) + XtHeight(smw) = 0; + if (!XtWidth(smw) || !XtHeight(smw)) + MakeResizeRequest((Widget)smw); + + widths = (Dimension *)XtMalloc(sizeof(Dimension)); +#ifndef OLDXAW + hadd = smw->simple_menu.left_margin; +#else + hadd = 0; +#endif + vadd = smw->simple_menu.top_margin; + if (smw->simple_menu.label) + vadd += XtHeight(smw->simple_menu.label); + + count = 1; + width = tmp_w = tmp_h = n = 0; + height = vadd; + + for (i = smw->simple_menu.label ? 1 : 0; + i < smw->composite.num_children; + i++) { + kid = smw->composite.children[i]; + if (!XtIsManaged(kid)) + continue; + width_kid = XtWidth(kid); + height_kid = XtHeight(kid); + + if (n && (height + height_kid + smw->simple_menu.bottom_margin + > XtHeight(smw))) { + ++count; + widths = (Dimension *)XtRealloc((char *)widths, + sizeof(Dimension) * count); + widths[count - 1] = width_kid; + width += tmp_w; + tmp_w = width_kid; + height = height_kid + vadd; + } + else + height += height_kid; + if (height > tmp_h) + tmp_h = height; + if (width_kid > tmp_w) + widths[count - 1] = tmp_w = width_kid; + ++n; + } + + height = tmp_h + smw->simple_menu.bottom_margin; + width += tmp_w; + + if (smw->simple_menu.label && width < XtWidth(smw->simple_menu.label)) { + float inc; + + inc = (XtWidth(smw->simple_menu.label) - width) / (float)count; + width = XtWidth(smw->simple_menu.label); + for (n = 0; n < count; n++) + widths[n] += inc; + } + +#ifndef OLDXAW + width += hadd + smw->simple_menu.right_margin; +#endif + + x_ins = n = count = 0; + tmp_w = widths[0]; + tmp_h = vadd; + + for (i = smw->simple_menu.label ? 1 : 0; + i < smw->composite.num_children; + i++) { + kid = smw->composite.children[i]; + if (!XtIsManaged(kid)) + continue; + + height_kid = XtHeight(kid); + + if (n && (tmp_h + height_kid + smw->simple_menu.bottom_margin + > XtHeight(smw))) { + x_ins = tmp_w; + y_ins = vadd; + ++count; + tmp_w += widths[count]; + tmp_h = height_kid + vadd; + } + else { + y_ins = tmp_h; + tmp_h += height_kid; + } + ++n; + + XtX(kid) = x_ins + hadd; + XtY(kid) = y_ins; + XtWidth(kid) = widths[count]; + } + + XtFree((char *)widths); + + if (allow_change_size) + MakeSetValuesRequest((Widget) smw, width, height); + + if (smw->simple_menu.label) { + XtX(smw->simple_menu.label) = 0; + XtY(smw->simple_menu.label) = smw->simple_menu.top_margin; + XtWidth(smw->simple_menu.label) = XtWidth(smw) +#ifndef OLDXAW + - (smw->simple_menu.left_margin + smw->simple_menu.right_margin) +#endif + ; + } + if (current_entry) { + if (width_ret) + *width_ret = XtWidth(current_entry); + if (height_ret) + *height_ret = XtHeight(current_entry); + } +} + +/* + * Function: + * AddPositionAction + * + * Parameters: + * app_con - application context + * data - (not used) + * + * Description: + * Adds the XawPositionSimpleMenu action to the global + * action list for this appcon. + */ +/*ARGSUSED*/ +static void +AddPositionAction(XtAppContext app_con, XPointer data) +{ + static XtActionsRec pos_action[] = { + {"XawPositionSimpleMenu", PositionMenuAction}, + }; + + XtAppAddActions(app_con, pos_action, XtNumber(pos_action)); +} + +/* + * Function: + * FindMenu + * + * Parameters: + * widget - reference widget + * name - menu widget's name + * + * Description: + * Find the menu give a name and reference widget + * + * Returns: + * The menu widget or NULL. + */ +static Widget +FindMenu(Widget widget, String name) +{ + Widget w, menu; + + for (w = widget; w != NULL; w = XtParent(w)) + if ((menu = XtNameToWidget(w, name)) != NULL) + return (menu); + + return (NULL); +} + +/* + * Function: + * PositionMenu + * + * Parameters: + * w - simple menu widget + * location - pointer the the position or NULL + * + * Description: + * Places the menu + */ +static void +PositionMenu(Widget w, XPoint *location) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject entry; + XPoint t_point; + + if (location == NULL) { + Window temp1, temp2; + int root_x, root_y, tempX, tempY; + unsigned int tempM; + + location = &t_point; + if (XQueryPointer(XtDisplay(w), XtWindow(w), &temp1, &temp2, + &root_x, &root_y, &tempX, &tempY, &tempM) == False) { + XtAppWarning(XtWidgetToApplicationContext(w), + "Xaw Simple Menu Widget: " + "Could not find location of mouse pointer"); + return; + } + location->x = (short) root_x; + location->y = (short) root_y; + } + + /* + * The width will not be correct unless it is realized + */ + XtRealizeWidget(w); + + location->x -= XtWidth(w) >> 1; + + if (smw->simple_menu.popup_entry == NULL) + entry = smw->simple_menu.label; + else + entry = smw->simple_menu.popup_entry; + + if (entry != NULL) + location->y -= XtY(entry) + (XtHeight(entry) >> 1); + + MoveMenu(w, location->x, location->y); +} + +/* + * Function: + * MoveMenu + * + * Parameters: + * w - simple menu widget + * x - current location of the widget + * y - "" + * + * Description: + * Actually moves the menu, may force it to + * to be fully visable if menu_on_screen is True. + */ +static void +MoveMenu(Widget w, int x, int y) +{ + Arg arglist[2]; + Cardinal num_args = 0; + SimpleMenuWidget smw = (SimpleMenuWidget)w; + + if (smw->simple_menu.menu_on_screen) { + int width = XtWidth(w) + (XtBorderWidth(w) << 1); + int height = XtHeight(w) + (XtBorderWidth(w) << 1); + + if (x >= 0) { + int scr_width = WidthOfScreen(XtScreen(w)); + + if (x + width > scr_width) + x = scr_width - width; + } + if (x < 0) + x = 0; + + if (y >= 0) { + int scr_height = HeightOfScreen(XtScreen(w)); + + if (y + height > scr_height) + y = scr_height - height; + } + if (y < 0) + y = 0; + } + + XtSetArg(arglist[num_args], XtNx, x); num_args++; + XtSetArg(arglist[num_args], XtNy, y); num_args++; + XtSetValues(w, arglist, num_args); +} + +/* + * Function: + * ChangeCursorOnGrab + * + * Parameters: + * w - menu widget + * temp1 - not used + * temp2 - "" + * + * Description: + * Changes the cursor on the active grab to the one + * specified in out resource list. + */ +/*ARGSUSED*/ +static void +ChangeCursorOnGrab(Widget w, XtPointer temp1, XtPointer temp2) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + + /* + * The event mask here is what is currently in the MIT implementation. + * There really needs to be a way to get the value of the mask out + * of the toolkit (CDP 5/26/89). + */ + XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask | ButtonReleaseMask, + smw->simple_menu.cursor, + XtLastTimestampProcessed(XtDisplay(w))); +} + +/* + * Function: + * MakeSetValuesRequest + * + * Parameters: + * w - simple menu widget + * width - size requested + * height - "" + */ +static void +MakeSetValuesRequest(Widget w, unsigned int width, unsigned int height) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + Arg arglist[2]; + Cardinal num_args = 0; + + if (!smw->simple_menu.recursive_set_values) { + if (XtWidth(smw) != width || XtHeight(smw) != height) { + smw->simple_menu.recursive_set_values = True; + XtSetArg(arglist[num_args], XtNwidth, width); num_args++; + XtSetArg(arglist[num_args], XtNheight, height); num_args++; + XtSetValues(w, arglist, num_args); + } + else if (XtIsRealized((Widget)smw)) + XawSimpleMenuRedisplay((Widget)smw, NULL, NULL); + } + smw->simple_menu.recursive_set_values = False; +} + +static SmeObject +DoGetEventEntry(Widget w, int x_loc, int y_loc) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject *entry; + + ForAllChildren(smw, entry) { + if (!XtIsManaged((Widget)*entry)) + continue; + + if (x_loc > XtX(*entry) + && x_loc <= XtX(*entry) + XtWidth(*entry) + && y_loc > XtY(*entry) + && y_loc <= XtY(*entry) + XtHeight(*entry)) { + if (*entry == smw->simple_menu.label) + return (NULL); /* cannot select the label */ + else + return (*entry); + } + } + + return (NULL); +} + +/* + * Function: + * GetEventEntry + * + * Parameters: + * w - simple menu widget + * event - X event + * + * Description: + * Gets an entry given an event that has X and Y coords. + * + * Returns: + * The entry that this point is in + */ +static SmeObject +GetEventEntry(Widget w, XEvent *event) +{ + int x_loc, y_loc, x_root; + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject entry; + int warp, move; + + switch (event->type) { + case MotionNotify: + x_loc = event->xmotion.x; + y_loc = event->xmotion.y; + x_root = event->xmotion.x_root; + break; + case EnterNotify: + case LeaveNotify: + x_loc = event->xcrossing.x; + y_loc = event->xcrossing.y; + x_root = event->xcrossing.x_root; + break; + case ButtonPress: + case ButtonRelease: + x_loc = event->xbutton.x; + y_loc = event->xbutton.y; + x_root = event->xbutton.x_root; + break; + default: + XtAppError(XtWidgetToApplicationContext(w), + "Unknown event type in GetEventEntry()."); + return (NULL); + } + + if (x_loc < 0 || x_loc >= XtWidth(smw) || + y_loc < 0 || y_loc >= XtHeight(smw)) + return (NULL); + + /* Move the menu if it's outside the screen, does not check + * smw->simple_menu.menu_on_screen because menus is bigger than screen + */ + if (x_root == WidthOfScreen(XtScreen(w)) - 1 && + XtX(w) + XtWidth(w) + (XtBorderWidth(w)) > x_root) { + warp = -8; + if (smw->simple_menu.entry_set) { + entry = DoGetEventEntry(w, + XtX(smw->simple_menu.entry_set) + + XtWidth(smw->simple_menu.entry_set) + 1, + y_loc); + Unhighlight(w, event, NULL, NULL); + if (entry) { + warp = -(int)XtWidth(entry) >> 1; + move = x_loc - XtWidth(entry) - XtX(entry) + XtBorderWidth(w); + } + else { + warp = 0; + move = WidthOfScreen(XtScreen(w)) - + (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1)); + } + } + else { + warp = 0; + move = WidthOfScreen(XtScreen(w)) - + (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1)); + } + } + else if (x_root == 0 && XtX(w) < 0) { + warp = 8; + if (smw->simple_menu.entry_set) { + entry = DoGetEventEntry(w, XtX(smw->simple_menu.entry_set) - 1, + y_loc); + Unhighlight(w, event, NULL, NULL); + if (entry) { + warp = XtWidth(entry) >> 1; + move = x_loc - XtX(entry); + } + else + move = x_loc + XtBorderWidth(w); + } + else + move = x_loc + XtBorderWidth(w); + } + else + move = warp = 0; + + if (move) + XtMoveWidget(w, XtX(w) + move, XtY(w)); + if (warp) + XWarpPointer(XtDisplay(w), None, None, 0, 0, 0, 0, warp, 0); + + return (DoGetEventEntry(w, x_loc, y_loc)); +} + +static void +CalculateNewSize(Widget w, Dimension *width_return, Dimension *height_return) +{ + SimpleMenuWidget xaw = (SimpleMenuWidget)w; + Widget kid; + Cardinal i; + int width_kid, height_kid; + int width, height, tmp_w, tmp_h, max_dim; + short vadd, hadd; + int n, columns, test_h, num_children = 0; + Boolean try_layout = False; + +#ifndef OLDXAW + hadd = xaw->simple_menu.left_margin + xaw->simple_menu.right_margin; +#else + hadd = 0; +#endif + vadd = xaw->simple_menu.top_margin + xaw->simple_menu.bottom_margin; + if (xaw->simple_menu.label) + vadd += XtHeight(xaw->simple_menu.label); + + if (*height_return) + max_dim = *height_return; + else if (!XtHeight(w)) { + max_dim = HeightOfScreen(XtScreen(w)); + try_layout = True; + } + else + max_dim = XtHeight(w); + max_dim -= vadd; + + width = height = tmp_w = tmp_h = n = test_h = 0; + columns = 1; + for (i = xaw->simple_menu.label ? 1 : 0; + i < xaw->composite.num_children; + i++) { + kid = xaw->composite.children[i]; + if (!XtIsManaged(kid)) + continue; + ++num_children; + width_kid = XtWidth(kid); + height_kid = XtHeight(kid); + + if (try_layout) { + if (!test_h) + test_h = height_kid; + else if (test_h != height_kid) + try_layout = False; + } + + if (n && (height + height_kid > max_dim)) { + ++columns; + width += tmp_w; + tmp_w = width_kid; + height = height_kid; + } + else + height += height_kid; + if (height > tmp_h) + tmp_h = height; + if (width_kid > tmp_w) + tmp_w = width_kid; + ++n; + } + + height = tmp_h + vadd; + width += tmp_w + hadd; + + if (xaw->simple_menu.label) + width = XawMax(width, XtWidth(xaw->simple_menu.label) + hadd); + + *width_return = width; + *height_return = height; + + if (try_layout && columns > 1 && num_children > 2) { + int space; + + height = test_h * (xaw->simple_menu.label ? + num_children - 1 : + num_children); + + max_dim -= max_dim % test_h; + space = max_dim - (height % max_dim); + if (space >= test_h * columns) { + height = max_dim - space / columns; + if (height % test_h) + height += test_h - (height % test_h); + *height_return = height + vadd; + CalculateNewSize(w, width_return, height_return); + } + } +} + +static void +MakeResizeRequest(Widget w) +{ + int tries; + Dimension width, height; + + width = XtWidth(w); + height = XtHeight(w); + + for (tries = 0; tries < 100; tries++) { + CalculateNewSize(w, &width, &height); + if (width == XtWidth(w) && height == XtHeight(w)) + break; + if (XtMakeResizeRequest(w, width, height, &width, &height) == + XtGeometryNo) + break; + } +} + +#ifndef OLDXAW +static void +Popdown(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + + while (XtParent(w) && + XtIsSubclass(XtParent(w), simpleMenuWidgetClass)) { + if (((SimpleMenuWidget)XtParent(w))->simple_menu.sub_menu == (Widget)w) { + w = XtParent(w); + smw = (SimpleMenuWidget)w; + smw->simple_menu.entry_set = NULL; + } + else + break; + } + + smw->simple_menu.state |= SMW_UNMAPPING; + if (smw->simple_menu.sub_menu) + PopdownSubMenu(smw); + XtCallActionProc(w, "XtMenuPopdown", event, params, *num_params); +} + +static void +PopupSubMenu(SimpleMenuWidget smw) +{ + Arg args[2]; + Cardinal num_args; + Widget menu; + SmeBSBObject entry = (SmeBSBObject)smw->simple_menu.entry_set; + Position menu_x, menu_y; + Bool popleft; + + if (entry->sme_bsb.menu_name == NULL) + return; + + if ((menu = FindMenu((Widget)smw, entry->sme_bsb.menu_name)) == NULL) + return; + + smw->simple_menu.sub_menu = menu; + + if (!XtIsRealized(menu)) + XtRealizeWidget(menu); + + popleft = (smw->simple_menu.state & SMW_POPLEFT) != 0; + + if (popleft) + XtTranslateCoords((Widget)smw, -(int)XtWidth(menu), + XtY(entry) - XtBorderWidth(menu), &menu_x, &menu_y); + else + XtTranslateCoords((Widget)smw, XtWidth(smw), XtY(entry) + - XtBorderWidth(menu), &menu_x, &menu_y); + + if (!popleft && menu_x >= 0) { + int scr_width = WidthOfScreen(XtScreen(menu)); + + if (menu_x + XtWidth(menu) > scr_width) { + menu_x -= XtWidth(menu) + XtWidth(smw); + popleft = True; + } + } + else if (popleft && menu_x < 0) { + menu_x = 0; + popleft = False; + } + if (menu_y >= 0) { + int scr_height = HeightOfScreen(XtScreen(menu)); + + if (menu_y + XtHeight(menu) > scr_height) + menu_y = scr_height - XtHeight(menu) - XtBorderWidth(menu); + } + if (menu_y < 0) + menu_y = 0; + + num_args = 0; + XtSetArg(args[num_args], XtNx, menu_x); num_args++; + XtSetArg(args[num_args], XtNy, menu_y); num_args++; + XtSetValues(menu, args, num_args); + + if (popleft) + ((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT; + else + ((SimpleMenuWidget)menu)->simple_menu.state &= ~SMW_POPLEFT; + + XtPopup(menu, XtGrabNone); +} + +static void +PopdownSubMenu(SimpleMenuWidget smw) +{ + SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu; + + if (!menu) + return; + + menu->simple_menu.state |= SMW_UNMAPPING; + PopdownSubMenu(menu); + + XtPopdown((Widget)menu); + + smw->simple_menu.sub_menu = NULL; +} + +/*ARGSUSED*/ +static void +PopupCB(Widget w, XtPointer client_data, XtPointer call_data) +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + + smw->simple_menu.state &= ~(SMW_UNMAPPING | SMW_POPLEFT); +} +#endif /* OLDXAW */ diff --git a/libXaw/src/Sme.c b/libXaw/src/Sme.c index 462353b56..b01a81c6c 100644 --- a/libXaw/src/Sme.c +++ b/libXaw/src/Sme.c @@ -1,269 +1,269 @@ -/*
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- */
-
-/*
- * Date: September 26, 1989
- *
- * By: Chris D. Peterson
- * MIT X Consortium
- * kit@expo.lcs.mit.edu
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/SmeP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * Class Methods
- */
-static void Highlight(Widget);
-static void Notify(Widget);
-static void Unhighlight(Widget);
-static void XawSmeClassPartInitialize(WidgetClass);
-static void XawSmeInitialize(Widget, Widget, ArgList, Cardinal*);
-static XtGeometryResult XawSmeQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(SmeRec, sme.field)
-static XtResource resources[] = {
- {
- XtNcallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(callbacks),
- XtRCallback,
- NULL
- },
- {
- XtNinternational,
- XtCInternational,
- XtRBoolean,
- sizeof(Boolean),
- offset(international),
- XtRImmediate,
- (XtPointer)False
- },
-};
-#undef offset
-
-#define Superclass (&rectObjClassRec)
-SmeClassRec smeClassRec = {
- /* rectangle */
- {
- (WidgetClass)Superclass, /* superclass */
- "Sme", /* class_name */
- sizeof(SmeRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- XawSmeClassPartInitialize, /* class_part_initialize */
- False, /* class_initialized */
- XawSmeInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* compress_motion */
- False, /* compress_exposure */
- False, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- NULL, /* resize */
- NULL, /* expose */
- NULL, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* intrinsics_version */
- NULL, /* callback offsets */
- NULL, /* tm_table */
- XawSmeQueryGeometry, /* query_geometry */
- NULL, /* display_accelerator */
- NULL, /* extension */
- },
- /* sme */
- {
- Highlight, /* highlight */
- Unhighlight, /* unhighlight */
- Notify, /* notify */
- NULL, /* extension */
- }
-};
-
-WidgetClass smeObjectClass = (WidgetClass)&smeClassRec;
-
-/*
- * Implementation
- */
-/*
- * Function:
- * XawSmeClassPartInitialize
- *
- * Parameters:
- * cclass - widget classs of this widget
- *
- * Description:
- * Handles inheritance of class functions.
- */
-static void
-XawSmeClassPartInitialize(WidgetClass cclass)
-{
- SmeObjectClass m_ent, superC;
-
- m_ent = (SmeObjectClass)cclass;
- superC = (SmeObjectClass)m_ent->rect_class.superclass;
-
- if (m_ent->sme_class.highlight == XtInheritHighlight)
- m_ent->sme_class.highlight = superC->sme_class.highlight;
-
- if (m_ent->sme_class.unhighlight == XtInheritUnhighlight)
- m_ent->sme_class.unhighlight = superC->sme_class.unhighlight;
-
- if (m_ent->sme_class.notify == XtInheritNotify)
- m_ent->sme_class.notify = superC->sme_class.notify;
-}
-
-/*
- * Function:
- * XawSmeInitialize
- *
- * Parameters:
- * request - widget requested by the argument list
- * cnew - new widget with both resource and non resource values
- *
- * Description:
- * Initializes the simple menu widget entry
- */
-/*ARGSUSED*/
-static void
-XawSmeInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SmeObject entry = (SmeObject)cnew;
-
- entry->rectangle.border_width = 0;
-}
-
-/*
- * Function:
- * Highlight
- *
- * Parameters:
- * w - menu entry
- *
- * Description:
- * Default highlight proceedure for menu entries.
- */
-/*ARGSUSED*/
-static void
-Highlight(Widget w)
-{
-}
-
-/*
- * Function:
- * Unhighlight
- *
- * Parameters:
- * w - menu entry
- *
- * Description:
- * Default unhighlight proceedure for menu entries.
- */
-/*ARGSUSED*/
-static void
-Unhighlight(Widget w)
-{
-}
-
-/*
- * Function:
- * Notify
- *
- * Parameters:
- * w - menu entry
- *
- * Description:
- * Calls the callback proceedures for this entry.
- */
-static void
-Notify(Widget w)
-{
- XtCallCallbacks(w, XtNcallback, NULL);
-}
-
-/*
- * Function:
- * QueryGeometry
- *
- * Parameeters:
- * w - menu entry object
- * itended - intended and return geometry info
- * return_val -
- *
- * Description:
- * Returns the preferred geometry for this widget.
- *
- * Returns:
- * Geometry Result
- *
- * Note:
- * See the Intrinsics manual for details on what this function is for.
- */
-static XtGeometryResult
-XawSmeQueryGeometry(Widget w, XtWidgetGeometry *intended,
- XtWidgetGeometry *return_val)
-{
- SmeObject entry = (SmeObject)w;
- Dimension width;
- XtGeometryResult ret_val = XtGeometryYes;
- XtGeometryMask mode = intended->request_mode;
-
- width = 1;
-
- if (((mode & CWWidth) && intended->width != width) || !(mode & CWWidth)) {
- return_val->request_mode |= CWWidth;
- return_val->width = width;
- mode = return_val->request_mode;
-
- if ((mode & CWWidth) && width == XtWidth(entry))
- return (XtGeometryNo);
- return (XtGeometryAlmost);
- }
-
- return (ret_val);
-}
+/* +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ + +/* + * Date: September 26, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/SmeP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * Class Methods + */ +static void Highlight(Widget); +static void Notify(Widget); +static void Unhighlight(Widget); +static void XawSmeClassPartInitialize(WidgetClass); +static void XawSmeInitialize(Widget, Widget, ArgList, Cardinal*); +static XtGeometryResult XawSmeQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(SmeRec, sme.field) +static XtResource resources[] = { + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(callbacks), + XtRCallback, + NULL + }, + { + XtNinternational, + XtCInternational, + XtRBoolean, + sizeof(Boolean), + offset(international), + XtRImmediate, + (XtPointer)False + }, +}; +#undef offset + +#define Superclass (&rectObjClassRec) +SmeClassRec smeClassRec = { + /* rectangle */ + { + (WidgetClass)Superclass, /* superclass */ + "Sme", /* class_name */ + sizeof(SmeRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + XawSmeClassPartInitialize, /* class_part_initialize */ + False, /* class_initialized */ + XawSmeInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + False, /* compress_exposure */ + False, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + NULL, /* resize */ + NULL, /* expose */ + NULL, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* intrinsics_version */ + NULL, /* callback offsets */ + NULL, /* tm_table */ + XawSmeQueryGeometry, /* query_geometry */ + NULL, /* display_accelerator */ + NULL, /* extension */ + }, + /* sme */ + { + Highlight, /* highlight */ + Unhighlight, /* unhighlight */ + Notify, /* notify */ + NULL, /* extension */ + } +}; + +WidgetClass smeObjectClass = (WidgetClass)&smeClassRec; + +/* + * Implementation + */ +/* + * Function: + * XawSmeClassPartInitialize + * + * Parameters: + * cclass - widget classs of this widget + * + * Description: + * Handles inheritance of class functions. + */ +static void +XawSmeClassPartInitialize(WidgetClass cclass) +{ + SmeObjectClass m_ent, superC; + + m_ent = (SmeObjectClass)cclass; + superC = (SmeObjectClass)m_ent->rect_class.superclass; + + if (m_ent->sme_class.highlight == XtInheritHighlight) + m_ent->sme_class.highlight = superC->sme_class.highlight; + + if (m_ent->sme_class.unhighlight == XtInheritUnhighlight) + m_ent->sme_class.unhighlight = superC->sme_class.unhighlight; + + if (m_ent->sme_class.notify == XtInheritNotify) + m_ent->sme_class.notify = superC->sme_class.notify; +} + +/* + * Function: + * XawSmeInitialize + * + * Parameters: + * request - widget requested by the argument list + * cnew - new widget with both resource and non resource values + * + * Description: + * Initializes the simple menu widget entry + */ +/*ARGSUSED*/ +static void +XawSmeInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SmeObject entry = (SmeObject)cnew; + + entry->rectangle.border_width = 0; +} + +/* + * Function: + * Highlight + * + * Parameters: + * w - menu entry + * + * Description: + * Default highlight proceedure for menu entries. + */ +/*ARGSUSED*/ +static void +Highlight(Widget w) +{ +} + +/* + * Function: + * Unhighlight + * + * Parameters: + * w - menu entry + * + * Description: + * Default unhighlight proceedure for menu entries. + */ +/*ARGSUSED*/ +static void +Unhighlight(Widget w) +{ +} + +/* + * Function: + * Notify + * + * Parameters: + * w - menu entry + * + * Description: + * Calls the callback proceedures for this entry. + */ +static void +Notify(Widget w) +{ + XtCallCallbacks(w, XtNcallback, NULL); +} + +/* + * Function: + * QueryGeometry + * + * Parameeters: + * w - menu entry object + * itended - intended and return geometry info + * return_val - + * + * Description: + * Returns the preferred geometry for this widget. + * + * Returns: + * Geometry Result + * + * Note: + * See the Intrinsics manual for details on what this function is for. + */ +static XtGeometryResult +XawSmeQueryGeometry(Widget w, XtWidgetGeometry *intended, + XtWidgetGeometry *return_val) +{ + SmeObject entry = (SmeObject)w; + Dimension width; + XtGeometryResult ret_val = XtGeometryYes; + XtGeometryMask mode = intended->request_mode; + + width = 1; + + if (((mode & CWWidth) && intended->width != width) || !(mode & CWWidth)) { + return_val->request_mode |= CWWidth; + return_val->width = width; + mode = return_val->request_mode; + + if ((mode & CWWidth) && width == XtWidth(entry)) + return (XtGeometryNo); + return (XtGeometryAlmost); + } + + return (ret_val); +} diff --git a/libXaw/src/SmeBSB.c b/libXaw/src/SmeBSB.c index 1941edff1..b56874b3c 100644 --- a/libXaw/src/SmeBSB.c +++ b/libXaw/src/SmeBSB.c @@ -1,770 +1,770 @@ -/*
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- */
-
-/*
- * SmeBSB.c - Source code file for BSB Menu Entry object.
- *
- * Date: September 26, 1989
- *
- * By: Chris D. Peterson
- * MIT X Consortium
- * kit@expo.lcs.mit.edu
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xos.h>
-#include <X11/Xmu/Drawing.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/SimpleMenu.h>
-#include <X11/Xaw/SmeBSBP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#define ONE_HUNDRED 100
-
-/*
- * Class Methods
- */
-static void FlipColors(Widget);
-static void XawSmeBSBClassInitialize(void);
-static void XawSmeBSBInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawSmeBSBDestroy(Widget);
-static XtGeometryResult XawSmeBSBQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawSmeBSBRedisplay(Widget, XEvent*, Region);
-static Boolean XawSmeBSBSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void CreateGCs(Widget);
-static void GetBitmapInfo(Widget, Bool);
-static void GetDefaultSize(Widget, Dimension*, Dimension*);
-static void DestroyGCs(Widget);
-static void DrawBitmaps(Widget, GC);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(SmeBSBRec, sme_bsb.field)
-static XtResource resources[] = {
- {
- XtNlabel,
- XtCLabel,
- XtRString,
- sizeof(String),
- offset(label),
- XtRString,
- NULL
- },
- {
- XtNvertSpace,
- XtCVertSpace,
- XtRInt,
- sizeof(int),
- offset(vert_space),
- XtRImmediate,
- (XtPointer)25
- },
- {
- XtNleftBitmap,
- XtCLeftBitmap,
- XtRBitmap,
- sizeof(Pixmap),
- offset(left_bitmap),
- XtRImmediate,
- (XtPointer)None
- },
- {
- XtNjustify,
- XtCJustify,
- XtRJustify,
- sizeof(XtJustify),
- offset(justify),
- XtRImmediate,
- (XtPointer)XtJustifyLeft
- },
- {
- XtNrightBitmap,
- XtCRightBitmap,
- XtRBitmap,
- sizeof(Pixmap),
- offset(right_bitmap),
- XtRImmediate,
- (XtPointer)None
- },
- {
- XtNleftMargin,
- XtCHorizontalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(left_margin),
- XtRImmediate,
- (XtPointer)4
- },
- {
- XtNrightMargin,
- XtCHorizontalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(right_margin),
- XtRImmediate,
- (XtPointer)4
- },
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(foreground),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNfont,
- XtCFont,
- XtRFontStruct,
- sizeof(XFontStruct*),
- offset(font),
- XtRString,
- XtDefaultFont
- },
- {
- XtNfontSet,
- XtCFontSet,
- XtRFontSet,
- sizeof(XFontSet),
- offset(fontset),
- XtRString,
- XtDefaultFontSet
- },
-#ifndef OLDXAW
- {
- XtNmenuName,
- XtCMenuName,
- XtRString,
- sizeof(String),
- offset(menu_name),
- XtRImmediate,
- (XtPointer)NULL
- },
-#endif
-};
-#undef offset
-
-#define superclass (&smeClassRec)
-SmeBSBClassRec smeBSBClassRec = {
- /* rectangle */
- {
- (WidgetClass)superclass, /* superclass */
- "SmeBSB", /* class_name */
- sizeof(SmeBSBRec), /* size */
- XawSmeBSBClassInitialize, /* class_init */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawSmeBSBInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* compress_motion */
- False, /* compress_exposure */
- False, /* compress_enterleave */
- False, /* visible_interest */
- XawSmeBSBDestroy, /* destroy */
- NULL, /* resize */
- XawSmeBSBRedisplay, /* expose */
- XawSmeBSBSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* intrinsics version */
- NULL, /* callback offsets */
- NULL, /* tm_table */
- XawSmeBSBQueryGeometry, /* query_geometry */
- NULL, /* display_accelerator */
- NULL, /* extension */
- },
- /* sme */
- {
- FlipColors, /* highlight */
- FlipColors, /* unhighlight */
- XtInheritNotify, /* notify */
- NULL, /* extension */
- },
- /* sme_bsb */
- {
- NULL, /* extension */
- },
-};
-WidgetClass smeBSBObjectClass = (WidgetClass)&smeBSBClassRec;
-
-/*
- * Function:
- * XawSmeBSBClassInitialize
- *
- * Description:
- * Initializes the SmeBSBObject.
- */
-static void
-XawSmeBSBClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0);
- XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-/*
- * Function:
- * XawSmeBSBInitialize
- *
- * Parameters:
- * request - widget requested by the argument list
- * cnew - new widget with both resource and non resource values
- *
- * Description:
- * Initializes the simple menu widget entry.
- */
-/*ARGSUSED*/
-static void
-XawSmeBSBInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SmeBSBObject entry = (SmeBSBObject)cnew;
-
- if (!entry->sme_bsb.font) XtError("Aborting: no font found\n");
-
- if (entry->sme_bsb.label == NULL)
- entry->sme_bsb.label = XtName(cnew);
- else
- entry->sme_bsb.label = XtNewString(entry->sme_bsb.label);
-
- GetDefaultSize(cnew, &entry->rectangle.width, &entry->rectangle.height);
- CreateGCs(cnew);
-
- entry->sme_bsb.left_bitmap_width = entry->sme_bsb.left_bitmap_height = 0;
- entry->sme_bsb.right_bitmap_width = entry->sme_bsb.right_bitmap_height = 0;
-
- GetBitmapInfo(cnew, True); /* Left Bitmap Info */
- GetBitmapInfo(cnew, False); /* Right Bitmap Info */
-}
-
-/*
- * Function:
- * XawSmeBSBDestroy
- *
- * Parameters:
- * w - simple menu widget entry
- */
-static void
-XawSmeBSBDestroy(Widget w)
-{
- SmeBSBObject entry = (SmeBSBObject)w;
-
- DestroyGCs(w);
- if (entry->sme_bsb.label != XtName(w))
- XtFree(entry->sme_bsb.label);
-}
-
-/*
- * Function:
- * XawSmeBSBRedisplay
- *
- * Parameters:
- * w - simple menu widget entry
- * event - X event that caused this redisplay
- * region - region the needs to be repainted
- *
- * Description:
- * Redisplays the contents of the widget.
- */
-/* ARGSUSED */
-static void
-XawSmeBSBRedisplay(Widget w, XEvent *event, Region region)
-{
- GC gc;
- SmeBSBObject entry = (SmeBSBObject)w;
- int font_ascent, font_descent, y_loc;
- int fontset_ascent, fontset_descent;
- XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset);
-
- font_ascent = font_descent = fontset_ascent = fontset_descent = 0;
- entry->sme_bsb.set_values_area_cleared = False;
-
- if (entry->sme.international == True) {
- fontset_ascent = XawAbs(ext->max_ink_extent.y);
- fontset_descent = ext->max_ink_extent.height - fontset_ascent;
- }
- else {
- font_ascent = entry->sme_bsb.font->max_bounds.ascent;
- font_descent = entry->sme_bsb.font->max_bounds.descent;
- }
- y_loc = XtY(entry);
-
- if (XtIsSensitive(w) && XtIsSensitive(XtParent(w))) {
- if (w == XawSimpleMenuGetActiveEntry(XtParent(w))) {
- XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
- entry->sme_bsb.norm_gc, XtX(w), y_loc,
- XtWidth(entry), XtHeight(entry));
- gc = entry->sme_bsb.rev_gc;
- }
- else
- gc = entry->sme_bsb.norm_gc;
- }
- else
- gc = entry->sme_bsb.norm_gray_gc;
-
- if (entry->sme_bsb.label != NULL) {
- int x_loc = entry->sme_bsb.left_margin;
- int len = strlen(entry->sme_bsb.label);
- char *label = entry->sme_bsb.label;
- int width, t_width;
-
- switch(entry->sme_bsb.justify) {
- case XtJustifyCenter:
- if (entry->sme.international == True) {
- t_width = XmbTextEscapement(entry->sme_bsb.fontset,label,
- len);
- width = XtWidth(entry) - (entry->sme_bsb.left_margin +
- entry->sme_bsb.right_margin);
- }
- else {
- t_width = XTextWidth(entry->sme_bsb.font, label, len);
- width = XtWidth(entry) - (entry->sme_bsb.left_margin +
- entry->sme_bsb.right_margin);
- }
- x_loc += (width - t_width) >> 1;
- break;
- case XtJustifyRight:
- if (entry->sme.international == True) {
- t_width = XmbTextEscapement(entry->sme_bsb.fontset,label,
- len);
- x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin +
- t_width);
- }
- else {
- t_width = XTextWidth(entry->sme_bsb.font, label, len);
- x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin +
- t_width);
- }
- break;
- case XtJustifyLeft:
- /*FALLTHROUGH*/
- default:
- break;
- }
-
- /* this will center the text in the gadget top-to-bottom */
- if (entry->sme.international == True) {
- y_loc += ((XtHeight(entry) -
- (fontset_ascent + fontset_descent)) >> 1) +
- fontset_ascent;
-
- XmbDrawString(XtDisplayOfObject(w), XtWindowOfObject(w),
- entry->sme_bsb.fontset, gc,
- XtX(w) + x_loc, y_loc, label, len);
- }
- else {
- y_loc += ((XtHeight(entry) -
- (font_ascent + font_descent)) >> 1) + font_ascent;
-
- XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), gc,
- XtX(w) + x_loc, y_loc, label, len);
- }
- }
-
- DrawBitmaps(w, gc);
-}
-
-
-/*
- * Function:
- * XawSmeBSBSetValues
- *
- * Parameters:
- * current - current state of the widget
- * request - what was requested
- * cnew - what the widget will become
- *
- * Description:
- * Relayout the menu when one of the resources is changed.
- */
-
-/*ARGSUSED*/
-static Boolean
-XawSmeBSBSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SmeBSBObject entry = (SmeBSBObject)cnew;
- SmeBSBObject old_entry = (SmeBSBObject)current;
- Boolean ret_val = False;
-
- if (old_entry->sme_bsb.label != entry->sme_bsb.label) {
- if (old_entry->sme_bsb.label != XtName(cnew))
- XtFree((char *)old_entry->sme_bsb.label);
-
- if (entry->sme_bsb.label != XtName(cnew))
- entry->sme_bsb.label = XtNewString(entry->sme_bsb.label);
-
- ret_val = True;
- }
-
- if (entry->rectangle.sensitive != old_entry->rectangle.sensitive)
- ret_val = True;
-
- if (entry->sme_bsb.left_bitmap != old_entry->sme_bsb.left_bitmap) {
- GetBitmapInfo(cnew, True);
- ret_val = True;
- }
-
- if (entry->sme_bsb.right_bitmap != old_entry->sme_bsb.right_bitmap) {
- GetBitmapInfo(cnew, False);
- ret_val = True;
- }
-
- if ((old_entry->sme_bsb.font != entry->sme_bsb.font
- && old_entry->sme.international == False)
- || old_entry->sme_bsb.foreground != entry->sme_bsb.foreground) {
- DestroyGCs(current);
- CreateGCs(cnew);
- ret_val = True;
- }
-
- if (old_entry->sme_bsb.fontset != entry->sme_bsb.fontset &&
- old_entry->sme.international == True)
- /* DONT changes the GCs, because the fontset is not in them */
- ret_val = True;
-
- if (ret_val) {
- Dimension width, height;
-
- GetDefaultSize(cnew, &width, &height);
- entry->sme_bsb.set_values_area_cleared = True;
- XtMakeResizeRequest(cnew, width, height, NULL, NULL);
- }
-
- return (ret_val);
-}
-
-/*
- * Function:
- * XawSmeBSBQueryGeometry
- *
- * Parameters:
- * w - menu entry object
- * itended - intended and return geometry info
- * return_val - ""
- *
- * Returns:
- * Geometry Result
- *
- * Description:
- * Returns the preferred geometry for this widget.
- * See the Intrinsics manual for details on what this function is for.
- */
-static XtGeometryResult
-XawSmeBSBQueryGeometry(Widget w, XtWidgetGeometry *intended,
- XtWidgetGeometry *return_val)
-{
- SmeBSBObject entry = (SmeBSBObject)w;
- Dimension width, height;
- XtGeometryResult ret_val = XtGeometryYes;
- XtGeometryMask mode = intended->request_mode;
-
- GetDefaultSize(w, &width, &height);
-
- if (((mode & CWWidth) && intended->width != width) || !(mode & CWWidth)) {
- return_val->request_mode |= CWWidth;
- return_val->width = width;
- ret_val = XtGeometryAlmost;
- }
-
- if (((mode & CWHeight) && intended->height != height) || !(mode & CWHeight)) {
- return_val->request_mode |= CWHeight;
- return_val->height = height;
- ret_val = XtGeometryAlmost;
- }
-
- if (ret_val == XtGeometryAlmost) {
- mode = return_val->request_mode;
- if (((mode & CWWidth) && width == XtWidth(entry)) &&
- ((mode & CWHeight) && height == XtHeight(entry)))
- return (XtGeometryNo);
- }
-
- return (ret_val);
-}
-
-/*
- * Function:
- * FlipColors
- *
- * Parameters:
- * w - bsb menu entry widget
- *
- * Description:
- * Invert the colors of the current entry.
- */
-static void
-FlipColors(Widget w)
-{
- SmeBSBObject entry = (SmeBSBObject)w;
-
- if (entry->sme_bsb.set_values_area_cleared)
- return;
-
- XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
- entry->sme_bsb.invert_gc,
- XtX(w), XtY(entry), XtWidth(entry), XtHeight(entry));
-}
-
-/*
- * Function:
- * GetDefaultSize
- *
- * Parameters:
- * w - menu entry widget.
- * width - default width (return)
- * height - default height (return)
- *
- * Description:
- * Calculates the Default (preferred) size of this menu entry.
- */
-static void
-GetDefaultSize(Widget w, Dimension *width, Dimension *height)
-{
- SmeBSBObject entry = (SmeBSBObject)w;
-
- if (entry->sme.international == True) {
- XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset);
-
- if (entry->sme_bsb.label == NULL)
- *width = 0;
- else
- *width = XmbTextEscapement(entry->sme_bsb.fontset,
- entry->sme_bsb.label,
- strlen(entry->sme_bsb.label));
- *width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin;
- *height = ext->max_ink_extent.height;
- *height = ((int)*height * (ONE_HUNDRED +
- entry->sme_bsb.vert_space)) / ONE_HUNDRED;
- }
- else {
- if (entry->sme_bsb.label == NULL)
- *width = 0;
- else
- *width = XTextWidth(entry->sme_bsb.font, entry->sme_bsb.label,
- strlen(entry->sme_bsb.label));
-
- *width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin;
-
- *height = entry->sme_bsb.font->max_bounds.ascent +
- entry->sme_bsb.font->max_bounds.descent;
-
- *height = ((int)*height * (ONE_HUNDRED +
- entry->sme_bsb.vert_space)) / ONE_HUNDRED;
- }
-}
-
-/*
- * Function:
- * DrawBitmaps
- *
- * Parameters:
- * w - simple menu widget entry
- * gc - graphics context to use for drawing
- *
- * Description:
- * Draws left and right bitmaps.
- */
-static void
-DrawBitmaps(Widget w, GC gc)
-{
- int x_loc, y_loc;
- SmeBSBObject entry = (SmeBSBObject)w;
-
- if (entry->sme_bsb.left_bitmap == None &&
- entry->sme_bsb.right_bitmap == None)
- return;
-
- /*
- * Draw Left Bitmap
- */
- if (entry->sme_bsb.left_bitmap != None) {
- x_loc = ((entry->sme_bsb.left_margin -
- entry->sme_bsb.left_bitmap_width) >> 1) + XtX(w);
-
- y_loc = XtY(entry) + ((XtHeight(entry) -
- entry->sme_bsb.left_bitmap_height) >> 1);
-
- XCopyPlane(XtDisplayOfObject(w), entry->sme_bsb.left_bitmap,
- XtWindowOfObject(w), gc, 0, 0,
- entry->sme_bsb.left_bitmap_width,
- entry->sme_bsb.left_bitmap_height, x_loc, y_loc, 1);
- }
-
- /*
- * Draw Right Bitmap
- */
- if (entry->sme_bsb.right_bitmap != None) {
- x_loc = XtWidth(entry) - ((entry->sme_bsb.right_margin +
- entry->sme_bsb.right_bitmap_width) >> 1) +
- XtX(w);
- y_loc = XtY(entry) + ((XtHeight(entry) -
- entry->sme_bsb.right_bitmap_height) >> 1);
-
- XCopyPlane(XtDisplayOfObject(w), entry->sme_bsb.right_bitmap,
- XtWindowOfObject(w), gc, 0, 0,
- entry->sme_bsb.right_bitmap_width,
- entry->sme_bsb.right_bitmap_height, x_loc, y_loc, 1);
- }
-}
-
-/*
- * Function:
- * GetBitmapInfo
- *
- * Parameters:
- * w - bsb menu entry object
- * is_left - True: if we are testing left bitmap
- * False: if we are testing the right bitmap
- *
- * Description:
- * Gets the bitmap information from either of the bitmaps.
- */
-static void
-GetBitmapInfo(Widget w, Bool is_left)
-{
- SmeBSBObject entry = (SmeBSBObject)w;
- unsigned int depth, bw;
- Window root;
- int x, y;
- unsigned int width, height;
-
- if (is_left) {
- if (entry->sme_bsb.left_bitmap != None &&
- XGetGeometry(XtDisplayOfObject(w),
- entry->sme_bsb.left_bitmap, &root,
- &x, &y, &width, &height, &bw, &depth)) {
- entry->sme_bsb.left_bitmap_width = width;
- entry->sme_bsb.left_bitmap_height = height;
- }
- }
- else if (entry->sme_bsb.right_bitmap != None &&
- XGetGeometry(XtDisplayOfObject(w),
- entry->sme_bsb.right_bitmap, &root,
- &x, &y, &width, &height, &bw, &depth)) {
- entry->sme_bsb.right_bitmap_width = width;
- entry->sme_bsb.right_bitmap_height = height;
- }
-}
-
-/*
- * Function:
- * CreateGCs
- *
- * Parameters:
- * w - simple menu widget entry
- *
- * Description:
- * Creates all gc's for the simple menu widget.
- */
-static void
-CreateGCs(Widget w)
-{
- SmeBSBObject entry = (SmeBSBObject)w;
- XGCValues values;
- XtGCMask mask, mask_i18n;
-
- values.foreground = XtParent(w)->core.background_pixel;
- values.background = entry->sme_bsb.foreground;
- values.font = entry->sme_bsb.font->fid;
- values.graphics_exposures = False;
- mask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
- mask_i18n = GCForeground | GCBackground | GCGraphicsExposures;
- if (entry->sme.international == True)
- entry->sme_bsb.rev_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0);
- else
- entry->sme_bsb.rev_gc = XtGetGC(w, mask, &values);
-
- values.foreground = entry->sme_bsb.foreground;
- values.background = XtParent(w)->core.background_pixel;
- if (entry->sme.international == True)
- entry->sme_bsb.norm_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0);
- else
- entry->sme_bsb.norm_gc = XtGetGC(w, mask, &values);
-
- values.fill_style = FillTiled;
- values.tile = XmuCreateStippledPixmap(XtScreenOfObject(w),
- entry->sme_bsb.foreground,
- XtParent(w)->core.background_pixel,
- XtParent(w)->core.depth);
- values.graphics_exposures = False;
- mask |= GCTile | GCFillStyle;
- mask_i18n |= GCTile | GCFillStyle;
- if (entry->sme.international == True)
- entry->sme_bsb.norm_gray_gc = XtAllocateGC(w, 0, mask_i18n, &values,
- GCFont, 0);
- else
- entry->sme_bsb.norm_gray_gc = XtGetGC(w, mask, &values);
-
- values.foreground ^= values.background;
- values.background = 0;
- values.function = GXxor;
- mask = GCForeground | GCBackground | GCGraphicsExposures | GCFunction;
- entry->sme_bsb.invert_gc = XtGetGC(w, mask, &values);
-}
-
-/*
- * Function:
- * DestroyGCs
- *
- * Parameters:
- * w - simple menu widget entry
- *
- * Description:
- * Removes all gc's for the simple menu widget.
- */
-static void
-DestroyGCs(Widget w)
-{
- SmeBSBObject entry = (SmeBSBObject)w;
-
- XtReleaseGC(w, entry->sme_bsb.norm_gc);
- XtReleaseGC(w, entry->sme_bsb.norm_gray_gc);
- XtReleaseGC(w, entry->sme_bsb.rev_gc);
- XtReleaseGC(w, entry->sme_bsb.invert_gc);
-}
+/* +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ + +/* + * SmeBSB.c - Source code file for BSB Menu Entry object. + * + * Date: September 26, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/SimpleMenu.h> +#include <X11/Xaw/SmeBSBP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define ONE_HUNDRED 100 + +/* + * Class Methods + */ +static void FlipColors(Widget); +static void XawSmeBSBClassInitialize(void); +static void XawSmeBSBInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawSmeBSBDestroy(Widget); +static XtGeometryResult XawSmeBSBQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawSmeBSBRedisplay(Widget, XEvent*, Region); +static Boolean XawSmeBSBSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void CreateGCs(Widget); +static void GetBitmapInfo(Widget, Bool); +static void GetDefaultSize(Widget, Dimension*, Dimension*); +static void DestroyGCs(Widget); +static void DrawBitmaps(Widget, GC); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(SmeBSBRec, sme_bsb.field) +static XtResource resources[] = { + { + XtNlabel, + XtCLabel, + XtRString, + sizeof(String), + offset(label), + XtRString, + NULL + }, + { + XtNvertSpace, + XtCVertSpace, + XtRInt, + sizeof(int), + offset(vert_space), + XtRImmediate, + (XtPointer)25 + }, + { + XtNleftBitmap, + XtCLeftBitmap, + XtRBitmap, + sizeof(Pixmap), + offset(left_bitmap), + XtRImmediate, + (XtPointer)None + }, + { + XtNjustify, + XtCJustify, + XtRJustify, + sizeof(XtJustify), + offset(justify), + XtRImmediate, + (XtPointer)XtJustifyLeft + }, + { + XtNrightBitmap, + XtCRightBitmap, + XtRBitmap, + sizeof(Pixmap), + offset(right_bitmap), + XtRImmediate, + (XtPointer)None + }, + { + XtNleftMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(left_margin), + XtRImmediate, + (XtPointer)4 + }, + { + XtNrightMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(right_margin), + XtRImmediate, + (XtPointer)4 + }, + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(foreground), + XtRString, + XtDefaultForeground + }, + { + XtNfont, + XtCFont, + XtRFontStruct, + sizeof(XFontStruct*), + offset(font), + XtRString, + XtDefaultFont + }, + { + XtNfontSet, + XtCFontSet, + XtRFontSet, + sizeof(XFontSet), + offset(fontset), + XtRString, + XtDefaultFontSet + }, +#ifndef OLDXAW + { + XtNmenuName, + XtCMenuName, + XtRString, + sizeof(String), + offset(menu_name), + XtRImmediate, + (XtPointer)NULL + }, +#endif +}; +#undef offset + +#define superclass (&smeClassRec) +SmeBSBClassRec smeBSBClassRec = { + /* rectangle */ + { + (WidgetClass)superclass, /* superclass */ + "SmeBSB", /* class_name */ + sizeof(SmeBSBRec), /* size */ + XawSmeBSBClassInitialize, /* class_init */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawSmeBSBInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + False, /* compress_exposure */ + False, /* compress_enterleave */ + False, /* visible_interest */ + XawSmeBSBDestroy, /* destroy */ + NULL, /* resize */ + XawSmeBSBRedisplay, /* expose */ + XawSmeBSBSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* intrinsics version */ + NULL, /* callback offsets */ + NULL, /* tm_table */ + XawSmeBSBQueryGeometry, /* query_geometry */ + NULL, /* display_accelerator */ + NULL, /* extension */ + }, + /* sme */ + { + FlipColors, /* highlight */ + FlipColors, /* unhighlight */ + XtInheritNotify, /* notify */ + NULL, /* extension */ + }, + /* sme_bsb */ + { + NULL, /* extension */ + }, +}; +WidgetClass smeBSBObjectClass = (WidgetClass)&smeBSBClassRec; + +/* + * Function: + * XawSmeBSBClassInitialize + * + * Description: + * Initializes the SmeBSBObject. + */ +static void +XawSmeBSBClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0); + XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString, + NULL, 0, XtCacheNone, NULL); +} + +/* + * Function: + * XawSmeBSBInitialize + * + * Parameters: + * request - widget requested by the argument list + * cnew - new widget with both resource and non resource values + * + * Description: + * Initializes the simple menu widget entry. + */ +/*ARGSUSED*/ +static void +XawSmeBSBInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SmeBSBObject entry = (SmeBSBObject)cnew; + + if (!entry->sme_bsb.font) XtError("Aborting: no font found\n"); + + if (entry->sme_bsb.label == NULL) + entry->sme_bsb.label = XtName(cnew); + else + entry->sme_bsb.label = XtNewString(entry->sme_bsb.label); + + GetDefaultSize(cnew, &entry->rectangle.width, &entry->rectangle.height); + CreateGCs(cnew); + + entry->sme_bsb.left_bitmap_width = entry->sme_bsb.left_bitmap_height = 0; + entry->sme_bsb.right_bitmap_width = entry->sme_bsb.right_bitmap_height = 0; + + GetBitmapInfo(cnew, True); /* Left Bitmap Info */ + GetBitmapInfo(cnew, False); /* Right Bitmap Info */ +} + +/* + * Function: + * XawSmeBSBDestroy + * + * Parameters: + * w - simple menu widget entry + */ +static void +XawSmeBSBDestroy(Widget w) +{ + SmeBSBObject entry = (SmeBSBObject)w; + + DestroyGCs(w); + if (entry->sme_bsb.label != XtName(w)) + XtFree(entry->sme_bsb.label); +} + +/* + * Function: + * XawSmeBSBRedisplay + * + * Parameters: + * w - simple menu widget entry + * event - X event that caused this redisplay + * region - region the needs to be repainted + * + * Description: + * Redisplays the contents of the widget. + */ +/* ARGSUSED */ +static void +XawSmeBSBRedisplay(Widget w, XEvent *event, Region region) +{ + GC gc; + SmeBSBObject entry = (SmeBSBObject)w; + int font_ascent, font_descent, y_loc; + int fontset_ascent, fontset_descent; + XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset); + + font_ascent = font_descent = fontset_ascent = fontset_descent = 0; + entry->sme_bsb.set_values_area_cleared = False; + + if (entry->sme.international == True) { + fontset_ascent = XawAbs(ext->max_ink_extent.y); + fontset_descent = ext->max_ink_extent.height - fontset_ascent; + } + else { + font_ascent = entry->sme_bsb.font->max_bounds.ascent; + font_descent = entry->sme_bsb.font->max_bounds.descent; + } + y_loc = XtY(entry); + + if (XtIsSensitive(w) && XtIsSensitive(XtParent(w))) { + if (w == XawSimpleMenuGetActiveEntry(XtParent(w))) { + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.norm_gc, XtX(w), y_loc, + XtWidth(entry), XtHeight(entry)); + gc = entry->sme_bsb.rev_gc; + } + else + gc = entry->sme_bsb.norm_gc; + } + else + gc = entry->sme_bsb.norm_gray_gc; + + if (entry->sme_bsb.label != NULL) { + int x_loc = entry->sme_bsb.left_margin; + int len = strlen(entry->sme_bsb.label); + char *label = entry->sme_bsb.label; + int width, t_width; + + switch(entry->sme_bsb.justify) { + case XtJustifyCenter: + if (entry->sme.international == True) { + t_width = XmbTextEscapement(entry->sme_bsb.fontset,label, + len); + width = XtWidth(entry) - (entry->sme_bsb.left_margin + + entry->sme_bsb.right_margin); + } + else { + t_width = XTextWidth(entry->sme_bsb.font, label, len); + width = XtWidth(entry) - (entry->sme_bsb.left_margin + + entry->sme_bsb.right_margin); + } + x_loc += (width - t_width) >> 1; + break; + case XtJustifyRight: + if (entry->sme.international == True) { + t_width = XmbTextEscapement(entry->sme_bsb.fontset,label, + len); + x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin + + t_width); + } + else { + t_width = XTextWidth(entry->sme_bsb.font, label, len); + x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin + + t_width); + } + break; + case XtJustifyLeft: + /*FALLTHROUGH*/ + default: + break; + } + + /* this will center the text in the gadget top-to-bottom */ + if (entry->sme.international == True) { + y_loc += ((XtHeight(entry) - + (fontset_ascent + fontset_descent)) >> 1) + + fontset_ascent; + + XmbDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.fontset, gc, + XtX(w) + x_loc, y_loc, label, len); + } + else { + y_loc += ((XtHeight(entry) - + (font_ascent + font_descent)) >> 1) + font_ascent; + + XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), gc, + XtX(w) + x_loc, y_loc, label, len); + } + } + + DrawBitmaps(w, gc); +} + + +/* + * Function: + * XawSmeBSBSetValues + * + * Parameters: + * current - current state of the widget + * request - what was requested + * cnew - what the widget will become + * + * Description: + * Relayout the menu when one of the resources is changed. + */ + +/*ARGSUSED*/ +static Boolean +XawSmeBSBSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SmeBSBObject entry = (SmeBSBObject)cnew; + SmeBSBObject old_entry = (SmeBSBObject)current; + Boolean ret_val = False; + + if (old_entry->sme_bsb.label != entry->sme_bsb.label) { + if (old_entry->sme_bsb.label != XtName(cnew)) + XtFree((char *)old_entry->sme_bsb.label); + + if (entry->sme_bsb.label != XtName(cnew)) + entry->sme_bsb.label = XtNewString(entry->sme_bsb.label); + + ret_val = True; + } + + if (entry->rectangle.sensitive != old_entry->rectangle.sensitive) + ret_val = True; + + if (entry->sme_bsb.left_bitmap != old_entry->sme_bsb.left_bitmap) { + GetBitmapInfo(cnew, True); + ret_val = True; + } + + if (entry->sme_bsb.right_bitmap != old_entry->sme_bsb.right_bitmap) { + GetBitmapInfo(cnew, False); + ret_val = True; + } + + if ((old_entry->sme_bsb.font != entry->sme_bsb.font + && old_entry->sme.international == False) + || old_entry->sme_bsb.foreground != entry->sme_bsb.foreground) { + DestroyGCs(current); + CreateGCs(cnew); + ret_val = True; + } + + if (old_entry->sme_bsb.fontset != entry->sme_bsb.fontset && + old_entry->sme.international == True) + /* DONT changes the GCs, because the fontset is not in them */ + ret_val = True; + + if (ret_val) { + Dimension width, height; + + GetDefaultSize(cnew, &width, &height); + entry->sme_bsb.set_values_area_cleared = True; + XtMakeResizeRequest(cnew, width, height, NULL, NULL); + } + + return (ret_val); +} + +/* + * Function: + * XawSmeBSBQueryGeometry + * + * Parameters: + * w - menu entry object + * itended - intended and return geometry info + * return_val - "" + * + * Returns: + * Geometry Result + * + * Description: + * Returns the preferred geometry for this widget. + * See the Intrinsics manual for details on what this function is for. + */ +static XtGeometryResult +XawSmeBSBQueryGeometry(Widget w, XtWidgetGeometry *intended, + XtWidgetGeometry *return_val) +{ + SmeBSBObject entry = (SmeBSBObject)w; + Dimension width, height; + XtGeometryResult ret_val = XtGeometryYes; + XtGeometryMask mode = intended->request_mode; + + GetDefaultSize(w, &width, &height); + + if (((mode & CWWidth) && intended->width != width) || !(mode & CWWidth)) { + return_val->request_mode |= CWWidth; + return_val->width = width; + ret_val = XtGeometryAlmost; + } + + if (((mode & CWHeight) && intended->height != height) || !(mode & CWHeight)) { + return_val->request_mode |= CWHeight; + return_val->height = height; + ret_val = XtGeometryAlmost; + } + + if (ret_val == XtGeometryAlmost) { + mode = return_val->request_mode; + if (((mode & CWWidth) && width == XtWidth(entry)) && + ((mode & CWHeight) && height == XtHeight(entry))) + return (XtGeometryNo); + } + + return (ret_val); +} + +/* + * Function: + * FlipColors + * + * Parameters: + * w - bsb menu entry widget + * + * Description: + * Invert the colors of the current entry. + */ +static void +FlipColors(Widget w) +{ + SmeBSBObject entry = (SmeBSBObject)w; + + if (entry->sme_bsb.set_values_area_cleared) + return; + + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.invert_gc, + XtX(w), XtY(entry), XtWidth(entry), XtHeight(entry)); +} + +/* + * Function: + * GetDefaultSize + * + * Parameters: + * w - menu entry widget. + * width - default width (return) + * height - default height (return) + * + * Description: + * Calculates the Default (preferred) size of this menu entry. + */ +static void +GetDefaultSize(Widget w, Dimension *width, Dimension *height) +{ + SmeBSBObject entry = (SmeBSBObject)w; + + if (entry->sme.international == True) { + XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset); + + if (entry->sme_bsb.label == NULL) + *width = 0; + else + *width = XmbTextEscapement(entry->sme_bsb.fontset, + entry->sme_bsb.label, + strlen(entry->sme_bsb.label)); + *width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin; + *height = ext->max_ink_extent.height; + *height = ((int)*height * (ONE_HUNDRED + + entry->sme_bsb.vert_space)) / ONE_HUNDRED; + } + else { + if (entry->sme_bsb.label == NULL) + *width = 0; + else + *width = XTextWidth(entry->sme_bsb.font, entry->sme_bsb.label, + strlen(entry->sme_bsb.label)); + + *width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin; + + *height = entry->sme_bsb.font->max_bounds.ascent + + entry->sme_bsb.font->max_bounds.descent; + + *height = ((int)*height * (ONE_HUNDRED + + entry->sme_bsb.vert_space)) / ONE_HUNDRED; + } +} + +/* + * Function: + * DrawBitmaps + * + * Parameters: + * w - simple menu widget entry + * gc - graphics context to use for drawing + * + * Description: + * Draws left and right bitmaps. + */ +static void +DrawBitmaps(Widget w, GC gc) +{ + int x_loc, y_loc; + SmeBSBObject entry = (SmeBSBObject)w; + + if (entry->sme_bsb.left_bitmap == None && + entry->sme_bsb.right_bitmap == None) + return; + + /* + * Draw Left Bitmap + */ + if (entry->sme_bsb.left_bitmap != None) { + x_loc = ((entry->sme_bsb.left_margin - + entry->sme_bsb.left_bitmap_width) >> 1) + XtX(w); + + y_loc = XtY(entry) + ((XtHeight(entry) - + entry->sme_bsb.left_bitmap_height) >> 1); + + XCopyPlane(XtDisplayOfObject(w), entry->sme_bsb.left_bitmap, + XtWindowOfObject(w), gc, 0, 0, + entry->sme_bsb.left_bitmap_width, + entry->sme_bsb.left_bitmap_height, x_loc, y_loc, 1); + } + + /* + * Draw Right Bitmap + */ + if (entry->sme_bsb.right_bitmap != None) { + x_loc = XtWidth(entry) - ((entry->sme_bsb.right_margin + + entry->sme_bsb.right_bitmap_width) >> 1) + + XtX(w); + y_loc = XtY(entry) + ((XtHeight(entry) - + entry->sme_bsb.right_bitmap_height) >> 1); + + XCopyPlane(XtDisplayOfObject(w), entry->sme_bsb.right_bitmap, + XtWindowOfObject(w), gc, 0, 0, + entry->sme_bsb.right_bitmap_width, + entry->sme_bsb.right_bitmap_height, x_loc, y_loc, 1); + } +} + +/* + * Function: + * GetBitmapInfo + * + * Parameters: + * w - bsb menu entry object + * is_left - True: if we are testing left bitmap + * False: if we are testing the right bitmap + * + * Description: + * Gets the bitmap information from either of the bitmaps. + */ +static void +GetBitmapInfo(Widget w, Bool is_left) +{ + SmeBSBObject entry = (SmeBSBObject)w; + unsigned int depth, bw; + Window root; + int x, y; + unsigned int width, height; + + if (is_left) { + if (entry->sme_bsb.left_bitmap != None && + XGetGeometry(XtDisplayOfObject(w), + entry->sme_bsb.left_bitmap, &root, + &x, &y, &width, &height, &bw, &depth)) { + entry->sme_bsb.left_bitmap_width = width; + entry->sme_bsb.left_bitmap_height = height; + } + } + else if (entry->sme_bsb.right_bitmap != None && + XGetGeometry(XtDisplayOfObject(w), + entry->sme_bsb.right_bitmap, &root, + &x, &y, &width, &height, &bw, &depth)) { + entry->sme_bsb.right_bitmap_width = width; + entry->sme_bsb.right_bitmap_height = height; + } +} + +/* + * Function: + * CreateGCs + * + * Parameters: + * w - simple menu widget entry + * + * Description: + * Creates all gc's for the simple menu widget. + */ +static void +CreateGCs(Widget w) +{ + SmeBSBObject entry = (SmeBSBObject)w; + XGCValues values; + XtGCMask mask, mask_i18n; + + values.foreground = XtParent(w)->core.background_pixel; + values.background = entry->sme_bsb.foreground; + values.font = entry->sme_bsb.font->fid; + values.graphics_exposures = False; + mask = GCForeground | GCBackground | GCGraphicsExposures | GCFont; + mask_i18n = GCForeground | GCBackground | GCGraphicsExposures; + if (entry->sme.international == True) + entry->sme_bsb.rev_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0); + else + entry->sme_bsb.rev_gc = XtGetGC(w, mask, &values); + + values.foreground = entry->sme_bsb.foreground; + values.background = XtParent(w)->core.background_pixel; + if (entry->sme.international == True) + entry->sme_bsb.norm_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0); + else + entry->sme_bsb.norm_gc = XtGetGC(w, mask, &values); + + values.fill_style = FillTiled; + values.tile = XmuCreateStippledPixmap(XtScreenOfObject(w), + entry->sme_bsb.foreground, + XtParent(w)->core.background_pixel, + XtParent(w)->core.depth); + values.graphics_exposures = False; + mask |= GCTile | GCFillStyle; + mask_i18n |= GCTile | GCFillStyle; + if (entry->sme.international == True) + entry->sme_bsb.norm_gray_gc = XtAllocateGC(w, 0, mask_i18n, &values, + GCFont, 0); + else + entry->sme_bsb.norm_gray_gc = XtGetGC(w, mask, &values); + + values.foreground ^= values.background; + values.background = 0; + values.function = GXxor; + mask = GCForeground | GCBackground | GCGraphicsExposures | GCFunction; + entry->sme_bsb.invert_gc = XtGetGC(w, mask, &values); +} + +/* + * Function: + * DestroyGCs + * + * Parameters: + * w - simple menu widget entry + * + * Description: + * Removes all gc's for the simple menu widget. + */ +static void +DestroyGCs(Widget w) +{ + SmeBSBObject entry = (SmeBSBObject)w; + + XtReleaseGC(w, entry->sme_bsb.norm_gc); + XtReleaseGC(w, entry->sme_bsb.norm_gray_gc); + XtReleaseGC(w, entry->sme_bsb.rev_gc); + XtReleaseGC(w, entry->sme_bsb.invert_gc); +} diff --git a/libXaw/src/SmeLine.c b/libXaw/src/SmeLine.c index f735a3c9f..80de18ed4 100644 --- a/libXaw/src/SmeLine.c +++ b/libXaw/src/SmeLine.c @@ -1,264 +1,264 @@ -/*
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- * Author: Chris D. Peterson, MIT X Consortium
- */
-
-/*
- * Sme.c - Source code for the generic menu entry
- *
- * Date: September 26, 1989
- *
- * By: Chris D. Peterson
- * MIT X Consortium
- * kit@expo.lcs.mit.edu
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/SmeLineP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * Class Methods
- */
-static void XawSmeLineDestroy(Widget);
-static void XawSmeLineInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawSmeLineRedisplay(Widget, XEvent*, Region);
-static Boolean XawSmeLineSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void CreateGC(Widget);
-static void DestroyGC(Widget);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(SmeLineRec, sme_line.field)
-static XtResource resources[] = {
- {
- XtNlineWidth,
- XtCLineWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(line_width),
- XtRImmediate,
- (XtPointer)1
- },
- {
- XtNstipple,
- XtCStipple,
- XtRBitmap,
- sizeof(Pixmap),
- offset(stipple),
- XtRImmediate,
- (XtPointer)XtUnspecifiedPixmap
- },
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(foreground),
- XtRString,
- XtDefaultForeground
- },
-};
-#undef offset
-
-#define Superclass (&smeClassRec)
-SmeLineClassRec smeLineClassRec = {
- /* rectangle */
- {
- (WidgetClass)Superclass, /* superclass */
- "SmeLine", /* class_name */
- sizeof(SmeLineRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class inited */
- XawSmeLineInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* compress_motion */
- False, /* compress_exposure */
- False, /* compress_enterleave */
- False, /* visible_interest */
- XawSmeLineDestroy, /* destroy */
- NULL, /* resize */
- XawSmeLineRedisplay, /* expose */
- XawSmeLineSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* intrinsics version */
- NULL, /* callback offsets */
- NULL, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- NULL, /* display_accelerator */
- NULL, /* extension */
- },
- /* sme */
- {
- XtInheritHighlight, /* highlight */
- XtInheritUnhighlight, /* unhighlight */
- XtInheritNotify, /* notify */
- NULL, /* extension */
- },
- /* sme_line */
- {
- NULL, /* extension */
- }
-};
-
-WidgetClass smeLineObjectClass = (WidgetClass)&smeLineClassRec;
-
-/*
- * Implementation
- */
-/*ARGSUSED*/
-static void
-XawSmeLineInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SmeLineObject entry = (SmeLineObject)cnew;
-
- if (XtHeight(entry) == 0)
- XtHeight(entry) = entry->sme_line.line_width;
-
- CreateGC(cnew);
-}
-
-/*
- * Function:
- * CreateGC
- *
- * Parameters:
- * w - Line entry widget
- *
- * Description:
- * Creates the GC for the line entry widget.
- *
- * Note:
- * We can only share the GC if there is no stipple, because
- * we need to change the stipple origin when drawing
- */
-static void
-CreateGC(Widget w)
-{
- SmeLineObject entry = (SmeLineObject)w;
- XGCValues values;
- XtGCMask mask = GCForeground | GCGraphicsExposures | GCLineWidth;
-
- values.foreground = entry->sme_line.foreground;
- values.graphics_exposures = False;
- values.line_width = entry->sme_line.line_width;
-
- if (entry->sme_line.stipple != XtUnspecifiedPixmap) {
- values.stipple = entry->sme_line.stipple;
- values.fill_style = FillStippled;
- mask |= GCStipple | GCFillStyle;
-
- entry->sme_line.gc = XCreateGC(XtDisplayOfObject(w),
- RootWindowOfScreen(XtScreenOfObject(w)),
- mask, &values);
- }
- else
- entry->sme_line.gc = XtGetGC(w, mask, &values);
-}
-
-static void
-XawSmeLineDestroy(Widget w)
-{
- DestroyGC(w);
-}
-
-static void
-DestroyGC(Widget w)
-{
- SmeLineObject entry = (SmeLineObject)w;
-
- if (entry->sme_line.stipple != XtUnspecifiedPixmap)
- XFreeGC(XtDisplayOfObject(w), entry->sme_line.gc);
- else
- XtReleaseGC(w, entry->sme_line.gc);
-}
-
-/*ARGSUSED*/
-static void
-XawSmeLineRedisplay(Widget w, XEvent *event, Region region)
-{
- SmeLineObject entry = (SmeLineObject)w;
- int y = XtY(w) + (((int)XtHeight(w) - entry->sme_line.line_width) >> 1);
-
- if (entry->sme_line.stipple != XtUnspecifiedPixmap)
- XSetTSOrigin(XtDisplayOfObject(w), entry->sme_line.gc, 0, y);
-
- XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
- entry->sme_line.gc, XtX(w), y,
- XtWidth(w), entry->sme_line.line_width);
-}
-
-/*
- * Function:
- * XawSmeLineSetValues
- *
- * Parameters:
- * current - current state of the widget
- * request - what was requested
- * cnew - what the widget will become
- *
- * Description:
- * Relayout the menu when one of the resources is changed.
- */
-/*ARGSUSED*/
-static Boolean
-XawSmeLineSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- SmeLineObject entry = (SmeLineObject)cnew;
- SmeLineObject old_entry = (SmeLineObject)current;
-
- if (entry->sme_line.line_width != old_entry->sme_line.line_width &&
- entry->sme_line.stipple != old_entry->sme_line.stipple) {
- DestroyGC(current);
- CreateGC(cnew);
- return (True);
- }
-
- return (False);
-}
+/* +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Chris D. Peterson, MIT X Consortium + */ + +/* + * Sme.c - Source code for the generic menu entry + * + * Date: September 26, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/SmeLineP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * Class Methods + */ +static void XawSmeLineDestroy(Widget); +static void XawSmeLineInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawSmeLineRedisplay(Widget, XEvent*, Region); +static Boolean XawSmeLineSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void CreateGC(Widget); +static void DestroyGC(Widget); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(SmeLineRec, sme_line.field) +static XtResource resources[] = { + { + XtNlineWidth, + XtCLineWidth, + XtRDimension, + sizeof(Dimension), + offset(line_width), + XtRImmediate, + (XtPointer)1 + }, + { + XtNstipple, + XtCStipple, + XtRBitmap, + sizeof(Pixmap), + offset(stipple), + XtRImmediate, + (XtPointer)XtUnspecifiedPixmap + }, + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(foreground), + XtRString, + XtDefaultForeground + }, +}; +#undef offset + +#define Superclass (&smeClassRec) +SmeLineClassRec smeLineClassRec = { + /* rectangle */ + { + (WidgetClass)Superclass, /* superclass */ + "SmeLine", /* class_name */ + sizeof(SmeLineRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class inited */ + XawSmeLineInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + False, /* compress_exposure */ + False, /* compress_enterleave */ + False, /* visible_interest */ + XawSmeLineDestroy, /* destroy */ + NULL, /* resize */ + XawSmeLineRedisplay, /* expose */ + XawSmeLineSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* intrinsics version */ + NULL, /* callback offsets */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + NULL, /* display_accelerator */ + NULL, /* extension */ + }, + /* sme */ + { + XtInheritHighlight, /* highlight */ + XtInheritUnhighlight, /* unhighlight */ + XtInheritNotify, /* notify */ + NULL, /* extension */ + }, + /* sme_line */ + { + NULL, /* extension */ + } +}; + +WidgetClass smeLineObjectClass = (WidgetClass)&smeLineClassRec; + +/* + * Implementation + */ +/*ARGSUSED*/ +static void +XawSmeLineInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SmeLineObject entry = (SmeLineObject)cnew; + + if (XtHeight(entry) == 0) + XtHeight(entry) = entry->sme_line.line_width; + + CreateGC(cnew); +} + +/* + * Function: + * CreateGC + * + * Parameters: + * w - Line entry widget + * + * Description: + * Creates the GC for the line entry widget. + * + * Note: + * We can only share the GC if there is no stipple, because + * we need to change the stipple origin when drawing + */ +static void +CreateGC(Widget w) +{ + SmeLineObject entry = (SmeLineObject)w; + XGCValues values; + XtGCMask mask = GCForeground | GCGraphicsExposures | GCLineWidth; + + values.foreground = entry->sme_line.foreground; + values.graphics_exposures = False; + values.line_width = entry->sme_line.line_width; + + if (entry->sme_line.stipple != XtUnspecifiedPixmap) { + values.stipple = entry->sme_line.stipple; + values.fill_style = FillStippled; + mask |= GCStipple | GCFillStyle; + + entry->sme_line.gc = XCreateGC(XtDisplayOfObject(w), + RootWindowOfScreen(XtScreenOfObject(w)), + mask, &values); + } + else + entry->sme_line.gc = XtGetGC(w, mask, &values); +} + +static void +XawSmeLineDestroy(Widget w) +{ + DestroyGC(w); +} + +static void +DestroyGC(Widget w) +{ + SmeLineObject entry = (SmeLineObject)w; + + if (entry->sme_line.stipple != XtUnspecifiedPixmap) + XFreeGC(XtDisplayOfObject(w), entry->sme_line.gc); + else + XtReleaseGC(w, entry->sme_line.gc); +} + +/*ARGSUSED*/ +static void +XawSmeLineRedisplay(Widget w, XEvent *event, Region region) +{ + SmeLineObject entry = (SmeLineObject)w; + int y = XtY(w) + (((int)XtHeight(w) - entry->sme_line.line_width) >> 1); + + if (entry->sme_line.stipple != XtUnspecifiedPixmap) + XSetTSOrigin(XtDisplayOfObject(w), entry->sme_line.gc, 0, y); + + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_line.gc, XtX(w), y, + XtWidth(w), entry->sme_line.line_width); +} + +/* + * Function: + * XawSmeLineSetValues + * + * Parameters: + * current - current state of the widget + * request - what was requested + * cnew - what the widget will become + * + * Description: + * Relayout the menu when one of the resources is changed. + */ +/*ARGSUSED*/ +static Boolean +XawSmeLineSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + SmeLineObject entry = (SmeLineObject)cnew; + SmeLineObject old_entry = (SmeLineObject)current; + + if (entry->sme_line.line_width != old_entry->sme_line.line_width && + entry->sme_line.stipple != old_entry->sme_line.stipple) { + DestroyGC(current); + CreateGC(cnew); + return (True); + } + + return (False); +} diff --git a/libXaw/src/StripChart.c b/libXaw/src/StripChart.c index 85e3e3914..237cf66a5 100644 --- a/libXaw/src/StripChart.c +++ b/libXaw/src/StripChart.c @@ -1,576 +1,576 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xaw/StripCharP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-#define MS_PER_SEC 1000
-
-/*
- * Class Methods
- */
-static void XawStripChartInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawStripChartDestroy(Widget);
-static void XawStripChartRedisplay(Widget, XEvent*, Region);
-static void XawStripChartResize(Widget);
-static Boolean XawStripChartSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void CreateGC(StripChartWidget, unsigned int);
-static void DestroyGC(StripChartWidget, unsigned int);
-static void draw_it(XtPointer, XtIntervalId*);
-static void MoveChart(StripChartWidget, Bool);
-static int repaint_window(StripChartWidget, int, int);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(StripChartRec, field)
-static XtResource resources[] = {
- {
- XtNwidth,
- XtCWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(core.width),
- XtRImmediate,
- (XtPointer)
- 120
- },
- {
- XtNheight,
- XtCHeight,
- XtRDimension,
- sizeof(Dimension),
- offset(core.height),
- XtRImmediate,
- (XtPointer)120
- },
- {
- XtNupdate,
- XtCInterval,
- XtRInt,
- sizeof(int),
- offset(strip_chart.update),
- XtRImmediate,
- (XtPointer)10
- },
- {
- XtNminScale,
- XtCScale,
- XtRInt,
- sizeof(int),
- offset(strip_chart.min_scale),
- XtRImmediate,
- (XtPointer)1
- },
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(strip_chart.fgpixel),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNhighlight,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(strip_chart.hipixel),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNgetValue,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(strip_chart.get_value),
- XtRImmediate,
- NULL
- },
- {
- XtNjumpScroll,
- XtCJumpScroll,
- XtRInt,
- sizeof(int),
- offset(strip_chart.jump_val),
- XtRImmediate,
- (XtPointer)DEFAULT_JUMP
- },
-};
-#undef offset
-
-StripChartClassRec stripChartClassRec = {
- /* core */
- {
- (WidgetClass)&simpleClassRec, /* superclass */
- "StripChart", /* class_name */
- sizeof(StripChartRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawStripChartInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- XtExposeCompressMultiple /* compress_exposure */
- | XtExposeGraphicsExposeMerged,
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawStripChartDestroy, /* destroy */
- XawStripChartResize, /* resize */
- XawStripChartRedisplay, /* expose */
- XawStripChartSetValues, /* set_values */
- NULL, /* set_values_hook */
- NULL, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- }
-};
-
-WidgetClass stripChartWidgetClass = (WidgetClass)&stripChartClassRec;
-
-/*
- * Implementation
- */
-/*
- * Function:
- * CreateGC
- *
- * Parameters:
- * w - strip chart widget
- * which - GC's to create
- *
- * Description:
- * Creates the GC's
- */
-static void
-CreateGC(StripChartWidget w, unsigned int which)
-{
- XGCValues myXGCV;
-
- if (which & FOREGROUND) {
- myXGCV.foreground = w->strip_chart.fgpixel;
- w->strip_chart.fgGC = XtGetGC((Widget)w, GCForeground, &myXGCV);
- }
-
- if (which & HIGHLIGHT) {
- myXGCV.foreground = w->strip_chart.hipixel;
- w->strip_chart.hiGC = XtGetGC((Widget)w, GCForeground, &myXGCV);
- }
-}
-
-/*
- * Function:
- * DestroyGC
- *
- * Arguments:
- * w - strip chart widget
- * which - which GC's to destroy
- *
- * Description:
- * Destroys the GC's
- */
-static void
-DestroyGC(StripChartWidget w, unsigned int which)
-{
- if (which & FOREGROUND)
- XtReleaseGC((Widget)w, w->strip_chart.fgGC);
-
- if (which & HIGHLIGHT)
- XtReleaseGC((Widget)w, w->strip_chart.hiGC);
-}
-
-/*ARGSUSED*/
-static void
-XawStripChartInitialize(Widget greq, Widget gnew,
- ArgList args, Cardinal *num_args)
-{
- StripChartWidget w = (StripChartWidget)gnew;
-
- if (w->strip_chart.update > 0)
- w->strip_chart.interval_id =
- XtAppAddTimeOut(XtWidgetToApplicationContext(gnew),
- w->strip_chart.update * MS_PER_SEC,
- draw_it, (XtPointer)gnew);
- CreateGC(w, ALL_GCS);
-
- w->strip_chart.scale = w->strip_chart.min_scale;
- w->strip_chart.interval = 0;
- w->strip_chart.max_value = 0.0;
- w->strip_chart.points = NULL;
- XawStripChartResize(gnew);
-}
-
-static void
-XawStripChartDestroy(Widget gw)
-{
- StripChartWidget w = (StripChartWidget)gw;
-
- if (w->strip_chart.update > 0)
- XtRemoveTimeOut(w->strip_chart.interval_id);
- if (w->strip_chart.points)
- XtFree((char *)w->strip_chart.points);
- DestroyGC(w, ALL_GCS);
-}
-
-/*
- * NOTE: This function really needs to recieve graphics exposure
- * events, but since this is not easily supported until R4 I am
- * going to hold off until then.
- */
-/*ARGSUSED*/
-static void
-XawStripChartRedisplay(Widget w, XEvent *event, Region region)
-{
- if (event->type == GraphicsExpose)
- (void)repaint_window((StripChartWidget)w, event->xgraphicsexpose.x,
- event->xgraphicsexpose.width);
- else
- (void)repaint_window((StripChartWidget)w, event->xexpose.x,
- event->xexpose.width);
-}
-
-/*ARGSUSED*/
-static void
-draw_it(XtPointer client_data, XtIntervalId *id)
-{
- StripChartWidget w = (StripChartWidget)client_data;
- double value;
-
- if (w->strip_chart.update > 0)
- w->strip_chart.interval_id =
- XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)w),
- w->strip_chart.update * MS_PER_SEC,draw_it,
- client_data);
-
- if (w->strip_chart.interval >= XtWidth(w))
- MoveChart((StripChartWidget)w, True);
-
- /* Get the value, stash the point and draw corresponding line */
- if (w->strip_chart.get_value == NULL)
- return;
-
- XtCallCallbacks((Widget)w, XtNgetValue, (XtPointer)&value);
-
- /*
- * Keep w->strip_chart.max_value up to date, and if this data
- * point is off the graph, change the scale to make it fit
- */
- if (value > w->strip_chart.max_value) {
- w->strip_chart.max_value = value;
- if (XtIsRealized((Widget)w) &&
- w->strip_chart.max_value > w->strip_chart.scale) {
- XClearWindow(XtDisplay(w), XtWindow(w));
- w->strip_chart.interval = repaint_window(w, 0, XtWidth(w));
- }
- }
-
- w->strip_chart.valuedata[w->strip_chart.interval] = value;
- if (XtIsRealized((Widget)w)) {
- int y = (int)(XtHeight(w) - XtHeight(w) * value
- / w->strip_chart.scale);
-
- XFillRectangle(XtDisplay(w), XtWindow(w), w->strip_chart.fgGC,
- w->strip_chart.interval, y,
- 1, XtHeight(w) - y);
-
- /*
- * Fill in the graph lines we just painted over
- */
- if (w->strip_chart.points != NULL) {
- w->strip_chart.points[0].x = w->strip_chart.interval;
- XDrawPoints(XtDisplay(w), XtWindow(w), w->strip_chart.hiGC,
- w->strip_chart.points, w->strip_chart.scale - 1,
- CoordModePrevious);
- }
-
- XFlush(XtDisplay(w)); /* Flush output buffers */
- }
- w->strip_chart.interval++; /* Next point */
-}
-
-/* Blts data according to current size, then redraws the stripChart window
- * Next represents the number of valid points in data. Returns the (possibly)
- * adjusted value of next. If next is 0, this routine draws an empty window
- * (scale - 1 lines for graph). If next is less than the current window width,
- * the returned value is identical to the initial value of next and data is
- * unchanged. Otherwise keeps half a window's worth of data. If data is
- * changed, then w->strip_chart.max_value is updated to reflect the
- * largest data point
- */
-static int
-repaint_window(StripChartWidget w, int left, int width)
-{
- int i, j;
- int next = w->strip_chart.interval;
- int scale = w->strip_chart.scale;
- int scalewidth = 0;
-
- /* Compute the minimum scale required to graph the data, but don't go
- lower than min_scale */
- if (w->strip_chart.interval != 0 || scale <= w->strip_chart.max_value)
- scale = w->strip_chart.max_value + 1;
- if (scale < w->strip_chart.min_scale)
- scale = w->strip_chart.min_scale;
-
- if (scale != w->strip_chart.scale) {
- w->strip_chart.scale = scale;
- left = 0;
- width = next;
- scalewidth = XtWidth(w);
-
- XawStripChartResize((Widget)w);
-
- if (XtIsRealized((Widget)w))
- XClearWindow(XtDisplay(w), XtWindow(w));
- }
-
- if (XtIsRealized((Widget)w)) {
- Display *dpy = XtDisplay(w);
- Window win = XtWindow(w);
-
- width += left - 1;
- if (!scalewidth)
- scalewidth = width;
-
- if (next < ++width)
- width = next;
-
- /* Draw data point lines */
- for (i = left; i < width; i++) {
- int y = XtHeight(w) - (XtHeight(w) * w->strip_chart.valuedata[i])
- / w->strip_chart.scale;
-
- XFillRectangle(dpy, win, w->strip_chart.fgGC,
- i, y, 1, XtHeight(w) - y);
- }
-
- /* Draw graph reference lines */
- for (i = 1; i < w->strip_chart.scale; i++) {
- j = i * ((int)XtHeight(w) / w->strip_chart.scale);
- XDrawLine(dpy, win, w->strip_chart.hiGC, left, j, scalewidth, j);
- }
- }
- return (next);
-}
-
-/*
- * Function:
- * MoveChart
- *
- * Parameters:
- * w - chart widget
- * blit - blit the bits?
- *
- * Description:
- * Moves the chart over when it would run off the end.
- */
-static void
-MoveChart(StripChartWidget w, Bool blit)
-{
- double old_max;
- int left, i, j;
- int next = w->strip_chart.interval;
-
- if (!XtIsRealized((Widget)w))
- return;
-
- if (w->strip_chart.jump_val < 0)
- w->strip_chart.jump_val = DEFAULT_JUMP;
- if (w->strip_chart.jump_val == DEFAULT_JUMP)
- j = XtWidth(w) >> 1;
- else {
- j = (int)XtWidth(w) - w->strip_chart.jump_val;
- if (j < 0)
- j = 0;
- }
-
- (void)memmove((char *)w->strip_chart.valuedata,
- (char *)(w->strip_chart.valuedata + next - j),
- j * sizeof(double));
- next = w->strip_chart.interval = j;
-
- /*
- * Since we just lost some data, recompute the
- * w->strip_chart.max_value
- */
- old_max = w->strip_chart.max_value;
- w->strip_chart.max_value = 0.0;
- for (i = 0; i < next; i++) {
- if (w->strip_chart.valuedata[i] > w->strip_chart.max_value)
- w->strip_chart.max_value = w->strip_chart.valuedata[i];
- }
-
- if (!blit)
- return;
-
- if (old_max != w->strip_chart.max_value) {
- XClearWindow(XtDisplay(w), XtWindow(w));
- repaint_window(w, 0, XtWidth(w));
- return;
- }
-
- XCopyArea(XtDisplay((Widget)w), XtWindow((Widget)w), XtWindow((Widget)w),
- w->strip_chart.hiGC, (int)XtWidth(w) - j, 0, j, XtHeight(w), 0, 0);
-
- XClearArea(XtDisplay((Widget)w), XtWindow((Widget)w),
- j, 0, XtWidth(w) - j, XtHeight(w), False);
-
- /* Draw graph reference lines */
- left = j;
- for (i = 1; i < w->strip_chart.scale; i++) {
- j = i * (XtHeight(w) / w->strip_chart.scale);
- XDrawLine(XtDisplay((Widget)w), XtWindow((Widget)w),
- w->strip_chart.hiGC, left, j, XtWidth(w), j);
- }
-}
-
-/*ARGSUSED*/
-static Boolean
-XawStripChartSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- StripChartWidget old = (StripChartWidget)current;
- StripChartWidget w = (StripChartWidget)cnew;
- Bool ret_val = False;
- unsigned int new_gc = NO_GCS;
-
- if (w->strip_chart.update != old->strip_chart.update) {
- if (old->strip_chart.update > 0)
- XtRemoveTimeOut(old->strip_chart.interval_id);
- if (w->strip_chart.update > 0)
- w->strip_chart.interval_id =
- XtAppAddTimeOut(XtWidgetToApplicationContext(cnew),
- w->strip_chart.update * MS_PER_SEC,
- draw_it, (XtPointer)w);
- }
-
- if (w->strip_chart.min_scale > w->strip_chart.max_value + 1)
- ret_val = True;
-
- if (w->strip_chart.fgpixel != old->strip_chart.fgpixel) {
- new_gc |= FOREGROUND;
- ret_val = True;
- }
-
- if (w->strip_chart.hipixel != old->strip_chart.hipixel) {
- new_gc |= HIGHLIGHT;
- ret_val = True;
- }
-
- DestroyGC(old, new_gc);
- CreateGC(w, new_gc);
-
- return (ret_val);
-}
-
-/*
- * Function:
- * XawStripChartResize
- *
- * Parameters:
- * w - StripChart widget
- *
- * Description:
- * Sets up the polypoint that will be used to draw in the graph lines.
- */
-static void
-XawStripChartResize(Widget widget)
-{
- StripChartWidget w = (StripChartWidget)widget;
- XPoint *points;
- Cardinal size;
- int i;
-
- if (w->strip_chart.scale <= 1) {
- XtFree((char *)w->strip_chart.points);
- w->strip_chart.points = NULL;
- return;
- }
-
- size = sizeof(XPoint) * (w->strip_chart.scale - 1);
-
- points = (XPoint *)XtRealloc((XtPointer)w->strip_chart.points, size);
- w->strip_chart.points = points;
-
- /* Draw graph reference lines into clip mask */
-
- for (i = 1; i < w->strip_chart.scale; i++) {
- points[i - 1].x = 0;
- points[i - 1].y = XtHeight(w) / w->strip_chart.scale;
- }
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xfuncs.h> +#include <X11/Xaw/StripCharP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +#define MS_PER_SEC 1000 + +/* + * Class Methods + */ +static void XawStripChartInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawStripChartDestroy(Widget); +static void XawStripChartRedisplay(Widget, XEvent*, Region); +static void XawStripChartResize(Widget); +static Boolean XawStripChartSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void CreateGC(StripChartWidget, unsigned int); +static void DestroyGC(StripChartWidget, unsigned int); +static void draw_it(XtPointer, XtIntervalId*); +static void MoveChart(StripChartWidget, Bool); +static int repaint_window(StripChartWidget, int, int); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(StripChartRec, field) +static XtResource resources[] = { + { + XtNwidth, + XtCWidth, + XtRDimension, + sizeof(Dimension), + offset(core.width), + XtRImmediate, + (XtPointer) + 120 + }, + { + XtNheight, + XtCHeight, + XtRDimension, + sizeof(Dimension), + offset(core.height), + XtRImmediate, + (XtPointer)120 + }, + { + XtNupdate, + XtCInterval, + XtRInt, + sizeof(int), + offset(strip_chart.update), + XtRImmediate, + (XtPointer)10 + }, + { + XtNminScale, + XtCScale, + XtRInt, + sizeof(int), + offset(strip_chart.min_scale), + XtRImmediate, + (XtPointer)1 + }, + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(strip_chart.fgpixel), + XtRString, + XtDefaultForeground + }, + { + XtNhighlight, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(strip_chart.hipixel), + XtRString, + XtDefaultForeground + }, + { + XtNgetValue, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(strip_chart.get_value), + XtRImmediate, + NULL + }, + { + XtNjumpScroll, + XtCJumpScroll, + XtRInt, + sizeof(int), + offset(strip_chart.jump_val), + XtRImmediate, + (XtPointer)DEFAULT_JUMP + }, +}; +#undef offset + +StripChartClassRec stripChartClassRec = { + /* core */ + { + (WidgetClass)&simpleClassRec, /* superclass */ + "StripChart", /* class_name */ + sizeof(StripChartRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawStripChartInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + XtExposeCompressMultiple /* compress_exposure */ + | XtExposeGraphicsExposeMerged, + True, /* compress_enterleave */ + False, /* visible_interest */ + XawStripChartDestroy, /* destroy */ + XawStripChartResize, /* resize */ + XawStripChartRedisplay, /* expose */ + XawStripChartSetValues, /* set_values */ + NULL, /* set_values_hook */ + NULL, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + } +}; + +WidgetClass stripChartWidgetClass = (WidgetClass)&stripChartClassRec; + +/* + * Implementation + */ +/* + * Function: + * CreateGC + * + * Parameters: + * w - strip chart widget + * which - GC's to create + * + * Description: + * Creates the GC's + */ +static void +CreateGC(StripChartWidget w, unsigned int which) +{ + XGCValues myXGCV; + + if (which & FOREGROUND) { + myXGCV.foreground = w->strip_chart.fgpixel; + w->strip_chart.fgGC = XtGetGC((Widget)w, GCForeground, &myXGCV); + } + + if (which & HIGHLIGHT) { + myXGCV.foreground = w->strip_chart.hipixel; + w->strip_chart.hiGC = XtGetGC((Widget)w, GCForeground, &myXGCV); + } +} + +/* + * Function: + * DestroyGC + * + * Arguments: + * w - strip chart widget + * which - which GC's to destroy + * + * Description: + * Destroys the GC's + */ +static void +DestroyGC(StripChartWidget w, unsigned int which) +{ + if (which & FOREGROUND) + XtReleaseGC((Widget)w, w->strip_chart.fgGC); + + if (which & HIGHLIGHT) + XtReleaseGC((Widget)w, w->strip_chart.hiGC); +} + +/*ARGSUSED*/ +static void +XawStripChartInitialize(Widget greq, Widget gnew, + ArgList args, Cardinal *num_args) +{ + StripChartWidget w = (StripChartWidget)gnew; + + if (w->strip_chart.update > 0) + w->strip_chart.interval_id = + XtAppAddTimeOut(XtWidgetToApplicationContext(gnew), + w->strip_chart.update * MS_PER_SEC, + draw_it, (XtPointer)gnew); + CreateGC(w, ALL_GCS); + + w->strip_chart.scale = w->strip_chart.min_scale; + w->strip_chart.interval = 0; + w->strip_chart.max_value = 0.0; + w->strip_chart.points = NULL; + XawStripChartResize(gnew); +} + +static void +XawStripChartDestroy(Widget gw) +{ + StripChartWidget w = (StripChartWidget)gw; + + if (w->strip_chart.update > 0) + XtRemoveTimeOut(w->strip_chart.interval_id); + if (w->strip_chart.points) + XtFree((char *)w->strip_chart.points); + DestroyGC(w, ALL_GCS); +} + +/* + * NOTE: This function really needs to recieve graphics exposure + * events, but since this is not easily supported until R4 I am + * going to hold off until then. + */ +/*ARGSUSED*/ +static void +XawStripChartRedisplay(Widget w, XEvent *event, Region region) +{ + if (event->type == GraphicsExpose) + (void)repaint_window((StripChartWidget)w, event->xgraphicsexpose.x, + event->xgraphicsexpose.width); + else + (void)repaint_window((StripChartWidget)w, event->xexpose.x, + event->xexpose.width); +} + +/*ARGSUSED*/ +static void +draw_it(XtPointer client_data, XtIntervalId *id) +{ + StripChartWidget w = (StripChartWidget)client_data; + double value; + + if (w->strip_chart.update > 0) + w->strip_chart.interval_id = + XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)w), + w->strip_chart.update * MS_PER_SEC,draw_it, + client_data); + + if (w->strip_chart.interval >= XtWidth(w)) + MoveChart((StripChartWidget)w, True); + + /* Get the value, stash the point and draw corresponding line */ + if (w->strip_chart.get_value == NULL) + return; + + XtCallCallbacks((Widget)w, XtNgetValue, (XtPointer)&value); + + /* + * Keep w->strip_chart.max_value up to date, and if this data + * point is off the graph, change the scale to make it fit + */ + if (value > w->strip_chart.max_value) { + w->strip_chart.max_value = value; + if (XtIsRealized((Widget)w) && + w->strip_chart.max_value > w->strip_chart.scale) { + XClearWindow(XtDisplay(w), XtWindow(w)); + w->strip_chart.interval = repaint_window(w, 0, XtWidth(w)); + } + } + + w->strip_chart.valuedata[w->strip_chart.interval] = value; + if (XtIsRealized((Widget)w)) { + int y = (int)(XtHeight(w) - XtHeight(w) * value + / w->strip_chart.scale); + + XFillRectangle(XtDisplay(w), XtWindow(w), w->strip_chart.fgGC, + w->strip_chart.interval, y, + 1, XtHeight(w) - y); + + /* + * Fill in the graph lines we just painted over + */ + if (w->strip_chart.points != NULL) { + w->strip_chart.points[0].x = w->strip_chart.interval; + XDrawPoints(XtDisplay(w), XtWindow(w), w->strip_chart.hiGC, + w->strip_chart.points, w->strip_chart.scale - 1, + CoordModePrevious); + } + + XFlush(XtDisplay(w)); /* Flush output buffers */ + } + w->strip_chart.interval++; /* Next point */ +} + +/* Blts data according to current size, then redraws the stripChart window + * Next represents the number of valid points in data. Returns the (possibly) + * adjusted value of next. If next is 0, this routine draws an empty window + * (scale - 1 lines for graph). If next is less than the current window width, + * the returned value is identical to the initial value of next and data is + * unchanged. Otherwise keeps half a window's worth of data. If data is + * changed, then w->strip_chart.max_value is updated to reflect the + * largest data point + */ +static int +repaint_window(StripChartWidget w, int left, int width) +{ + int i, j; + int next = w->strip_chart.interval; + int scale = w->strip_chart.scale; + int scalewidth = 0; + + /* Compute the minimum scale required to graph the data, but don't go + lower than min_scale */ + if (w->strip_chart.interval != 0 || scale <= w->strip_chart.max_value) + scale = w->strip_chart.max_value + 1; + if (scale < w->strip_chart.min_scale) + scale = w->strip_chart.min_scale; + + if (scale != w->strip_chart.scale) { + w->strip_chart.scale = scale; + left = 0; + width = next; + scalewidth = XtWidth(w); + + XawStripChartResize((Widget)w); + + if (XtIsRealized((Widget)w)) + XClearWindow(XtDisplay(w), XtWindow(w)); + } + + if (XtIsRealized((Widget)w)) { + Display *dpy = XtDisplay(w); + Window win = XtWindow(w); + + width += left - 1; + if (!scalewidth) + scalewidth = width; + + if (next < ++width) + width = next; + + /* Draw data point lines */ + for (i = left; i < width; i++) { + int y = XtHeight(w) - (XtHeight(w) * w->strip_chart.valuedata[i]) + / w->strip_chart.scale; + + XFillRectangle(dpy, win, w->strip_chart.fgGC, + i, y, 1, XtHeight(w) - y); + } + + /* Draw graph reference lines */ + for (i = 1; i < w->strip_chart.scale; i++) { + j = i * ((int)XtHeight(w) / w->strip_chart.scale); + XDrawLine(dpy, win, w->strip_chart.hiGC, left, j, scalewidth, j); + } + } + return (next); +} + +/* + * Function: + * MoveChart + * + * Parameters: + * w - chart widget + * blit - blit the bits? + * + * Description: + * Moves the chart over when it would run off the end. + */ +static void +MoveChart(StripChartWidget w, Bool blit) +{ + double old_max; + int left, i, j; + int next = w->strip_chart.interval; + + if (!XtIsRealized((Widget)w)) + return; + + if (w->strip_chart.jump_val < 0) + w->strip_chart.jump_val = DEFAULT_JUMP; + if (w->strip_chart.jump_val == DEFAULT_JUMP) + j = XtWidth(w) >> 1; + else { + j = (int)XtWidth(w) - w->strip_chart.jump_val; + if (j < 0) + j = 0; + } + + (void)memmove((char *)w->strip_chart.valuedata, + (char *)(w->strip_chart.valuedata + next - j), + j * sizeof(double)); + next = w->strip_chart.interval = j; + + /* + * Since we just lost some data, recompute the + * w->strip_chart.max_value + */ + old_max = w->strip_chart.max_value; + w->strip_chart.max_value = 0.0; + for (i = 0; i < next; i++) { + if (w->strip_chart.valuedata[i] > w->strip_chart.max_value) + w->strip_chart.max_value = w->strip_chart.valuedata[i]; + } + + if (!blit) + return; + + if (old_max != w->strip_chart.max_value) { + XClearWindow(XtDisplay(w), XtWindow(w)); + repaint_window(w, 0, XtWidth(w)); + return; + } + + XCopyArea(XtDisplay((Widget)w), XtWindow((Widget)w), XtWindow((Widget)w), + w->strip_chart.hiGC, (int)XtWidth(w) - j, 0, j, XtHeight(w), 0, 0); + + XClearArea(XtDisplay((Widget)w), XtWindow((Widget)w), + j, 0, XtWidth(w) - j, XtHeight(w), False); + + /* Draw graph reference lines */ + left = j; + for (i = 1; i < w->strip_chart.scale; i++) { + j = i * (XtHeight(w) / w->strip_chart.scale); + XDrawLine(XtDisplay((Widget)w), XtWindow((Widget)w), + w->strip_chart.hiGC, left, j, XtWidth(w), j); + } +} + +/*ARGSUSED*/ +static Boolean +XawStripChartSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + StripChartWidget old = (StripChartWidget)current; + StripChartWidget w = (StripChartWidget)cnew; + Bool ret_val = False; + unsigned int new_gc = NO_GCS; + + if (w->strip_chart.update != old->strip_chart.update) { + if (old->strip_chart.update > 0) + XtRemoveTimeOut(old->strip_chart.interval_id); + if (w->strip_chart.update > 0) + w->strip_chart.interval_id = + XtAppAddTimeOut(XtWidgetToApplicationContext(cnew), + w->strip_chart.update * MS_PER_SEC, + draw_it, (XtPointer)w); + } + + if (w->strip_chart.min_scale > w->strip_chart.max_value + 1) + ret_val = True; + + if (w->strip_chart.fgpixel != old->strip_chart.fgpixel) { + new_gc |= FOREGROUND; + ret_val = True; + } + + if (w->strip_chart.hipixel != old->strip_chart.hipixel) { + new_gc |= HIGHLIGHT; + ret_val = True; + } + + DestroyGC(old, new_gc); + CreateGC(w, new_gc); + + return (ret_val); +} + +/* + * Function: + * XawStripChartResize + * + * Parameters: + * w - StripChart widget + * + * Description: + * Sets up the polypoint that will be used to draw in the graph lines. + */ +static void +XawStripChartResize(Widget widget) +{ + StripChartWidget w = (StripChartWidget)widget; + XPoint *points; + Cardinal size; + int i; + + if (w->strip_chart.scale <= 1) { + XtFree((char *)w->strip_chart.points); + w->strip_chart.points = NULL; + return; + } + + size = sizeof(XPoint) * (w->strip_chart.scale - 1); + + points = (XPoint *)XtRealloc((XtPointer)w->strip_chart.points, size); + w->strip_chart.points = points; + + /* Draw graph reference lines into clip mask */ + + for (i = 1; i < w->strip_chart.scale; i++) { + points[i - 1].x = 0; + points[i - 1].y = XtHeight(w) / w->strip_chart.scale; + } +} diff --git a/libXaw/src/Text.c b/libXaw/src/Text.c index b95231c56..060057d1f 100644 --- a/libXaw/src/Text.c +++ b/libXaw/src/Text.c @@ -1,4158 +1,4158 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
- * Copyright (c) 1998 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the XFree86 Project shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from the
- * XFree86 Project.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Shell.h>
-#include <X11/Xatom.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xutil.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xmu/Xmu.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/MultiSinkP.h>
-#include <X11/Xaw/TextP.h>
-#include <X11/Xaw/TextSrcP.h>
-#include <X11/Xaw/TextSinkP.h>
-#include <X11/Xaw/Scrollbar.h>
-#include <X11/Xaw/XawImP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-#include "XawI18n.h"
-
-#ifndef MAX_LEN_CT
-#define MAX_LEN_CT 6 /* for sequence: ESC $ ( A \xx \xx */
-#endif
-
-unsigned long FMT8BIT = 0L;
-unsigned long XawFmt8Bit = 0L;
-unsigned long XawFmtWide = 0L;
-
-#define SinkClearToBG _XawTextSinkClearToBackground
-
-#define SrcScan XawTextSourceScan
-#define SrcRead XawTextSourceRead
-#define SrcReplace XawTextSourceReplace
-#define SrcSearch XawTextSourceSearch
-#define SrcCvtSel XawTextSourceConvertSelection
-#define SrcSetSelection XawTextSourceSetSelection
-
-#define MULTI_CLICK_TIME 500L
-
-#define SRC_CHANGE_NONE 0
-#define SRC_CHANGE_AFTER 1
-#define SRC_CHANGE_BEFORE 2
-#define SRC_CHANGE_OVERLAP 3
-
-#define Superclass (&simpleClassRec)
-
-/*
- * Compute a the maximum length of a cut buffer that we can pass at any
- * time. The 64 allows for the overhead of the Change Property request.
- */
-#define MAX_CUT_LEN(dpy) (XMaxRequestSize(dpy) - 64)
-
-#define ClearWindow(ctx) \
- _XawTextNeedsUpdating((ctx), \
- (ctx)->text.lt.top, \
- (ctx)->text.lt.info[ctx->text.lt.lines].position)
-
-/*
- * Class Methods
- */
-static void XawTextClassInitialize(void);
-static void XawTextInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawTextRealize(Widget, XtValueMask*, XSetWindowAttributes*);
-static void XawTextDestroy(Widget);
-static void XawTextResize(Widget);
-static void XawTextExpose(Widget, XEvent*, Region);
-static Boolean XawTextSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-static void XawTextGetValuesHook(Widget, ArgList, Cardinal*);
-static Bool XawTextChangeSensitive(Widget);
-
-/*
- * Prototypes
- */
-static XawTextPosition _BuildLineTable(TextWidget, XawTextPosition, int);
-static void _CreateCutBuffers(Display*);
-static Boolean TextConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*,
- unsigned long*, int*);
-static int CountLines(TextWidget, XawTextPosition, XawTextPosition);
-static void CreateHScrollBar(TextWidget);
-static void CreateVScrollBar(TextWidget);
-static void CvtStringToScrollMode(XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr);
-static Boolean CvtScrollModeToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static void CvtStringToWrapMode(XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr);
-static Boolean CvtWrapModeToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean CvtStringToJustifyMode(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean CvtJustifyModeToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static void DestroyHScrollBar(TextWidget);
-static void DestroyVScrollBar(TextWidget);
-#ifndef OLDXAW
-static void DisplayText(Widget, XawTextPosition, XawTextPosition);
-#endif
-static void OldDisplayText(Widget, XawTextPosition, XawTextPosition);
-static void DisplayTextWindow(Widget);
-static void DoCopyArea(TextWidget, int, int, unsigned int, unsigned int,
- int, int);
-static void DoSelection(TextWidget, XawTextPosition, Time, Bool);
-static void ExtendSelection(TextWidget, XawTextPosition, Bool);
-static XawTextPosition FindGoodPosition(TextWidget, XawTextPosition);
-static void FlushUpdate(TextWidget);
-static int GetCutBufferNumber(Atom);
-static int GetMaxTextWidth(TextWidget);
-static unsigned int GetWidestLine(TextWidget);
-static void HScroll(Widget, XtPointer, XtPointer);
-static void HJump(Widget, XtPointer, XtPointer);
-static void InsertCursor(Widget, XawTextInsertState);
-static Bool LineAndXYForPosition(TextWidget, XawTextPosition, int*,
- int*, int*);
-static int LineForPosition(TextWidget, XawTextPosition);
-static void TextLoseSelection(Widget, Atom*);
-static Bool MatchSelection(Atom, XawTextSelection*);
-static void ModifySelection(TextWidget, XawTextPosition, XawTextPosition);
-static XawTextPosition PositionForXY(TextWidget, int, int);
-static void PositionHScrollBar(TextWidget);
-static void PositionVScrollBar(TextWidget);
-#ifndef OLDXAW
-static int ResolveColumnNumber(TextWidget);
-static int ResolveLineNumber(TextWidget);
-#endif
-static void _SetSelection(TextWidget, XawTextPosition, XawTextPosition,
- Atom*, Cardinal);
-static void TextSinkResize(Widget);
-static void UpdateTextInRectangle(TextWidget, XRectangle*);
-static void UpdateTextInLine(TextWidget, int, int, int);
-static void VScroll(Widget, XtPointer, XtPointer);
-static void VJump(Widget, XtPointer, XtPointer);
-
-/*
- * External
- */
-void _XawTextAlterSelection(TextWidget,
- XawTextSelectionMode, XawTextSelectionAction,
- String*, Cardinal*);
-void _XawTextCheckResize(TextWidget);
-void _XawTextClearAndCenterDisplay(TextWidget);
-void _XawTextExecuteUpdate(TextWidget);
-char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition);
-void _XawTextPrepareToUpdate(TextWidget);
-int _XawTextReplace(TextWidget, XawTextPosition, XawTextPosition,
- XawTextBlock*);
-Atom *_XawTextSelectionList(TextWidget, String*, Cardinal);
-void _XawTextSetScrollBars(TextWidget);
-void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition,
- String*, Cardinal);
-void _XawTextVScroll(TextWidget, int);
-void XawTextScroll(TextWidget, int, int);
-void _XawTextSetSource(Widget, Widget, XawTextPosition, XawTextPosition);
-#ifndef OLDXAW
-void _XawTextSetLineAndColumnNumber(TextWidget, Bool);
-#endif
-void _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition,
- XawTextBlock*, int);
-
-/* Not used by other modules, but were extern on previous versions
- * of the library
- */
-void _XawTextShowPosition(TextWidget);
-
-/*
- * From TextAction.c
- */
-extern void _XawTextZapSelection(TextWidget, XEvent*, Bool);
-
-/*
- * From TextSrc.c
- */
-void _XawSourceAddText(Widget, Widget);
-void _XawSourceRemoveText(Widget, Widget, Bool);
-Bool _XawTextSourceNewLineAtEOF(Widget);
-
-/*
- * From TextSink.c
- */
-void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
-void _XawTextSinkDisplayText(Widget, int, int, XawTextPosition, XawTextPosition,
- Bool);
-
-/****************************************************************
- *
- * Full class record constant
- *
- ****************************************************************/
-/*
- * From TextTr.c
- */
-static XawTextSelectType defaultSelectTypes[] = {
- XawselectPosition, XawselectAlphaNumeric, XawselectWord, XawselectLine,
- XawselectParagraph, XawselectAll, XawselectNull,
-};
-
-static XPointer defaultSelectTypesPtr = (XPointer)defaultSelectTypes;
-static Dimension defWidth = 100;
-static Dimension defHeight = DEFAULT_TEXT_HEIGHT;
-
-#define offset(field) XtOffsetOf(TextRec, field)
-static XtResource resources[] = {
- {
- XtNwidth,
- XtCWidth,
- XtRDimension,
- sizeof(Dimension),
- offset(core.width),
- XtRDimension,
- (XtPointer)&defWidth
- },
- {
- XtNcursor,
- XtCCursor,
- XtRCursor,
- sizeof(Cursor),
- offset(simple.cursor),
- XtRString,
- "xterm"
- },
- {
- XtNheight,
- XtCHeight,
- XtRDimension,
- sizeof(Dimension),
- offset(core.height),
- XtRDimension,
- (XtPointer)&defHeight
- },
- {
- XtNdisplayPosition,
- XtCTextPosition,
- XtRInt,
- sizeof(XawTextPosition),
- offset(text.lt.top),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNinsertPosition,
- XtCTextPosition,
- XtRInt,
- sizeof(XawTextPosition),
- offset(text.insertPos),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNleftMargin,
- XtCMargin,
- XtRPosition,
- sizeof(Position),
- offset(text.r_margin.left),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNrightMargin,
- XtCMargin,
- XtRPosition,
- sizeof(Position),
- offset(text.r_margin.right),
- XtRImmediate,
- (XtPointer)4
- },
- {
- XtNtopMargin,
- XtCMargin,
- XtRPosition,
- sizeof(Position),
- offset(text.r_margin.top),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNbottomMargin,
- XtCMargin,
- XtRPosition,
- sizeof(Position),
- offset(text.r_margin.bottom),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNselectTypes,
- XtCSelectTypes,
- XtRPointer,
- sizeof(XawTextSelectType*),
- offset(text.sarray),
- XtRPointer,
- (XtPointer)&defaultSelectTypesPtr
- },
- {
- XtNtextSource,
- XtCTextSource,
- XtRWidget,
- sizeof(Widget),
- offset(text.source),
- XtRImmediate,
- NULL
- },
- {
- XtNtextSink,
- XtCTextSink,
- XtRWidget,
- sizeof(Widget),
- offset(text.sink),
- XtRImmediate,
- NULL
- },
- {
- XtNdisplayCaret,
- XtCOutput,
- XtRBoolean,
- sizeof(Boolean),
- offset(text.display_caret),
- XtRImmediate,
- (XtPointer)True
- },
- {
- XtNscrollVertical,
- XtCScroll,
- XtRScrollMode,
- sizeof(XawTextScrollMode),
- offset(text.scroll_vert),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNscrollHorizontal,
- XtCScroll,
- XtRScrollMode,
- sizeof(XawTextScrollMode),
- offset(text.scroll_horiz),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNwrap,
- XtCWrap,
- XtRWrapMode,
- sizeof(XawTextWrapMode),
- offset(text.wrap),
- XtRImmediate,
- (XtPointer)XawtextWrapNever
- },
- {
- XtNautoFill,
- XtCAutoFill,
- XtRBoolean,
- sizeof(Boolean),
- offset(text.auto_fill),
- XtRImmediate,
- (XtPointer)False
- },
-#ifndef OLDXAW
- {
- XtNpositionCallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(text.position_callbacks),
- XtRCallback,
- NULL
- },
- {
- XtNleftColumn,
- XtCColumn,
- XtRShort,
- sizeof(short),
- offset(text.left_column),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNrightColumn,
- XtCColumn,
- XtRShort,
- sizeof(short),
- offset(text.right_column),
- XtRImmediate,
- (XtPointer)0
- },
- {
- XtNjustifyMode,
- XtCJustifyMode,
- XtRJustifyMode,
- sizeof(XawTextJustifyMode),
- offset(text.justify),
- XtRImmediate,
- (XtPointer)XawjustifyLeft
- },
-#endif /* OLDXAW */
-};
-#undef offset
-
-#define done(address, type) \
- { toVal->size = sizeof(type); toVal->addr = (XPointer)address; }
-
-static XrmQuark QWrapNever, QWrapLine, QWrapWord;
-#ifndef notdef
-static XrmQuark QScrollNever, QScrollWhenNeeded, QScrollAlways;
-#endif
-static XrmQuark QJustifyLeft, QJustifyRight, QJustifyCenter, QJustifyFull;
-
-/*ARGSUSED*/
-static void
-CvtStringToScrollMode(XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal)
-{
- static XawTextScrollMode scrollMode = XawtextScrollNever;
- XrmQuark q;
- char name[32];
-
- XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
- q = XrmStringToQuark(name);
-
- if (q == QScrollNever || q == QScrollWhenNeeded)
- scrollMode = XawtextScrollNever;
- else if (q == QScrollAlways)
- scrollMode = XawtextScrollAlways;
- else if (strcmp(name, "true") == 0 || strcmp(name, "1") == 0)
- scrollMode = XawtextScrollAlways;
- else if (strcmp(name, "false") == 0 || strcmp(name, "0") == 0)
- scrollMode = XawtextScrollNever;
- else
- XtStringConversionWarning((char *)fromVal->addr, XtRScrollMode);
-
- done(&scrollMode, XawTextScrollMode);
-}
-
-/*ARGSUSED*/
-static Boolean
-CvtScrollModeToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal, XtPointer *data)
-{
- static char *buffer;
- Cardinal size;
-
- switch (*(XawTextScrollMode *)fromVal->addr) {
- case XawtextScrollNever:
- case XawtextScrollWhenNeeded:
- buffer = XtEtextScrollNever;
- break;
- case XawtextScrollAlways:
- buffer = XtEtextScrollAlways;
- break;
- default:
- XawTypeToStringWarning(dpy, XtRScrollMode);
- toVal->addr = NULL;
- toVal->size = 0;
- return (False);
- }
- size = strlen(buffer) + 1;
- if (toVal->addr != NULL) {
- if (toVal->size < size) {
- toVal->size = size;
- return (False);
- }
- strcpy((char *)toVal->addr, buffer);
- }
- else
- toVal->addr = (XPointer)buffer;
- toVal->size = sizeof(String);
-
- return (True);
-}
-
-/*ARGSUSED*/
-static void
-CvtStringToWrapMode(XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal)
-{
- static XawTextWrapMode wrapMode = XawtextWrapNever;
- XrmQuark q;
- char lowerName[6];
-
- XmuNCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr,
- sizeof(lowerName));
- q = XrmStringToQuark(lowerName);
-
- if (q == QWrapNever)
- wrapMode = XawtextWrapNever;
- else if (q == QWrapLine)
- wrapMode = XawtextWrapLine;
- else if (q == QWrapWord)
- wrapMode = XawtextWrapWord;
- else
- XtStringConversionWarning((char *)fromVal->addr, XtRWrapMode);
-
- done(&wrapMode, XawTextWrapMode);
-}
-
-/*ARGSUSED*/
-static Boolean
-CvtWrapModeToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal, XtPointer *data)
-{
- static char *buffer;
- Cardinal size;
-
- switch (*(XawTextWrapMode *)fromVal->addr) {
- case XawtextWrapNever:
- buffer = XtEtextWrapNever;
- break;
- case XawtextWrapLine:
- buffer = XtEtextWrapLine;
- break;
- case XawtextWrapWord:
- buffer = XtEtextWrapWord;
- break;
- default:
- XawTypeToStringWarning(dpy, XtRWrapMode);
- toVal->addr = NULL;
- toVal->size = 0;
- return (False);
- }
- size = strlen(buffer) + 1;
- if (toVal->addr != NULL) {
- if (toVal->size < size) {
- toVal->size = size;
- return (False);
- }
- strcpy((char *)toVal->addr, buffer);
- }
- else
- toVal->addr = (XPointer)buffer;
- toVal->size = sizeof(String);
-
- return (True);
-}
-
-/*ARGSUSED*/
-static Boolean
-CvtStringToJustifyMode(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal, XtPointer *data)
-{
- XawTextJustifyMode justify;
- XrmQuark q;
- char lowerName[8];
-
- XmuNCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr,
- sizeof(lowerName));
- q = XrmStringToQuark(lowerName);
-
- if (q == QJustifyLeft)
- justify = XawjustifyLeft;
- else if (q == QJustifyRight)
- justify = XawjustifyRight;
- else if (q == QJustifyCenter)
- justify = XawjustifyCenter;
- else if(q == QJustifyFull)
- justify = XawjustifyFull;
- else {
- XtStringConversionWarning((char *)fromVal->addr, XtRJustifyMode);
- return (False);
- }
-
- toVal->size = sizeof(XawTextJustifyMode);
- *(XawTextJustifyMode *)(toVal->addr) = justify;
-
- return (True);
-}
-
-
-/*ARGSUSED*/
-static Boolean
-CvtJustifyModeToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal, XtPointer *data)
-{
- static char *buffer;
- Cardinal size;
-
- switch (*(XawTextJustifyMode *)fromVal->addr) {
- case XawjustifyLeft:
- buffer = XtEtextJustifyLeft;
- break;
- case XawjustifyRight:
- buffer = XtEtextJustifyRight;
- break;
- case XawjustifyCenter:
- buffer = XtEtextJustifyCenter;
- break;
- case XawjustifyFull:
- buffer = XtEtextJustifyFull;
- break;
- default:
- XawTypeToStringWarning(dpy, XtRJustifyMode);
- toVal->addr = NULL;
- toVal->size = 0;
- return (False);
- }
- size = strlen(buffer) + 1;
- if (toVal->addr != NULL) {
- if (toVal->size < size) {
- toVal->size = size;
- return (False);
- }
- strcpy((char *)toVal->addr, buffer);
- }
- else
- toVal->addr = (XPointer)buffer;
- toVal->size = sizeof(String);
-
- return (True);
-}
-
-#undef done
-
-static void
-XawTextClassInitialize(void)
-{
- if (!XawFmt8Bit)
- FMT8BIT = XawFmt8Bit = XrmPermStringToQuark("FMT8BIT");
- if (!XawFmtWide)
- XawFmtWide = XrmPermStringToQuark("FMTWIDE");
-
- XawInitializeWidgetSet();
-
- textClassRec.core_class.num_actions = _XawTextActionsTableCount;
-
- QWrapNever = XrmPermStringToQuark(XtEtextWrapNever);
- QWrapLine = XrmPermStringToQuark(XtEtextWrapLine);
- QWrapWord = XrmPermStringToQuark(XtEtextWrapWord);
- XtAddConverter(XtRString, XtRWrapMode, CvtStringToWrapMode, NULL, 0);
- XtSetTypeConverter(XtRWrapMode, XtRString, CvtWrapModeToString,
- NULL, 0, XtCacheNone, NULL);
- QScrollNever = XrmPermStringToQuark(XtEtextScrollNever);
- QScrollWhenNeeded = XrmPermStringToQuark(XtEtextScrollWhenNeeded);
- QScrollAlways = XrmPermStringToQuark(XtEtextScrollAlways);
- XtAddConverter(XtRString, XtRScrollMode, CvtStringToScrollMode,
- NULL, 0);
- XtSetTypeConverter(XtRScrollMode, XtRString, CvtScrollModeToString,
- NULL, 0, XtCacheNone, NULL);
- QJustifyLeft = XrmPermStringToQuark(XtEtextJustifyLeft);
- QJustifyRight = XrmPermStringToQuark(XtEtextJustifyRight);
- QJustifyCenter = XrmPermStringToQuark(XtEtextJustifyCenter);
- QJustifyFull = XrmPermStringToQuark(XtEtextJustifyFull);
- XtSetTypeConverter(XtRString, XtRJustifyMode, CvtStringToJustifyMode,
- NULL, 0, XtCacheNone, NULL);
- XtSetTypeConverter(XtRJustifyMode, XtRString, CvtJustifyModeToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-/*
- * Function:
- * PositionHScrollBar
- *
- * Parameters:
- * ctx - text widget
- *
- * Description:
- * Positions the Horizontal scrollbar.
- */
-static void
-PositionHScrollBar(TextWidget ctx)
-{
- Widget hbar = ctx->text.hbar, vbar = ctx->text.vbar;
- Position x, y;
- Dimension width, height;
-
- if (ctx->text.hbar == NULL)
- return;
-
- if (vbar != NULL)
- x = XtWidth(vbar);
- else
- x = -XtBorderWidth(hbar);
- y = XtHeight(ctx) - XtHeight(hbar) - XtBorderWidth(hbar);
- if (vbar != NULL) {
- width = XtWidth(ctx) - XtWidth(vbar) - XtBorderWidth(vbar);
- if (width > XtWidth(ctx))
- width = XtWidth(ctx);
- }
- else
- width = XtWidth(ctx);
- height = XtHeight(hbar);
-
- XtConfigureWidget(hbar, x, y, width, height, XtBorderWidth(hbar));
-}
-
-/*
- * Function:
- * PositionVScrollBar
- *
- * Parameters:
- * ctx - text widget
- *
- * Description:
- * Positions the Vertical scrollbar.
- */
-static void
-PositionVScrollBar(TextWidget ctx)
-{
- Widget vbar = ctx->text.vbar;
- Position x, y;
- Dimension width, height;
-
- if (vbar == NULL)
- return;
-
- x = y = -XtBorderWidth(vbar);
- height = XtHeight(ctx);
- width = XtWidth(vbar);
-
- XtConfigureWidget(vbar, x, y, width, height, XtBorderWidth(vbar));
-}
-
-static void
-CreateVScrollBar(TextWidget ctx)
-{
- Widget vbar;
-
- if (ctx->text.vbar != NULL)
- return;
-
- ctx->text.vbar = vbar =
- XtCreateWidget("vScrollbar", scrollbarWidgetClass, (Widget)ctx, NULL, 0);
- XtAddCallback(vbar, XtNscrollProc, VScroll, (XtPointer)ctx);
- XtAddCallback(vbar, XtNjumpProc, VJump, (XtPointer)ctx);
-
- ctx->text.r_margin.left += XtWidth(vbar) + XtBorderWidth(vbar);
- ctx->text.left_margin = ctx->text.margin.left = ctx->text.r_margin.left;
-
- PositionVScrollBar(ctx);
- PositionHScrollBar(ctx);
- TextSinkResize(ctx->text.sink);
-
- if (XtIsRealized((Widget)ctx)) {
- XtRealizeWidget(vbar);
- XtMapWidget(vbar);
- }
- XtSetKeyboardFocus(vbar, (Widget)ctx);
-}
-
-/*
- * Function:
- * DestroyVScrollBar
- *
- * Parameters:
- * ctx - parent text widget
- *
- * Description:
- * Removes vertical ScrollBar.
- */
-static void
-DestroyVScrollBar(TextWidget ctx)
-{
- Widget vbar = ctx->text.vbar;
-
- if (vbar == NULL)
- return;
-
- ctx->text.r_margin.left -= XtWidth(vbar) + XtBorderWidth(vbar);
- ctx->text.left_margin = ctx->text.margin.left = ctx->text.r_margin.left;
-
- XtDestroyWidget(vbar);
- ctx->text.vbar = NULL;
- if (!ctx->core.being_destroyed) {
- PositionHScrollBar(ctx);
- TextSinkResize(ctx->text.sink);
- }
-}
-
-static void
-CreateHScrollBar(TextWidget ctx)
-{
- Arg args[1];
- Widget hbar;
- int bottom;
-
- if (ctx->text.hbar != NULL)
- return;
-
- XtSetArg(args[0], XtNorientation, XtorientHorizontal);
- ctx->text.hbar = hbar =
- XtCreateWidget("hScrollbar", scrollbarWidgetClass, (Widget)ctx, args, 1);
- XtAddCallback(hbar, XtNscrollProc, HScroll, (XtPointer)ctx);
- XtAddCallback(hbar, XtNjumpProc, HJump, (XtPointer)ctx);
-
- bottom = ctx->text.r_margin.bottom + XtHeight(hbar) + XtBorderWidth(hbar);
-
- ctx->text.margin.bottom = ctx->text.r_margin.bottom = bottom;
-
- PositionHScrollBar(ctx);
- TextSinkResize(ctx->text.sink);
-
- if (XtIsRealized((Widget)ctx)) {
- XtRealizeWidget(hbar);
- XtMapWidget(hbar);
- }
- XtSetKeyboardFocus(hbar, (Widget)ctx);
-}
-
-/*
- * Function:
- * DestroyHScrollBar
- *
- * Parameters:
- * ctx - parent text widget
- *
- * Description:
- * Removes horizontal ScrollBar.
- */
-static void
-DestroyHScrollBar(TextWidget ctx)
-{
- Widget hbar = ctx->text.hbar;
-
- if (hbar == NULL)
- return;
-
- ctx->text.r_margin.bottom -= XtHeight(hbar) + XtBorderWidth(hbar);
- ctx->text.margin.bottom = ctx->text.r_margin.bottom;
-
- XtDestroyWidget(hbar);
- ctx->text.hbar = NULL;
- if (!ctx->core.being_destroyed)
- TextSinkResize(ctx->text.sink);
-}
-
-/*ARGSUSED*/
-static void
-XawTextInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- TextWidget ctx = (TextWidget)cnew;
-
- ctx->text.lt.lines = 0;
- ctx->text.lt.info = (XawTextLineTableEntry *)
- XtCalloc(1, sizeof(XawTextLineTableEntry));
-#ifndef OLDXAW
- ctx->text.lt.base_line = 1;
-#endif
- (void)bzero(&ctx->text.origSel, sizeof(XawTextSelection));
- (void)bzero(&ctx->text.s, sizeof(XawTextSelection));
- ctx->text.s.type = XawselectPosition;
- ctx->text.salt = NULL;
- ctx->text.hbar = ctx->text.vbar = NULL;
- ctx->text.lasttime = 0;
- ctx->text.time = 0;
- ctx->text.showposition = True;
- ctx->text.lastPos = ctx->text.source != NULL ?
- XawTextGetLastPosition(ctx) : 0;
- ctx->text.file_insert = NULL;
- ctx->text.search = NULL;
- ctx->text.update = XmuNewScanline(0, 0, 0);
- ctx->text.gc = XtGetGC(cnew, 0, 0);
- ctx->text.hasfocus = False;
- ctx->text.margin = ctx->text.r_margin; /* Strucure copy */
- ctx->text.left_margin = ctx->text.r_margin.left;
- ctx->text.update_disabled = False;
- ctx->text.clear_to_eol = True;
- ctx->text.old_insert = -1;
- ctx->text.mult = 1;
- ctx->text.salt2 = NULL;
- ctx->text.from_left = -1;
-
-#ifndef OLDXAW
- ctx->text.numeric = False;
- ctx->text.selection_state = False;
- ctx->text.kill_ring = 0;
-
- ctx->text.line_number = -1;
- ctx->text.column_number = -1;
- ctx->text.source_changed = SRC_CHANGE_NONE;
-
- ctx->text.kill_ring_ptr = NULL;
- ctx->text.overwrite = False;
-#endif
-
- if (XtHeight(ctx) == DEFAULT_TEXT_HEIGHT) {
- XtHeight(ctx) = VMargins(ctx);
- if (ctx->text.sink != NULL)
- XtHeight(ctx) += XawTextSinkMaxHeight(ctx->text.sink, 1);
- }
-
- if (ctx->text.scroll_vert == XawtextScrollAlways)
- CreateVScrollBar(ctx);
- if (ctx->text.scroll_horiz == XawtextScrollAlways)
- CreateHScrollBar(ctx);
-
-#ifndef OLDXAW
- if (ctx->text.left_column < 0)
- ctx->text.left_column = 0;
- if (ctx->text.right_column < 0)
- ctx->text.right_column = 0;
-#endif
-}
-
-static void
-XawTextRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attr)
-{
- TextWidget ctx = (TextWidget)w;
-
- (*textClassRec.core_class.superclass->core_class.realize)(w, mask, attr);
-
- if (ctx->text.hbar != NULL) {
- XtRealizeWidget(ctx->text.hbar);
- XtMapWidget(ctx->text.hbar);
- }
-
- if (ctx->text.vbar != NULL) {
- XtRealizeWidget(ctx->text.vbar);
- XtMapWidget(ctx->text.vbar);
- }
-
- _XawTextBuildLineTable(ctx, ctx->text.lt.top, True);
-
-#ifndef OLDXAW
- _XawTextSetLineAndColumnNumber(ctx, True);
-#endif
-}
-
-/* Utility routines for support of Text */
-static void
-_CreateCutBuffers(Display *d)
-{
- static struct _DisplayRec {
- struct _DisplayRec *next;
- Display *dpy;
- } *dpy_list = NULL;
- struct _DisplayRec *dpy_ptr;
-
- for (dpy_ptr = dpy_list; dpy_ptr != NULL; dpy_ptr = dpy_ptr->next)
- if (dpy_ptr->dpy == d)
- return;
-
- dpy_ptr = XtNew(struct _DisplayRec);
- dpy_ptr->next = dpy_list;
- dpy_ptr->dpy = d;
- dpy_list = dpy_ptr;
-
-#define Create(buffer) \
- XChangeProperty(d, RootWindow(d, 0), buffer, XA_STRING, 8, \
- PropModeAppend, NULL, 0);
-
- Create(XA_CUT_BUFFER0);
- Create(XA_CUT_BUFFER1);
- Create(XA_CUT_BUFFER2);
- Create(XA_CUT_BUFFER3);
- Create(XA_CUT_BUFFER4);
- Create(XA_CUT_BUFFER5);
- Create(XA_CUT_BUFFER6);
- Create(XA_CUT_BUFFER7);
-
-#undef Create
-}
-
-/*
- * Procedure to manage insert cursor visibility for editable text. It uses
- * the value of ctx->insertPos and an implicit argument. In the event that
- * position is immediately preceded by an eol graphic, then the insert cursor
- * is displayed at the beginning of the next line.
- */
-static void
-InsertCursor(Widget w, XawTextInsertState state)
-{
- TextWidget ctx = (TextWidget)w;
- int x, y;
- int line;
-
- if (ctx->text.lt.lines < 1)
- return;
-
- if (ctx->text.display_caret &&
- LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y)) {
- if (line < ctx->text.lt.lines)
- y += (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1;
- else
- y += (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1;
-
- XawTextSinkInsertCursor(ctx->text.sink, x, y, state);
- }
-
- /* Keep Input Method up to speed */
- if (ctx->simple.international) {
- Arg list[1];
-
- XtSetArg(list[0], XtNinsertPosition, ctx->text.insertPos);
- _XawImSetValues(w, list, 1);
- }
-}
-
-/*
- * Procedure to register a span of text that is no longer valid on the display
- * It is used to avoid a number of small, and potentially overlapping, screen
- * updates.
-*/
-void
-_XawTextNeedsUpdating(TextWidget ctx,
- XawTextPosition left, XawTextPosition right)
-{
- XmuSegment segment;
-
- if (left >= right)
- return;
-
- segment.x1 = (int)left;
- segment.x2 = (int)right;
- (void)XmuScanlineOrSegment(ctx->text.update, &segment);
-}
-
-/*
- * Procedure to read a span of text in Ascii form. This is purely a hack and
- * we probably need to add a function to sources to provide this functionality.
- * [note: this is really a private procedure but is used in multiple modules].
- */
-char *
-_XawTextGetText(TextWidget ctx, XawTextPosition left, XawTextPosition right)
-{
- char *result, *tempResult;
- XawTextBlock text;
- int bytes;
-
- if (XawTextFormat(ctx, XawFmt8Bit))
- bytes = sizeof(unsigned char);
- else if (XawTextFormat(ctx, XawFmtWide))
- bytes = sizeof(wchar_t);
- else /* if there is another fomat, add here */
- bytes = 1;
-
- /* leave space for ZERO */
- tempResult = result = XtMalloc((unsigned)(right - left + ONE) * bytes);
-
- while (left < right) {
- left = SrcRead(ctx->text.source, left, &text, (int)(right - left));
- if (!text.length)
- break;
- memmove(tempResult, text.ptr, (unsigned)(text.length * bytes));
- tempResult += text.length * bytes;
- }
-
- if (bytes == sizeof(wchar_t))
- *((wchar_t*)tempResult) = (wchar_t)0;
- else
- *tempResult = '\0';
-
- return (result);
-}
-
-/* Like _XawTextGetText, but enforces ICCCM STRING type encoding. This
- * routine is currently used to put just the ASCII chars in the selection
- * into a cut buffer.
- */
-char *
-_XawTextGetSTRING(TextWidget ctx, XawTextPosition left, XawTextPosition right)
-{
- unsigned char *s;
- unsigned char c;
- long i, j, n;
- wchar_t *ws, wc;
-
- /* allow ESC in accordance with ICCCM */
- if (XawTextFormat(ctx, XawFmtWide)) {
- MultiSinkObject sink = (MultiSinkObject)ctx->text.sink;
- ws = (wchar_t *)_XawTextGetText(ctx, left, right);
- n = wcslen(ws);
- for (j = 0, i = 0; j < n; j++) {
- wc = ws[j];
- if (XwcTextEscapement (sink->multi_sink.fontset, &wc, 1)
- || (wc == _Xaw_atowc(XawTAB)) || (wc == _Xaw_atowc(XawLF))
- || (wc == _Xaw_atowc(XawESC)))
- ws[i++] = wc;
- }
- ws[i] = (wchar_t)0;
- return ((char *)ws);
- }
- else {
- s = (unsigned char *)_XawTextGetText(ctx, left, right);
- /* only HT and NL control chars are allowed, strip out others */
- n = strlen((char *)s);
- i = 0;
- for (j = 0; j < n; j++) {
- c = s[j];
- if (((c >= 0x20) && c <= 0x7f)
- ||(c >= 0xa0) || (c == XawTAB) || (c == XawLF)
- || (c == XawESC)) {
- s[i] = c;
- i++;
- }
- }
- s[i] = 0;
-
- return ((char *)s);
- }
-}
-
-/*
- * This routine maps an x and y position in a window that is displaying text
- * into the corresponding position in the source.
- */
-static XawTextPosition
-PositionForXY(TextWidget ctx, int x, int y)
-{
- int fromx, line, width, height;
- XawTextPosition position;
-
- if (ctx->text.lt.lines == 0)
- return (0);
-
- for (line = 0; line < ctx->text.lt.lines - 1; line++) {
- if (y <= ctx->text.lt.info[line + 1].y)
- break;
- }
- position = ctx->text.lt.info[line].position;
- if (position >= ctx->text.lastPos)
- return (ctx->text.lastPos);
- fromx = ctx->text.left_margin;
- XawTextSinkFindPosition(ctx->text.sink, position, fromx, x - fromx,
- False, &position, &width, &height);
-
- if (position > ctx->text.lastPos)
- return (ctx->text.lastPos);
-
- if (position >= ctx->text.lt.info[line + 1].position)
- position = SrcScan(ctx->text.source, ctx->text.lt.info[line + 1].position,
- XawstPositions, XawsdLeft, 1, True);
-
- return (position);
-}
-
-/*
- * This routine maps a source position in to the corresponding line number
- * of the text that is displayed in the window.
- */
-static int
-LineForPosition(TextWidget ctx, XawTextPosition position)
-{
- int line;
-
- for (line = 0; line < ctx->text.lt.lines; line++)
- if (position < ctx->text.lt.info[line + 1].position)
- break;
-
- return (line);
-}
-
-/*
- * This routine maps a source position into the corresponding line number
- * and the x, y coordinates of the text that is displayed in the window.
- */
-static Bool
-LineAndXYForPosition(TextWidget ctx, XawTextPosition pos,
- int *line, int *x, int *y)
-{
- XawTextPosition linePos, endPos;
- Boolean visible;
- int realW, realH;
-
- *line = 0;
- *x = ctx->text.left_margin;
- *y = ctx->text.margin.top + 1;
- if ((visible = IsPositionVisible(ctx, pos)) != False) {
- *line = LineForPosition(ctx, pos);
- *y = ctx->text.lt.info[*line].y;
- linePos = ctx->text.lt.info[*line].position;
- XawTextSinkFindDistance(ctx->text.sink, linePos,
- *x, pos, &realW, &endPos, &realH);
- *x += realW;
- }
-
- return (visible);
-}
-
-/*
- * This routine builds a line table. It does this by starting at the
- * specified position and measuring text to determine the staring position
- * of each line to be displayed. It also determines and saves in the
- * linetable all the required metrics for displaying a given line (e.g.
- * x offset, y offset, line length, etc.).
- */
-void
-_XawTextBuildLineTable(TextWidget ctx, XawTextPosition position,
- _XtBoolean force_rebuild)
-{
- Dimension height = 0;
- int lines = 0;
- Cardinal size;
-
- if ((int)XtHeight(ctx) > VMargins(ctx)) {
- height = XtHeight(ctx) - VMargins(ctx);
- lines = XawTextSinkMaxLines(ctx->text.sink, height);
- }
- size = sizeof(XawTextLineTableEntry) * (lines + 1);
-
- if (lines != ctx->text.lt.lines || ctx->text.lt.info == NULL) {
- ctx->text.lt.info = (XawTextLineTableEntry *)
- XtRealloc((char *)ctx->text.lt.info, size);
- ctx->text.lt.lines = lines;
- force_rebuild = True;
- }
-
- if (force_rebuild) {
- (void)bzero((char *)ctx->text.lt.info, size);
- /* force a text update in the first text line if it is visible */
- ctx->text.lt.info[0].position = (XawTextPosition)-1;
- }
- if (position != ctx->text.lt.info[0].position) {
- (void)_BuildLineTable(ctx, position, 0);
- ctx->text.clear_to_eol = True;
- }
-}
-
-/*
- * We may need to resize the line table here, since there maybe lines with
- * different fonts (that can be shorter or taller than the default one)
- */
-static XawTextPosition
-_BuildLineTable(TextWidget ctx, XawTextPosition position, int line)
-{
- XawTextLineTableEntry *lt = ctx->text.lt.info + line;
- XawTextPosition end, update_from = -1;
- Position y;
- int wwidth, width, height;
-#ifndef OLDXAW
- Widget src = ctx->text.source;
-#endif
- int max_y = (int)XtHeight(ctx) - (int)ctx->text.margin.bottom;
-
- if (ctx->text.wrap == XawtextWrapNever)
- wwidth = 0x7fffffff;
- else
- wwidth = GetMaxTextWidth(ctx);
-
- /* XXX y may change, due to font size changes. See later */
- y = line == 0 ? ctx->text.margin.top : lt->y;
-
-#ifndef OLDXAW
- if (ctx->text.lt.base_line < 0) {
- if (line == 0)
- ctx->text.lt.top = position;
- }
- else if (line == 0) {
- XawTextPosition pos = ctx->text.lt.top;
- int base_line = ctx->text.lt.base_line;
-
- if (position == 0)
- base_line = 1;
- else if (ctx->text.lt.base_line == 0 ||
- ctx->text.source_changed == SRC_CHANGE_OVERLAP) {
- pos = 0;
- base_line = 1;
-
- while (pos < position) {
- pos = SrcScan(src, pos, XawstEOL, XawsdRight, 1, True);
- if (pos <= position) {
- ++base_line;
- if (pos == ctx->text.lastPos) {
- base_line -= !_XawTextSourceNewLineAtEOF(src);
- break;
- }
- }
- }
- }
- else if (ctx->text.wrap == XawtextWrapNever
- && IsPositionVisible(ctx, position))
- base_line += LineForPosition(ctx, position);
- else if (pos < position) {
- while (pos < position) {
- pos = SrcScan(src, pos, XawstEOL, XawsdRight, 1, True);
- if (pos <= position) {
- ++base_line;
- if (pos == ctx->text.lastPos) {
- base_line -= !_XawTextSourceNewLineAtEOF(src);
- break;
- }
- }
- }
- }
- else if (pos > position) {
- while (pos > position) {
- pos = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False);
- if (--pos >= position)
- --base_line;
- }
- }
-
- ctx->text.lt.top = position;
- ctx->text.lt.base_line = base_line;
- }
-#else
- if (line == 0)
- ctx->text.lt.top = position;
-#endif
-
- /* CONSTCOND */
- while (True) {
- XawTextSinkFindPosition(ctx->text.sink, position, ctx->text.left_margin,
- wwidth, ctx->text.wrap == XawtextWrapWord,
- &end, &width, &height);
-
- if (lt->position != position) {
- _XawTextNeedsUpdating(ctx, position,
- end <= position ? position + 1 : end);
- ctx->text.clear_to_eol = True;
- lt->position = position;
- }
- if (lt->y != y) {
- if (update_from < 0)
- update_from = line == 0 ?
- ctx->text.lt.info[0].position :
- ctx->text.lt.info[line - 1].position;
- lt->y = y;
- ctx->text.clear_to_eol = True;
- }
- if (lt->textWidth != width) {
- if (lt->textWidth > width)
- ctx->text.clear_to_eol = True;
- lt->textWidth = width;
- }
- y += height;
-
- if (end > ctx->text.lastPos) {
- position = end;
- ctx->text.clear_to_eol = True;
- _XawTextNeedsUpdating(ctx, end, end + ctx->text.lt.lines - line);
- while (line++ < ctx->text.lt.lines) {
- if (line > 1 && y > max_y) {
- ctx->text.lt.lines = line - 1;
- break;
- }
- ++lt;
- if (lt->y != y) {
- if (update_from < 0)
- update_from = line < 2 ?
- ctx->text.lt.info[0].position :
- ctx->text.lt.info[line - 2].position;
- lt->y = y;
- }
- lt->position = ++position;
- lt->textWidth = 0;
- y += height;
- }
- if (update_from >= 0)
- _XawTextNeedsUpdating(ctx, update_from,
- ctx->text.lt.info[ctx->text.lt.lines].position);
- _XawTextSetScrollBars(ctx);
-
- return (ctx->text.lastPos);
- }
-
- if (line && y > max_y)
- /* will return in the next loop */
- ctx->text.lt.lines = line;
-
- if (++line > ctx->text.lt.lines && y < max_y) {
- /* grow the line table */
- ctx->text.lt.info = (XawTextLineTableEntry *)
- XtRealloc((char *)ctx->text.lt.info,
- sizeof(XawTextLineTableEntry) * (line + 1));
- lt = ctx->text.lt.info + line;
- bzero(lt, sizeof(XawTextLineTableEntry));
- ++ctx->text.lt.lines;
- }
- else
- ++lt;
- if (position == end)
- ++position;
- else
- position = end;
-
- if (line > ctx->text.lt.lines) {
- if (update_from >= 0)
- _XawTextNeedsUpdating(ctx, update_from,
- ctx->text.lt.info[ctx->text.lt.lines].position);
- _XawTextSetScrollBars(ctx);
-
- return (position);
- }
- }
- /*NOTREACHED*/
-}
-
-/*
- * Function:
- * GetWidestLine
- *
- * Parameters:
- * ctx - text widget
- *
- * Description:
- * Returns the width (in pixels) of the widest line that
- * is currently visable.
- *
- * Returns:
- * The width of the widest line
- */
-static unsigned int
-GetWidestLine(TextWidget ctx)
-{
- int i;
- unsigned int widest;
- XawTextLineTablePtr lt = &(ctx->text.lt);
-
- for (i = 0, widest = 0; i < lt->lines; i++)
- if (widest < lt->info[i].textWidth)
- widest = lt->info[i].textWidth;
-
- return (widest);
-}
-
-/*
- * This routine is used by Text to notify an associated scrollbar of the
- * correct metrics (position and shown fraction) for the text being currently
- * displayed in the window.
- */
-void
-_XawTextSetScrollBars(TextWidget ctx)
-{
- float first, last, denom, widest;
-
- if (ctx->text.scroll_vert == XawtextScrollAlways) {
- if (ctx->text.lastPos == 0)
- first = 0.0;
- else
- first = ctx->text.lt.top / (float)ctx->text.lastPos;
-
- if (ctx->text.lt.info[ctx->text.lt.lines].position < ctx->text.lastPos)
- last = ctx->text.lt.info[ctx->text.lt.lines].position /
- (float)ctx->text.lastPos;
- else
- last = 1.0;
-
- XawScrollbarSetThumb(ctx->text.vbar, first, last - first);
- }
-
- if (ctx->text.scroll_horiz == XawtextScrollAlways) {
- denom = GetWidestLine(ctx);
- if (denom <= 0)
- denom = (int)XtWidth(ctx) - RHMargins(ctx);
- if (denom <= 0)
- denom = 1;
- widest = ((int)XtWidth(ctx) - RHMargins(ctx)) / denom;
- first = ctx->text.r_margin.left - ctx->text.left_margin;
- first /= denom;
-
- XawScrollbarSetThumb(ctx->text.hbar, first, widest);
- }
-}
-
-static void
-DoCopyArea(TextWidget ctx, int src_x, int src_y,
- unsigned int width, unsigned int height, int dst_x, int dst_y)
-{
- int x1, y1, x2, y2;
-
- x1 = ctx->text.r_margin.left;
- y1 = ctx->text.r_margin.top;
- x2 = XtWidth(ctx) - ctx->text.r_margin.right;
- y2 = XtHeight(ctx) - ctx->text.r_margin.bottom;
-
- if (x1 >= x2 || y1 >= y2)
- return;
-
- src_x = XawMax(x1, XawMin(src_x, x2));
- src_y = XawMax(y1, XawMin(src_y, y2));
- dst_x = XawMax(x1, XawMin(dst_x, x2));
- dst_y = XawMax(y1, XawMin(dst_y, y2));
- width = XawMax(0, XawMin(x2 - dst_x, (int)width));
- height = XawMax(0, XawMin(y2 - dst_y, (int)height));
-
- XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc,
- src_x, src_y, width, height, dst_x, dst_y);
-}
-
-/*
- * Function:
- * XawTextScroll
- *
- * Parameters:
- * ctx - text widget
- * vlines - number of lines to scroll vertically
- * hpixels - number of pixels to scroll horizontally
- *
- * Description:
- * Generic function for scrolling the text window.
- * Allows vertical and horizontal scroll at the same time.
- */
-void
-XawTextScroll(TextWidget ctx, int vlines, int hpixels)
-{
- XawTextPosition top, tmp, update_from, update_to;
- XawTextLineTable *lt;
- Arg arglist[1];
- int y0, y1, y2, count, dim, wwidth, lines = ctx->text.lt.lines;
- int vwidth, vheight; /* visible width and height */
- Bool scroll;
-
- vwidth = (int)XtWidth(ctx) - RHMargins(ctx);
- vheight = (int)XtHeight(ctx) - RVMargins(ctx);
- lt = &ctx->text.lt;
-
- if (!lt || vwidth <= 0 || vheight <= 0)
- return;
-
- if ((scroll = ctx->core.background_pixmap == XtUnspecifiedPixmap) == True) {
- dim = lt->info[1].y - lt->info[0].y;
- for (count = 1; count < lt->lines - 1; count++)
- if (lt->info[count + 1].y - lt->info[count].y != dim) {
- scroll = False;
- break;
- }
- }
-
- wwidth = GetMaxTextWidth(ctx);
-
- /*
- * Do the horizontall scrolling
- */
- if (hpixels < 0 && ctx->text.left_margin - hpixels > ctx->text.r_margin.left)
- hpixels = ctx->text.left_margin - ctx->text.r_margin.left;
- ctx->text.left_margin -= hpixels;
-
- update_from = lt->top; /* remember the old value */
- /*
- * Checks the requested number of lines and calculates the top
- * of the line table
- */
- if (vlines < 0) { /* VScroll Up */
- if (IsPositionVisible(ctx, 0))
- vlines = 0;
- else if (ctx->text.wrap != XawtextWrapNever) {
- XawTextPosition end;
- int n_lines = 0;
-
- count = -vlines;
- end = lt->top;
- while (n_lines < count) {
- top = SrcScan(ctx->text.source, end, XawstEOL,
- XawsdLeft, 2, False);
- n_lines += CountLines(ctx, top, end);
- end = top;
- }
-
- while (count++ < n_lines) {
- tmp = top;
- XawTextSinkFindPosition(ctx->text.sink, top,
- ctx->text.left_margin,
- wwidth,ctx->text.wrap == XawtextWrapWord,
- &top, &dim, &dim);
- if (tmp == top)
- ++top;
- }
- }
- else
- top = SrcScan(ctx->text.source, lt->top, XawstEOL,
- XawsdLeft, -vlines + 1, False);
- if (-vlines >= ctx->text.lt.lines)
- scroll = False;
- }
- else if (vlines > 0) { /* VScroll Down */
- if (LineForPosition(ctx, ctx->text.lastPos) == 0)
- vlines = 0;
- if (vlines < lt->lines)
- top = XawMin(lt->info[vlines].position, ctx->text.lastPos);
- else if (ctx->text.wrap == XawtextWrapNever)
- top = SrcScan(ctx->text.source,
- SrcScan(ctx->text.source, lt->top,
- XawstEOL, XawsdRight, vlines,
- True),
- XawstEOL, XawsdLeft, 1, False);
- else {
- top = lt->top;
- count = 0;
- while (count++ < vlines) {
- tmp = top;
- XawTextSinkFindPosition(ctx->text.sink, top,
- ctx->text.left_margin,
- wwidth, ctx->text.wrap == XawtextWrapWord,
- &top, &dim, &dim);
- if (tmp == top)
- ++top;
- }
- }
- if (vlines >= ctx->text.lt.lines
- || lt->info[vlines].position >= ctx->text.lastPos)
- scroll = False;
- }
-
- if (!vlines) {
- if (hpixels) {
- ClearWindow(ctx);
- ctx->text.clear_to_eol = True;
- }
- _XawTextSetScrollBars(ctx);
- return;
- }
-
- /* Flushes any pending updates. Normally, there may be a call to
- * XawTextUnsetSelection not yet updated.
- */
- if (!hpixels && scroll) {
- ctx->text.clear_to_eol = True;
- FlushUpdate(ctx);
- }
-
- /*
- * Rebuild the line table, doing the vertical scroll
- */
- (void)_BuildLineTable(ctx, top, 0);
- lt = &ctx->text.lt;
- if (scroll) {
- for (count = 0; count < lt->lines - 1; count++)
- if (lt->info[count + 1].y - lt->info[count].y != dim) {
- scroll = False;
- break;
- }
- }
-
- XtSetArg(arglist[0], XtNinsertPosition, lt->top + lt->lines);
- _XawImSetValues((Widget)ctx, arglist, 1);
-
- if (hpixels || !scroll || lines != lt->lines)
- return;
-
- /* _BuildLineTable updates everything if the top position changes.
- * It is not required here.
- */
- (void)XmuScanlineXor(ctx->text.update, ctx->text.update);
- if (vlines < 0 && IsPositionVisible(ctx, 0))
- vlines = -LineForPosition(ctx, update_from);
-
- y0 = ctx->text.r_margin.top;
- if (vlines < 0) {
- update_from = lt->top;
- update_to = lt->info[-vlines + 1].position - 1;
- y1 = lt->info[lt->lines + vlines].y;
- y2 = lt->info[-vlines].y;
- DoCopyArea(ctx, ctx->text.r_margin.left, y0, vwidth,
- y1 - y0,
- ctx->text.r_margin.left, y2);
- }
- else {
- update_from = lt->info[lt->lines - vlines].position;
- update_to = lt->info[lt->lines].position;
- y1 = lt->info[lt->lines - vlines].y;
- y2 = lt->info[vlines].y;
- DoCopyArea(ctx, ctx->text.r_margin.left, y2,
- vwidth, lt->info[lt->lines].y - y2,
- ctx->text.r_margin.left, y0);
- }
- _XawTextNeedsUpdating(ctx, update_from, update_to);
- ctx->text.clear_to_eol = True;
-}
-
-/*
- * The routine will scroll the displayed text by lines. If the arg is
- * positive, move up; otherwise, move down. [note: this is really a private
- * procedure but is used in multiple modules].
- */
-void
-_XawTextVScroll(TextWidget ctx, int n)
-{
- XawTextScroll(ctx, n, 0);
-}
-
-/*ARGSUSED*/
-static void
-HScroll(Widget w, XtPointer closure, XtPointer callData)
-{
- TextWidget ctx = (TextWidget)closure;
- long pixels = (long)callData;
-
- if (pixels > 0) {
- long max;
-
- max = (int)GetWidestLine(ctx) + ctx->text.left_margin -
- ctx->text.r_margin.left;
- max = XawMax(0, max);
- pixels = XawMin(pixels, max);
- }
-
- if (pixels) {
- _XawTextPrepareToUpdate(ctx);
- XawTextScroll(ctx, 0, pixels);
- _XawTextExecuteUpdate(ctx);
- }
-}
-
-/*ARGSUSED*/
-static void
-HJump(Widget w, XtPointer closure, XtPointer callData)
-{
- TextWidget ctx = (TextWidget)closure;
- float percent = *(float *)callData;
- long pixels;
-
- pixels = ctx->text.left_margin -
- (ctx->text.r_margin.left - (int)(percent * GetWidestLine(ctx)));
-
- HScroll(w, (XtPointer)ctx, (XtPointer)pixels);
-}
-
-/*
- * Function:
- * UpdateTextInLine
- *
- * Parameters:
- * ctx - text widget
- * line - line to update
- * x1 - left pixel
- * x2 - right pixel
- *
- * Description:
- * Updates the text in the given line and pixel interval
- */
-static void
-UpdateTextInLine(TextWidget ctx, int line, int x1, int x2)
-{
- XawTextLineTableEntry *lt = ctx->text.lt.info + line;
- XawTextPosition left, right;
- int from_x, width, height;
-
- if (lt->position >= ctx->text.lastPos
- || ctx->text.left_margin > x2
- || (int)lt->textWidth + ctx->text.left_margin < x1) {
- /* Mark line to be cleared */
- if (ctx->text.clear_to_eol)
- _XawTextNeedsUpdating(ctx, lt->position, lt->position + 1);
- return;
- }
-
- from_x = ctx->text.left_margin;
- XawTextSinkFindPosition(ctx->text.sink, lt->position,
- from_x, x1 - from_x,
- False, &left, &width, &height);
- if (line == ctx->text.lt.lines)
- right = -1;
- else if (x2 >= lt->textWidth - from_x)
- right = lt[1].position - 1;
- else {
- from_x += width;
- XawTextSinkFindPosition(ctx->text.sink, left,
- from_x, x2 - from_x,
- False, &right, &width, &height);
- }
-
- if ((right < 0) || (right + 1 <= lt[1].position))
- ++right;
-
- /* Mark text interval to be repainted */
- _XawTextNeedsUpdating(ctx, left, right);
-}
-
-/*
- * The routine will scroll the displayed text by pixels. If the calldata is
- * positive, move up; otherwise, move down.
- */
-/*ARGSUSED*/
-static void
-VScroll(Widget w, XtPointer closure, XtPointer callData)
-{
- TextWidget ctx = (TextWidget)closure;
- long height, lines = (long)callData;
-
- height = XtHeight(ctx) - VMargins(ctx);
- if (height < 1)
- height = 1;
- lines = (lines * ctx->text.lt.lines) / height;
- _XawTextPrepareToUpdate(ctx);
- XawTextScroll(ctx, lines, 0);
- _XawTextExecuteUpdate(ctx);
-}
-
-/*ARGSUSED*/
-static void
-VJump(Widget w, XtPointer closure, XtPointer callData)
-{
- float percent = *(float *)callData;
- TextWidget ctx = (TextWidget)closure;
- XawTextPosition top, last, position, tmp;
- XawTextLineTable *lt = &(ctx->text.lt);
- int dim, vlines = 0, wwidth = GetMaxTextWidth(ctx);
- Bool scroll = True;
-
- position = percent * ctx->text.lastPos;
- top = lt->top;
-
- if (!lt->lines || (position >= lt->top && position < lt->info[1].position)) {
- _XawTextSetScrollBars(ctx);
- return;
- }
-
-#ifndef OLDXAW
- ctx->text.lt.base_line = -1;
-#endif
-
- if (position > lt->top) { /* VScroll Up */
- if (position > lt->top && position < lt->info[lt->lines].position)
- vlines = LineForPosition(ctx, position);
- else {
- scroll = False;
- top = SrcScan(ctx->text.source, position, XawstEOL,
- XawsdLeft, 1, False);
- if (ctx->text.wrap != XawtextWrapNever) {
- last = top;
- while (last < position) {
- tmp = last;
- XawTextSinkFindPosition(ctx->text.sink, last,
- ctx->text.left_margin, wwidth,
- ctx->text.wrap == XawtextWrapWord,
- &last, &dim, &dim);
- if (last == tmp)
- ++last;
- if (last < position)
- top = last;
- }
- }
- }
- }
- else { /* VScroll Down */
- /*
- * Calculates the number of lines
- */
- while (top > position) {
- last = top;
- top = SrcScan(ctx->text.source, top, XawstEOL,
- XawsdLeft, 2, False);
- vlines -= CountLines(ctx, top, last);
- if (-vlines >= ctx->text.lt.lines) {
- scroll = False;
- top = SrcScan(ctx->text.source, position, XawstEOL,
- XawsdLeft, 1, False);
- break;
- }
- }
- /*
- * Normalize
- */
- if (ctx->text.wrap != XawtextWrapNever) {
- last = top;
- while (last < position) {
- tmp = last;
- XawTextSinkFindPosition(ctx->text.sink, last,
- ctx->text.left_margin,
- wwidth,
- ctx->text.wrap == XawtextWrapWord,
- &last, &dim, &dim);
- if (last == tmp)
- ++last;
- if (last < position)
- top = last;
- ++vlines;
- }
- }
- }
-
- if (vlines || !scroll) {
- _XawTextPrepareToUpdate(ctx);
- if (scroll)
- XawTextScroll(ctx, vlines, 0);
- else
- _BuildLineTable(ctx, top, 0);
- _XawTextExecuteUpdate(ctx);
- }
-}
-
-static Bool
-MatchSelection(Atom selection, XawTextSelection *s)
-{
- Atom *match;
- int count;
-
- for (count = 0, match = s->selections; count < s->atom_count;
- match++, count++)
- if (*match == selection)
- return (True);
-
- return (False);
-}
-
-static Boolean
-TextConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type,
- XtPointer *value, unsigned long *length, int *format)
-{
- Display *d = XtDisplay(w);
- TextWidget ctx = (TextWidget)w;
- Widget src = ctx->text.source;
- XawTextEditType edit_mode;
- Arg args[1];
- XawTextSelectionSalt *salt = NULL;
- XawTextSelection *s;
-
- if (*target == XA_TARGETS(d)) {
- Atom *targetP, *std_targets;
- unsigned long std_length;
-
- if (SrcCvtSel(src, selection, target, type, value, length, format))
- return (True);
-
- XtSetArg(args[0], XtNeditType, &edit_mode);
- XtGetValues(src, args, ONE);
-
- XmuConvertStandardSelection(w, ctx->text.time, selection,
- target, type, (XPointer*)&std_targets,
- &std_length, format);
-
- *length = 7 + (edit_mode == XawtextEdit) + std_length;
- *value = XtMalloc((unsigned)sizeof(Atom)*(*length));
- targetP = *(Atom**)value;
- *targetP++ = XA_STRING;
- *targetP++ = XA_TEXT(d);
- *targetP++ = XA_UTF8_STRING(d);
- *targetP++ = XA_COMPOUND_TEXT(d);
- *targetP++ = XA_LENGTH(d);
- *targetP++ = XA_LIST_LENGTH(d);
- *targetP++ = XA_CHARACTER_POSITION(d);
- if (edit_mode == XawtextEdit) {
- *targetP++ = XA_DELETE(d);
- }
- (void)memmove((char*)targetP, (char*)std_targets,
- sizeof(Atom) * std_length);
- XtFree((char*)std_targets);
- *type = XA_ATOM;
- *format = 32;
- return (True);
- }
-
- if (SrcCvtSel(src, selection, target, type, value, length, format))
- return (True);
-
- if (MatchSelection(*selection, &ctx->text.s))
- s = &ctx->text.s;
- else {
- for (salt = ctx->text.salt; salt; salt = salt->next)
- if (MatchSelection(*selection, &salt->s))
- break;
- if (!salt)
- return (False);
- s = &salt->s;
- }
- if (*target == XA_STRING
- || *target == XA_TEXT(d)
- || *target == XA_UTF8_STRING(d)
- || *target == XA_COMPOUND_TEXT(d)) {
- if (*target == XA_TEXT(d)) {
- if (XawTextFormat(ctx, XawFmtWide))
- *type = XA_COMPOUND_TEXT(d);
- else
- *type = XA_STRING;
- }
- else
- *type = *target;
- /*
- * If salt is True, the salt->contents stores CT string,
- * its length is measured in bytes.
- * Refer to _XawTextSaltAwaySelection().
- *
- * by Li Yuhong, Mar. 20, 1991.
- */
- if (!salt) {
- *value = _XawTextGetSTRING(ctx, s->left, s->right);
- if (XawTextFormat(ctx, XawFmtWide)) {
- XTextProperty textprop;
- if (XwcTextListToTextProperty(d, (wchar_t **)value, 1,
- XCompoundTextStyle, &textprop)
- < Success) {
- XtFree((char *)*value);
- return (False);
- }
- XtFree((char *)*value);
- *value = (XtPointer)textprop.value;
- *length = textprop.nitems;
- }
- else
- *length = strlen((char *)*value);
- }
- else {
- *value = XtMalloc((salt->length + 1) * sizeof(unsigned char));
- strcpy ((char *)*value, salt->contents);
- *length = salt->length;
- }
- /* Got *value,*length, now in COMPOUND_TEXT format. */
- if (XawTextFormat(ctx, XawFmtWide) && *type == XA_STRING) {
- XTextProperty textprop;
- wchar_t **wlist;
- int count;
-
- textprop.encoding = XA_COMPOUND_TEXT(d);
- textprop.value = (unsigned char *)*value;
- textprop.nitems = strlen(*value);
- textprop.format = 8;
- if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count)
- < Success
- || count < 1) {
- XtFree((char *)*value);
- return (False);
- }
- XtFree((char *)*value);
- if (XwcTextListToTextProperty(d, wlist, 1, XStringStyle, &textprop)
- < Success) {
- XwcFreeStringList((wchar_t**) wlist);
- return (False);
- }
- *value = (XtPointer)textprop.value;
- *length = textprop.nitems;
- XwcFreeStringList(wlist);
- } else if (*type == XA_UTF8_STRING(d)) {
- XTextProperty textprop;
- char **list;
- int count;
-
- textprop.encoding = XA_COMPOUND_TEXT(d);
- textprop.value = (unsigned char *)*value;
- textprop.nitems = strlen(*value);
- textprop.format = 8;
- if (Xutf8TextPropertyToTextList(d, &textprop, &list, &count)
- < Success
- || count < 1) {
- XtFree((char *)*value);
- return (False);
- }
- XtFree((char *)*value);
- *value = *list;
- *length = strlen(*list);
- XFree(list);
- }
- *format = 8;
- return (True);
- }
-
- if ((*target == XA_LIST_LENGTH(d)) || (*target == XA_LENGTH(d))) {
- long * temp;
-
- temp = (long *)XtMalloc((unsigned)sizeof(long));
- if (*target == XA_LIST_LENGTH(d))
- *temp = 1L;
- else /* *target == XA_LENGTH(d) */
- *temp = (long) (s->right - s->left);
-
- *value = (XPointer)temp;
- *type = XA_INTEGER;
- *length = 1L;
- *format = 32;
- return (True);
- }
-
- if (*target == XA_CHARACTER_POSITION(d)) {
- long * temp;
-
- temp = (long *)XtMalloc((unsigned)(2 * sizeof(long)));
- temp[0] = (long)(s->left + 1);
- temp[1] = s->right;
- *value = (XPointer)temp;
- *type = XA_SPAN(d);
- *length = 2L;
- *format = 32;
- return (True);
- }
-
- if (*target == XA_DELETE(d)) {
- if (!salt)
- _XawTextZapSelection(ctx, NULL, True);
- *value = NULL;
- *type = XA_NULL(d);
- *length = 0;
- *format = 32;
- return (True);
- }
-
- if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type,
- (XPointer *)value, length, format))
- return (True);
-
- /* else */
- return (False);
-}
-
-/*
- * Function:
- * GetCutBuffferNumber
- *
- * Parameters:
- * atom - atom to check
- *
- * Description:
- * Returns the number of the cut buffer.
- *
- * Returns:
- * The number of the cut buffer representing this atom or NOT_A_CUT_BUFFER
- */
-#define NOT_A_CUT_BUFFER -1
-static int
-GetCutBufferNumber(Atom atom)
-{
- if (atom == XA_CUT_BUFFER0) return (0);
- if (atom == XA_CUT_BUFFER1) return (1);
- if (atom == XA_CUT_BUFFER2) return (2);
- if (atom == XA_CUT_BUFFER3) return (3);
- if (atom == XA_CUT_BUFFER4) return (4);
- if (atom == XA_CUT_BUFFER5) return (5);
- if (atom == XA_CUT_BUFFER6) return (6);
- if (atom == XA_CUT_BUFFER7) return (7);
- return (NOT_A_CUT_BUFFER);
-}
-
-static void
-TextLoseSelection(Widget w, Atom *selection)
-{
- TextWidget ctx = (TextWidget)w;
- Atom *atomP;
- int i;
- XawTextSelectionSalt*salt, *prevSalt, *nextSalt;
-
- atomP = ctx->text.s.selections;
- for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++)
- if ((*selection == *atomP)
- || (GetCutBufferNumber(*atomP) != NOT_A_CUT_BUFFER))
- *atomP = (Atom)0;
-
- while (ctx->text.s.atom_count
- && ctx->text.s.selections[ctx->text.s.atom_count - 1] == 0)
- ctx->text.s.atom_count--;
-
- /*
- * Must walk the selection list in opposite order from UnsetSelection
- */
- atomP = ctx->text.s.selections;
- for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++)
- if (*atomP == (Atom)0) {
- *atomP = ctx->text.s.selections[--ctx->text.s.atom_count];
- while (ctx->text.s.atom_count
- && ctx->text.s.selections[ctx->text.s.atom_count-1] == 0)
- ctx->text.s.atom_count--;
- }
-
- if (ctx->text.s.atom_count == 0)
- ModifySelection(ctx, ctx->text.insertPos, ctx->text.insertPos);
-
- prevSalt = 0;
- for (salt = ctx->text.salt; salt; salt = nextSalt) {
- atomP = salt->s.selections;
- nextSalt = salt->next;
- for (i = 0 ; i < salt->s.atom_count; i++, atomP++)
- if (*selection == *atomP)
- *atomP = (Atom)0;
-
- while (salt->s.atom_count
- && salt->s.selections[salt->s.atom_count-1] == 0)
- salt->s.atom_count--;
-
- /*
- * Must walk the selection list in opposite order from UnsetSelection
- */
- atomP = salt->s.selections;
- for (i = 0 ; i < salt->s.atom_count; i++, atomP++)
- if (*atomP == (Atom)0) {
- *atomP = salt->s.selections[--salt->s.atom_count];
- while (salt->s.atom_count
- && salt->s.selections[salt->s.atom_count-1] == 0)
- salt->s.atom_count--;
- }
-
- if (salt->s.atom_count == 0) {
- XtFree ((char *) salt->s.selections);
- XtFree (salt->contents);
- if (prevSalt)
- prevSalt->next = nextSalt;
- else
- ctx->text.salt = nextSalt;
- XtFree((char *)salt);
- }
- else
- prevSalt = salt;
- }
-}
-
-void
-_XawTextSaltAwaySelection(TextWidget ctx, Atom *selections, int num_atoms)
-{
- XawTextSelectionSalt *salt;
- int i, j;
-
- for (i = 0; i < num_atoms; i++)
- TextLoseSelection((Widget)ctx, selections + i);
- if (num_atoms == 0)
- return;
- salt = (XawTextSelectionSalt *)
- XtMalloc((unsigned)sizeof(XawTextSelectionSalt));
- if (!salt)
- return;
- salt->s.selections = (Atom *)XtMalloc((unsigned)(num_atoms * sizeof(Atom)));
- if (!salt->s.selections) {
- XtFree((char *)salt);
- return;
- }
- salt->s.left = ctx->text.s.left;
- salt->s.right = ctx->text.s.right;
- salt->s.type = ctx->text.s.type;
- salt->contents = _XawTextGetSTRING(ctx, ctx->text.s.left, ctx->text.s.right);
- if (XawTextFormat(ctx, XawFmtWide)) {
- XTextProperty textprop;
- if (XwcTextListToTextProperty(XtDisplay((Widget)ctx),
- (wchar_t**)(&(salt->contents)), 1,
- XCompoundTextStyle,
- &textprop) < Success) {
- XtFree(salt->contents);
- salt->length = 0;
- return;
- }
- XtFree(salt->contents);
- salt->contents = (char *)textprop.value;
- salt->length = textprop.nitems;
- }
- else
- salt->length = strlen (salt->contents);
- salt->next = ctx->text.salt;
- ctx->text.salt = salt;
- j = 0;
- for (i = 0; i < num_atoms; i++) {
- if (GetCutBufferNumber (selections[i]) == NOT_A_CUT_BUFFER) {
- salt->s.selections[j++] = selections[i];
- XtOwnSelection((Widget)ctx, selections[i], ctx->text.time,
- TextConvertSelection, TextLoseSelection, NULL);
- }
- }
- salt->s.atom_count = j;
-}
-
-static void
-_SetSelection(TextWidget ctx, XawTextPosition left, XawTextPosition right,
- Atom *selections, Cardinal count)
-{
-#ifndef OLDXAW
- Cardinal i;
- XawTextPosition pos;
- TextSrcObject src = (TextSrcObject)ctx->text.source;
-
- for (i = 0; i < src->textSrc.num_text; i++) {
- TextWidget tw = (TextWidget)src->textSrc.text[i];
- Bool needs_updating = tw->text.old_insert < 0;
- Bool showposition = tw->text.showposition;
-
- if (needs_updating) {
- tw->text.showposition = False;
- _XawTextPrepareToUpdate(tw);
- }
-#else
- TextWidget tw = ctx;
- XawTextPosition pos;
-#endif /* OLDXAW */
-
- if (left < tw->text.s.left) {
- pos = Min(right, tw->text.s.left);
- _XawTextNeedsUpdating(tw, left, pos);
- }
- if (left > tw->text.s.left) {
- pos = Min(left, tw->text.s.right);
- _XawTextNeedsUpdating(tw, tw->text.s.left, pos);
- }
- if (right < tw->text.s.right) {
- pos = Max(right, tw->text.s.left);
- _XawTextNeedsUpdating(tw, pos, tw->text.s.right);
- }
- if (right > tw->text.s.right) {
- pos = Max(left, tw->text.s.right);
- _XawTextNeedsUpdating(tw, pos, right);
- }
-
- tw->text.s.left = left;
- tw->text.s.right = right;
-
-#ifndef OLDXAW
- if (needs_updating) {
- _XawTextExecuteUpdate(tw);
- tw->text.showposition = showposition;
- }
- }
-#endif /* OLDXAW */
-
- SrcSetSelection(ctx->text.source, left, right,
- (count == 0) ? None : selections[0]);
-
- if (left < right) {
- Widget w = (Widget)ctx;
- int buffer;
-
- while (count) {
- Atom selection = selections[--count];
-
- /*
- * If this is a cut buffer
- */
- if ((buffer = GetCutBufferNumber(selection)) != NOT_A_CUT_BUFFER) {
- unsigned char *ptr, *tptr;
- unsigned int amount, max_len = MAX_CUT_LEN(XtDisplay(w));
- unsigned long len;
-
- tptr= ptr= (unsigned char *)_XawTextGetSTRING(ctx,
- ctx->text.s.left,
- ctx->text.s.right);
- if (XawTextFormat(ctx, XawFmtWide)) {
- /*
- * Only XA_STRING(Latin 1) is allowed in CUT_BUFFER,
- * so we get it from wchar string, then free the wchar string
- */
- XTextProperty textprop;
-
- if (XwcTextListToTextProperty(XtDisplay(w), (wchar_t**)&ptr,
- 1, XStringStyle, &textprop)
- < Success){
- XtFree((char *)ptr);
- return;
- }
- XtFree((char *)ptr);
- tptr = ptr = textprop.value;
- }
- if (buffer == 0) {
- _CreateCutBuffers(XtDisplay(w));
- XRotateBuffers(XtDisplay(w), 1);
- }
- amount = Min ((len = strlen((char *)ptr)), max_len);
- XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0),
- selection, XA_STRING, 8, PropModeReplace,
- ptr, amount);
-
- while (len > max_len) {
- len -= max_len;
- tptr += max_len;
- amount = Min (len, max_len);
- XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0),
- selection, XA_STRING, 8, PropModeAppend,
- tptr, amount);
- }
- XtFree ((char *)ptr);
- }
- else /* This is a real selection */
- XtOwnSelection(w, selection, ctx->text.time, TextConvertSelection,
- TextLoseSelection, NULL);
- }
- }
- else
- XawTextUnsetSelection((Widget)ctx);
-}
-
-#ifndef OLDXAW
-void
-_XawTextSetLineAndColumnNumber(TextWidget ctx, Bool force)
-{
- int line_number, column_number;
-
- if (ctx->text.old_insert != ctx->text.insertPos &&
- ctx->text.lt.base_line < 0) {
- ctx->text.lt.base_line = 0;
- (void)_BuildLineTable(ctx, ctx->text.lt.top, 0);
- }
-
- line_number = ResolveLineNumber(ctx);
- column_number = ResolveColumnNumber(ctx);
-
- if (force || (ctx->text.column_number != column_number
- || ctx->text.line_number != line_number)) {
- XawTextPositionInfo info;
-
- ctx->text.line_number = info.line_number = line_number;
- ctx->text.column_number = info.column_number = column_number;
- info.insert_position = ctx->text.insertPos;
- info.last_position = ctx->text.lastPos;
- info.overwrite_mode = ctx->text.overwrite;
-
- XtCallCallbacks((Widget)ctx, XtNpositionCallback, (XtPointer)&info);
- }
-}
-
-static int
-ResolveColumnNumber(TextWidget ctx)
-{
- Widget src = ctx->text.source;
- short column_number = 0;
- XawTextPosition position;
- XawTextBlock block;
- unsigned long format = _XawTextFormat(ctx);
- TextSinkObject sink = (TextSinkObject)ctx->text.sink;
- short *char_tabs = sink->text_sink.char_tabs;
- int tab_count = sink->text_sink.tab_count;
- int tab_index = 0, tab_column = 0, tab_base = 0;
-
- if (ctx->text.lt.base_line < 1)
- return (ctx->text.column_number);
-
- position = SrcScan(src, ctx->text.insertPos, XawstEOL, XawsdLeft, 1, False);
- XawTextSourceRead(src, position, &block, ctx->text.insertPos - position);
-
- for (; position < ctx->text.insertPos; position++) {
- if (position - block.firstPos >= block.length)
- XawTextSourceRead(src, position, &block, ctx->text.insertPos - position);
- if ((format == XawFmt8Bit && block.ptr[position - block.firstPos] == '\t') ||
- (format == XawFmtWide && ((wchar_t*)block.ptr)[position - block.firstPos] == _Xaw_atowc(XawTAB))) {
- while (tab_base + tab_column <= column_number) {
- if (tab_count) {
- for (; tab_index < tab_count; ++tab_index)
- if (tab_base + char_tabs[tab_index] > column_number) {
- tab_column = char_tabs[tab_index];
- break;
- }
- if (tab_index >= tab_count) {
- tab_base += char_tabs[tab_count - 1];
- tab_column = tab_index = 0;
- }
- }
- else
- tab_column += DEFAULT_TAB_SIZE;
- }
- column_number = tab_base + tab_column;
- }
- else
- ++column_number;
- if (column_number >= 16384) {
- column_number = 16383;
- break;
- }
- }
-
- return (column_number);
-}
-#endif /* OLDXAW */
-
-void
-_XawTextSourceChanged(Widget w, XawTextPosition left, XawTextPosition right,
- XawTextBlock *block, int lines)
-{
- TextWidget ctx = (TextWidget)w;
- Widget src = ctx->text.source;
- XawTextPosition update_from, update_to, top;
- Boolean update_disabled;
- int delta, line, line_from;
-
- if (left < ctx->text.old_insert) {
- XawTextPosition old_insert = ctx->text.old_insert;
-
- if (right < ctx->text.old_insert)
- old_insert -= right - left;
- else
- old_insert = left;
-
- ctx->text.insertPos = old_insert + block->length;
- }
-#ifndef OLDXAW
- if (left <= ctx->text.lt.top) {
- if (left + block->length - (right - left) < ctx->text.lt.top) {
- ctx->text.source_changed = SRC_CHANGE_BEFORE;
- ctx->text.lt.base_line += lines;
- }
- else
- ctx->text.source_changed = SRC_CHANGE_OVERLAP;
- }
- else
- ctx->text.source_changed = SRC_CHANGE_AFTER;
-#endif
-
- update_from = left;
- update_to = left + block->length;
- update_to = SrcScan(src, update_to, XawstEOL, XawsdRight, 1, False);
- delta = block->length - (right - left);
- if (delta < 0)
- ctx->text.clear_to_eol = True;
- if (update_to == update_from)
- ++update_to;
- update_disabled = ctx->text.update_disabled;
- ctx->text.update_disabled = True;
- ctx->text.lastPos = XawTextGetLastPosition(ctx);
- top = ctx->text.lt.info[0].position;
-
- XawTextUnsetSelection((Widget)ctx);
-
- if (delta) {
- int i;
- XmuSegment *seg;
-
- for (seg = ctx->text.update->segment; seg; seg = seg->next) {
- if (seg->x1 > (int)left)
- break;
- else if (seg->x2 > (int)left) {
- seg->x2 += delta;
- seg = seg->next;
- break;
- }
- }
- for (; seg; seg = seg->next) {
- seg->x1 += delta;
- seg->x2 += delta;
- }
- XmuOptimizeScanline(ctx->text.update);
-
- for (i = 0; i <= ctx->text.lt.lines; i++)
- if (ctx->text.lt.info[i].position > left)
- break;
- for (; i <= ctx->text.lt.lines; i++)
- ctx->text.lt.info[i].position += delta;
- }
-
- if (top != ctx->text.lt.info[0].position) {
- line_from = line = 0;
- ctx->text.lt.top = top = SrcScan(src, ctx->text.lt.info[0].position,
- XawstEOL, XawsdLeft, 1, False);
- update_from = top;
- }
- else {
- line_from = line = LineForPosition(ctx, update_from + delta);
- top = ctx->text.lt.info[line].position;
- }
-
- if (line > 0 && ctx->text.wrap == XawtextWrapWord) {
- --line;
- top = ctx->text.lt.info[line].position;
- }
-
- (void)_BuildLineTable(ctx, top, line);
-
- if (ctx->text.wrap == XawtextWrapWord) {
- if (line_from != LineForPosition(ctx, update_from)
- || line_from != LineForPosition(ctx, update_to)) {
- ctx->text.clear_to_eol = True;
- update_from = SrcScan(src, update_from,
- XawstWhiteSpace, XawsdLeft, 1, True);
- if (update_to >= ctx->text.lastPos)
- /* this is not an error, it just tells _BuildLineTable to
- * clear to the bottom of the window. The value of update_to
- * should not be > ctx->text.lastPos.
- */
- ++update_to;
- }
- }
- else if (!ctx->text.clear_to_eol) {
- if (LineForPosition(ctx, update_from)
- != LineForPosition(ctx, update_to))
- ctx->text.clear_to_eol = True;
- }
-
- _XawTextNeedsUpdating(ctx, update_from, update_to);
- ctx->text.update_disabled = update_disabled;
-}
-
-/*
- * Function:
- * _XawTextReplace
- *
- * Parameters:
- * ctx - text widget
- * left - left offset
- * right - right offset
- * block - text block
- *
- * Description:
- * Replaces the text between left and right by the text in block.
- * Does all the required calculations of offsets, and rebuild the
- * the line table, from the insertion point (or previous line, if
- * wrap mode is 'word').
- *
- * Returns:
- * XawEditDone - success
- * any other value - error code
- */
-int
-_XawTextReplace(TextWidget ctx, XawTextPosition left, XawTextPosition right,
- XawTextBlock *block)
-{
- Arg args[1];
- Widget src;
- XawTextEditType edit_mode;
-
- if (left == right && block->length == 0)
- return (XawEditDone);
-
- src = ctx->text.source;
- XtSetArg(args[0], XtNeditType, &edit_mode);
- XtGetValues(src, args, 1);
-
- if (edit_mode == XawtextAppend) {
- if (block->length == 0)
- return (XawEditError);
- ctx->text.insertPos = ctx->text.lastPos;
- }
-
-#ifndef OLDXAW
- return (SrcReplace(src, left, right, block));
-#else
- if (SrcReplace(src, left, right, block) == XawEditDone) {
- _XawTextSourceChanged((Widget)ctx, left, right, block, 0);
-
- return (XawEditDone);
- }
-
- return (XawEditError);
-#endif
-}
-
-/*
- * This routine will display text between two arbitrary source positions.
- * In the event that this span contains highlighted text for the selection,
- * only that portion will be displayed highlighted.
- */
-static void
-OldDisplayText(Widget w, XawTextPosition left, XawTextPosition right)
-{
- static XmuSegment segment;
- static XmuScanline next;
- static XmuScanline scanline = {0, &segment, &next};
- static XmuArea area = {&scanline};
-
- TextWidget ctx = (TextWidget)w;
- int x, y, line;
- XawTextPosition start, end, last, final;
- XmuScanline *scan;
- XmuSegment *seg;
- XmuArea *clip = NULL;
- Bool cleol = ctx->text.clear_to_eol;
- Bool has_selection = ctx->text.s.right > ctx->text.s.left;
-
- left = left < ctx->text.lt.top ? ctx->text.lt.top : left;
-
- if (left > right || !LineAndXYForPosition(ctx, left, &line, &x, &y))
- return;
-
- last = XawTextGetLastPosition(ctx);
- segment.x2 = (int)XtWidth(ctx) - ctx->text.r_margin.right;
-
- if (cleol)
- clip = XmuCreateArea();
-
- for (start = left; start < right && line < ctx->text.lt.lines; line++) {
- if ((end = ctx->text.lt.info[line + 1].position) > right)
- end = right;
-
- final = end;
- if (end > last)
- end = last;
-
- if (end > start) {
- if (!has_selection
- || (start >= ctx->text.s.right || end <= ctx->text.s.left))
- _XawTextSinkDisplayText(ctx->text.sink, x, y, start, end, False);
- else if (start >= ctx->text.s.left && end <= ctx->text.s.right)
- _XawTextSinkDisplayText(ctx->text.sink, x, y, start, end, True);
- else {
- OldDisplayText(w, start, ctx->text.s.left);
- OldDisplayText(w, Max(start, ctx->text.s.left),
- Min(end, ctx->text.s.right));
- OldDisplayText(w, ctx->text.s.right, end);
- }
- }
-
- x = ctx->text.left_margin;
- if (cleol) {
- segment.x1 = ctx->text.lt.info[line].textWidth + x;
- if (XmuValidSegment(&segment)) {
- scanline.y = y;
- next.y = ctx->text.lt.info[line + 1].y;
- XmuAreaOr(clip, &area);
- }
- }
-
- start = final;
- y = ctx->text.lt.info[line + 1].y;
- }
-
- if (cleol) {
- for (scan = clip->scanline; scan && scan->next; scan = scan->next)
- for (seg = scan->segment; seg; seg = seg->next)
- SinkClearToBG(ctx->text.sink,
- seg->x1, scan->y,
- seg->x2 - seg->x1, scan->next->y - scan->y);
- XmuDestroyArea(clip);
- }
-}
-
-#ifndef OLDXAW
-/*ARGSUSED*/
-static void
-DisplayText(Widget w, XawTextPosition left, XawTextPosition right)
-{
- static XmuSegment segment;
- static XmuScanline next;
- static XmuScanline scanline = {0, &segment, &next};
- static XmuArea area = {&scanline};
-
- TextWidget ctx = (TextWidget)w;
- int y, line;
- XawTextPosition from, to, lastPos;
- Bool cleol = ctx->text.clear_to_eol;
- Bool has_selection = ctx->text.s.right > ctx->text.s.left;
- XawTextPaintList *paint_list;
-
- left = left < ctx->text.lt.top ? ctx->text.lt.top : left;
-
- if (left > right || !IsPositionVisible(ctx, left))
- return;
-
- line = LineForPosition(ctx, left);
- y = ctx->text.lt.info[line].y;
- segment.x2 = (int)XtWidth(ctx) - ctx->text.r_margin.right;
- lastPos = XawTextGetLastPosition(ctx);
-
- paint_list = ((TextSinkObject)ctx->text.sink)->text_sink.paint;
-
- for (from = left; from < right && line < ctx->text.lt.lines; line++) {
- if ((to = ctx->text.lt.info[line + 1].position) > right)
- to = right;
-
- if (to > lastPos)
- to = lastPos;
-
- if (from < to) {
- if (!has_selection
- || (from >= ctx->text.s.right || to <= ctx->text.s.left))
- XawTextSinkPreparePaint(ctx->text.sink, y, line, from, to, False);
- else if (from >= ctx->text.s.left && to <= ctx->text.s.right)
- XawTextSinkPreparePaint(ctx->text.sink, y, line, from, to, True);
- else {
- XawTextSinkPreparePaint(ctx->text.sink, y, line, from,
- ctx->text.s.left, False);
- XawTextSinkPreparePaint(ctx->text.sink, y, line,
- XawMax(from, ctx->text.s.left),
- XawMin(to, ctx->text.s.right), True);
- XawTextSinkPreparePaint(ctx->text.sink, y, line,
- ctx->text.s.right, to, False);
- }
- }
-
- if (cleol) {
- segment.x1 = ctx->text.lt.info[line].textWidth + ctx->text.left_margin;
- if (XmuValidSegment(&segment)) {
- scanline.y = y;
- next.y = ctx->text.lt.info[line + 1].y;
- XmuAreaOr(paint_list->clip, &area);
- }
- }
- y = ctx->text.lt.info[line + 1].y;
- from = to;
- }
-
- /* clear to the bottom of the window */
- if (cleol && line >= ctx->text.lt.lines) {
- segment.x1 = ctx->text.left_margin;
- if (XmuValidSegment(&segment)) {
- scanline.y = y;
- next.y = (int)XtHeight(ctx) - (int)ctx->text.margin.bottom;
- XmuAreaOr(paint_list->clip, &area);
- }
- }
-}
-#endif
-
-/*
- * This routine implements multi-click selection in a hardwired manner.
- * It supports multi-click entity cycling (char, word, line, file) and mouse
- * motion adjustment of the selected entitie (i.e. select a word then, with
- * button still down, adjust wich word you really meant by moving the mouse).
- * [NOTE: This routine is to be replaced by a set of procedures that
- * will allows clients to implements a wide class of draw through and
- * multi-click selection user interfaces.]
- */
-static void
-DoSelection(TextWidget ctx, XawTextPosition pos, Time time, Bool motion)
-{
- XawTextPosition newLeft, newRight;
- XawTextSelectType newType, *sarray;
- Widget src = ctx->text.source;
-
- if (motion)
- newType = ctx->text.s.type;
- else {
- if ((abs((long) time - (long) ctx->text.lasttime) < MULTI_CLICK_TIME)
- && (pos >= ctx->text.s.left && pos <= ctx->text.s.right)) {
- sarray = ctx->text.sarray;
- for (; *sarray != XawselectNull && *sarray != ctx->text.s.type;
- sarray++)
- ;
- if (*sarray == XawselectNull)
- newType = *(ctx->text.sarray);
- else {
- newType = *(sarray + 1);
- if (newType == XawselectNull)
- newType = *(ctx->text.sarray);
- }
- }
- else /* single-click event */
- newType = *(ctx->text.sarray);
-
- ctx->text.lasttime = time;
- }
- switch (newType) {
- case XawselectPosition:
- newLeft = newRight = pos;
- break;
- case XawselectChar:
- newLeft = pos;
- newRight = SrcScan(src, pos, XawstPositions, XawsdRight, 1, False);
- break;
- case XawselectWord:
- case XawselectParagraph:
- case XawselectAlphaNumeric: {
- XawTextScanType stype;
-
- if (newType == XawselectWord)
- stype = XawstWhiteSpace;
- else if (newType == XawselectParagraph)
- stype = XawstParagraph;
- else
- stype = XawstAlphaNumeric;
-
- /*
- * Somewhat complicated, but basically I treat the space between
- * two objects as another object. The object that I am currently
- * in then becomes the end of the selection.
- *
- * Chris Peterson - 4/19/90.
- */
- newRight = SrcScan(ctx->text.source, pos, stype,
- XawsdRight, 1, False);
- newRight = SrcScan(ctx->text.source, newRight, stype,
- XawsdLeft, 1, False);
-
- if (pos != newRight)
- newLeft = SrcScan(ctx->text.source, pos, stype,
- XawsdLeft, 1, False);
- else
- newLeft = pos;
-
- newLeft =SrcScan(ctx->text.source, newLeft, stype,
- XawsdRight, 1, False);
-
- if (newLeft > newRight) {
- XawTextPosition temp = newLeft;
- newLeft = newRight;
- newRight = temp;
- }
- } break;
- case XawselectLine:
- newLeft = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False);
- newRight = SrcScan(src, pos, XawstEOL, XawsdRight, 1, False);
- break;
- case XawselectAll:
- newLeft = SrcScan(src, pos, XawstAll, XawsdLeft, 1, False);
- newRight = SrcScan(src, pos, XawstAll, XawsdRight, 1, False);
- break;
- default:
- XtAppWarning(XtWidgetToApplicationContext((Widget) ctx),
- "Text Widget: empty selection array.");
- return;
- }
-
- if (newLeft != ctx->text.s.left || newRight != ctx->text.s.right
- || newType != ctx->text.s.type) {
- ModifySelection(ctx, newLeft, newRight);
- if (pos - ctx->text.s.left < ctx->text.s.right - pos)
- ctx->text.insertPos = newLeft;
- else
- ctx->text.insertPos = newRight;
- ctx->text.s.type = newType;
- }
- if (!motion) { /* setup so we can freely mix select extend calls*/
- ctx->text.origSel.type = ctx->text.s.type;
- ctx->text.origSel.left = ctx->text.s.left;
- ctx->text.origSel.right = ctx->text.s.right;
-
- if (pos >= ctx->text.s.left + (ctx->text.s.right - ctx->text.s.left) / 2)
- ctx->text.extendDir = XawsdRight;
- else
- ctx->text.extendDir = XawsdLeft;
- }
-}
-
-/*
- * This routine implements extension of the currently selected text in
- * the "current" mode (i.e. char word, line, etc.). It worries about
- * extending from either end of the selection and handles the case when you
- * cross through the "center" of the current selection (e.g. switch which
- * end you are extending!).
- */
-static void
-ExtendSelection(TextWidget ctx, XawTextPosition pos, Bool motion)
-{
- XawTextScanDirection dir;
-
- if (!motion) { /* setup for extending selection */
- if (ctx->text.s.left == ctx->text.s.right) /* no current selection. */
- ctx->text.s.left = ctx->text.s.right = ctx->text.insertPos;
- else {
- ctx->text.origSel.left = ctx->text.s.left;
- ctx->text.origSel.right = ctx->text.s.right;
- }
-
- ctx->text.origSel.type = ctx->text.s.type;
-
- if (pos >= ctx->text.s.left + (ctx->text.s.right - ctx->text.s.left) / 2)
- ctx->text.extendDir = XawsdRight;
- else
- ctx->text.extendDir = XawsdLeft;
- }
- else /* check for change in extend direction */
- if ((ctx->text.extendDir == XawsdRight &&
- pos <= ctx->text.origSel.left) ||
- (ctx->text.extendDir == XawsdLeft &&
- pos >= ctx->text.origSel.right)) {
- ctx->text.extendDir = (ctx->text.extendDir == XawsdRight) ?
- XawsdLeft : XawsdRight;
- ModifySelection(ctx, ctx->text.origSel.left, ctx->text.origSel.right);
- }
-
- dir = ctx->text.extendDir;
- switch (ctx->text.s.type) {
- case XawselectWord:
- case XawselectParagraph:
- case XawselectAlphaNumeric: {
- XawTextPosition left_pos, right_pos;
- XawTextScanType stype;
-
- if (ctx->text.s.type == XawselectWord)
- stype = XawstWhiteSpace;
- else if (ctx->text.s.type == XawselectParagraph)
- stype = XawstParagraph;
- else
- stype = XawstAlphaNumeric;
-
- /*
- * Somewhat complicated, but basically I treat the space between
- * two objects as another object. The object that I am currently
- * in then becomes the end of the selection.
- *
- * Chris Peterson - 4/19/90.
- */
- right_pos = SrcScan(ctx->text.source, pos, stype,
- XawsdRight, 1, False);
- right_pos =SrcScan(ctx->text.source, right_pos, stype,
- XawsdLeft, 1, False);
-
- if (pos != right_pos)
- left_pos = SrcScan(ctx->text.source, pos, stype,
- XawsdLeft, 1, False);
- else
- left_pos = pos;
-
- left_pos =SrcScan(ctx->text.source, left_pos, stype,
- XawsdRight, 1, False);
-
- if (dir == XawsdLeft)
- pos = Min(left_pos, right_pos);
- else /* dir == XawsdRight */
- pos = Max(left_pos, right_pos);
- } break;
- case XawselectLine:
- pos = SrcScan(ctx->text.source, pos, XawstEOL,
- dir, 1, dir == XawsdRight);
- break;
- case XawselectAll:
- pos = ctx->text.insertPos;
- /*FALLTHROUGH*/
- case XawselectPosition:
- default:
- break;
- }
-
- if (dir == XawsdRight)
- ModifySelection(ctx, ctx->text.s.left, pos);
- else
- ModifySelection(ctx, pos, ctx->text.s.right);
-
- ctx->text.insertPos = pos;
-}
-
-/*
- * Function:
- * _XawTextClearAndCenterDisplay
- *
- * Parameters:
- * ctx - text widget
- *
- * Description:
- * Redraws the display with the cursor in insert point
- * centered vertically.
- */
-void
-_XawTextClearAndCenterDisplay(TextWidget ctx)
-{
- int left_margin = ctx->text.left_margin;
- Bool visible = IsPositionVisible(ctx, ctx->text.insertPos);
-
- _XawTextShowPosition(ctx);
-
- if (XtIsRealized((Widget)ctx) && visible &&
- left_margin == ctx->text.left_margin) {
- int insert_line = LineForPosition(ctx, ctx->text.insertPos);
- int scroll_by = insert_line - (ctx->text.lt.lines >> 1);
- Boolean clear_to_eol = ctx->text.clear_to_eol;
-
- XawTextScroll(ctx, scroll_by, 0);
- SinkClearToBG(ctx->text.sink, 0, 0, XtWidth(ctx), XtHeight(ctx));
- ClearWindow(ctx);
- clear_to_eol = ctx->text.clear_to_eol;
- ctx->text.clear_to_eol = False;
- FlushUpdate(ctx);
- ctx->text.clear_to_eol = clear_to_eol;
- }
-}
-
-/*
- * Internal redisplay entire window
- * Legal to call only if widget is realized
- */
-static void
-DisplayTextWindow(Widget w)
-{
- TextWidget ctx = (TextWidget)w;
-
- _XawTextBuildLineTable(ctx, ctx->text.lt.top, False);
- ClearWindow(ctx);
-}
-
-static void
-TextSinkResize(Widget w)
-{
- if (w && XtClass(w)->core_class.resize)
- XtClass(w)->core_class.resize(w);
-}
-
-/* ARGSUSED */
-void
-_XawTextCheckResize(TextWidget ctx)
-{
- return;
-}
-
-/*
- * Converts (params, num_params) to a list of atoms & caches the
- * list in the TextWidget instance.
- */
-Atom *
-_XawTextSelectionList(TextWidget ctx, String *list, Cardinal nelems)
-{
- Atom *sel = ctx->text.s.selections;
- Display *dpy = XtDisplay((Widget)ctx);
- int n;
-
- if (nelems > (Cardinal)ctx->text.s.array_size) {
- sel = (Atom *)XtRealloc((char *)sel, sizeof(Atom) * nelems);
- ctx->text.s.array_size = nelems;
- ctx->text.s.selections = sel;
- }
- for (n = nelems; --n >= 0; sel++, list++)
- *sel = XInternAtom(dpy, *list, False);
- ctx->text.s.atom_count = nelems;
-
- return (ctx->text.s.selections);
-}
-
-/*
- * Function:
- * SetSelection
- *
- * Parameters:
- * ctx - text widget
- * defaultSel - default selection
- * l - left and right ends of the selection
- * r - ""
- * list - the selection list (as strings).
- * nelems - ""
- *
- * Description:
- * Sets the current selection.
- *
- * Note:
- * if (ctx->text.s.left >= ctx->text.s.right) then the selection is unset
- */
-void
-_XawTextSetSelection(TextWidget ctx, XawTextPosition l, XawTextPosition r,
- String *list, Cardinal nelems)
-{
- if (nelems == 1 && !strcmp (list[0], "none"))
- return;
- if (nelems == 0) {
- String defaultSel = "PRIMARY";
- list = &defaultSel;
- nelems = 1;
- }
- _SetSelection(ctx, l, r, _XawTextSelectionList(ctx, list, nelems), nelems);
-}
-
-/*
- * Function:
- * ModifySelection
- *
- * Parameters:
- * ctx - text widget
- * left - left and right ends of the selection
- * right - ""
- *
- * Description:
- * Modifies the current selection.
- *
- * Note:
- * if (ctx->text.s.left >= ctx->text.s.right) then the selection is unset
- */
-static void
-ModifySelection(TextWidget ctx, XawTextPosition left, XawTextPosition right)
-{
- if (left == right)
- ctx->text.insertPos = left;
- _SetSelection(ctx, left, right, NULL, 0);
-}
-
-/*
- * This routine is used to perform various selection functions. The goal is
- * to be able to specify all the more popular forms of draw-through and
- * multi-click selection user interfaces from the outside.
- */
-void
-_XawTextAlterSelection(TextWidget ctx, XawTextSelectionMode mode,
- XawTextSelectionAction action, String *params,
- Cardinal *num_params)
-{
- XawTextPosition position;
- Boolean flag;
-
- /*
- * This flag is used by TextPop.c:DoReplace() to determine if the selection
- * is okay to use, or if it has been modified.
- */
- if (ctx->text.search != NULL)
- ctx->text.search->selection_changed = True;
-
- position = PositionForXY(ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y);
-
- flag = (action != XawactionStart);
- if (mode == XawsmTextSelect)
- DoSelection(ctx, position, ctx->text.time, flag);
- else /* mode == XawsmTextExtend */
- ExtendSelection (ctx, position, flag);
-
- if (action == XawactionEnd)
- _XawTextSetSelection(ctx, ctx->text.s.left, ctx->text.s.right,
- params, *num_params);
-}
-
-/*
- * Function:
- * UpdateTextInRectangle
- *
- * Parameters:
- * ctx - the text widget
- * rect - rectangle
- *
- * Description:
- * Updates the text in the given rectangle
- */
-static void
-UpdateTextInRectangle(TextWidget ctx, XRectangle *rect)
-{
- XawTextLineTable *lt;
- int line, y1, y2, x2;
-
- y1 = rect->y;
- y2 = y1 + rect->height;
- x2 = rect->x + rect->width;
-
- for (line = 0, lt = &ctx->text.lt; line < lt->lines; line++)
- if (lt->info[line + 1].y > y1)
- break;
- for (; line <= lt->lines; line++) {
- if (lt->info[line].y > y2)
- break;
- UpdateTextInLine(ctx, line, rect->x, x2);
- }
-}
-
-/*
- * This routine processes all "expose region" XEvents. In general, its job
- * is to the best job at minimal re-paint of the text, displayed in the
- * window, that it can.
- */
-/* ARGSUSED */
-static void
-XawTextExpose(Widget w, XEvent *event, Region region)
-{
- TextWidget ctx = (TextWidget)w;
- Boolean clear_to_eol;
- XRectangle expose;
-
- if (event->type == Expose) {
- expose.x = event->xexpose.x;
- expose.y = event->xexpose.y;
- expose.width = event->xexpose.width;
- expose.height = event->xexpose.height;
- }
- else if (event->type == GraphicsExpose) {
- expose.x = event->xgraphicsexpose.x;
- expose.y = event->xgraphicsexpose.y;
- expose.width = event->xgraphicsexpose.width;
- expose.height = event->xgraphicsexpose.height;
- }
- else
- return;
-
- _XawTextPrepareToUpdate(ctx);
-
- if (Superclass->core_class.expose)
- (*Superclass->core_class.expose)(w, event, region);
-
- clear_to_eol = ctx->text.clear_to_eol;
- ctx->text.clear_to_eol = False;
-
- UpdateTextInRectangle(ctx, &expose);
- XawTextSinkGetCursorBounds(ctx->text.sink, &expose);
- UpdateTextInRectangle(ctx, &expose);
- SinkClearToBG(ctx->text.sink, expose.x, expose.y,
- expose.width, expose.height);
- _XawTextExecuteUpdate(ctx);
- ctx->text.clear_to_eol = clear_to_eol;
-}
-
-/*
- * This routine does all setup required to syncronize batched screen updates
- */
-void
-_XawTextPrepareToUpdate(TextWidget ctx)
-{
- if (ctx->text.old_insert < 0) {
- InsertCursor((Widget)ctx, XawisOff);
- ctx->text.showposition = False;
- ctx->text.old_insert = ctx->text.insertPos;
- ctx->text.clear_to_eol = False;
-#ifndef OLDXAW
- ctx->text.source_changed = SRC_CHANGE_NONE;
-#endif
- }
-}
-
-/*
- * This is a private utility routine used by _XawTextExecuteUpdate. It
- * processes all the outstanding update requests and merges update
- * ranges where possible.
- */
-static void
-FlushUpdate(TextWidget ctx)
-{
- XmuSegment *seg;
- void (*display_text)(Widget, XawTextPosition, XawTextPosition);
-
- if (XtIsRealized((Widget)ctx)) {
- ctx->text.s.right = XawMin(ctx->text.s.right, ctx->text.lastPos);
- ctx->text.s.left = XawMin(ctx->text.s.left, ctx->text.s.right);
-
-#ifndef OLDXAW
- if (XawTextSinkBeginPaint(ctx->text.sink) == False)
-#endif
- display_text = OldDisplayText;
-#ifndef OLDXAW
- else
- display_text = DisplayText;
-#endif
- for (seg = ctx->text.update->segment; seg; seg = seg->next)
- (*display_text)((Widget)ctx,
- (XawTextPosition)seg->x1,
- (XawTextPosition)seg->x2);
-#ifndef OLDXAW
- if (display_text != OldDisplayText) {
- XawTextSinkDoPaint(ctx->text.sink);
- XawTextSinkEndPaint(ctx->text.sink);
- }
-#endif
- }
- (void)XmuScanlineXor(ctx->text.update, ctx->text.update);
-}
-
-static int
-CountLines(TextWidget ctx, XawTextPosition left, XawTextPosition right)
-{
- if (ctx->text.wrap == XawtextWrapNever || left >= right)
- return (1);
- else {
- XawTextPosition tmp;
- int dim, lines = 0, wwidth = GetMaxTextWidth(ctx);
-
- while (left < right) {
- tmp = left;
- XawTextSinkFindPosition(ctx->text.sink, left,
- ctx->text.left_margin,
- wwidth, ctx->text.wrap == XawtextWrapWord,
- &left, &dim, &dim);
- ++lines;
- if (tmp == left)
- ++left;
- }
-
- return (lines);
- }
- /*NOTREACHED*/
-}
-
-static int
-GetMaxTextWidth(TextWidget ctx)
-{
- XRectangle cursor;
- int width;
-
- XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
- width = (int)XtWidth(ctx) - RHMargins(ctx) - cursor.width;
-
- return (XawMax(0, width));
-}
-
-/*
- * Function:
- * _XawTextShowPosition
- *
- * Parameters:
- * ctx - the text widget to show the position
- *
- * Description:
- * Makes sure the text cursor visible, scrolling the text window
- * if required.
- */
-void
-_XawTextShowPosition(TextWidget ctx)
-{
- /*
- * Variable scroll is used to avoid scanning large files to calculate
- * line offsets
- */
- int hpixels, vlines;
- XawTextPosition first, last, top, tmp;
- Bool visible, scroll;
-
- if (!XtIsRealized((Widget)ctx))
- return;
-
- /*
- * Checks if a horizontal scroll is required
- */
- if (ctx->text.wrap == XawtextWrapNever) {
- int x, vwidth, distance, dim;
- XRectangle rect;
-
- vwidth = (int)XtWidth(ctx) - RHMargins(ctx);
- last = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstEOL, XawsdLeft, 1, False);
- XawTextSinkFindDistance(ctx->text.sink, last,
- ctx->text.left_margin,
- ctx->text.insertPos,
- &distance, &first, &dim);
- XawTextSinkGetCursorBounds(ctx->text.sink, &rect);
- x = ctx->text.left_margin - ctx->text.r_margin.left;
-
- if (x + distance + rect.width > vwidth)
- hpixels = x + distance + rect.width - vwidth + (vwidth >> 2);
- else if (x + distance < 0)
- hpixels = x + distance - (vwidth >> 2);
- else
- hpixels = 0;
- }
- else
- hpixels = 0;
-
- visible = IsPositionVisible(ctx, ctx->text.insertPos);
-
- /*
- * If the cursor is already visible
- */
- if (!hpixels && visible)
- return;
-
- scroll = ctx->core.background_pixmap == XtUnspecifiedPixmap && !hpixels;
- vlines = 0;
- first = ctx->text.lt.top;
-
- /*
- * Needs to scroll the text window
- */
- if (visible)
- top = ctx->text.lt.top;
- else {
- top = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstEOL, XawsdLeft, 1, False);
-
- /*
- * Finds the nearest left position from ctx->text.insertPos
- */
- if (ctx->text.wrap != XawtextWrapNever) {
- int dim, vwidth = GetMaxTextWidth(ctx);
-
- last = top;
- /*CONSTCOND*/
- while (1) {
- tmp = last;
- XawTextSinkFindPosition(ctx->text.sink, last,
- ctx->text.left_margin, vwidth,
- ctx->text.wrap == XawtextWrapWord,
- &last, &dim, &dim);
- if (last == tmp)
- ++last;
- if (last <= ctx->text.insertPos)
- top = last;
- else
- break;
- }
- }
- }
-
- if (scroll) {
- if (ctx->text.insertPos < first) { /* Scroll Down */
- while (first > top) {
- last = first;
- first = SrcScan(ctx->text.source, first,
- XawstEOL, XawsdLeft, 2, False);
- vlines -= CountLines(ctx, first, last);
- if (-vlines >= ctx->text.lt.lines) {
- scroll = False;
- break;
- }
- }
- }
- else if (!visible) { /* Scroll Up */
- while (first < top) {
- last = first;
- first = SrcScan(ctx->text.source, first,
- XawstEOL, XawsdRight, 1, True);
- vlines += CountLines(ctx, last, first);
- if (vlines > ctx->text.lt.lines) {
- scroll = False;
- break;
- }
- }
- }
- else
- scroll = False;
- }
-
- /*
- * If a portion of the text that will be scrolled is visible
- */
- if (scroll)
- XawTextScroll(ctx, vlines ? vlines - (ctx->text.lt.lines >> 1) : 0, 0);
- /*
- * Else redraw the entire text window
- */
- else {
- ctx->text.left_margin -= hpixels;
- if (ctx->text.left_margin > ctx->text.r_margin.left)
- ctx->text.left_margin = ctx->text.margin.left =
- ctx->text.r_margin.left;
-
- if (!visible) {
- vlines = ctx->text.lt.lines >> 1;
- if (vlines)
- top = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstEOL, XawsdLeft, vlines + 1, False);
-
- if (ctx->text.wrap != XawtextWrapNever) {
- int dim;
- int n_lines = CountLines(ctx, top, ctx->text.insertPos);
- int vwidth = GetMaxTextWidth(ctx);
-
- while (n_lines-- > vlines) {
- tmp = top;
- XawTextSinkFindPosition(ctx->text.sink, top,
- ctx->text.left_margin,
- vwidth,
- ctx->text.wrap == XawtextWrapWord,
- &top, &dim, &dim);
- if (tmp == top)
- ++top;
- }
- }
- _XawTextBuildLineTable(ctx, top, True);
- }
- else
- ClearWindow(ctx);
- }
- ctx->text.clear_to_eol = True;
-}
-
-#ifndef OLDXAW
-static int
-ResolveLineNumber(TextWidget ctx)
-{
- int line_number = ctx->text.lt.base_line;
- XawTextPosition position = ctx->text.lt.top;
-
- if (ctx->text.lt.base_line < 1)
- return (ctx->text.line_number);
-
- if (ctx->text.wrap == XawtextWrapNever
- && IsPositionVisible(ctx, ctx->text.insertPos))
- line_number += LineForPosition(ctx, ctx->text.insertPos);
- else if (position < ctx->text.insertPos) {
- while (position < ctx->text.insertPos) {
- position = SrcScan(ctx->text.source, position,
- XawstEOL, XawsdRight, 1, True);
- if (position <= ctx->text.insertPos) {
- ++line_number;
- if (position == ctx->text.lastPos) {
- line_number -= !_XawTextSourceNewLineAtEOF(ctx->text.source);
- break;
- }
- }
- }
- }
- else if (position > ctx->text.insertPos) {
- while (position > ctx->text.insertPos) {
- position = SrcScan(ctx->text.source, position,
- XawstEOL, XawsdLeft, 1, False);
- if (--position >= ctx->text.insertPos)
- --line_number;
- }
- }
-
- return (line_number);
-}
-#endif
-
-/*
- * This routine causes all batched screen updates to be performed
- */
-void
-_XawTextExecuteUpdate(TextWidget ctx)
-{
- if (ctx->text.update_disabled || ctx->text.old_insert < 0)
- return;
-
- if(ctx->text.old_insert != ctx->text.insertPos || ctx->text.showposition)
- _XawTextShowPosition(ctx);
-
- FlushUpdate(ctx);
- InsertCursor((Widget)ctx, XawisOn);
- ctx->text.old_insert = -1;
-#ifndef OLDXAW
- _XawTextSetLineAndColumnNumber(ctx, False);
-#endif
-}
-
-static void
-XawTextDestroy(Widget w)
-{
- TextWidget ctx = (TextWidget)w;
-
- DestroyHScrollBar(ctx);
- DestroyVScrollBar(ctx);
-
- XtFree((char *)ctx->text.s.selections);
- XtFree((char *)ctx->text.lt.info);
- XtFree((char *)ctx->text.search);
- XmuDestroyScanline(ctx->text.update);
- XtReleaseGC((Widget)ctx, ctx->text.gc);
-}
-
-/*
- * by the time we are managed (and get this far) we had better
- * have both a source and a sink
- */
-static void
-XawTextResize(Widget w)
-{
- TextWidget ctx = (TextWidget)w;
-
- PositionVScrollBar(ctx);
- PositionHScrollBar(ctx);
- TextSinkResize(ctx->text.sink);
-
- ctx->text.showposition = True;
- _XawTextBuildLineTable(ctx, ctx->text.lt.top, True);
-}
-
-/*
- * This routine allow the application program to Set attributes.
- */
-/*ARGSUSED*/
-static Boolean
-XawTextSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- TextWidget oldtw = (TextWidget)current;
- TextWidget newtw = (TextWidget)cnew;
- Boolean redisplay = False;
- Boolean display_caret = newtw->text.display_caret;
-#ifndef OLDXAW
- Boolean show_lc = False;
-#endif
-
- newtw->text.display_caret = oldtw->text.display_caret;
- _XawTextPrepareToUpdate(newtw);
- newtw->text.display_caret = display_caret;
-
- if (oldtw->text.r_margin.left != newtw->text.r_margin.left) {
- newtw->text.left_margin = newtw->text.margin.left =
- newtw->text.r_margin.left;
- if (newtw->text.vbar != NULL) {
- newtw->text.left_margin += XtWidth(newtw->text.vbar) +
- XtBorderWidth(newtw->text.vbar);
- }
- redisplay = True;
- }
-
- if (oldtw->text.scroll_vert != newtw->text.scroll_vert) {
- if (newtw->text.scroll_vert == XawtextScrollAlways)
- CreateVScrollBar(newtw);
- else
- DestroyVScrollBar(newtw);
-
- redisplay = True;
- }
-
- if (oldtw->text.r_margin.bottom != newtw->text.r_margin.bottom) {
- newtw->text.margin.bottom = newtw->text.r_margin.bottom;
- if (newtw->text.hbar != NULL)
- newtw->text.margin.bottom += newtw->text.hbar->core.height +
- newtw->text.hbar->core.border_width;
- redisplay = True;
- }
-
- if (oldtw->text.scroll_horiz != newtw->text.scroll_horiz) {
- if (newtw->text.scroll_horiz == XawtextScrollAlways)
- CreateHScrollBar(newtw);
- else
- DestroyHScrollBar(newtw);
-
- redisplay = True;
- }
-
- if (oldtw->text.source != newtw->text.source) {
-#ifndef OLDXAW
- show_lc = True;
- _XawSourceRemoveText(oldtw->text.source, cnew,
- oldtw->text.source &&
- XtParent(oldtw->text.source) == cnew);
- _XawSourceAddText(newtw->text.source, cnew);
-#endif
- _XawTextSetSource((Widget)newtw, newtw->text.source, newtw->text.lt.top,
- newtw->text.insertPos);
- }
-
- newtw->text.redisplay_needed = False;
- XtSetValues((Widget)newtw->text.source, args, *num_args);
- XtSetValues((Widget)newtw->text.sink, args, *num_args);
-
- if (oldtw->text.wrap != newtw->text.wrap
- || oldtw->text.lt.top != newtw->text.lt.top
- || oldtw->text.insertPos != newtw->text.insertPos
- || oldtw->text.r_margin.right != newtw->text.r_margin.right
- || oldtw->text.r_margin.top != newtw->text.r_margin.top
- || oldtw->text.sink != newtw->text.sink
- || newtw->text.redisplay_needed) {
- if (oldtw->text.wrap != newtw->text.wrap) {
- newtw->text.left_margin = newtw->text.margin.left =
- newtw->text.r_margin.left;
- if (oldtw->text.lt.top == newtw->text.lt.top)
- newtw->text.lt.top = SrcScan(newtw->text.source, 0, XawstEOL,
- XawsdLeft, 1, False);
- }
- newtw->text.showposition = True;
-#ifndef OLDXAW
- show_lc = True;
- newtw->text.source_changed = SRC_CHANGE_OVERLAP;
-#endif
- _XawTextBuildLineTable(newtw, newtw->text.lt.top, True);
- redisplay = True;
- }
-
-#ifndef OLDXAW
- if (newtw->text.left_column < 0)
- newtw->text.left_column = 0;
- if (newtw->text.right_column < 0)
- newtw->text.right_column = 0;
-#endif
-
- _XawTextExecuteUpdate(newtw);
-
-#ifndef OLDXAW
- if (show_lc)
- _XawTextSetLineAndColumnNumber(newtw, True);
-#endif
-
- if (redisplay)
- _XawTextSetScrollBars(newtw);
-
- return (redisplay);
-}
-
-/* invoked by the Simple widget's SetValues */
-static Bool
-XawTextChangeSensitive(Widget w)
-{
- Arg args[1];
- TextWidget tw = (TextWidget)w;
-
- (*(&simpleClassRec)->simple_class.change_sensitive)(w);
-
- XtSetArg(args[0], XtNancestorSensitive,
- (tw->core.ancestor_sensitive && tw->core.sensitive));
- if (tw->text.vbar)
- XtSetValues(tw->text.vbar, args, ONE);
- if (tw->text.hbar)
- XtSetValues(tw->text.hbar, args, ONE);
- return (False);
-}
-
-/*
- * Function:
- * XawTextGetValuesHook
- *
- * Parameters:
- * w - Text Widget
- * args - argument list
- * num_args - number of args
- *
- * Description:
- * This is a get values hook routine that gets the
- * values in the text source and sink.
- */
-static void
-XawTextGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
-{
- XtGetValues(((TextWidget)w)->text.source, args, *num_args);
- XtGetValues(((TextWidget)w)->text.sink, args, *num_args);
-}
-
-/*
- * Function:
- * FindGoodPosition
- *
- * Parameters:
- * pos - any position
- *
- * Description:
- * Returns a valid position given any postition.
- *
- * Returns:
- * A position between (0 and lastPos)
- */
-static XawTextPosition
-FindGoodPosition(TextWidget ctx, XawTextPosition pos)
-{
- if (pos < 0)
- return (0);
- return (((pos > ctx->text.lastPos) ? ctx->text.lastPos : pos));
-}
-
-/* Li wrote this so the IM can find a given text position's screen position */
-void
-_XawTextPosToXY(Widget w, XawTextPosition pos, Position *x, Position *y)
-{
- int line, ix, iy;
-
- LineAndXYForPosition((TextWidget)w, pos, &line, &ix, &iy);
- *x = ix;
- *y = iy;
-}
-
-/*******************************************************************
-The following routines provide procedural interfaces to Text window state
-setting and getting. They need to be redone so than the args code can use
-them. I suggest we create a complete set that takes the context as an
-argument and then have the public version lookup the context and call the
-internal one. The major value of this set is that they have actual application
-clients and therefore the functionality provided is required for any future
-version of Text.
-********************************************************************/
-void
-XawTextDisplay(Widget w)
-{
- TextWidget ctx = (TextWidget)w;
-
- if (!XtIsRealized(w))
- return;
-
- _XawTextPrepareToUpdate(ctx);
- ctx->text.clear_to_eol = True;
- DisplayTextWindow(w);
- _XawTextExecuteUpdate(ctx);
-}
-
-void
-XawTextSetSelectionArray(Widget w, XawTextSelectType *sarray)
-{
- ((TextWidget)w)->text.sarray = sarray;
-}
-
-void
-XawTextGetSelectionPos(Widget w, XawTextPosition *left, XawTextPosition *right)
-{
- *left = ((TextWidget)w)->text.s.left;
- *right = ((TextWidget)w)->text.s.right;
-}
-
-void
-_XawTextSetSource(Widget w, Widget source,
- XawTextPosition top, XawTextPosition startPos)
-{
- TextWidget ctx = (TextWidget)w;
-#ifndef OLDXAW
- Bool resolve = False;
-#endif
-
-#ifndef OLDXAW
- if (source != ctx->text.source)
- _XawSourceRemoveText(ctx->text.source, w, ctx->text.source &&
- XtParent(ctx->text.source) == w);
- _XawSourceAddText(source, w);
-
- if (source != ctx->text.source || ctx->text.insertPos != startPos)
- resolve = True;
-
- ctx->text.source_changed = SRC_CHANGE_OVERLAP;
-#endif
- ctx->text.source = source;
- ctx->text.s.left = ctx->text.s.right = 0;
- ctx->text.lastPos = GETLASTPOS;
- top = FindGoodPosition(ctx, top);
- startPos = FindGoodPosition(ctx, startPos);
- ctx->text.insertPos = ctx->text.old_insert = startPos;
- _XawTextPrepareToUpdate(ctx);
-
- _XawTextBuildLineTable(ctx, top, True);
-
- _XawTextExecuteUpdate(ctx);
-#ifndef OLDXAW
- if (resolve)
- _XawTextSetLineAndColumnNumber(ctx, True);
-#endif
-}
-
-void
-XawTextSetSource(Widget w, Widget source, XawTextPosition top)
-{
- _XawTextSetSource(w, source, top, top);
-}
-
-/*
- * This public routine deletes the text from startPos to endPos in a source and
- * then inserts, at startPos, the text that was passed. As a side effect it
- * "invalidates" that portion of the displayed text (if any), so that things
- * will be repainted properly.
- */
-int
-XawTextReplace(Widget w, XawTextPosition startPos, XawTextPosition endPos,
- XawTextBlock *text)
-{
- TextWidget ctx = (TextWidget)w;
- int result;
-#ifndef OLDXAW
- Cardinal i;
- TextSrcObject src = (TextSrcObject)ctx->text.source;
-
- for (i = 0; i < src->textSrc.num_text; i++)
- _XawTextPrepareToUpdate((TextWidget)src->textSrc.text[i]);
-#else
- _XawTextPrepareToUpdate(ctx);
-#endif
-
- endPos = FindGoodPosition(ctx, endPos);
- startPos = FindGoodPosition(ctx, startPos);
- result = _XawTextReplace(ctx, startPos, endPos, text);
-
-#ifndef OLDXAW
- for (i = 0; i < src->textSrc.num_text; i++)
- _XawTextExecuteUpdate((TextWidget)src->textSrc.text[i]);
-#else
- _XawTextExecuteUpdate(ctx);
-#endif
-
- return (result);
-}
-
-XawTextPosition
-XawTextTopPosition(Widget w)
-{
- return (((TextWidget)w)->text.lt.top);
-}
-
-XawTextPosition
-XawTextLastPosition(Widget w)
-{
- return (((TextWidget)w)->text.lastPos);
-}
-
-void
-XawTextSetInsertionPoint(Widget w, XawTextPosition position)
-{
- TextWidget ctx = (TextWidget)w;
-
- _XawTextPrepareToUpdate(ctx);
- ctx->text.insertPos = FindGoodPosition(ctx, position);
- ctx->text.showposition = True;
- ctx->text.from_left = -1;
-
- _XawTextExecuteUpdate(ctx);
-#ifndef OLDXAW
- _XawTextSetLineAndColumnNumber(ctx, False);
-#endif
-}
-
-XawTextPosition
-XawTextGetInsertionPoint(Widget w)
-{
- return (((TextWidget)w)->text.insertPos);
-}
-
-/*
- * Note: Must walk the selection list in opposite order from TextLoseSelection
- */
-void
-XawTextUnsetSelection(Widget w)
-{
- TextWidget ctx = (TextWidget)w;
-
- while (ctx->text.s.atom_count != 0) {
- Atom sel = ctx->text.s.selections[ctx->text.s.atom_count - 1];
-
- if (sel != (Atom) 0) {
- /*
- * As selections are lost the atom_count will decrement
- */
- if (GetCutBufferNumber(sel) == NOT_A_CUT_BUFFER)
- XtDisownSelection(w, sel, ctx->text.time);
- TextLoseSelection(w, &sel); /* In case this is a cut buffer, or
- XtDisownSelection failed to call us */
- }
- }
-}
-
-void
-XawTextSetSelection(Widget w, XawTextPosition left, XawTextPosition right)
-{
- TextWidget ctx = (TextWidget)w;
-
- _XawTextPrepareToUpdate(ctx);
- _XawTextSetSelection(ctx, FindGoodPosition(ctx, left),
- FindGoodPosition(ctx, right), NULL, 0);
- _XawTextExecuteUpdate(ctx);
-}
-
-void
-XawTextInvalidate(Widget w, XawTextPosition from, XawTextPosition to)
-{
- TextWidget ctx = (TextWidget)w;
-
- from = FindGoodPosition(ctx, from);
- to = FindGoodPosition(ctx, to);
- ctx->text.lastPos = GETLASTPOS;
- _XawTextPrepareToUpdate(ctx);
- _XawTextNeedsUpdating(ctx, from, to);
- _XawTextExecuteUpdate(ctx);
-}
-
-/*ARGSUSED*/
-void
-XawTextDisableRedisplay(Widget w)
-{
- ((TextWidget)w)->text.update_disabled = True;
- _XawTextPrepareToUpdate((TextWidget)w);
-}
-
-void
-XawTextEnableRedisplay(Widget w)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition lastPos;
-
- if (!ctx->text.update_disabled)
- return;
-
- ctx->text.update_disabled = False;
- lastPos = ctx->text.lastPos = GETLASTPOS;
- ctx->text.lt.top = FindGoodPosition(ctx, ctx->text.lt.top);
- ctx->text.insertPos = FindGoodPosition(ctx, ctx->text.insertPos);
-
- if (ctx->text.s.left > lastPos || ctx->text.s.right > lastPos)
- ctx->text.s.left = ctx->text.s.right = 0;
-
- _XawTextExecuteUpdate(ctx);
-}
-
-Widget
-XawTextGetSource(Widget w)
-{
- return (((TextWidget)w)->text.source);
-}
-
-Widget
-XawTextGetSink(Widget w)
-{
- return (((TextWidget)w)->text.sink);
-}
-
-void
-XawTextDisplayCaret(Widget w,
-#if NeedWidePrototypes
- int display_caret
-#else
- Boolean display_caret
-#endif
-)
-{
- TextWidget ctx = (TextWidget)w;
-
- if (XtIsRealized(w)) {
- _XawTextPrepareToUpdate(ctx);
- ctx->text.display_caret = display_caret;
- _XawTextExecuteUpdate(ctx);
- }
- else
- ctx->text.display_caret = display_caret;
-}
-
-/*
- * Function:
- * XawTextSearch
- *
- * Parameters:
- * w - text widget
- * dir - direction to search
- * text - text block containing info about the string to search for
- *
- * Description:
- * Searches for the given text block.
- *
- * Returns:
- * The position of the text found, or XawTextSearchError on an error
- */
-XawTextPosition
-XawTextSearch(Widget w,
-#if NeedWidePrototypes
- int dir,
-#else
- XawTextScanDirection dir,
-#endif
- XawTextBlock *text)
-{
- TextWidget ctx = (TextWidget)w;
-
- return (SrcSearch(ctx->text.source, ctx->text.insertPos, dir, text));
-}
-
-TextClassRec textClassRec = {
- /* core */
- {
- (WidgetClass)&simpleClassRec, /* superclass */
- "Text", /* class_name */
- sizeof(TextRec), /* widget_size */
- XawTextClassInitialize, /* class_initialize */
- NULL, /* class_part_init */
- False, /* class_inited */
- XawTextInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawTextRealize, /* realize */
- _XawTextActionsTable, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resource */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- XtExposeGraphicsExpose | /* compress_exposure */
- XtExposeNoExpose,
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawTextDestroy, /* destroy */
- XawTextResize, /* resize */
- XawTextExpose, /* expose */
- XawTextSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- XawTextGetValuesHook, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- _XawDefaultTextTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XawTextChangeSensitive, /* change_sensitive */
- },
- /* text */
- {
- NULL, /* extension */
- }
-};
-
-WidgetClass textWidgetClass = (WidgetClass)&textClassRec;
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Copyright (c) 1998 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <X11/Xatom.h> +#include <X11/Xfuncs.h> +#include <X11/Xutil.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xmu/Xmu.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/MultiSinkP.h> +#include <X11/Xaw/TextP.h> +#include <X11/Xaw/TextSrcP.h> +#include <X11/Xaw/TextSinkP.h> +#include <X11/Xaw/Scrollbar.h> +#include <X11/Xaw/XawImP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" +#include "XawI18n.h" + +#ifndef MAX_LEN_CT +#define MAX_LEN_CT 6 /* for sequence: ESC $ ( A \xx \xx */ +#endif + +unsigned long FMT8BIT = 0L; +unsigned long XawFmt8Bit = 0L; +unsigned long XawFmtWide = 0L; + +#define SinkClearToBG _XawTextSinkClearToBackground + +#define SrcScan XawTextSourceScan +#define SrcRead XawTextSourceRead +#define SrcReplace XawTextSourceReplace +#define SrcSearch XawTextSourceSearch +#define SrcCvtSel XawTextSourceConvertSelection +#define SrcSetSelection XawTextSourceSetSelection + +#define MULTI_CLICK_TIME 500L + +#define SRC_CHANGE_NONE 0 +#define SRC_CHANGE_AFTER 1 +#define SRC_CHANGE_BEFORE 2 +#define SRC_CHANGE_OVERLAP 3 + +#define Superclass (&simpleClassRec) + +/* + * Compute a the maximum length of a cut buffer that we can pass at any + * time. The 64 allows for the overhead of the Change Property request. + */ +#define MAX_CUT_LEN(dpy) (XMaxRequestSize(dpy) - 64) + +#define ClearWindow(ctx) \ + _XawTextNeedsUpdating((ctx), \ + (ctx)->text.lt.top, \ + (ctx)->text.lt.info[ctx->text.lt.lines].position) + +/* + * Class Methods + */ +static void XawTextClassInitialize(void); +static void XawTextInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawTextRealize(Widget, XtValueMask*, XSetWindowAttributes*); +static void XawTextDestroy(Widget); +static void XawTextResize(Widget); +static void XawTextExpose(Widget, XEvent*, Region); +static Boolean XawTextSetValues(Widget, Widget, Widget, ArgList, Cardinal*); +static void XawTextGetValuesHook(Widget, ArgList, Cardinal*); +static Bool XawTextChangeSensitive(Widget); + +/* + * Prototypes + */ +static XawTextPosition _BuildLineTable(TextWidget, XawTextPosition, int); +static void _CreateCutBuffers(Display*); +static Boolean TextConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*, + unsigned long*, int*); +static int CountLines(TextWidget, XawTextPosition, XawTextPosition); +static void CreateHScrollBar(TextWidget); +static void CreateVScrollBar(TextWidget); +static void CvtStringToScrollMode(XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr); +static Boolean CvtScrollModeToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static void CvtStringToWrapMode(XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr); +static Boolean CvtWrapModeToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean CvtStringToJustifyMode(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean CvtJustifyModeToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static void DestroyHScrollBar(TextWidget); +static void DestroyVScrollBar(TextWidget); +#ifndef OLDXAW +static void DisplayText(Widget, XawTextPosition, XawTextPosition); +#endif +static void OldDisplayText(Widget, XawTextPosition, XawTextPosition); +static void DisplayTextWindow(Widget); +static void DoCopyArea(TextWidget, int, int, unsigned int, unsigned int, + int, int); +static void DoSelection(TextWidget, XawTextPosition, Time, Bool); +static void ExtendSelection(TextWidget, XawTextPosition, Bool); +static XawTextPosition FindGoodPosition(TextWidget, XawTextPosition); +static void FlushUpdate(TextWidget); +static int GetCutBufferNumber(Atom); +static int GetMaxTextWidth(TextWidget); +static unsigned int GetWidestLine(TextWidget); +static void HScroll(Widget, XtPointer, XtPointer); +static void HJump(Widget, XtPointer, XtPointer); +static void InsertCursor(Widget, XawTextInsertState); +static Bool LineAndXYForPosition(TextWidget, XawTextPosition, int*, + int*, int*); +static int LineForPosition(TextWidget, XawTextPosition); +static void TextLoseSelection(Widget, Atom*); +static Bool MatchSelection(Atom, XawTextSelection*); +static void ModifySelection(TextWidget, XawTextPosition, XawTextPosition); +static XawTextPosition PositionForXY(TextWidget, int, int); +static void PositionHScrollBar(TextWidget); +static void PositionVScrollBar(TextWidget); +#ifndef OLDXAW +static int ResolveColumnNumber(TextWidget); +static int ResolveLineNumber(TextWidget); +#endif +static void _SetSelection(TextWidget, XawTextPosition, XawTextPosition, + Atom*, Cardinal); +static void TextSinkResize(Widget); +static void UpdateTextInRectangle(TextWidget, XRectangle*); +static void UpdateTextInLine(TextWidget, int, int, int); +static void VScroll(Widget, XtPointer, XtPointer); +static void VJump(Widget, XtPointer, XtPointer); + +/* + * External + */ +void _XawTextAlterSelection(TextWidget, + XawTextSelectionMode, XawTextSelectionAction, + String*, Cardinal*); +void _XawTextCheckResize(TextWidget); +void _XawTextClearAndCenterDisplay(TextWidget); +void _XawTextExecuteUpdate(TextWidget); +char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); +void _XawTextPrepareToUpdate(TextWidget); +int _XawTextReplace(TextWidget, XawTextPosition, XawTextPosition, + XawTextBlock*); +Atom *_XawTextSelectionList(TextWidget, String*, Cardinal); +void _XawTextSetScrollBars(TextWidget); +void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition, + String*, Cardinal); +void _XawTextVScroll(TextWidget, int); +void XawTextScroll(TextWidget, int, int); +void _XawTextSetSource(Widget, Widget, XawTextPosition, XawTextPosition); +#ifndef OLDXAW +void _XawTextSetLineAndColumnNumber(TextWidget, Bool); +#endif +void _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition, + XawTextBlock*, int); + +/* Not used by other modules, but were extern on previous versions + * of the library + */ +void _XawTextShowPosition(TextWidget); + +/* + * From TextAction.c + */ +extern void _XawTextZapSelection(TextWidget, XEvent*, Bool); + +/* + * From TextSrc.c + */ +void _XawSourceAddText(Widget, Widget); +void _XawSourceRemoveText(Widget, Widget, Bool); +Bool _XawTextSourceNewLineAtEOF(Widget); + +/* + * From TextSink.c + */ +void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned); +void _XawTextSinkDisplayText(Widget, int, int, XawTextPosition, XawTextPosition, + Bool); + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ +/* + * From TextTr.c + */ +static XawTextSelectType defaultSelectTypes[] = { + XawselectPosition, XawselectAlphaNumeric, XawselectWord, XawselectLine, + XawselectParagraph, XawselectAll, XawselectNull, +}; + +static XPointer defaultSelectTypesPtr = (XPointer)defaultSelectTypes; +static Dimension defWidth = 100; +static Dimension defHeight = DEFAULT_TEXT_HEIGHT; + +#define offset(field) XtOffsetOf(TextRec, field) +static XtResource resources[] = { + { + XtNwidth, + XtCWidth, + XtRDimension, + sizeof(Dimension), + offset(core.width), + XtRDimension, + (XtPointer)&defWidth + }, + { + XtNcursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + offset(simple.cursor), + XtRString, + "xterm" + }, + { + XtNheight, + XtCHeight, + XtRDimension, + sizeof(Dimension), + offset(core.height), + XtRDimension, + (XtPointer)&defHeight + }, + { + XtNdisplayPosition, + XtCTextPosition, + XtRInt, + sizeof(XawTextPosition), + offset(text.lt.top), + XtRImmediate, + (XtPointer)0 + }, + { + XtNinsertPosition, + XtCTextPosition, + XtRInt, + sizeof(XawTextPosition), + offset(text.insertPos), + XtRImmediate, + (XtPointer)0 + }, + { + XtNleftMargin, + XtCMargin, + XtRPosition, + sizeof(Position), + offset(text.r_margin.left), + XtRImmediate, + (XtPointer)2 + }, + { + XtNrightMargin, + XtCMargin, + XtRPosition, + sizeof(Position), + offset(text.r_margin.right), + XtRImmediate, + (XtPointer)4 + }, + { + XtNtopMargin, + XtCMargin, + XtRPosition, + sizeof(Position), + offset(text.r_margin.top), + XtRImmediate, + (XtPointer)2 + }, + { + XtNbottomMargin, + XtCMargin, + XtRPosition, + sizeof(Position), + offset(text.r_margin.bottom), + XtRImmediate, + (XtPointer)2 + }, + { + XtNselectTypes, + XtCSelectTypes, + XtRPointer, + sizeof(XawTextSelectType*), + offset(text.sarray), + XtRPointer, + (XtPointer)&defaultSelectTypesPtr + }, + { + XtNtextSource, + XtCTextSource, + XtRWidget, + sizeof(Widget), + offset(text.source), + XtRImmediate, + NULL + }, + { + XtNtextSink, + XtCTextSink, + XtRWidget, + sizeof(Widget), + offset(text.sink), + XtRImmediate, + NULL + }, + { + XtNdisplayCaret, + XtCOutput, + XtRBoolean, + sizeof(Boolean), + offset(text.display_caret), + XtRImmediate, + (XtPointer)True + }, + { + XtNscrollVertical, + XtCScroll, + XtRScrollMode, + sizeof(XawTextScrollMode), + offset(text.scroll_vert), + XtRImmediate, + (XtPointer)False + }, + { + XtNscrollHorizontal, + XtCScroll, + XtRScrollMode, + sizeof(XawTextScrollMode), + offset(text.scroll_horiz), + XtRImmediate, + (XtPointer)False + }, + { + XtNwrap, + XtCWrap, + XtRWrapMode, + sizeof(XawTextWrapMode), + offset(text.wrap), + XtRImmediate, + (XtPointer)XawtextWrapNever + }, + { + XtNautoFill, + XtCAutoFill, + XtRBoolean, + sizeof(Boolean), + offset(text.auto_fill), + XtRImmediate, + (XtPointer)False + }, +#ifndef OLDXAW + { + XtNpositionCallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(text.position_callbacks), + XtRCallback, + NULL + }, + { + XtNleftColumn, + XtCColumn, + XtRShort, + sizeof(short), + offset(text.left_column), + XtRImmediate, + (XtPointer)0 + }, + { + XtNrightColumn, + XtCColumn, + XtRShort, + sizeof(short), + offset(text.right_column), + XtRImmediate, + (XtPointer)0 + }, + { + XtNjustifyMode, + XtCJustifyMode, + XtRJustifyMode, + sizeof(XawTextJustifyMode), + offset(text.justify), + XtRImmediate, + (XtPointer)XawjustifyLeft + }, +#endif /* OLDXAW */ +}; +#undef offset + +#define done(address, type) \ + { toVal->size = sizeof(type); toVal->addr = (XPointer)address; } + +static XrmQuark QWrapNever, QWrapLine, QWrapWord; +#ifndef notdef +static XrmQuark QScrollNever, QScrollWhenNeeded, QScrollAlways; +#endif +static XrmQuark QJustifyLeft, QJustifyRight, QJustifyCenter, QJustifyFull; + +/*ARGSUSED*/ +static void +CvtStringToScrollMode(XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal) +{ + static XawTextScrollMode scrollMode = XawtextScrollNever; + XrmQuark q; + char name[32]; + + XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); + q = XrmStringToQuark(name); + + if (q == QScrollNever || q == QScrollWhenNeeded) + scrollMode = XawtextScrollNever; + else if (q == QScrollAlways) + scrollMode = XawtextScrollAlways; + else if (strcmp(name, "true") == 0 || strcmp(name, "1") == 0) + scrollMode = XawtextScrollAlways; + else if (strcmp(name, "false") == 0 || strcmp(name, "0") == 0) + scrollMode = XawtextScrollNever; + else + XtStringConversionWarning((char *)fromVal->addr, XtRScrollMode); + + done(&scrollMode, XawTextScrollMode); +} + +/*ARGSUSED*/ +static Boolean +CvtScrollModeToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, XtPointer *data) +{ + static char *buffer; + Cardinal size; + + switch (*(XawTextScrollMode *)fromVal->addr) { + case XawtextScrollNever: + case XawtextScrollWhenNeeded: + buffer = XtEtextScrollNever; + break; + case XawtextScrollAlways: + buffer = XtEtextScrollAlways; + break; + default: + XawTypeToStringWarning(dpy, XtRScrollMode); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + size = strlen(buffer) + 1; + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +/*ARGSUSED*/ +static void +CvtStringToWrapMode(XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal) +{ + static XawTextWrapMode wrapMode = XawtextWrapNever; + XrmQuark q; + char lowerName[6]; + + XmuNCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr, + sizeof(lowerName)); + q = XrmStringToQuark(lowerName); + + if (q == QWrapNever) + wrapMode = XawtextWrapNever; + else if (q == QWrapLine) + wrapMode = XawtextWrapLine; + else if (q == QWrapWord) + wrapMode = XawtextWrapWord; + else + XtStringConversionWarning((char *)fromVal->addr, XtRWrapMode); + + done(&wrapMode, XawTextWrapMode); +} + +/*ARGSUSED*/ +static Boolean +CvtWrapModeToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, XtPointer *data) +{ + static char *buffer; + Cardinal size; + + switch (*(XawTextWrapMode *)fromVal->addr) { + case XawtextWrapNever: + buffer = XtEtextWrapNever; + break; + case XawtextWrapLine: + buffer = XtEtextWrapLine; + break; + case XawtextWrapWord: + buffer = XtEtextWrapWord; + break; + default: + XawTypeToStringWarning(dpy, XtRWrapMode); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + size = strlen(buffer) + 1; + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +/*ARGSUSED*/ +static Boolean +CvtStringToJustifyMode(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, XtPointer *data) +{ + XawTextJustifyMode justify; + XrmQuark q; + char lowerName[8]; + + XmuNCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr, + sizeof(lowerName)); + q = XrmStringToQuark(lowerName); + + if (q == QJustifyLeft) + justify = XawjustifyLeft; + else if (q == QJustifyRight) + justify = XawjustifyRight; + else if (q == QJustifyCenter) + justify = XawjustifyCenter; + else if(q == QJustifyFull) + justify = XawjustifyFull; + else { + XtStringConversionWarning((char *)fromVal->addr, XtRJustifyMode); + return (False); + } + + toVal->size = sizeof(XawTextJustifyMode); + *(XawTextJustifyMode *)(toVal->addr) = justify; + + return (True); +} + + +/*ARGSUSED*/ +static Boolean +CvtJustifyModeToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, XtPointer *data) +{ + static char *buffer; + Cardinal size; + + switch (*(XawTextJustifyMode *)fromVal->addr) { + case XawjustifyLeft: + buffer = XtEtextJustifyLeft; + break; + case XawjustifyRight: + buffer = XtEtextJustifyRight; + break; + case XawjustifyCenter: + buffer = XtEtextJustifyCenter; + break; + case XawjustifyFull: + buffer = XtEtextJustifyFull; + break; + default: + XawTypeToStringWarning(dpy, XtRJustifyMode); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + size = strlen(buffer) + 1; + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +#undef done + +static void +XawTextClassInitialize(void) +{ + if (!XawFmt8Bit) + FMT8BIT = XawFmt8Bit = XrmPermStringToQuark("FMT8BIT"); + if (!XawFmtWide) + XawFmtWide = XrmPermStringToQuark("FMTWIDE"); + + XawInitializeWidgetSet(); + + textClassRec.core_class.num_actions = _XawTextActionsTableCount; + + QWrapNever = XrmPermStringToQuark(XtEtextWrapNever); + QWrapLine = XrmPermStringToQuark(XtEtextWrapLine); + QWrapWord = XrmPermStringToQuark(XtEtextWrapWord); + XtAddConverter(XtRString, XtRWrapMode, CvtStringToWrapMode, NULL, 0); + XtSetTypeConverter(XtRWrapMode, XtRString, CvtWrapModeToString, + NULL, 0, XtCacheNone, NULL); + QScrollNever = XrmPermStringToQuark(XtEtextScrollNever); + QScrollWhenNeeded = XrmPermStringToQuark(XtEtextScrollWhenNeeded); + QScrollAlways = XrmPermStringToQuark(XtEtextScrollAlways); + XtAddConverter(XtRString, XtRScrollMode, CvtStringToScrollMode, + NULL, 0); + XtSetTypeConverter(XtRScrollMode, XtRString, CvtScrollModeToString, + NULL, 0, XtCacheNone, NULL); + QJustifyLeft = XrmPermStringToQuark(XtEtextJustifyLeft); + QJustifyRight = XrmPermStringToQuark(XtEtextJustifyRight); + QJustifyCenter = XrmPermStringToQuark(XtEtextJustifyCenter); + QJustifyFull = XrmPermStringToQuark(XtEtextJustifyFull); + XtSetTypeConverter(XtRString, XtRJustifyMode, CvtStringToJustifyMode, + NULL, 0, XtCacheNone, NULL); + XtSetTypeConverter(XtRJustifyMode, XtRString, CvtJustifyModeToString, + NULL, 0, XtCacheNone, NULL); +} + +/* + * Function: + * PositionHScrollBar + * + * Parameters: + * ctx - text widget + * + * Description: + * Positions the Horizontal scrollbar. + */ +static void +PositionHScrollBar(TextWidget ctx) +{ + Widget hbar = ctx->text.hbar, vbar = ctx->text.vbar; + Position x, y; + Dimension width, height; + + if (ctx->text.hbar == NULL) + return; + + if (vbar != NULL) + x = XtWidth(vbar); + else + x = -XtBorderWidth(hbar); + y = XtHeight(ctx) - XtHeight(hbar) - XtBorderWidth(hbar); + if (vbar != NULL) { + width = XtWidth(ctx) - XtWidth(vbar) - XtBorderWidth(vbar); + if (width > XtWidth(ctx)) + width = XtWidth(ctx); + } + else + width = XtWidth(ctx); + height = XtHeight(hbar); + + XtConfigureWidget(hbar, x, y, width, height, XtBorderWidth(hbar)); +} + +/* + * Function: + * PositionVScrollBar + * + * Parameters: + * ctx - text widget + * + * Description: + * Positions the Vertical scrollbar. + */ +static void +PositionVScrollBar(TextWidget ctx) +{ + Widget vbar = ctx->text.vbar; + Position x, y; + Dimension width, height; + + if (vbar == NULL) + return; + + x = y = -XtBorderWidth(vbar); + height = XtHeight(ctx); + width = XtWidth(vbar); + + XtConfigureWidget(vbar, x, y, width, height, XtBorderWidth(vbar)); +} + +static void +CreateVScrollBar(TextWidget ctx) +{ + Widget vbar; + + if (ctx->text.vbar != NULL) + return; + + ctx->text.vbar = vbar = + XtCreateWidget("vScrollbar", scrollbarWidgetClass, (Widget)ctx, NULL, 0); + XtAddCallback(vbar, XtNscrollProc, VScroll, (XtPointer)ctx); + XtAddCallback(vbar, XtNjumpProc, VJump, (XtPointer)ctx); + + ctx->text.r_margin.left += XtWidth(vbar) + XtBorderWidth(vbar); + ctx->text.left_margin = ctx->text.margin.left = ctx->text.r_margin.left; + + PositionVScrollBar(ctx); + PositionHScrollBar(ctx); + TextSinkResize(ctx->text.sink); + + if (XtIsRealized((Widget)ctx)) { + XtRealizeWidget(vbar); + XtMapWidget(vbar); + } + XtSetKeyboardFocus(vbar, (Widget)ctx); +} + +/* + * Function: + * DestroyVScrollBar + * + * Parameters: + * ctx - parent text widget + * + * Description: + * Removes vertical ScrollBar. + */ +static void +DestroyVScrollBar(TextWidget ctx) +{ + Widget vbar = ctx->text.vbar; + + if (vbar == NULL) + return; + + ctx->text.r_margin.left -= XtWidth(vbar) + XtBorderWidth(vbar); + ctx->text.left_margin = ctx->text.margin.left = ctx->text.r_margin.left; + + XtDestroyWidget(vbar); + ctx->text.vbar = NULL; + if (!ctx->core.being_destroyed) { + PositionHScrollBar(ctx); + TextSinkResize(ctx->text.sink); + } +} + +static void +CreateHScrollBar(TextWidget ctx) +{ + Arg args[1]; + Widget hbar; + int bottom; + + if (ctx->text.hbar != NULL) + return; + + XtSetArg(args[0], XtNorientation, XtorientHorizontal); + ctx->text.hbar = hbar = + XtCreateWidget("hScrollbar", scrollbarWidgetClass, (Widget)ctx, args, 1); + XtAddCallback(hbar, XtNscrollProc, HScroll, (XtPointer)ctx); + XtAddCallback(hbar, XtNjumpProc, HJump, (XtPointer)ctx); + + bottom = ctx->text.r_margin.bottom + XtHeight(hbar) + XtBorderWidth(hbar); + + ctx->text.margin.bottom = ctx->text.r_margin.bottom = bottom; + + PositionHScrollBar(ctx); + TextSinkResize(ctx->text.sink); + + if (XtIsRealized((Widget)ctx)) { + XtRealizeWidget(hbar); + XtMapWidget(hbar); + } + XtSetKeyboardFocus(hbar, (Widget)ctx); +} + +/* + * Function: + * DestroyHScrollBar + * + * Parameters: + * ctx - parent text widget + * + * Description: + * Removes horizontal ScrollBar. + */ +static void +DestroyHScrollBar(TextWidget ctx) +{ + Widget hbar = ctx->text.hbar; + + if (hbar == NULL) + return; + + ctx->text.r_margin.bottom -= XtHeight(hbar) + XtBorderWidth(hbar); + ctx->text.margin.bottom = ctx->text.r_margin.bottom; + + XtDestroyWidget(hbar); + ctx->text.hbar = NULL; + if (!ctx->core.being_destroyed) + TextSinkResize(ctx->text.sink); +} + +/*ARGSUSED*/ +static void +XawTextInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + TextWidget ctx = (TextWidget)cnew; + + ctx->text.lt.lines = 0; + ctx->text.lt.info = (XawTextLineTableEntry *) + XtCalloc(1, sizeof(XawTextLineTableEntry)); +#ifndef OLDXAW + ctx->text.lt.base_line = 1; +#endif + (void)bzero(&ctx->text.origSel, sizeof(XawTextSelection)); + (void)bzero(&ctx->text.s, sizeof(XawTextSelection)); + ctx->text.s.type = XawselectPosition; + ctx->text.salt = NULL; + ctx->text.hbar = ctx->text.vbar = NULL; + ctx->text.lasttime = 0; + ctx->text.time = 0; + ctx->text.showposition = True; + ctx->text.lastPos = ctx->text.source != NULL ? + XawTextGetLastPosition(ctx) : 0; + ctx->text.file_insert = NULL; + ctx->text.search = NULL; + ctx->text.update = XmuNewScanline(0, 0, 0); + ctx->text.gc = XtGetGC(cnew, 0, 0); + ctx->text.hasfocus = False; + ctx->text.margin = ctx->text.r_margin; /* Strucure copy */ + ctx->text.left_margin = ctx->text.r_margin.left; + ctx->text.update_disabled = False; + ctx->text.clear_to_eol = True; + ctx->text.old_insert = -1; + ctx->text.mult = 1; + ctx->text.salt2 = NULL; + ctx->text.from_left = -1; + +#ifndef OLDXAW + ctx->text.numeric = False; + ctx->text.selection_state = False; + ctx->text.kill_ring = 0; + + ctx->text.line_number = -1; + ctx->text.column_number = -1; + ctx->text.source_changed = SRC_CHANGE_NONE; + + ctx->text.kill_ring_ptr = NULL; + ctx->text.overwrite = False; +#endif + + if (XtHeight(ctx) == DEFAULT_TEXT_HEIGHT) { + XtHeight(ctx) = VMargins(ctx); + if (ctx->text.sink != NULL) + XtHeight(ctx) += XawTextSinkMaxHeight(ctx->text.sink, 1); + } + + if (ctx->text.scroll_vert == XawtextScrollAlways) + CreateVScrollBar(ctx); + if (ctx->text.scroll_horiz == XawtextScrollAlways) + CreateHScrollBar(ctx); + +#ifndef OLDXAW + if (ctx->text.left_column < 0) + ctx->text.left_column = 0; + if (ctx->text.right_column < 0) + ctx->text.right_column = 0; +#endif +} + +static void +XawTextRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attr) +{ + TextWidget ctx = (TextWidget)w; + + (*textClassRec.core_class.superclass->core_class.realize)(w, mask, attr); + + if (ctx->text.hbar != NULL) { + XtRealizeWidget(ctx->text.hbar); + XtMapWidget(ctx->text.hbar); + } + + if (ctx->text.vbar != NULL) { + XtRealizeWidget(ctx->text.vbar); + XtMapWidget(ctx->text.vbar); + } + + _XawTextBuildLineTable(ctx, ctx->text.lt.top, True); + +#ifndef OLDXAW + _XawTextSetLineAndColumnNumber(ctx, True); +#endif +} + +/* Utility routines for support of Text */ +static void +_CreateCutBuffers(Display *d) +{ + static struct _DisplayRec { + struct _DisplayRec *next; + Display *dpy; + } *dpy_list = NULL; + struct _DisplayRec *dpy_ptr; + + for (dpy_ptr = dpy_list; dpy_ptr != NULL; dpy_ptr = dpy_ptr->next) + if (dpy_ptr->dpy == d) + return; + + dpy_ptr = XtNew(struct _DisplayRec); + dpy_ptr->next = dpy_list; + dpy_ptr->dpy = d; + dpy_list = dpy_ptr; + +#define Create(buffer) \ + XChangeProperty(d, RootWindow(d, 0), buffer, XA_STRING, 8, \ + PropModeAppend, NULL, 0); + + Create(XA_CUT_BUFFER0); + Create(XA_CUT_BUFFER1); + Create(XA_CUT_BUFFER2); + Create(XA_CUT_BUFFER3); + Create(XA_CUT_BUFFER4); + Create(XA_CUT_BUFFER5); + Create(XA_CUT_BUFFER6); + Create(XA_CUT_BUFFER7); + +#undef Create +} + +/* + * Procedure to manage insert cursor visibility for editable text. It uses + * the value of ctx->insertPos and an implicit argument. In the event that + * position is immediately preceded by an eol graphic, then the insert cursor + * is displayed at the beginning of the next line. + */ +static void +InsertCursor(Widget w, XawTextInsertState state) +{ + TextWidget ctx = (TextWidget)w; + int x, y; + int line; + + if (ctx->text.lt.lines < 1) + return; + + if (ctx->text.display_caret && + LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y)) { + if (line < ctx->text.lt.lines) + y += (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1; + else + y += (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1; + + XawTextSinkInsertCursor(ctx->text.sink, x, y, state); + } + + /* Keep Input Method up to speed */ + if (ctx->simple.international) { + Arg list[1]; + + XtSetArg(list[0], XtNinsertPosition, ctx->text.insertPos); + _XawImSetValues(w, list, 1); + } +} + +/* + * Procedure to register a span of text that is no longer valid on the display + * It is used to avoid a number of small, and potentially overlapping, screen + * updates. +*/ +void +_XawTextNeedsUpdating(TextWidget ctx, + XawTextPosition left, XawTextPosition right) +{ + XmuSegment segment; + + if (left >= right) + return; + + segment.x1 = (int)left; + segment.x2 = (int)right; + (void)XmuScanlineOrSegment(ctx->text.update, &segment); +} + +/* + * Procedure to read a span of text in Ascii form. This is purely a hack and + * we probably need to add a function to sources to provide this functionality. + * [note: this is really a private procedure but is used in multiple modules]. + */ +char * +_XawTextGetText(TextWidget ctx, XawTextPosition left, XawTextPosition right) +{ + char *result, *tempResult; + XawTextBlock text; + int bytes; + + if (XawTextFormat(ctx, XawFmt8Bit)) + bytes = sizeof(unsigned char); + else if (XawTextFormat(ctx, XawFmtWide)) + bytes = sizeof(wchar_t); + else /* if there is another fomat, add here */ + bytes = 1; + + /* leave space for ZERO */ + tempResult = result = XtMalloc((unsigned)(right - left + ONE) * bytes); + + while (left < right) { + left = SrcRead(ctx->text.source, left, &text, (int)(right - left)); + if (!text.length) + break; + memmove(tempResult, text.ptr, (unsigned)(text.length * bytes)); + tempResult += text.length * bytes; + } + + if (bytes == sizeof(wchar_t)) + *((wchar_t*)tempResult) = (wchar_t)0; + else + *tempResult = '\0'; + + return (result); +} + +/* Like _XawTextGetText, but enforces ICCCM STRING type encoding. This + * routine is currently used to put just the ASCII chars in the selection + * into a cut buffer. + */ +char * +_XawTextGetSTRING(TextWidget ctx, XawTextPosition left, XawTextPosition right) +{ + unsigned char *s; + unsigned char c; + long i, j, n; + wchar_t *ws, wc; + + /* allow ESC in accordance with ICCCM */ + if (XawTextFormat(ctx, XawFmtWide)) { + MultiSinkObject sink = (MultiSinkObject)ctx->text.sink; + ws = (wchar_t *)_XawTextGetText(ctx, left, right); + n = wcslen(ws); + for (j = 0, i = 0; j < n; j++) { + wc = ws[j]; + if (XwcTextEscapement (sink->multi_sink.fontset, &wc, 1) + || (wc == _Xaw_atowc(XawTAB)) || (wc == _Xaw_atowc(XawLF)) + || (wc == _Xaw_atowc(XawESC))) + ws[i++] = wc; + } + ws[i] = (wchar_t)0; + return ((char *)ws); + } + else { + s = (unsigned char *)_XawTextGetText(ctx, left, right); + /* only HT and NL control chars are allowed, strip out others */ + n = strlen((char *)s); + i = 0; + for (j = 0; j < n; j++) { + c = s[j]; + if (((c >= 0x20) && c <= 0x7f) + ||(c >= 0xa0) || (c == XawTAB) || (c == XawLF) + || (c == XawESC)) { + s[i] = c; + i++; + } + } + s[i] = 0; + + return ((char *)s); + } +} + +/* + * This routine maps an x and y position in a window that is displaying text + * into the corresponding position in the source. + */ +static XawTextPosition +PositionForXY(TextWidget ctx, int x, int y) +{ + int fromx, line, width, height; + XawTextPosition position; + + if (ctx->text.lt.lines == 0) + return (0); + + for (line = 0; line < ctx->text.lt.lines - 1; line++) { + if (y <= ctx->text.lt.info[line + 1].y) + break; + } + position = ctx->text.lt.info[line].position; + if (position >= ctx->text.lastPos) + return (ctx->text.lastPos); + fromx = ctx->text.left_margin; + XawTextSinkFindPosition(ctx->text.sink, position, fromx, x - fromx, + False, &position, &width, &height); + + if (position > ctx->text.lastPos) + return (ctx->text.lastPos); + + if (position >= ctx->text.lt.info[line + 1].position) + position = SrcScan(ctx->text.source, ctx->text.lt.info[line + 1].position, + XawstPositions, XawsdLeft, 1, True); + + return (position); +} + +/* + * This routine maps a source position in to the corresponding line number + * of the text that is displayed in the window. + */ +static int +LineForPosition(TextWidget ctx, XawTextPosition position) +{ + int line; + + for (line = 0; line < ctx->text.lt.lines; line++) + if (position < ctx->text.lt.info[line + 1].position) + break; + + return (line); +} + +/* + * This routine maps a source position into the corresponding line number + * and the x, y coordinates of the text that is displayed in the window. + */ +static Bool +LineAndXYForPosition(TextWidget ctx, XawTextPosition pos, + int *line, int *x, int *y) +{ + XawTextPosition linePos, endPos; + Boolean visible; + int realW, realH; + + *line = 0; + *x = ctx->text.left_margin; + *y = ctx->text.margin.top + 1; + if ((visible = IsPositionVisible(ctx, pos)) != False) { + *line = LineForPosition(ctx, pos); + *y = ctx->text.lt.info[*line].y; + linePos = ctx->text.lt.info[*line].position; + XawTextSinkFindDistance(ctx->text.sink, linePos, + *x, pos, &realW, &endPos, &realH); + *x += realW; + } + + return (visible); +} + +/* + * This routine builds a line table. It does this by starting at the + * specified position and measuring text to determine the staring position + * of each line to be displayed. It also determines and saves in the + * linetable all the required metrics for displaying a given line (e.g. + * x offset, y offset, line length, etc.). + */ +void +_XawTextBuildLineTable(TextWidget ctx, XawTextPosition position, + _XtBoolean force_rebuild) +{ + Dimension height = 0; + int lines = 0; + Cardinal size; + + if ((int)XtHeight(ctx) > VMargins(ctx)) { + height = XtHeight(ctx) - VMargins(ctx); + lines = XawTextSinkMaxLines(ctx->text.sink, height); + } + size = sizeof(XawTextLineTableEntry) * (lines + 1); + + if (lines != ctx->text.lt.lines || ctx->text.lt.info == NULL) { + ctx->text.lt.info = (XawTextLineTableEntry *) + XtRealloc((char *)ctx->text.lt.info, size); + ctx->text.lt.lines = lines; + force_rebuild = True; + } + + if (force_rebuild) { + (void)bzero((char *)ctx->text.lt.info, size); + /* force a text update in the first text line if it is visible */ + ctx->text.lt.info[0].position = (XawTextPosition)-1; + } + if (position != ctx->text.lt.info[0].position) { + (void)_BuildLineTable(ctx, position, 0); + ctx->text.clear_to_eol = True; + } +} + +/* + * We may need to resize the line table here, since there maybe lines with + * different fonts (that can be shorter or taller than the default one) + */ +static XawTextPosition +_BuildLineTable(TextWidget ctx, XawTextPosition position, int line) +{ + XawTextLineTableEntry *lt = ctx->text.lt.info + line; + XawTextPosition end, update_from = -1; + Position y; + int wwidth, width, height; +#ifndef OLDXAW + Widget src = ctx->text.source; +#endif + int max_y = (int)XtHeight(ctx) - (int)ctx->text.margin.bottom; + + if (ctx->text.wrap == XawtextWrapNever) + wwidth = 0x7fffffff; + else + wwidth = GetMaxTextWidth(ctx); + + /* XXX y may change, due to font size changes. See later */ + y = line == 0 ? ctx->text.margin.top : lt->y; + +#ifndef OLDXAW + if (ctx->text.lt.base_line < 0) { + if (line == 0) + ctx->text.lt.top = position; + } + else if (line == 0) { + XawTextPosition pos = ctx->text.lt.top; + int base_line = ctx->text.lt.base_line; + + if (position == 0) + base_line = 1; + else if (ctx->text.lt.base_line == 0 || + ctx->text.source_changed == SRC_CHANGE_OVERLAP) { + pos = 0; + base_line = 1; + + while (pos < position) { + pos = SrcScan(src, pos, XawstEOL, XawsdRight, 1, True); + if (pos <= position) { + ++base_line; + if (pos == ctx->text.lastPos) { + base_line -= !_XawTextSourceNewLineAtEOF(src); + break; + } + } + } + } + else if (ctx->text.wrap == XawtextWrapNever + && IsPositionVisible(ctx, position)) + base_line += LineForPosition(ctx, position); + else if (pos < position) { + while (pos < position) { + pos = SrcScan(src, pos, XawstEOL, XawsdRight, 1, True); + if (pos <= position) { + ++base_line; + if (pos == ctx->text.lastPos) { + base_line -= !_XawTextSourceNewLineAtEOF(src); + break; + } + } + } + } + else if (pos > position) { + while (pos > position) { + pos = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False); + if (--pos >= position) + --base_line; + } + } + + ctx->text.lt.top = position; + ctx->text.lt.base_line = base_line; + } +#else + if (line == 0) + ctx->text.lt.top = position; +#endif + + /* CONSTCOND */ + while (True) { + XawTextSinkFindPosition(ctx->text.sink, position, ctx->text.left_margin, + wwidth, ctx->text.wrap == XawtextWrapWord, + &end, &width, &height); + + if (lt->position != position) { + _XawTextNeedsUpdating(ctx, position, + end <= position ? position + 1 : end); + ctx->text.clear_to_eol = True; + lt->position = position; + } + if (lt->y != y) { + if (update_from < 0) + update_from = line == 0 ? + ctx->text.lt.info[0].position : + ctx->text.lt.info[line - 1].position; + lt->y = y; + ctx->text.clear_to_eol = True; + } + if (lt->textWidth != width) { + if (lt->textWidth > width) + ctx->text.clear_to_eol = True; + lt->textWidth = width; + } + y += height; + + if (end > ctx->text.lastPos) { + position = end; + ctx->text.clear_to_eol = True; + _XawTextNeedsUpdating(ctx, end, end + ctx->text.lt.lines - line); + while (line++ < ctx->text.lt.lines) { + if (line > 1 && y > max_y) { + ctx->text.lt.lines = line - 1; + break; + } + ++lt; + if (lt->y != y) { + if (update_from < 0) + update_from = line < 2 ? + ctx->text.lt.info[0].position : + ctx->text.lt.info[line - 2].position; + lt->y = y; + } + lt->position = ++position; + lt->textWidth = 0; + y += height; + } + if (update_from >= 0) + _XawTextNeedsUpdating(ctx, update_from, + ctx->text.lt.info[ctx->text.lt.lines].position); + _XawTextSetScrollBars(ctx); + + return (ctx->text.lastPos); + } + + if (line && y > max_y) + /* will return in the next loop */ + ctx->text.lt.lines = line; + + if (++line > ctx->text.lt.lines && y < max_y) { + /* grow the line table */ + ctx->text.lt.info = (XawTextLineTableEntry *) + XtRealloc((char *)ctx->text.lt.info, + sizeof(XawTextLineTableEntry) * (line + 1)); + lt = ctx->text.lt.info + line; + bzero(lt, sizeof(XawTextLineTableEntry)); + ++ctx->text.lt.lines; + } + else + ++lt; + if (position == end) + ++position; + else + position = end; + + if (line > ctx->text.lt.lines) { + if (update_from >= 0) + _XawTextNeedsUpdating(ctx, update_from, + ctx->text.lt.info[ctx->text.lt.lines].position); + _XawTextSetScrollBars(ctx); + + return (position); + } + } + /*NOTREACHED*/ +} + +/* + * Function: + * GetWidestLine + * + * Parameters: + * ctx - text widget + * + * Description: + * Returns the width (in pixels) of the widest line that + * is currently visable. + * + * Returns: + * The width of the widest line + */ +static unsigned int +GetWidestLine(TextWidget ctx) +{ + int i; + unsigned int widest; + XawTextLineTablePtr lt = &(ctx->text.lt); + + for (i = 0, widest = 0; i < lt->lines; i++) + if (widest < lt->info[i].textWidth) + widest = lt->info[i].textWidth; + + return (widest); +} + +/* + * This routine is used by Text to notify an associated scrollbar of the + * correct metrics (position and shown fraction) for the text being currently + * displayed in the window. + */ +void +_XawTextSetScrollBars(TextWidget ctx) +{ + float first, last, denom, widest; + + if (ctx->text.scroll_vert == XawtextScrollAlways) { + if (ctx->text.lastPos == 0) + first = 0.0; + else + first = ctx->text.lt.top / (float)ctx->text.lastPos; + + if (ctx->text.lt.info[ctx->text.lt.lines].position < ctx->text.lastPos) + last = ctx->text.lt.info[ctx->text.lt.lines].position / + (float)ctx->text.lastPos; + else + last = 1.0; + + XawScrollbarSetThumb(ctx->text.vbar, first, last - first); + } + + if (ctx->text.scroll_horiz == XawtextScrollAlways) { + denom = GetWidestLine(ctx); + if (denom <= 0) + denom = (int)XtWidth(ctx) - RHMargins(ctx); + if (denom <= 0) + denom = 1; + widest = ((int)XtWidth(ctx) - RHMargins(ctx)) / denom; + first = ctx->text.r_margin.left - ctx->text.left_margin; + first /= denom; + + XawScrollbarSetThumb(ctx->text.hbar, first, widest); + } +} + +static void +DoCopyArea(TextWidget ctx, int src_x, int src_y, + unsigned int width, unsigned int height, int dst_x, int dst_y) +{ + int x1, y1, x2, y2; + + x1 = ctx->text.r_margin.left; + y1 = ctx->text.r_margin.top; + x2 = XtWidth(ctx) - ctx->text.r_margin.right; + y2 = XtHeight(ctx) - ctx->text.r_margin.bottom; + + if (x1 >= x2 || y1 >= y2) + return; + + src_x = XawMax(x1, XawMin(src_x, x2)); + src_y = XawMax(y1, XawMin(src_y, y2)); + dst_x = XawMax(x1, XawMin(dst_x, x2)); + dst_y = XawMax(y1, XawMin(dst_y, y2)); + width = XawMax(0, XawMin(x2 - dst_x, (int)width)); + height = XawMax(0, XawMin(y2 - dst_y, (int)height)); + + XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc, + src_x, src_y, width, height, dst_x, dst_y); +} + +/* + * Function: + * XawTextScroll + * + * Parameters: + * ctx - text widget + * vlines - number of lines to scroll vertically + * hpixels - number of pixels to scroll horizontally + * + * Description: + * Generic function for scrolling the text window. + * Allows vertical and horizontal scroll at the same time. + */ +void +XawTextScroll(TextWidget ctx, int vlines, int hpixels) +{ + XawTextPosition top, tmp, update_from, update_to; + XawTextLineTable *lt; + Arg arglist[1]; + int y0, y1, y2, count, dim, wwidth, lines = ctx->text.lt.lines; + int vwidth, vheight; /* visible width and height */ + Bool scroll; + + vwidth = (int)XtWidth(ctx) - RHMargins(ctx); + vheight = (int)XtHeight(ctx) - RVMargins(ctx); + lt = &ctx->text.lt; + + if (!lt || vwidth <= 0 || vheight <= 0) + return; + + if ((scroll = ctx->core.background_pixmap == XtUnspecifiedPixmap) == True) { + dim = lt->info[1].y - lt->info[0].y; + for (count = 1; count < lt->lines - 1; count++) + if (lt->info[count + 1].y - lt->info[count].y != dim) { + scroll = False; + break; + } + } + + wwidth = GetMaxTextWidth(ctx); + + /* + * Do the horizontall scrolling + */ + if (hpixels < 0 && ctx->text.left_margin - hpixels > ctx->text.r_margin.left) + hpixels = ctx->text.left_margin - ctx->text.r_margin.left; + ctx->text.left_margin -= hpixels; + + update_from = lt->top; /* remember the old value */ + /* + * Checks the requested number of lines and calculates the top + * of the line table + */ + if (vlines < 0) { /* VScroll Up */ + if (IsPositionVisible(ctx, 0)) + vlines = 0; + else if (ctx->text.wrap != XawtextWrapNever) { + XawTextPosition end; + int n_lines = 0; + + count = -vlines; + end = lt->top; + while (n_lines < count) { + top = SrcScan(ctx->text.source, end, XawstEOL, + XawsdLeft, 2, False); + n_lines += CountLines(ctx, top, end); + end = top; + } + + while (count++ < n_lines) { + tmp = top; + XawTextSinkFindPosition(ctx->text.sink, top, + ctx->text.left_margin, + wwidth,ctx->text.wrap == XawtextWrapWord, + &top, &dim, &dim); + if (tmp == top) + ++top; + } + } + else + top = SrcScan(ctx->text.source, lt->top, XawstEOL, + XawsdLeft, -vlines + 1, False); + if (-vlines >= ctx->text.lt.lines) + scroll = False; + } + else if (vlines > 0) { /* VScroll Down */ + if (LineForPosition(ctx, ctx->text.lastPos) == 0) + vlines = 0; + if (vlines < lt->lines) + top = XawMin(lt->info[vlines].position, ctx->text.lastPos); + else if (ctx->text.wrap == XawtextWrapNever) + top = SrcScan(ctx->text.source, + SrcScan(ctx->text.source, lt->top, + XawstEOL, XawsdRight, vlines, + True), + XawstEOL, XawsdLeft, 1, False); + else { + top = lt->top; + count = 0; + while (count++ < vlines) { + tmp = top; + XawTextSinkFindPosition(ctx->text.sink, top, + ctx->text.left_margin, + wwidth, ctx->text.wrap == XawtextWrapWord, + &top, &dim, &dim); + if (tmp == top) + ++top; + } + } + if (vlines >= ctx->text.lt.lines + || lt->info[vlines].position >= ctx->text.lastPos) + scroll = False; + } + + if (!vlines) { + if (hpixels) { + ClearWindow(ctx); + ctx->text.clear_to_eol = True; + } + _XawTextSetScrollBars(ctx); + return; + } + + /* Flushes any pending updates. Normally, there may be a call to + * XawTextUnsetSelection not yet updated. + */ + if (!hpixels && scroll) { + ctx->text.clear_to_eol = True; + FlushUpdate(ctx); + } + + /* + * Rebuild the line table, doing the vertical scroll + */ + (void)_BuildLineTable(ctx, top, 0); + lt = &ctx->text.lt; + if (scroll) { + for (count = 0; count < lt->lines - 1; count++) + if (lt->info[count + 1].y - lt->info[count].y != dim) { + scroll = False; + break; + } + } + + XtSetArg(arglist[0], XtNinsertPosition, lt->top + lt->lines); + _XawImSetValues((Widget)ctx, arglist, 1); + + if (hpixels || !scroll || lines != lt->lines) + return; + + /* _BuildLineTable updates everything if the top position changes. + * It is not required here. + */ + (void)XmuScanlineXor(ctx->text.update, ctx->text.update); + if (vlines < 0 && IsPositionVisible(ctx, 0)) + vlines = -LineForPosition(ctx, update_from); + + y0 = ctx->text.r_margin.top; + if (vlines < 0) { + update_from = lt->top; + update_to = lt->info[-vlines + 1].position - 1; + y1 = lt->info[lt->lines + vlines].y; + y2 = lt->info[-vlines].y; + DoCopyArea(ctx, ctx->text.r_margin.left, y0, vwidth, + y1 - y0, + ctx->text.r_margin.left, y2); + } + else { + update_from = lt->info[lt->lines - vlines].position; + update_to = lt->info[lt->lines].position; + y1 = lt->info[lt->lines - vlines].y; + y2 = lt->info[vlines].y; + DoCopyArea(ctx, ctx->text.r_margin.left, y2, + vwidth, lt->info[lt->lines].y - y2, + ctx->text.r_margin.left, y0); + } + _XawTextNeedsUpdating(ctx, update_from, update_to); + ctx->text.clear_to_eol = True; +} + +/* + * The routine will scroll the displayed text by lines. If the arg is + * positive, move up; otherwise, move down. [note: this is really a private + * procedure but is used in multiple modules]. + */ +void +_XawTextVScroll(TextWidget ctx, int n) +{ + XawTextScroll(ctx, n, 0); +} + +/*ARGSUSED*/ +static void +HScroll(Widget w, XtPointer closure, XtPointer callData) +{ + TextWidget ctx = (TextWidget)closure; + long pixels = (long)callData; + + if (pixels > 0) { + long max; + + max = (int)GetWidestLine(ctx) + ctx->text.left_margin - + ctx->text.r_margin.left; + max = XawMax(0, max); + pixels = XawMin(pixels, max); + } + + if (pixels) { + _XawTextPrepareToUpdate(ctx); + XawTextScroll(ctx, 0, pixels); + _XawTextExecuteUpdate(ctx); + } +} + +/*ARGSUSED*/ +static void +HJump(Widget w, XtPointer closure, XtPointer callData) +{ + TextWidget ctx = (TextWidget)closure; + float percent = *(float *)callData; + long pixels; + + pixels = ctx->text.left_margin - + (ctx->text.r_margin.left - (int)(percent * GetWidestLine(ctx))); + + HScroll(w, (XtPointer)ctx, (XtPointer)pixels); +} + +/* + * Function: + * UpdateTextInLine + * + * Parameters: + * ctx - text widget + * line - line to update + * x1 - left pixel + * x2 - right pixel + * + * Description: + * Updates the text in the given line and pixel interval + */ +static void +UpdateTextInLine(TextWidget ctx, int line, int x1, int x2) +{ + XawTextLineTableEntry *lt = ctx->text.lt.info + line; + XawTextPosition left, right; + int from_x, width, height; + + if (lt->position >= ctx->text.lastPos + || ctx->text.left_margin > x2 + || (int)lt->textWidth + ctx->text.left_margin < x1) { + /* Mark line to be cleared */ + if (ctx->text.clear_to_eol) + _XawTextNeedsUpdating(ctx, lt->position, lt->position + 1); + return; + } + + from_x = ctx->text.left_margin; + XawTextSinkFindPosition(ctx->text.sink, lt->position, + from_x, x1 - from_x, + False, &left, &width, &height); + if (line == ctx->text.lt.lines) + right = -1; + else if (x2 >= lt->textWidth - from_x) + right = lt[1].position - 1; + else { + from_x += width; + XawTextSinkFindPosition(ctx->text.sink, left, + from_x, x2 - from_x, + False, &right, &width, &height); + } + + if ((right < 0) || (right + 1 <= lt[1].position)) + ++right; + + /* Mark text interval to be repainted */ + _XawTextNeedsUpdating(ctx, left, right); +} + +/* + * The routine will scroll the displayed text by pixels. If the calldata is + * positive, move up; otherwise, move down. + */ +/*ARGSUSED*/ +static void +VScroll(Widget w, XtPointer closure, XtPointer callData) +{ + TextWidget ctx = (TextWidget)closure; + long height, lines = (long)callData; + + height = XtHeight(ctx) - VMargins(ctx); + if (height < 1) + height = 1; + lines = (lines * ctx->text.lt.lines) / height; + _XawTextPrepareToUpdate(ctx); + XawTextScroll(ctx, lines, 0); + _XawTextExecuteUpdate(ctx); +} + +/*ARGSUSED*/ +static void +VJump(Widget w, XtPointer closure, XtPointer callData) +{ + float percent = *(float *)callData; + TextWidget ctx = (TextWidget)closure; + XawTextPosition top, last, position, tmp; + XawTextLineTable *lt = &(ctx->text.lt); + int dim, vlines = 0, wwidth = GetMaxTextWidth(ctx); + Bool scroll = True; + + position = percent * ctx->text.lastPos; + top = lt->top; + + if (!lt->lines || (position >= lt->top && position < lt->info[1].position)) { + _XawTextSetScrollBars(ctx); + return; + } + +#ifndef OLDXAW + ctx->text.lt.base_line = -1; +#endif + + if (position > lt->top) { /* VScroll Up */ + if (position > lt->top && position < lt->info[lt->lines].position) + vlines = LineForPosition(ctx, position); + else { + scroll = False; + top = SrcScan(ctx->text.source, position, XawstEOL, + XawsdLeft, 1, False); + if (ctx->text.wrap != XawtextWrapNever) { + last = top; + while (last < position) { + tmp = last; + XawTextSinkFindPosition(ctx->text.sink, last, + ctx->text.left_margin, wwidth, + ctx->text.wrap == XawtextWrapWord, + &last, &dim, &dim); + if (last == tmp) + ++last; + if (last < position) + top = last; + } + } + } + } + else { /* VScroll Down */ + /* + * Calculates the number of lines + */ + while (top > position) { + last = top; + top = SrcScan(ctx->text.source, top, XawstEOL, + XawsdLeft, 2, False); + vlines -= CountLines(ctx, top, last); + if (-vlines >= ctx->text.lt.lines) { + scroll = False; + top = SrcScan(ctx->text.source, position, XawstEOL, + XawsdLeft, 1, False); + break; + } + } + /* + * Normalize + */ + if (ctx->text.wrap != XawtextWrapNever) { + last = top; + while (last < position) { + tmp = last; + XawTextSinkFindPosition(ctx->text.sink, last, + ctx->text.left_margin, + wwidth, + ctx->text.wrap == XawtextWrapWord, + &last, &dim, &dim); + if (last == tmp) + ++last; + if (last < position) + top = last; + ++vlines; + } + } + } + + if (vlines || !scroll) { + _XawTextPrepareToUpdate(ctx); + if (scroll) + XawTextScroll(ctx, vlines, 0); + else + _BuildLineTable(ctx, top, 0); + _XawTextExecuteUpdate(ctx); + } +} + +static Bool +MatchSelection(Atom selection, XawTextSelection *s) +{ + Atom *match; + int count; + + for (count = 0, match = s->selections; count < s->atom_count; + match++, count++) + if (*match == selection) + return (True); + + return (False); +} + +static Boolean +TextConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type, + XtPointer *value, unsigned long *length, int *format) +{ + Display *d = XtDisplay(w); + TextWidget ctx = (TextWidget)w; + Widget src = ctx->text.source; + XawTextEditType edit_mode; + Arg args[1]; + XawTextSelectionSalt *salt = NULL; + XawTextSelection *s; + + if (*target == XA_TARGETS(d)) { + Atom *targetP, *std_targets; + unsigned long std_length; + + if (SrcCvtSel(src, selection, target, type, value, length, format)) + return (True); + + XtSetArg(args[0], XtNeditType, &edit_mode); + XtGetValues(src, args, ONE); + + XmuConvertStandardSelection(w, ctx->text.time, selection, + target, type, (XPointer*)&std_targets, + &std_length, format); + + *length = 7 + (edit_mode == XawtextEdit) + std_length; + *value = XtMalloc((unsigned)sizeof(Atom)*(*length)); + targetP = *(Atom**)value; + *targetP++ = XA_STRING; + *targetP++ = XA_TEXT(d); + *targetP++ = XA_UTF8_STRING(d); + *targetP++ = XA_COMPOUND_TEXT(d); + *targetP++ = XA_LENGTH(d); + *targetP++ = XA_LIST_LENGTH(d); + *targetP++ = XA_CHARACTER_POSITION(d); + if (edit_mode == XawtextEdit) { + *targetP++ = XA_DELETE(d); + } + (void)memmove((char*)targetP, (char*)std_targets, + sizeof(Atom) * std_length); + XtFree((char*)std_targets); + *type = XA_ATOM; + *format = 32; + return (True); + } + + if (SrcCvtSel(src, selection, target, type, value, length, format)) + return (True); + + if (MatchSelection(*selection, &ctx->text.s)) + s = &ctx->text.s; + else { + for (salt = ctx->text.salt; salt; salt = salt->next) + if (MatchSelection(*selection, &salt->s)) + break; + if (!salt) + return (False); + s = &salt->s; + } + if (*target == XA_STRING + || *target == XA_TEXT(d) + || *target == XA_UTF8_STRING(d) + || *target == XA_COMPOUND_TEXT(d)) { + if (*target == XA_TEXT(d)) { + if (XawTextFormat(ctx, XawFmtWide)) + *type = XA_COMPOUND_TEXT(d); + else + *type = XA_STRING; + } + else + *type = *target; + /* + * If salt is True, the salt->contents stores CT string, + * its length is measured in bytes. + * Refer to _XawTextSaltAwaySelection(). + * + * by Li Yuhong, Mar. 20, 1991. + */ + if (!salt) { + *value = _XawTextGetSTRING(ctx, s->left, s->right); + if (XawTextFormat(ctx, XawFmtWide)) { + XTextProperty textprop; + if (XwcTextListToTextProperty(d, (wchar_t **)value, 1, + XCompoundTextStyle, &textprop) + < Success) { + XtFree((char *)*value); + return (False); + } + XtFree((char *)*value); + *value = (XtPointer)textprop.value; + *length = textprop.nitems; + } + else + *length = strlen((char *)*value); + } + else { + *value = XtMalloc((salt->length + 1) * sizeof(unsigned char)); + strcpy ((char *)*value, salt->contents); + *length = salt->length; + } + /* Got *value,*length, now in COMPOUND_TEXT format. */ + if (XawTextFormat(ctx, XawFmtWide) && *type == XA_STRING) { + XTextProperty textprop; + wchar_t **wlist; + int count; + + textprop.encoding = XA_COMPOUND_TEXT(d); + textprop.value = (unsigned char *)*value; + textprop.nitems = strlen(*value); + textprop.format = 8; + if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count) + < Success + || count < 1) { + XtFree((char *)*value); + return (False); + } + XtFree((char *)*value); + if (XwcTextListToTextProperty(d, wlist, 1, XStringStyle, &textprop) + < Success) { + XwcFreeStringList((wchar_t**) wlist); + return (False); + } + *value = (XtPointer)textprop.value; + *length = textprop.nitems; + XwcFreeStringList(wlist); + } else if (*type == XA_UTF8_STRING(d)) { + XTextProperty textprop; + char **list; + int count; + + textprop.encoding = XA_COMPOUND_TEXT(d); + textprop.value = (unsigned char *)*value; + textprop.nitems = strlen(*value); + textprop.format = 8; + if (Xutf8TextPropertyToTextList(d, &textprop, &list, &count) + < Success + || count < 1) { + XtFree((char *)*value); + return (False); + } + XtFree((char *)*value); + *value = *list; + *length = strlen(*list); + XFree(list); + } + *format = 8; + return (True); + } + + if ((*target == XA_LIST_LENGTH(d)) || (*target == XA_LENGTH(d))) { + long * temp; + + temp = (long *)XtMalloc((unsigned)sizeof(long)); + if (*target == XA_LIST_LENGTH(d)) + *temp = 1L; + else /* *target == XA_LENGTH(d) */ + *temp = (long) (s->right - s->left); + + *value = (XPointer)temp; + *type = XA_INTEGER; + *length = 1L; + *format = 32; + return (True); + } + + if (*target == XA_CHARACTER_POSITION(d)) { + long * temp; + + temp = (long *)XtMalloc((unsigned)(2 * sizeof(long))); + temp[0] = (long)(s->left + 1); + temp[1] = s->right; + *value = (XPointer)temp; + *type = XA_SPAN(d); + *length = 2L; + *format = 32; + return (True); + } + + if (*target == XA_DELETE(d)) { + if (!salt) + _XawTextZapSelection(ctx, NULL, True); + *value = NULL; + *type = XA_NULL(d); + *length = 0; + *format = 32; + return (True); + } + + if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type, + (XPointer *)value, length, format)) + return (True); + + /* else */ + return (False); +} + +/* + * Function: + * GetCutBuffferNumber + * + * Parameters: + * atom - atom to check + * + * Description: + * Returns the number of the cut buffer. + * + * Returns: + * The number of the cut buffer representing this atom or NOT_A_CUT_BUFFER + */ +#define NOT_A_CUT_BUFFER -1 +static int +GetCutBufferNumber(Atom atom) +{ + if (atom == XA_CUT_BUFFER0) return (0); + if (atom == XA_CUT_BUFFER1) return (1); + if (atom == XA_CUT_BUFFER2) return (2); + if (atom == XA_CUT_BUFFER3) return (3); + if (atom == XA_CUT_BUFFER4) return (4); + if (atom == XA_CUT_BUFFER5) return (5); + if (atom == XA_CUT_BUFFER6) return (6); + if (atom == XA_CUT_BUFFER7) return (7); + return (NOT_A_CUT_BUFFER); +} + +static void +TextLoseSelection(Widget w, Atom *selection) +{ + TextWidget ctx = (TextWidget)w; + Atom *atomP; + int i; + XawTextSelectionSalt*salt, *prevSalt, *nextSalt; + + atomP = ctx->text.s.selections; + for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++) + if ((*selection == *atomP) + || (GetCutBufferNumber(*atomP) != NOT_A_CUT_BUFFER)) + *atomP = (Atom)0; + + while (ctx->text.s.atom_count + && ctx->text.s.selections[ctx->text.s.atom_count - 1] == 0) + ctx->text.s.atom_count--; + + /* + * Must walk the selection list in opposite order from UnsetSelection + */ + atomP = ctx->text.s.selections; + for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++) + if (*atomP == (Atom)0) { + *atomP = ctx->text.s.selections[--ctx->text.s.atom_count]; + while (ctx->text.s.atom_count + && ctx->text.s.selections[ctx->text.s.atom_count-1] == 0) + ctx->text.s.atom_count--; + } + + if (ctx->text.s.atom_count == 0) + ModifySelection(ctx, ctx->text.insertPos, ctx->text.insertPos); + + prevSalt = 0; + for (salt = ctx->text.salt; salt; salt = nextSalt) { + atomP = salt->s.selections; + nextSalt = salt->next; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*selection == *atomP) + *atomP = (Atom)0; + + while (salt->s.atom_count + && salt->s.selections[salt->s.atom_count-1] == 0) + salt->s.atom_count--; + + /* + * Must walk the selection list in opposite order from UnsetSelection + */ + atomP = salt->s.selections; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*atomP == (Atom)0) { + *atomP = salt->s.selections[--salt->s.atom_count]; + while (salt->s.atom_count + && salt->s.selections[salt->s.atom_count-1] == 0) + salt->s.atom_count--; + } + + if (salt->s.atom_count == 0) { + XtFree ((char *) salt->s.selections); + XtFree (salt->contents); + if (prevSalt) + prevSalt->next = nextSalt; + else + ctx->text.salt = nextSalt; + XtFree((char *)salt); + } + else + prevSalt = salt; + } +} + +void +_XawTextSaltAwaySelection(TextWidget ctx, Atom *selections, int num_atoms) +{ + XawTextSelectionSalt *salt; + int i, j; + + for (i = 0; i < num_atoms; i++) + TextLoseSelection((Widget)ctx, selections + i); + if (num_atoms == 0) + return; + salt = (XawTextSelectionSalt *) + XtMalloc((unsigned)sizeof(XawTextSelectionSalt)); + if (!salt) + return; + salt->s.selections = (Atom *)XtMalloc((unsigned)(num_atoms * sizeof(Atom))); + if (!salt->s.selections) { + XtFree((char *)salt); + return; + } + salt->s.left = ctx->text.s.left; + salt->s.right = ctx->text.s.right; + salt->s.type = ctx->text.s.type; + salt->contents = _XawTextGetSTRING(ctx, ctx->text.s.left, ctx->text.s.right); + if (XawTextFormat(ctx, XawFmtWide)) { + XTextProperty textprop; + if (XwcTextListToTextProperty(XtDisplay((Widget)ctx), + (wchar_t**)(&(salt->contents)), 1, + XCompoundTextStyle, + &textprop) < Success) { + XtFree(salt->contents); + salt->length = 0; + return; + } + XtFree(salt->contents); + salt->contents = (char *)textprop.value; + salt->length = textprop.nitems; + } + else + salt->length = strlen (salt->contents); + salt->next = ctx->text.salt; + ctx->text.salt = salt; + j = 0; + for (i = 0; i < num_atoms; i++) { + if (GetCutBufferNumber (selections[i]) == NOT_A_CUT_BUFFER) { + salt->s.selections[j++] = selections[i]; + XtOwnSelection((Widget)ctx, selections[i], ctx->text.time, + TextConvertSelection, TextLoseSelection, NULL); + } + } + salt->s.atom_count = j; +} + +static void +_SetSelection(TextWidget ctx, XawTextPosition left, XawTextPosition right, + Atom *selections, Cardinal count) +{ +#ifndef OLDXAW + Cardinal i; + XawTextPosition pos; + TextSrcObject src = (TextSrcObject)ctx->text.source; + + for (i = 0; i < src->textSrc.num_text; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + Bool needs_updating = tw->text.old_insert < 0; + Bool showposition = tw->text.showposition; + + if (needs_updating) { + tw->text.showposition = False; + _XawTextPrepareToUpdate(tw); + } +#else + TextWidget tw = ctx; + XawTextPosition pos; +#endif /* OLDXAW */ + + if (left < tw->text.s.left) { + pos = Min(right, tw->text.s.left); + _XawTextNeedsUpdating(tw, left, pos); + } + if (left > tw->text.s.left) { + pos = Min(left, tw->text.s.right); + _XawTextNeedsUpdating(tw, tw->text.s.left, pos); + } + if (right < tw->text.s.right) { + pos = Max(right, tw->text.s.left); + _XawTextNeedsUpdating(tw, pos, tw->text.s.right); + } + if (right > tw->text.s.right) { + pos = Max(left, tw->text.s.right); + _XawTextNeedsUpdating(tw, pos, right); + } + + tw->text.s.left = left; + tw->text.s.right = right; + +#ifndef OLDXAW + if (needs_updating) { + _XawTextExecuteUpdate(tw); + tw->text.showposition = showposition; + } + } +#endif /* OLDXAW */ + + SrcSetSelection(ctx->text.source, left, right, + (count == 0) ? None : selections[0]); + + if (left < right) { + Widget w = (Widget)ctx; + int buffer; + + while (count) { + Atom selection = selections[--count]; + + /* + * If this is a cut buffer + */ + if ((buffer = GetCutBufferNumber(selection)) != NOT_A_CUT_BUFFER) { + unsigned char *ptr, *tptr; + unsigned int amount, max_len = MAX_CUT_LEN(XtDisplay(w)); + unsigned long len; + + tptr= ptr= (unsigned char *)_XawTextGetSTRING(ctx, + ctx->text.s.left, + ctx->text.s.right); + if (XawTextFormat(ctx, XawFmtWide)) { + /* + * Only XA_STRING(Latin 1) is allowed in CUT_BUFFER, + * so we get it from wchar string, then free the wchar string + */ + XTextProperty textprop; + + if (XwcTextListToTextProperty(XtDisplay(w), (wchar_t**)&ptr, + 1, XStringStyle, &textprop) + < Success){ + XtFree((char *)ptr); + return; + } + XtFree((char *)ptr); + tptr = ptr = textprop.value; + } + if (buffer == 0) { + _CreateCutBuffers(XtDisplay(w)); + XRotateBuffers(XtDisplay(w), 1); + } + amount = Min ((len = strlen((char *)ptr)), max_len); + XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0), + selection, XA_STRING, 8, PropModeReplace, + ptr, amount); + + while (len > max_len) { + len -= max_len; + tptr += max_len; + amount = Min (len, max_len); + XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0), + selection, XA_STRING, 8, PropModeAppend, + tptr, amount); + } + XtFree ((char *)ptr); + } + else /* This is a real selection */ + XtOwnSelection(w, selection, ctx->text.time, TextConvertSelection, + TextLoseSelection, NULL); + } + } + else + XawTextUnsetSelection((Widget)ctx); +} + +#ifndef OLDXAW +void +_XawTextSetLineAndColumnNumber(TextWidget ctx, Bool force) +{ + int line_number, column_number; + + if (ctx->text.old_insert != ctx->text.insertPos && + ctx->text.lt.base_line < 0) { + ctx->text.lt.base_line = 0; + (void)_BuildLineTable(ctx, ctx->text.lt.top, 0); + } + + line_number = ResolveLineNumber(ctx); + column_number = ResolveColumnNumber(ctx); + + if (force || (ctx->text.column_number != column_number + || ctx->text.line_number != line_number)) { + XawTextPositionInfo info; + + ctx->text.line_number = info.line_number = line_number; + ctx->text.column_number = info.column_number = column_number; + info.insert_position = ctx->text.insertPos; + info.last_position = ctx->text.lastPos; + info.overwrite_mode = ctx->text.overwrite; + + XtCallCallbacks((Widget)ctx, XtNpositionCallback, (XtPointer)&info); + } +} + +static int +ResolveColumnNumber(TextWidget ctx) +{ + Widget src = ctx->text.source; + short column_number = 0; + XawTextPosition position; + XawTextBlock block; + unsigned long format = _XawTextFormat(ctx); + TextSinkObject sink = (TextSinkObject)ctx->text.sink; + short *char_tabs = sink->text_sink.char_tabs; + int tab_count = sink->text_sink.tab_count; + int tab_index = 0, tab_column = 0, tab_base = 0; + + if (ctx->text.lt.base_line < 1) + return (ctx->text.column_number); + + position = SrcScan(src, ctx->text.insertPos, XawstEOL, XawsdLeft, 1, False); + XawTextSourceRead(src, position, &block, ctx->text.insertPos - position); + + for (; position < ctx->text.insertPos; position++) { + if (position - block.firstPos >= block.length) + XawTextSourceRead(src, position, &block, ctx->text.insertPos - position); + if ((format == XawFmt8Bit && block.ptr[position - block.firstPos] == '\t') || + (format == XawFmtWide && ((wchar_t*)block.ptr)[position - block.firstPos] == _Xaw_atowc(XawTAB))) { + while (tab_base + tab_column <= column_number) { + if (tab_count) { + for (; tab_index < tab_count; ++tab_index) + if (tab_base + char_tabs[tab_index] > column_number) { + tab_column = char_tabs[tab_index]; + break; + } + if (tab_index >= tab_count) { + tab_base += char_tabs[tab_count - 1]; + tab_column = tab_index = 0; + } + } + else + tab_column += DEFAULT_TAB_SIZE; + } + column_number = tab_base + tab_column; + } + else + ++column_number; + if (column_number >= 16384) { + column_number = 16383; + break; + } + } + + return (column_number); +} +#endif /* OLDXAW */ + +void +_XawTextSourceChanged(Widget w, XawTextPosition left, XawTextPosition right, + XawTextBlock *block, int lines) +{ + TextWidget ctx = (TextWidget)w; + Widget src = ctx->text.source; + XawTextPosition update_from, update_to, top; + Boolean update_disabled; + int delta, line, line_from; + + if (left < ctx->text.old_insert) { + XawTextPosition old_insert = ctx->text.old_insert; + + if (right < ctx->text.old_insert) + old_insert -= right - left; + else + old_insert = left; + + ctx->text.insertPos = old_insert + block->length; + } +#ifndef OLDXAW + if (left <= ctx->text.lt.top) { + if (left + block->length - (right - left) < ctx->text.lt.top) { + ctx->text.source_changed = SRC_CHANGE_BEFORE; + ctx->text.lt.base_line += lines; + } + else + ctx->text.source_changed = SRC_CHANGE_OVERLAP; + } + else + ctx->text.source_changed = SRC_CHANGE_AFTER; +#endif + + update_from = left; + update_to = left + block->length; + update_to = SrcScan(src, update_to, XawstEOL, XawsdRight, 1, False); + delta = block->length - (right - left); + if (delta < 0) + ctx->text.clear_to_eol = True; + if (update_to == update_from) + ++update_to; + update_disabled = ctx->text.update_disabled; + ctx->text.update_disabled = True; + ctx->text.lastPos = XawTextGetLastPosition(ctx); + top = ctx->text.lt.info[0].position; + + XawTextUnsetSelection((Widget)ctx); + + if (delta) { + int i; + XmuSegment *seg; + + for (seg = ctx->text.update->segment; seg; seg = seg->next) { + if (seg->x1 > (int)left) + break; + else if (seg->x2 > (int)left) { + seg->x2 += delta; + seg = seg->next; + break; + } + } + for (; seg; seg = seg->next) { + seg->x1 += delta; + seg->x2 += delta; + } + XmuOptimizeScanline(ctx->text.update); + + for (i = 0; i <= ctx->text.lt.lines; i++) + if (ctx->text.lt.info[i].position > left) + break; + for (; i <= ctx->text.lt.lines; i++) + ctx->text.lt.info[i].position += delta; + } + + if (top != ctx->text.lt.info[0].position) { + line_from = line = 0; + ctx->text.lt.top = top = SrcScan(src, ctx->text.lt.info[0].position, + XawstEOL, XawsdLeft, 1, False); + update_from = top; + } + else { + line_from = line = LineForPosition(ctx, update_from + delta); + top = ctx->text.lt.info[line].position; + } + + if (line > 0 && ctx->text.wrap == XawtextWrapWord) { + --line; + top = ctx->text.lt.info[line].position; + } + + (void)_BuildLineTable(ctx, top, line); + + if (ctx->text.wrap == XawtextWrapWord) { + if (line_from != LineForPosition(ctx, update_from) + || line_from != LineForPosition(ctx, update_to)) { + ctx->text.clear_to_eol = True; + update_from = SrcScan(src, update_from, + XawstWhiteSpace, XawsdLeft, 1, True); + if (update_to >= ctx->text.lastPos) + /* this is not an error, it just tells _BuildLineTable to + * clear to the bottom of the window. The value of update_to + * should not be > ctx->text.lastPos. + */ + ++update_to; + } + } + else if (!ctx->text.clear_to_eol) { + if (LineForPosition(ctx, update_from) + != LineForPosition(ctx, update_to)) + ctx->text.clear_to_eol = True; + } + + _XawTextNeedsUpdating(ctx, update_from, update_to); + ctx->text.update_disabled = update_disabled; +} + +/* + * Function: + * _XawTextReplace + * + * Parameters: + * ctx - text widget + * left - left offset + * right - right offset + * block - text block + * + * Description: + * Replaces the text between left and right by the text in block. + * Does all the required calculations of offsets, and rebuild the + * the line table, from the insertion point (or previous line, if + * wrap mode is 'word'). + * + * Returns: + * XawEditDone - success + * any other value - error code + */ +int +_XawTextReplace(TextWidget ctx, XawTextPosition left, XawTextPosition right, + XawTextBlock *block) +{ + Arg args[1]; + Widget src; + XawTextEditType edit_mode; + + if (left == right && block->length == 0) + return (XawEditDone); + + src = ctx->text.source; + XtSetArg(args[0], XtNeditType, &edit_mode); + XtGetValues(src, args, 1); + + if (edit_mode == XawtextAppend) { + if (block->length == 0) + return (XawEditError); + ctx->text.insertPos = ctx->text.lastPos; + } + +#ifndef OLDXAW + return (SrcReplace(src, left, right, block)); +#else + if (SrcReplace(src, left, right, block) == XawEditDone) { + _XawTextSourceChanged((Widget)ctx, left, right, block, 0); + + return (XawEditDone); + } + + return (XawEditError); +#endif +} + +/* + * This routine will display text between two arbitrary source positions. + * In the event that this span contains highlighted text for the selection, + * only that portion will be displayed highlighted. + */ +static void +OldDisplayText(Widget w, XawTextPosition left, XawTextPosition right) +{ + static XmuSegment segment; + static XmuScanline next; + static XmuScanline scanline = {0, &segment, &next}; + static XmuArea area = {&scanline}; + + TextWidget ctx = (TextWidget)w; + int x, y, line; + XawTextPosition start, end, last, final; + XmuScanline *scan; + XmuSegment *seg; + XmuArea *clip = NULL; + Bool cleol = ctx->text.clear_to_eol; + Bool has_selection = ctx->text.s.right > ctx->text.s.left; + + left = left < ctx->text.lt.top ? ctx->text.lt.top : left; + + if (left > right || !LineAndXYForPosition(ctx, left, &line, &x, &y)) + return; + + last = XawTextGetLastPosition(ctx); + segment.x2 = (int)XtWidth(ctx) - ctx->text.r_margin.right; + + if (cleol) + clip = XmuCreateArea(); + + for (start = left; start < right && line < ctx->text.lt.lines; line++) { + if ((end = ctx->text.lt.info[line + 1].position) > right) + end = right; + + final = end; + if (end > last) + end = last; + + if (end > start) { + if (!has_selection + || (start >= ctx->text.s.right || end <= ctx->text.s.left)) + _XawTextSinkDisplayText(ctx->text.sink, x, y, start, end, False); + else if (start >= ctx->text.s.left && end <= ctx->text.s.right) + _XawTextSinkDisplayText(ctx->text.sink, x, y, start, end, True); + else { + OldDisplayText(w, start, ctx->text.s.left); + OldDisplayText(w, Max(start, ctx->text.s.left), + Min(end, ctx->text.s.right)); + OldDisplayText(w, ctx->text.s.right, end); + } + } + + x = ctx->text.left_margin; + if (cleol) { + segment.x1 = ctx->text.lt.info[line].textWidth + x; + if (XmuValidSegment(&segment)) { + scanline.y = y; + next.y = ctx->text.lt.info[line + 1].y; + XmuAreaOr(clip, &area); + } + } + + start = final; + y = ctx->text.lt.info[line + 1].y; + } + + if (cleol) { + for (scan = clip->scanline; scan && scan->next; scan = scan->next) + for (seg = scan->segment; seg; seg = seg->next) + SinkClearToBG(ctx->text.sink, + seg->x1, scan->y, + seg->x2 - seg->x1, scan->next->y - scan->y); + XmuDestroyArea(clip); + } +} + +#ifndef OLDXAW +/*ARGSUSED*/ +static void +DisplayText(Widget w, XawTextPosition left, XawTextPosition right) +{ + static XmuSegment segment; + static XmuScanline next; + static XmuScanline scanline = {0, &segment, &next}; + static XmuArea area = {&scanline}; + + TextWidget ctx = (TextWidget)w; + int y, line; + XawTextPosition from, to, lastPos; + Bool cleol = ctx->text.clear_to_eol; + Bool has_selection = ctx->text.s.right > ctx->text.s.left; + XawTextPaintList *paint_list; + + left = left < ctx->text.lt.top ? ctx->text.lt.top : left; + + if (left > right || !IsPositionVisible(ctx, left)) + return; + + line = LineForPosition(ctx, left); + y = ctx->text.lt.info[line].y; + segment.x2 = (int)XtWidth(ctx) - ctx->text.r_margin.right; + lastPos = XawTextGetLastPosition(ctx); + + paint_list = ((TextSinkObject)ctx->text.sink)->text_sink.paint; + + for (from = left; from < right && line < ctx->text.lt.lines; line++) { + if ((to = ctx->text.lt.info[line + 1].position) > right) + to = right; + + if (to > lastPos) + to = lastPos; + + if (from < to) { + if (!has_selection + || (from >= ctx->text.s.right || to <= ctx->text.s.left)) + XawTextSinkPreparePaint(ctx->text.sink, y, line, from, to, False); + else if (from >= ctx->text.s.left && to <= ctx->text.s.right) + XawTextSinkPreparePaint(ctx->text.sink, y, line, from, to, True); + else { + XawTextSinkPreparePaint(ctx->text.sink, y, line, from, + ctx->text.s.left, False); + XawTextSinkPreparePaint(ctx->text.sink, y, line, + XawMax(from, ctx->text.s.left), + XawMin(to, ctx->text.s.right), True); + XawTextSinkPreparePaint(ctx->text.sink, y, line, + ctx->text.s.right, to, False); + } + } + + if (cleol) { + segment.x1 = ctx->text.lt.info[line].textWidth + ctx->text.left_margin; + if (XmuValidSegment(&segment)) { + scanline.y = y; + next.y = ctx->text.lt.info[line + 1].y; + XmuAreaOr(paint_list->clip, &area); + } + } + y = ctx->text.lt.info[line + 1].y; + from = to; + } + + /* clear to the bottom of the window */ + if (cleol && line >= ctx->text.lt.lines) { + segment.x1 = ctx->text.left_margin; + if (XmuValidSegment(&segment)) { + scanline.y = y; + next.y = (int)XtHeight(ctx) - (int)ctx->text.margin.bottom; + XmuAreaOr(paint_list->clip, &area); + } + } +} +#endif + +/* + * This routine implements multi-click selection in a hardwired manner. + * It supports multi-click entity cycling (char, word, line, file) and mouse + * motion adjustment of the selected entitie (i.e. select a word then, with + * button still down, adjust wich word you really meant by moving the mouse). + * [NOTE: This routine is to be replaced by a set of procedures that + * will allows clients to implements a wide class of draw through and + * multi-click selection user interfaces.] + */ +static void +DoSelection(TextWidget ctx, XawTextPosition pos, Time time, Bool motion) +{ + XawTextPosition newLeft, newRight; + XawTextSelectType newType, *sarray; + Widget src = ctx->text.source; + + if (motion) + newType = ctx->text.s.type; + else { + if ((abs((long) time - (long) ctx->text.lasttime) < MULTI_CLICK_TIME) + && (pos >= ctx->text.s.left && pos <= ctx->text.s.right)) { + sarray = ctx->text.sarray; + for (; *sarray != XawselectNull && *sarray != ctx->text.s.type; + sarray++) + ; + if (*sarray == XawselectNull) + newType = *(ctx->text.sarray); + else { + newType = *(sarray + 1); + if (newType == XawselectNull) + newType = *(ctx->text.sarray); + } + } + else /* single-click event */ + newType = *(ctx->text.sarray); + + ctx->text.lasttime = time; + } + switch (newType) { + case XawselectPosition: + newLeft = newRight = pos; + break; + case XawselectChar: + newLeft = pos; + newRight = SrcScan(src, pos, XawstPositions, XawsdRight, 1, False); + break; + case XawselectWord: + case XawselectParagraph: + case XawselectAlphaNumeric: { + XawTextScanType stype; + + if (newType == XawselectWord) + stype = XawstWhiteSpace; + else if (newType == XawselectParagraph) + stype = XawstParagraph; + else + stype = XawstAlphaNumeric; + + /* + * Somewhat complicated, but basically I treat the space between + * two objects as another object. The object that I am currently + * in then becomes the end of the selection. + * + * Chris Peterson - 4/19/90. + */ + newRight = SrcScan(ctx->text.source, pos, stype, + XawsdRight, 1, False); + newRight = SrcScan(ctx->text.source, newRight, stype, + XawsdLeft, 1, False); + + if (pos != newRight) + newLeft = SrcScan(ctx->text.source, pos, stype, + XawsdLeft, 1, False); + else + newLeft = pos; + + newLeft =SrcScan(ctx->text.source, newLeft, stype, + XawsdRight, 1, False); + + if (newLeft > newRight) { + XawTextPosition temp = newLeft; + newLeft = newRight; + newRight = temp; + } + } break; + case XawselectLine: + newLeft = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False); + newRight = SrcScan(src, pos, XawstEOL, XawsdRight, 1, False); + break; + case XawselectAll: + newLeft = SrcScan(src, pos, XawstAll, XawsdLeft, 1, False); + newRight = SrcScan(src, pos, XawstAll, XawsdRight, 1, False); + break; + default: + XtAppWarning(XtWidgetToApplicationContext((Widget) ctx), + "Text Widget: empty selection array."); + return; + } + + if (newLeft != ctx->text.s.left || newRight != ctx->text.s.right + || newType != ctx->text.s.type) { + ModifySelection(ctx, newLeft, newRight); + if (pos - ctx->text.s.left < ctx->text.s.right - pos) + ctx->text.insertPos = newLeft; + else + ctx->text.insertPos = newRight; + ctx->text.s.type = newType; + } + if (!motion) { /* setup so we can freely mix select extend calls*/ + ctx->text.origSel.type = ctx->text.s.type; + ctx->text.origSel.left = ctx->text.s.left; + ctx->text.origSel.right = ctx->text.s.right; + + if (pos >= ctx->text.s.left + (ctx->text.s.right - ctx->text.s.left) / 2) + ctx->text.extendDir = XawsdRight; + else + ctx->text.extendDir = XawsdLeft; + } +} + +/* + * This routine implements extension of the currently selected text in + * the "current" mode (i.e. char word, line, etc.). It worries about + * extending from either end of the selection and handles the case when you + * cross through the "center" of the current selection (e.g. switch which + * end you are extending!). + */ +static void +ExtendSelection(TextWidget ctx, XawTextPosition pos, Bool motion) +{ + XawTextScanDirection dir; + + if (!motion) { /* setup for extending selection */ + if (ctx->text.s.left == ctx->text.s.right) /* no current selection. */ + ctx->text.s.left = ctx->text.s.right = ctx->text.insertPos; + else { + ctx->text.origSel.left = ctx->text.s.left; + ctx->text.origSel.right = ctx->text.s.right; + } + + ctx->text.origSel.type = ctx->text.s.type; + + if (pos >= ctx->text.s.left + (ctx->text.s.right - ctx->text.s.left) / 2) + ctx->text.extendDir = XawsdRight; + else + ctx->text.extendDir = XawsdLeft; + } + else /* check for change in extend direction */ + if ((ctx->text.extendDir == XawsdRight && + pos <= ctx->text.origSel.left) || + (ctx->text.extendDir == XawsdLeft && + pos >= ctx->text.origSel.right)) { + ctx->text.extendDir = (ctx->text.extendDir == XawsdRight) ? + XawsdLeft : XawsdRight; + ModifySelection(ctx, ctx->text.origSel.left, ctx->text.origSel.right); + } + + dir = ctx->text.extendDir; + switch (ctx->text.s.type) { + case XawselectWord: + case XawselectParagraph: + case XawselectAlphaNumeric: { + XawTextPosition left_pos, right_pos; + XawTextScanType stype; + + if (ctx->text.s.type == XawselectWord) + stype = XawstWhiteSpace; + else if (ctx->text.s.type == XawselectParagraph) + stype = XawstParagraph; + else + stype = XawstAlphaNumeric; + + /* + * Somewhat complicated, but basically I treat the space between + * two objects as another object. The object that I am currently + * in then becomes the end of the selection. + * + * Chris Peterson - 4/19/90. + */ + right_pos = SrcScan(ctx->text.source, pos, stype, + XawsdRight, 1, False); + right_pos =SrcScan(ctx->text.source, right_pos, stype, + XawsdLeft, 1, False); + + if (pos != right_pos) + left_pos = SrcScan(ctx->text.source, pos, stype, + XawsdLeft, 1, False); + else + left_pos = pos; + + left_pos =SrcScan(ctx->text.source, left_pos, stype, + XawsdRight, 1, False); + + if (dir == XawsdLeft) + pos = Min(left_pos, right_pos); + else /* dir == XawsdRight */ + pos = Max(left_pos, right_pos); + } break; + case XawselectLine: + pos = SrcScan(ctx->text.source, pos, XawstEOL, + dir, 1, dir == XawsdRight); + break; + case XawselectAll: + pos = ctx->text.insertPos; + /*FALLTHROUGH*/ + case XawselectPosition: + default: + break; + } + + if (dir == XawsdRight) + ModifySelection(ctx, ctx->text.s.left, pos); + else + ModifySelection(ctx, pos, ctx->text.s.right); + + ctx->text.insertPos = pos; +} + +/* + * Function: + * _XawTextClearAndCenterDisplay + * + * Parameters: + * ctx - text widget + * + * Description: + * Redraws the display with the cursor in insert point + * centered vertically. + */ +void +_XawTextClearAndCenterDisplay(TextWidget ctx) +{ + int left_margin = ctx->text.left_margin; + Bool visible = IsPositionVisible(ctx, ctx->text.insertPos); + + _XawTextShowPosition(ctx); + + if (XtIsRealized((Widget)ctx) && visible && + left_margin == ctx->text.left_margin) { + int insert_line = LineForPosition(ctx, ctx->text.insertPos); + int scroll_by = insert_line - (ctx->text.lt.lines >> 1); + Boolean clear_to_eol = ctx->text.clear_to_eol; + + XawTextScroll(ctx, scroll_by, 0); + SinkClearToBG(ctx->text.sink, 0, 0, XtWidth(ctx), XtHeight(ctx)); + ClearWindow(ctx); + clear_to_eol = ctx->text.clear_to_eol; + ctx->text.clear_to_eol = False; + FlushUpdate(ctx); + ctx->text.clear_to_eol = clear_to_eol; + } +} + +/* + * Internal redisplay entire window + * Legal to call only if widget is realized + */ +static void +DisplayTextWindow(Widget w) +{ + TextWidget ctx = (TextWidget)w; + + _XawTextBuildLineTable(ctx, ctx->text.lt.top, False); + ClearWindow(ctx); +} + +static void +TextSinkResize(Widget w) +{ + if (w && XtClass(w)->core_class.resize) + XtClass(w)->core_class.resize(w); +} + +/* ARGSUSED */ +void +_XawTextCheckResize(TextWidget ctx) +{ + return; +} + +/* + * Converts (params, num_params) to a list of atoms & caches the + * list in the TextWidget instance. + */ +Atom * +_XawTextSelectionList(TextWidget ctx, String *list, Cardinal nelems) +{ + Atom *sel = ctx->text.s.selections; + Display *dpy = XtDisplay((Widget)ctx); + int n; + + if (nelems > (Cardinal)ctx->text.s.array_size) { + sel = (Atom *)XtRealloc((char *)sel, sizeof(Atom) * nelems); + ctx->text.s.array_size = nelems; + ctx->text.s.selections = sel; + } + for (n = nelems; --n >= 0; sel++, list++) + *sel = XInternAtom(dpy, *list, False); + ctx->text.s.atom_count = nelems; + + return (ctx->text.s.selections); +} + +/* + * Function: + * SetSelection + * + * Parameters: + * ctx - text widget + * defaultSel - default selection + * l - left and right ends of the selection + * r - "" + * list - the selection list (as strings). + * nelems - "" + * + * Description: + * Sets the current selection. + * + * Note: + * if (ctx->text.s.left >= ctx->text.s.right) then the selection is unset + */ +void +_XawTextSetSelection(TextWidget ctx, XawTextPosition l, XawTextPosition r, + String *list, Cardinal nelems) +{ + if (nelems == 1 && !strcmp (list[0], "none")) + return; + if (nelems == 0) { + String defaultSel = "PRIMARY"; + list = &defaultSel; + nelems = 1; + } + _SetSelection(ctx, l, r, _XawTextSelectionList(ctx, list, nelems), nelems); +} + +/* + * Function: + * ModifySelection + * + * Parameters: + * ctx - text widget + * left - left and right ends of the selection + * right - "" + * + * Description: + * Modifies the current selection. + * + * Note: + * if (ctx->text.s.left >= ctx->text.s.right) then the selection is unset + */ +static void +ModifySelection(TextWidget ctx, XawTextPosition left, XawTextPosition right) +{ + if (left == right) + ctx->text.insertPos = left; + _SetSelection(ctx, left, right, NULL, 0); +} + +/* + * This routine is used to perform various selection functions. The goal is + * to be able to specify all the more popular forms of draw-through and + * multi-click selection user interfaces from the outside. + */ +void +_XawTextAlterSelection(TextWidget ctx, XawTextSelectionMode mode, + XawTextSelectionAction action, String *params, + Cardinal *num_params) +{ + XawTextPosition position; + Boolean flag; + + /* + * This flag is used by TextPop.c:DoReplace() to determine if the selection + * is okay to use, or if it has been modified. + */ + if (ctx->text.search != NULL) + ctx->text.search->selection_changed = True; + + position = PositionForXY(ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y); + + flag = (action != XawactionStart); + if (mode == XawsmTextSelect) + DoSelection(ctx, position, ctx->text.time, flag); + else /* mode == XawsmTextExtend */ + ExtendSelection (ctx, position, flag); + + if (action == XawactionEnd) + _XawTextSetSelection(ctx, ctx->text.s.left, ctx->text.s.right, + params, *num_params); +} + +/* + * Function: + * UpdateTextInRectangle + * + * Parameters: + * ctx - the text widget + * rect - rectangle + * + * Description: + * Updates the text in the given rectangle + */ +static void +UpdateTextInRectangle(TextWidget ctx, XRectangle *rect) +{ + XawTextLineTable *lt; + int line, y1, y2, x2; + + y1 = rect->y; + y2 = y1 + rect->height; + x2 = rect->x + rect->width; + + for (line = 0, lt = &ctx->text.lt; line < lt->lines; line++) + if (lt->info[line + 1].y > y1) + break; + for (; line <= lt->lines; line++) { + if (lt->info[line].y > y2) + break; + UpdateTextInLine(ctx, line, rect->x, x2); + } +} + +/* + * This routine processes all "expose region" XEvents. In general, its job + * is to the best job at minimal re-paint of the text, displayed in the + * window, that it can. + */ +/* ARGSUSED */ +static void +XawTextExpose(Widget w, XEvent *event, Region region) +{ + TextWidget ctx = (TextWidget)w; + Boolean clear_to_eol; + XRectangle expose; + + if (event->type == Expose) { + expose.x = event->xexpose.x; + expose.y = event->xexpose.y; + expose.width = event->xexpose.width; + expose.height = event->xexpose.height; + } + else if (event->type == GraphicsExpose) { + expose.x = event->xgraphicsexpose.x; + expose.y = event->xgraphicsexpose.y; + expose.width = event->xgraphicsexpose.width; + expose.height = event->xgraphicsexpose.height; + } + else + return; + + _XawTextPrepareToUpdate(ctx); + + if (Superclass->core_class.expose) + (*Superclass->core_class.expose)(w, event, region); + + clear_to_eol = ctx->text.clear_to_eol; + ctx->text.clear_to_eol = False; + + UpdateTextInRectangle(ctx, &expose); + XawTextSinkGetCursorBounds(ctx->text.sink, &expose); + UpdateTextInRectangle(ctx, &expose); + SinkClearToBG(ctx->text.sink, expose.x, expose.y, + expose.width, expose.height); + _XawTextExecuteUpdate(ctx); + ctx->text.clear_to_eol = clear_to_eol; +} + +/* + * This routine does all setup required to syncronize batched screen updates + */ +void +_XawTextPrepareToUpdate(TextWidget ctx) +{ + if (ctx->text.old_insert < 0) { + InsertCursor((Widget)ctx, XawisOff); + ctx->text.showposition = False; + ctx->text.old_insert = ctx->text.insertPos; + ctx->text.clear_to_eol = False; +#ifndef OLDXAW + ctx->text.source_changed = SRC_CHANGE_NONE; +#endif + } +} + +/* + * This is a private utility routine used by _XawTextExecuteUpdate. It + * processes all the outstanding update requests and merges update + * ranges where possible. + */ +static void +FlushUpdate(TextWidget ctx) +{ + XmuSegment *seg; + void (*display_text)(Widget, XawTextPosition, XawTextPosition); + + if (XtIsRealized((Widget)ctx)) { + ctx->text.s.right = XawMin(ctx->text.s.right, ctx->text.lastPos); + ctx->text.s.left = XawMin(ctx->text.s.left, ctx->text.s.right); + +#ifndef OLDXAW + if (XawTextSinkBeginPaint(ctx->text.sink) == False) +#endif + display_text = OldDisplayText; +#ifndef OLDXAW + else + display_text = DisplayText; +#endif + for (seg = ctx->text.update->segment; seg; seg = seg->next) + (*display_text)((Widget)ctx, + (XawTextPosition)seg->x1, + (XawTextPosition)seg->x2); +#ifndef OLDXAW + if (display_text != OldDisplayText) { + XawTextSinkDoPaint(ctx->text.sink); + XawTextSinkEndPaint(ctx->text.sink); + } +#endif + } + (void)XmuScanlineXor(ctx->text.update, ctx->text.update); +} + +static int +CountLines(TextWidget ctx, XawTextPosition left, XawTextPosition right) +{ + if (ctx->text.wrap == XawtextWrapNever || left >= right) + return (1); + else { + XawTextPosition tmp; + int dim, lines = 0, wwidth = GetMaxTextWidth(ctx); + + while (left < right) { + tmp = left; + XawTextSinkFindPosition(ctx->text.sink, left, + ctx->text.left_margin, + wwidth, ctx->text.wrap == XawtextWrapWord, + &left, &dim, &dim); + ++lines; + if (tmp == left) + ++left; + } + + return (lines); + } + /*NOTREACHED*/ +} + +static int +GetMaxTextWidth(TextWidget ctx) +{ + XRectangle cursor; + int width; + + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + width = (int)XtWidth(ctx) - RHMargins(ctx) - cursor.width; + + return (XawMax(0, width)); +} + +/* + * Function: + * _XawTextShowPosition + * + * Parameters: + * ctx - the text widget to show the position + * + * Description: + * Makes sure the text cursor visible, scrolling the text window + * if required. + */ +void +_XawTextShowPosition(TextWidget ctx) +{ + /* + * Variable scroll is used to avoid scanning large files to calculate + * line offsets + */ + int hpixels, vlines; + XawTextPosition first, last, top, tmp; + Bool visible, scroll; + + if (!XtIsRealized((Widget)ctx)) + return; + + /* + * Checks if a horizontal scroll is required + */ + if (ctx->text.wrap == XawtextWrapNever) { + int x, vwidth, distance, dim; + XRectangle rect; + + vwidth = (int)XtWidth(ctx) - RHMargins(ctx); + last = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, False); + XawTextSinkFindDistance(ctx->text.sink, last, + ctx->text.left_margin, + ctx->text.insertPos, + &distance, &first, &dim); + XawTextSinkGetCursorBounds(ctx->text.sink, &rect); + x = ctx->text.left_margin - ctx->text.r_margin.left; + + if (x + distance + rect.width > vwidth) + hpixels = x + distance + rect.width - vwidth + (vwidth >> 2); + else if (x + distance < 0) + hpixels = x + distance - (vwidth >> 2); + else + hpixels = 0; + } + else + hpixels = 0; + + visible = IsPositionVisible(ctx, ctx->text.insertPos); + + /* + * If the cursor is already visible + */ + if (!hpixels && visible) + return; + + scroll = ctx->core.background_pixmap == XtUnspecifiedPixmap && !hpixels; + vlines = 0; + first = ctx->text.lt.top; + + /* + * Needs to scroll the text window + */ + if (visible) + top = ctx->text.lt.top; + else { + top = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, False); + + /* + * Finds the nearest left position from ctx->text.insertPos + */ + if (ctx->text.wrap != XawtextWrapNever) { + int dim, vwidth = GetMaxTextWidth(ctx); + + last = top; + /*CONSTCOND*/ + while (1) { + tmp = last; + XawTextSinkFindPosition(ctx->text.sink, last, + ctx->text.left_margin, vwidth, + ctx->text.wrap == XawtextWrapWord, + &last, &dim, &dim); + if (last == tmp) + ++last; + if (last <= ctx->text.insertPos) + top = last; + else + break; + } + } + } + + if (scroll) { + if (ctx->text.insertPos < first) { /* Scroll Down */ + while (first > top) { + last = first; + first = SrcScan(ctx->text.source, first, + XawstEOL, XawsdLeft, 2, False); + vlines -= CountLines(ctx, first, last); + if (-vlines >= ctx->text.lt.lines) { + scroll = False; + break; + } + } + } + else if (!visible) { /* Scroll Up */ + while (first < top) { + last = first; + first = SrcScan(ctx->text.source, first, + XawstEOL, XawsdRight, 1, True); + vlines += CountLines(ctx, last, first); + if (vlines > ctx->text.lt.lines) { + scroll = False; + break; + } + } + } + else + scroll = False; + } + + /* + * If a portion of the text that will be scrolled is visible + */ + if (scroll) + XawTextScroll(ctx, vlines ? vlines - (ctx->text.lt.lines >> 1) : 0, 0); + /* + * Else redraw the entire text window + */ + else { + ctx->text.left_margin -= hpixels; + if (ctx->text.left_margin > ctx->text.r_margin.left) + ctx->text.left_margin = ctx->text.margin.left = + ctx->text.r_margin.left; + + if (!visible) { + vlines = ctx->text.lt.lines >> 1; + if (vlines) + top = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, vlines + 1, False); + + if (ctx->text.wrap != XawtextWrapNever) { + int dim; + int n_lines = CountLines(ctx, top, ctx->text.insertPos); + int vwidth = GetMaxTextWidth(ctx); + + while (n_lines-- > vlines) { + tmp = top; + XawTextSinkFindPosition(ctx->text.sink, top, + ctx->text.left_margin, + vwidth, + ctx->text.wrap == XawtextWrapWord, + &top, &dim, &dim); + if (tmp == top) + ++top; + } + } + _XawTextBuildLineTable(ctx, top, True); + } + else + ClearWindow(ctx); + } + ctx->text.clear_to_eol = True; +} + +#ifndef OLDXAW +static int +ResolveLineNumber(TextWidget ctx) +{ + int line_number = ctx->text.lt.base_line; + XawTextPosition position = ctx->text.lt.top; + + if (ctx->text.lt.base_line < 1) + return (ctx->text.line_number); + + if (ctx->text.wrap == XawtextWrapNever + && IsPositionVisible(ctx, ctx->text.insertPos)) + line_number += LineForPosition(ctx, ctx->text.insertPos); + else if (position < ctx->text.insertPos) { + while (position < ctx->text.insertPos) { + position = SrcScan(ctx->text.source, position, + XawstEOL, XawsdRight, 1, True); + if (position <= ctx->text.insertPos) { + ++line_number; + if (position == ctx->text.lastPos) { + line_number -= !_XawTextSourceNewLineAtEOF(ctx->text.source); + break; + } + } + } + } + else if (position > ctx->text.insertPos) { + while (position > ctx->text.insertPos) { + position = SrcScan(ctx->text.source, position, + XawstEOL, XawsdLeft, 1, False); + if (--position >= ctx->text.insertPos) + --line_number; + } + } + + return (line_number); +} +#endif + +/* + * This routine causes all batched screen updates to be performed + */ +void +_XawTextExecuteUpdate(TextWidget ctx) +{ + if (ctx->text.update_disabled || ctx->text.old_insert < 0) + return; + + if(ctx->text.old_insert != ctx->text.insertPos || ctx->text.showposition) + _XawTextShowPosition(ctx); + + FlushUpdate(ctx); + InsertCursor((Widget)ctx, XawisOn); + ctx->text.old_insert = -1; +#ifndef OLDXAW + _XawTextSetLineAndColumnNumber(ctx, False); +#endif +} + +static void +XawTextDestroy(Widget w) +{ + TextWidget ctx = (TextWidget)w; + + DestroyHScrollBar(ctx); + DestroyVScrollBar(ctx); + + XtFree((char *)ctx->text.s.selections); + XtFree((char *)ctx->text.lt.info); + XtFree((char *)ctx->text.search); + XmuDestroyScanline(ctx->text.update); + XtReleaseGC((Widget)ctx, ctx->text.gc); +} + +/* + * by the time we are managed (and get this far) we had better + * have both a source and a sink + */ +static void +XawTextResize(Widget w) +{ + TextWidget ctx = (TextWidget)w; + + PositionVScrollBar(ctx); + PositionHScrollBar(ctx); + TextSinkResize(ctx->text.sink); + + ctx->text.showposition = True; + _XawTextBuildLineTable(ctx, ctx->text.lt.top, True); +} + +/* + * This routine allow the application program to Set attributes. + */ +/*ARGSUSED*/ +static Boolean +XawTextSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + TextWidget oldtw = (TextWidget)current; + TextWidget newtw = (TextWidget)cnew; + Boolean redisplay = False; + Boolean display_caret = newtw->text.display_caret; +#ifndef OLDXAW + Boolean show_lc = False; +#endif + + newtw->text.display_caret = oldtw->text.display_caret; + _XawTextPrepareToUpdate(newtw); + newtw->text.display_caret = display_caret; + + if (oldtw->text.r_margin.left != newtw->text.r_margin.left) { + newtw->text.left_margin = newtw->text.margin.left = + newtw->text.r_margin.left; + if (newtw->text.vbar != NULL) { + newtw->text.left_margin += XtWidth(newtw->text.vbar) + + XtBorderWidth(newtw->text.vbar); + } + redisplay = True; + } + + if (oldtw->text.scroll_vert != newtw->text.scroll_vert) { + if (newtw->text.scroll_vert == XawtextScrollAlways) + CreateVScrollBar(newtw); + else + DestroyVScrollBar(newtw); + + redisplay = True; + } + + if (oldtw->text.r_margin.bottom != newtw->text.r_margin.bottom) { + newtw->text.margin.bottom = newtw->text.r_margin.bottom; + if (newtw->text.hbar != NULL) + newtw->text.margin.bottom += newtw->text.hbar->core.height + + newtw->text.hbar->core.border_width; + redisplay = True; + } + + if (oldtw->text.scroll_horiz != newtw->text.scroll_horiz) { + if (newtw->text.scroll_horiz == XawtextScrollAlways) + CreateHScrollBar(newtw); + else + DestroyHScrollBar(newtw); + + redisplay = True; + } + + if (oldtw->text.source != newtw->text.source) { +#ifndef OLDXAW + show_lc = True; + _XawSourceRemoveText(oldtw->text.source, cnew, + oldtw->text.source && + XtParent(oldtw->text.source) == cnew); + _XawSourceAddText(newtw->text.source, cnew); +#endif + _XawTextSetSource((Widget)newtw, newtw->text.source, newtw->text.lt.top, + newtw->text.insertPos); + } + + newtw->text.redisplay_needed = False; + XtSetValues((Widget)newtw->text.source, args, *num_args); + XtSetValues((Widget)newtw->text.sink, args, *num_args); + + if (oldtw->text.wrap != newtw->text.wrap + || oldtw->text.lt.top != newtw->text.lt.top + || oldtw->text.insertPos != newtw->text.insertPos + || oldtw->text.r_margin.right != newtw->text.r_margin.right + || oldtw->text.r_margin.top != newtw->text.r_margin.top + || oldtw->text.sink != newtw->text.sink + || newtw->text.redisplay_needed) { + if (oldtw->text.wrap != newtw->text.wrap) { + newtw->text.left_margin = newtw->text.margin.left = + newtw->text.r_margin.left; + if (oldtw->text.lt.top == newtw->text.lt.top) + newtw->text.lt.top = SrcScan(newtw->text.source, 0, XawstEOL, + XawsdLeft, 1, False); + } + newtw->text.showposition = True; +#ifndef OLDXAW + show_lc = True; + newtw->text.source_changed = SRC_CHANGE_OVERLAP; +#endif + _XawTextBuildLineTable(newtw, newtw->text.lt.top, True); + redisplay = True; + } + +#ifndef OLDXAW + if (newtw->text.left_column < 0) + newtw->text.left_column = 0; + if (newtw->text.right_column < 0) + newtw->text.right_column = 0; +#endif + + _XawTextExecuteUpdate(newtw); + +#ifndef OLDXAW + if (show_lc) + _XawTextSetLineAndColumnNumber(newtw, True); +#endif + + if (redisplay) + _XawTextSetScrollBars(newtw); + + return (redisplay); +} + +/* invoked by the Simple widget's SetValues */ +static Bool +XawTextChangeSensitive(Widget w) +{ + Arg args[1]; + TextWidget tw = (TextWidget)w; + + (*(&simpleClassRec)->simple_class.change_sensitive)(w); + + XtSetArg(args[0], XtNancestorSensitive, + (tw->core.ancestor_sensitive && tw->core.sensitive)); + if (tw->text.vbar) + XtSetValues(tw->text.vbar, args, ONE); + if (tw->text.hbar) + XtSetValues(tw->text.hbar, args, ONE); + return (False); +} + +/* + * Function: + * XawTextGetValuesHook + * + * Parameters: + * w - Text Widget + * args - argument list + * num_args - number of args + * + * Description: + * This is a get values hook routine that gets the + * values in the text source and sink. + */ +static void +XawTextGetValuesHook(Widget w, ArgList args, Cardinal *num_args) +{ + XtGetValues(((TextWidget)w)->text.source, args, *num_args); + XtGetValues(((TextWidget)w)->text.sink, args, *num_args); +} + +/* + * Function: + * FindGoodPosition + * + * Parameters: + * pos - any position + * + * Description: + * Returns a valid position given any postition. + * + * Returns: + * A position between (0 and lastPos) + */ +static XawTextPosition +FindGoodPosition(TextWidget ctx, XawTextPosition pos) +{ + if (pos < 0) + return (0); + return (((pos > ctx->text.lastPos) ? ctx->text.lastPos : pos)); +} + +/* Li wrote this so the IM can find a given text position's screen position */ +void +_XawTextPosToXY(Widget w, XawTextPosition pos, Position *x, Position *y) +{ + int line, ix, iy; + + LineAndXYForPosition((TextWidget)w, pos, &line, &ix, &iy); + *x = ix; + *y = iy; +} + +/******************************************************************* +The following routines provide procedural interfaces to Text window state +setting and getting. They need to be redone so than the args code can use +them. I suggest we create a complete set that takes the context as an +argument and then have the public version lookup the context and call the +internal one. The major value of this set is that they have actual application +clients and therefore the functionality provided is required for any future +version of Text. +********************************************************************/ +void +XawTextDisplay(Widget w) +{ + TextWidget ctx = (TextWidget)w; + + if (!XtIsRealized(w)) + return; + + _XawTextPrepareToUpdate(ctx); + ctx->text.clear_to_eol = True; + DisplayTextWindow(w); + _XawTextExecuteUpdate(ctx); +} + +void +XawTextSetSelectionArray(Widget w, XawTextSelectType *sarray) +{ + ((TextWidget)w)->text.sarray = sarray; +} + +void +XawTextGetSelectionPos(Widget w, XawTextPosition *left, XawTextPosition *right) +{ + *left = ((TextWidget)w)->text.s.left; + *right = ((TextWidget)w)->text.s.right; +} + +void +_XawTextSetSource(Widget w, Widget source, + XawTextPosition top, XawTextPosition startPos) +{ + TextWidget ctx = (TextWidget)w; +#ifndef OLDXAW + Bool resolve = False; +#endif + +#ifndef OLDXAW + if (source != ctx->text.source) + _XawSourceRemoveText(ctx->text.source, w, ctx->text.source && + XtParent(ctx->text.source) == w); + _XawSourceAddText(source, w); + + if (source != ctx->text.source || ctx->text.insertPos != startPos) + resolve = True; + + ctx->text.source_changed = SRC_CHANGE_OVERLAP; +#endif + ctx->text.source = source; + ctx->text.s.left = ctx->text.s.right = 0; + ctx->text.lastPos = GETLASTPOS; + top = FindGoodPosition(ctx, top); + startPos = FindGoodPosition(ctx, startPos); + ctx->text.insertPos = ctx->text.old_insert = startPos; + _XawTextPrepareToUpdate(ctx); + + _XawTextBuildLineTable(ctx, top, True); + + _XawTextExecuteUpdate(ctx); +#ifndef OLDXAW + if (resolve) + _XawTextSetLineAndColumnNumber(ctx, True); +#endif +} + +void +XawTextSetSource(Widget w, Widget source, XawTextPosition top) +{ + _XawTextSetSource(w, source, top, top); +} + +/* + * This public routine deletes the text from startPos to endPos in a source and + * then inserts, at startPos, the text that was passed. As a side effect it + * "invalidates" that portion of the displayed text (if any), so that things + * will be repainted properly. + */ +int +XawTextReplace(Widget w, XawTextPosition startPos, XawTextPosition endPos, + XawTextBlock *text) +{ + TextWidget ctx = (TextWidget)w; + int result; +#ifndef OLDXAW + Cardinal i; + TextSrcObject src = (TextSrcObject)ctx->text.source; + + for (i = 0; i < src->textSrc.num_text; i++) + _XawTextPrepareToUpdate((TextWidget)src->textSrc.text[i]); +#else + _XawTextPrepareToUpdate(ctx); +#endif + + endPos = FindGoodPosition(ctx, endPos); + startPos = FindGoodPosition(ctx, startPos); + result = _XawTextReplace(ctx, startPos, endPos, text); + +#ifndef OLDXAW + for (i = 0; i < src->textSrc.num_text; i++) + _XawTextExecuteUpdate((TextWidget)src->textSrc.text[i]); +#else + _XawTextExecuteUpdate(ctx); +#endif + + return (result); +} + +XawTextPosition +XawTextTopPosition(Widget w) +{ + return (((TextWidget)w)->text.lt.top); +} + +XawTextPosition +XawTextLastPosition(Widget w) +{ + return (((TextWidget)w)->text.lastPos); +} + +void +XawTextSetInsertionPoint(Widget w, XawTextPosition position) +{ + TextWidget ctx = (TextWidget)w; + + _XawTextPrepareToUpdate(ctx); + ctx->text.insertPos = FindGoodPosition(ctx, position); + ctx->text.showposition = True; + ctx->text.from_left = -1; + + _XawTextExecuteUpdate(ctx); +#ifndef OLDXAW + _XawTextSetLineAndColumnNumber(ctx, False); +#endif +} + +XawTextPosition +XawTextGetInsertionPoint(Widget w) +{ + return (((TextWidget)w)->text.insertPos); +} + +/* + * Note: Must walk the selection list in opposite order from TextLoseSelection + */ +void +XawTextUnsetSelection(Widget w) +{ + TextWidget ctx = (TextWidget)w; + + while (ctx->text.s.atom_count != 0) { + Atom sel = ctx->text.s.selections[ctx->text.s.atom_count - 1]; + + if (sel != (Atom) 0) { + /* + * As selections are lost the atom_count will decrement + */ + if (GetCutBufferNumber(sel) == NOT_A_CUT_BUFFER) + XtDisownSelection(w, sel, ctx->text.time); + TextLoseSelection(w, &sel); /* In case this is a cut buffer, or + XtDisownSelection failed to call us */ + } + } +} + +void +XawTextSetSelection(Widget w, XawTextPosition left, XawTextPosition right) +{ + TextWidget ctx = (TextWidget)w; + + _XawTextPrepareToUpdate(ctx); + _XawTextSetSelection(ctx, FindGoodPosition(ctx, left), + FindGoodPosition(ctx, right), NULL, 0); + _XawTextExecuteUpdate(ctx); +} + +void +XawTextInvalidate(Widget w, XawTextPosition from, XawTextPosition to) +{ + TextWidget ctx = (TextWidget)w; + + from = FindGoodPosition(ctx, from); + to = FindGoodPosition(ctx, to); + ctx->text.lastPos = GETLASTPOS; + _XawTextPrepareToUpdate(ctx); + _XawTextNeedsUpdating(ctx, from, to); + _XawTextExecuteUpdate(ctx); +} + +/*ARGSUSED*/ +void +XawTextDisableRedisplay(Widget w) +{ + ((TextWidget)w)->text.update_disabled = True; + _XawTextPrepareToUpdate((TextWidget)w); +} + +void +XawTextEnableRedisplay(Widget w) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition lastPos; + + if (!ctx->text.update_disabled) + return; + + ctx->text.update_disabled = False; + lastPos = ctx->text.lastPos = GETLASTPOS; + ctx->text.lt.top = FindGoodPosition(ctx, ctx->text.lt.top); + ctx->text.insertPos = FindGoodPosition(ctx, ctx->text.insertPos); + + if (ctx->text.s.left > lastPos || ctx->text.s.right > lastPos) + ctx->text.s.left = ctx->text.s.right = 0; + + _XawTextExecuteUpdate(ctx); +} + +Widget +XawTextGetSource(Widget w) +{ + return (((TextWidget)w)->text.source); +} + +Widget +XawTextGetSink(Widget w) +{ + return (((TextWidget)w)->text.sink); +} + +void +XawTextDisplayCaret(Widget w, +#if NeedWidePrototypes + int display_caret +#else + Boolean display_caret +#endif +) +{ + TextWidget ctx = (TextWidget)w; + + if (XtIsRealized(w)) { + _XawTextPrepareToUpdate(ctx); + ctx->text.display_caret = display_caret; + _XawTextExecuteUpdate(ctx); + } + else + ctx->text.display_caret = display_caret; +} + +/* + * Function: + * XawTextSearch + * + * Parameters: + * w - text widget + * dir - direction to search + * text - text block containing info about the string to search for + * + * Description: + * Searches for the given text block. + * + * Returns: + * The position of the text found, or XawTextSearchError on an error + */ +XawTextPosition +XawTextSearch(Widget w, +#if NeedWidePrototypes + int dir, +#else + XawTextScanDirection dir, +#endif + XawTextBlock *text) +{ + TextWidget ctx = (TextWidget)w; + + return (SrcSearch(ctx->text.source, ctx->text.insertPos, dir, text)); +} + +TextClassRec textClassRec = { + /* core */ + { + (WidgetClass)&simpleClassRec, /* superclass */ + "Text", /* class_name */ + sizeof(TextRec), /* widget_size */ + XawTextClassInitialize, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + XawTextInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawTextRealize, /* realize */ + _XawTextActionsTable, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resource */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + XtExposeGraphicsExpose | /* compress_exposure */ + XtExposeNoExpose, + True, /* compress_enterleave */ + False, /* visible_interest */ + XawTextDestroy, /* destroy */ + XawTextResize, /* resize */ + XawTextExpose, /* expose */ + XawTextSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + XawTextGetValuesHook, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + _XawDefaultTextTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XawTextChangeSensitive, /* change_sensitive */ + }, + /* text */ + { + NULL, /* extension */ + } +}; + +WidgetClass textWidgetClass = (WidgetClass)&textClassRec; diff --git a/libXaw/src/TextAction.c b/libXaw/src/TextAction.c index 2e55f662e..1e3d07bac 100644 --- a/libXaw/src/TextAction.c +++ b/libXaw/src/TextAction.c @@ -1,4402 +1,4402 @@ -/*
-
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <X11/Xos.h> /* for select() and struct timeval */
-#include <ctype.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xatom.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xutil.h>
-#include <X11/Xwinsock.h>
-#include <X11/Xmu/Atoms.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xmu/StdSel.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/MultiSinkP.h>
-#include <X11/Xaw/MultiSrcP.h>
-#include <X11/Xaw/TextP.h>
-#include <X11/Xaw/TextSrcP.h>
-#include <X11/Xaw/XawImP.h>
-#include "Private.h"
-#include "XawI18n.h"
-
-#define SrcScan XawTextSourceScan
-#define FindDist XawTextSinkFindDistance
-#define FindPos XawTextSinkFindPosition
-#define MULT(w) (w->text.mult == 0 ? 4 : \
- w->text.mult == 32767 ? -4 : w->text.mult)
-
-#define KILL_RING_APPEND 2
-#define KILL_RING_BEGIN 3
-#define KILL_RING_YANK 100
-#define KILL_RING_YANK_DONE 98
-
-#define XawTextActionMaxHexChars 100
-
-#ifdef _MSC_VER
-#define usleep(time) Sleep(time)
-#endif
-/*
- * Prototypes
- */
-static void _DeleteOrKill(TextWidget, XawTextPosition, XawTextPosition, Bool);
-static void _SelectionReceived(Widget, XtPointer, Atom*, Atom*, XtPointer,
- unsigned long*, int*);
-static void _LoseSelection(Widget, Atom*, char**, int*);
-static void AutoFill(TextWidget);
-static Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*,
- unsigned long*, int*);
-static void DeleteOrKill(TextWidget, XEvent*, XawTextScanDirection,
- XawTextScanType, Bool, Bool);
-static void EndAction(TextWidget);
-#ifndef OLDXAW
-static Bool BlankLine(Widget, XawTextPosition, int*);
-static int DoFormatText(TextWidget, XawTextPosition, Bool, int,
- XawTextBlock*, XawTextPosition*, int, Bool);
-static int FormatText(TextWidget, XawTextPosition, Bool,
- XawTextPosition*, int);
-static Bool GetBlockBoundaries(TextWidget, XawTextPosition*, XawTextPosition*);
-#endif
-static int FormRegion(TextWidget, XawTextPosition, XawTextPosition,
- XawTextPosition*, int);
-static void GetSelection(Widget, Time, String*, Cardinal);
-static char *IfHexConvertHexElseReturnParam(char*, int*);
-static void InsertNewCRs(TextWidget, XawTextPosition, XawTextPosition,
- XawTextPosition*, int);
-static int InsertNewLineAndBackupInternal(TextWidget);
-static int LocalInsertNewLine(TextWidget, XEvent*);
-static void LoseSelection(Widget, Atom*);
-static void ParameterError(Widget, String);
-static Bool MatchSelection(Atom, XawTextSelection*);
-static void ModifySelection(TextWidget, XEvent*, XawTextSelectionMode,
- XawTextSelectionAction, String*, Cardinal*);
-static void Move(TextWidget, XEvent*, XawTextScanDirection, XawTextScanType,
- Bool);
-static void NotePosition(TextWidget, XEvent*);
-static void StartAction(TextWidget, XEvent*);
-static XawTextPosition StripOutOldCRs(TextWidget, XawTextPosition,
- XawTextPosition, XawTextPosition*, int);
-#ifndef OLDXAW
-static Bool StripSpaces(TextWidget, XawTextPosition, XawTextPosition,
- XawTextPosition*, int, XawTextBlock*);
-static Bool Tabify(TextWidget, XawTextPosition, XawTextPosition,
- XawTextPosition*, int, XawTextBlock*);
-static Bool Untabify(TextWidget, XawTextPosition, XawTextPosition,
- XawTextPosition*, int, XawTextBlock*);
-#endif
-
-/*
- * Actions
- */
-static void CapitalizeWord(Widget, XEvent*, String*, Cardinal*);
-static void DisplayCaret(Widget, XEvent*, String*, Cardinal*);
-static void Delete(Widget, XEvent*, String*, Cardinal*);
-static void DeleteBackwardChar(Widget, XEvent*, String*, Cardinal*);
-static void DeleteBackwardWord(Widget, XEvent*, String*, Cardinal*);
-static void DeleteCurrentSelection(Widget, XEvent*, String*, Cardinal*);
-static void DeleteForwardChar(Widget, XEvent*, String*, Cardinal*);
-static void DeleteForwardWord(Widget, XEvent*, String*, Cardinal*);
-static void DowncaseWord(Widget, XEvent*, String*, Cardinal*);
-static void ExtendAdjust(Widget, XEvent*, String*, Cardinal*);
-static void ExtendEnd(Widget, XEvent*, String*, Cardinal*);
-static void ExtendStart(Widget, XEvent*, String*, Cardinal*);
-static void FormParagraph(Widget, XEvent*, String*, Cardinal*);
-#ifndef OLDXAW
-static void Indent(Widget, XEvent*, String*, Cardinal*);
-#endif
-static void InsertChar(Widget, XEvent*, String*, Cardinal*);
-static void InsertNewLine(Widget, XEvent*, String*, Cardinal*);
-static void InsertNewLineAndBackup(Widget, XEvent*, String*, Cardinal*);
-static void InsertNewLineAndIndent(Widget, XEvent*, String*, Cardinal*);
-static void InsertSelection(Widget, XEvent*, String*, Cardinal*);
-static void InsertString(Widget, XEvent*, String*, Cardinal*);
-#ifndef OLDXAW
-static void KeyboardReset(Widget, XEvent*, String*, Cardinal*);
-#endif
-static void KillBackwardWord(Widget, XEvent*, String*, Cardinal*);
-static void KillCurrentSelection(Widget, XEvent*, String*, Cardinal*);
-static void KillForwardWord(Widget, XEvent*, String*, Cardinal*);
-#ifndef OLDXAW
-static void KillRingYank(Widget, XEvent*, String*, Cardinal*);
-#endif
-static void KillToEndOfLine(Widget, XEvent*, String*, Cardinal*);
-static void KillToEndOfParagraph(Widget, XEvent*, String*, Cardinal*);
-static void MoveBackwardChar(Widget, XEvent*, String*, Cardinal*);
-static void MoveBackwardWord(Widget, XEvent*, String*, Cardinal*);
-static void MoveBackwardParagraph(Widget, XEvent*, String*, Cardinal*);
-static void MoveBeginningOfFile(Widget, XEvent*, String*, Cardinal*);
-static void MoveEndOfFile(Widget, XEvent*, String*, Cardinal*);
-static void MoveForwardChar(Widget, XEvent*, String*, Cardinal*);
-static void MoveForwardWord(Widget, XEvent*, String*, Cardinal*);
-static void MoveForwardParagraph(Widget, XEvent*, String*, Cardinal*);
-static void MoveNextLine(Widget, XEvent*, String*, Cardinal*);
-static void MoveNextPage(Widget, XEvent*, String*, Cardinal*);
-static void MovePage(TextWidget, XEvent*, XawTextScanDirection);
-static void MovePreviousLine(Widget, XEvent*, String*, Cardinal*);
-static void MovePreviousPage(Widget, XEvent*, String*, Cardinal*);
-static void MoveLine(TextWidget, XEvent*, XawTextScanDirection);
-static void MoveToLineEnd(Widget, XEvent*, String*, Cardinal*);
-static void MoveToLineStart(Widget, XEvent*, String*, Cardinal*);
-static void Multiply(Widget, XEvent*, String*, Cardinal*);
-static void NoOp(Widget, XEvent*, String*, Cardinal*);
-#ifndef OLDXAW
-static void Numeric(Widget, XEvent*, String*, Cardinal*);
-#endif
-static void Reconnect(Widget, XEvent*, String*, Cardinal*);
-static void RedrawDisplay(Widget, XEvent*, String*, Cardinal*);
-static void Scroll(TextWidget, XEvent*, XawTextScanDirection);
-static void ScrollOneLineDown(Widget, XEvent*, String*, Cardinal*);
-static void ScrollOneLineUp(Widget, XEvent*, String*, Cardinal*);
-static void SelectAdjust(Widget, XEvent*, String*, Cardinal*);
-static void SelectAll(Widget, XEvent*, String*, Cardinal*);
-static void SelectEnd(Widget, XEvent*, String*, Cardinal*);
-static void SelectSave(Widget, XEvent*, String*, Cardinal*);
-static void SelectStart(Widget, XEvent*, String*, Cardinal*);
-static void SelectWord(Widget, XEvent*, String*, Cardinal*);
-static void SetKeyboardFocus(Widget, XEvent*, String*, Cardinal*);
-static void TextEnterWindow(Widget, XEvent*, String*, Cardinal*);
-static void TextFocusIn(Widget, XEvent*, String*, Cardinal*);
-static void TextFocusOut(Widget, XEvent*, String*, Cardinal*);
-static void TextLeaveWindow(Widget, XEvent*, String*, Cardinal*);
-static void TransposeCharacters(Widget, XEvent*, String*, Cardinal*);
-#ifndef OLDXAW
-static void ToggleOverwrite(Widget, XEvent*, String*, Cardinal*);
-static void Undo(Widget, XEvent*, String*, Cardinal*);
-#endif
-static void UpcaseWord(Widget, XEvent*, String*, Cardinal*);
-static void DestroyFocusCallback(Widget, XtPointer, XtPointer);
-
-/*
- * External
- */
-void _XawTextZapSelection(TextWidget, XEvent*, Bool);
-
-/*
- * Defined in TextPop.c
- */
-void _XawTextInsertFileAction(Widget, XEvent*, String*, Cardinal*);
-void _XawTextInsertFile(Widget, XEvent*, String*, Cardinal*);
-void _XawTextSearch(Widget, XEvent*, String*, Cardinal*);
-void _XawTextDoSearchAction(Widget, XEvent*, String*, Cardinal*);
-void _XawTextDoReplaceAction(Widget, XEvent*, String*, Cardinal*);
-void _XawTextSetField(Widget, XEvent*, String*, Cardinal*);
-void _XawTextPopdownSearchAction(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * These are defined in Text.c
- */
-void _XawTextAlterSelection(TextWidget, XawTextSelectionMode,
- XawTextSelectionAction, String*, Cardinal*);
-void _XawTextClearAndCenterDisplay(TextWidget);
-void _XawTextExecuteUpdate(TextWidget);
-char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition);
-void _XawTextPrepareToUpdate(TextWidget);
-int _XawTextReplace(TextWidget, XawTextPosition, XawTextPosition,
- XawTextBlock*);
-Atom *_XawTextSelectionList(TextWidget, String*, Cardinal);
-void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition,
- String*, Cardinal);
-void _XawTextVScroll(TextWidget, int);
-void XawTextScroll(TextWidget, int, int);
-void _XawTextSetLineAndColumnNumber(TextWidget, Bool);
-
-#ifndef OLDXAW
-/*
- * Defined in TextSrc.c
- */
-Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*);
-Bool _XawTextSrcToggleUndo(TextSrcObject);
-void _XawSourceSetUndoErase(TextSrcObject, int);
-void _XawSourceSetUndoMerge(TextSrcObject, Bool);
-#endif /* OLDXAW */
-
-/*
- * Initialization
- */
-#ifndef OLDXAW
-#define MAX_KILL_RINGS 1024
-XawTextKillRing *xaw_text_kill_ring;
-static XawTextKillRing kill_ring_prev, kill_ring_null = { &kill_ring_prev, };
-static unsigned num_kill_rings;
-#endif
-
-/*
- * Implementation
- */
-static void
-ParameterError(Widget w, String param)
-{
- String params[2];
- Cardinal num_params = 2;
- params[0] = XtName(w);
- params[1] = param;
-
- XtAppWarningMsg(XtWidgetToApplicationContext(w),
- "parameterError", "textAction", "XawError",
- "Widget: %s Parameter: %s",
- params, &num_params);
- XBell(XtDisplay(w), 50);
-}
-
-static void
-StartAction(TextWidget ctx, XEvent *event)
-{
-#ifndef OLDXAW
- Cardinal i;
- TextSrcObject src = (TextSrcObject)ctx->text.source;
-
- for (i = 0; i < src->textSrc.num_text; i++)
- _XawTextPrepareToUpdate((TextWidget)src->textSrc.text[i]);
- _XawSourceSetUndoMerge(src, False);
-#else
- _XawTextPrepareToUpdate(ctx);
-#endif
-
- if (event != NULL) {
- switch (event->type) {
- case ButtonPress:
- case ButtonRelease:
- ctx->text.time = event->xbutton.time;
- break;
- case KeyPress:
- case KeyRelease:
- ctx->text.time = event->xkey.time;
- break;
- case MotionNotify:
- ctx->text.time = event->xmotion.time;
- break;
- case EnterNotify:
- case LeaveNotify:
- ctx->text.time = event->xcrossing.time;
- }
- }
-}
-
-static void
-NotePosition(TextWidget ctx, XEvent *event)
-{
- switch (event->type) {
- case ButtonPress:
- case ButtonRelease:
- ctx->text.ev_x = event->xbutton.x;
- ctx->text.ev_y = event->xbutton.y;
- break;
- case KeyPress:
- case KeyRelease: {
- XRectangle cursor;
- XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
- ctx->text.ev_x = cursor.x + cursor.width / 2;
- ctx->text.ev_y = cursor.y + cursor.height / 2;
- } break;
- case MotionNotify:
- ctx->text.ev_x = event->xmotion.x;
- ctx->text.ev_y = event->xmotion.y;
- break;
- case EnterNotify:
- case LeaveNotify:
- ctx->text.ev_x = event->xcrossing.x;
- ctx->text.ev_y = event->xcrossing.y;
- }
-}
-
-static void
-EndAction(TextWidget ctx)
-{
-#ifndef OLDXAW
- Cardinal i;
- TextSrcObject src = (TextSrcObject)ctx->text.source;
-
- for (i = 0; i < src->textSrc.num_text; i++)
- _XawTextExecuteUpdate((TextWidget)src->textSrc.text[i]);
-
- ctx->text.mult = 1;
- ctx->text.numeric = False;
- if (ctx->text.kill_ring) {
- if (--ctx->text.kill_ring == KILL_RING_YANK_DONE) {
- if (ctx->text.kill_ring_ptr) {
- --ctx->text.kill_ring_ptr->refcount;
- ctx->text.kill_ring_ptr = NULL;
- }
- }
- }
-#else
- ctx->text.mult = 1;
- _XawTextExecuteUpdate(ctx);
-#endif /* OLDXAW */
-}
-
-struct _SelectionList {
- String* params;
- Cardinal count;
- Time time;
- int asked; /* which selection currently has been asked for:
- 0 = UTF8_STRING, 1 = COMPOUND_TEXT, 2 = STRING */
- Atom selection; /* selection atom (normally XA_PRIMARY) */
-};
-
-/*ARGSUSED*/
-static void
-_SelectionReceived(Widget w, XtPointer client_data, Atom *selection,
- Atom *type, XtPointer value, unsigned long *length,
- int *format)
-{
- Display *d = XtDisplay(w);
- TextWidget ctx = (TextWidget)w;
- XawTextBlock text;
-
- if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) {
- struct _SelectionList* list = (struct _SelectionList*)client_data;
-
- if (list != NULL) {
- if (list->asked == 0) {
- /* If we just asked for XA_UTF8_STRING and got no response,
- we'll ask again, this time for XA_COMPOUND_TEXT. */
- list->asked++;
- XtGetSelectionValue(w, list->selection, XA_COMPOUND_TEXT(d),
- _SelectionReceived,
- (XtPointer)list, list->time);
- } else if (list->asked == 1) {
- /* If we just asked for XA_COMPOUND_TEXT and got no response,
- we'll ask again, this time for XA_STRING. */
- list->asked++;
- XtGetSelectionValue(w, list->selection, XA_STRING,
- _SelectionReceived,
- (XtPointer)list, list->time);
- } else {
- /* We tried all possible text targets in this param.
- Recurse on the tail of the params list. */
- GetSelection(w, list->time, list->params, list->count);
- XtFree(client_data);
- }
- }
- return;
- }
-
- StartAction(ctx, NULL);
- if (XawTextFormat(ctx, XawFmtWide)) {
- XTextProperty textprop;
- wchar_t **wlist;
- int count;
-
- textprop.encoding = *type;
- textprop.value = (unsigned char *)value;
- textprop.nitems = strlen(value);
- textprop.format = 8;
-
- if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count)
- != Success
- || count < 1) {
- XwcFreeStringList(wlist);
-
- /* Notify the user on strerr and in the insertion :) */
- fprintf(stderr, "Xaw Text Widget: An attempt was made to insert "
- "an illegal selection.\n");
-
- textprop.value = (unsigned char *)" >> ILLEGAL SELECTION << ";
- textprop.nitems = strlen((char *) textprop.value);
- if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count)
- != Success
- || count < 1)
- return;
- }
-
- XFree(value);
- value = (XPointer)wlist[0];
-
- *length = wcslen(wlist[0]);
- XtFree((XtPointer)wlist);
- text.format = XawFmtWide;
- }
- text.ptr = (char*)value;
- text.firstPos = 0;
- text.length = *length;
- if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
- XBell(XtDisplay(ctx), 0);
- EndAction(ctx);
- return;
- }
-
- ctx->text.from_left = -1;
- ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert,
- XawstPositions, XawsdRight, text.length, True);
-
- EndAction(ctx);
- XtFree(client_data);
- XFree(value); /* the selection value should be freed with XFree */
-}
-
-static void
-GetSelection(Widget w, Time timev, String *params, Cardinal num_params)
-{
- Display *d = XtDisplay(w);
- TextWidget ctx = (TextWidget)w;
- Atom selection;
- int buffer;
-
- selection = XInternAtom(XtDisplay(w), *params, False);
- switch (selection) {
- case XA_CUT_BUFFER0: buffer = 0; break;
- case XA_CUT_BUFFER1: buffer = 1; break;
- case XA_CUT_BUFFER2: buffer = 2; break;
- case XA_CUT_BUFFER3: buffer = 3; break;
- case XA_CUT_BUFFER4: buffer = 4; break;
- case XA_CUT_BUFFER5: buffer = 5; break;
- case XA_CUT_BUFFER6: buffer = 6; break;
- case XA_CUT_BUFFER7: buffer = 7; break;
- default: buffer = -1;
- }
- if (buffer >= 0) {
- int nbytes;
- unsigned long length;
- int fmt8 = 8;
- Atom type = XA_STRING;
- char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer);
-
- if ((length = nbytes) != 0L)
- _SelectionReceived(w, NULL, &selection, &type, line, &length, &fmt8);
- else if (num_params > 1)
- GetSelection(w, timev, params+1, num_params-1);
- }
- else {
- struct _SelectionList* list;
-
- if (--num_params) {
- list = XtNew(struct _SelectionList);
- list->params = params + 1;
- list->count = num_params;
- list->time = timev;
- list->asked = 0;
- list->selection = selection;
- }
- else
- list = NULL;
- XtGetSelectionValue(w, selection, XawTextFormat(ctx, XawFmtWide) ?
- XA_UTF8_STRING(d) : XA_TEXT(d),
- _SelectionReceived, (XtPointer)list, timev);
- }
-}
-
-static void
-InsertSelection(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- StartAction((TextWidget)w, event); /* Get Time. */
- GetSelection(w, ((TextWidget)w)->text.time, params, *num_params);
- EndAction((TextWidget)w);
-}
-
-/*
- * Routines for Moving Around
- */
-static void
-Move(TextWidget ctx, XEvent *event, XawTextScanDirection dir,
- XawTextScanType type, Bool include)
-{
- XawTextPosition insertPos;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- mult = -mult;
- dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
- }
-
- insertPos = SrcScan(ctx->text.source, ctx->text.insertPos,
- type, dir, mult, include);
-
- StartAction(ctx, event);
-
- if (ctx->text.s.left != ctx->text.s.right)
- XawTextUnsetSelection((Widget)ctx);
-
-#ifndef OLDXAW
- ctx->text.numeric = False;
-#endif
- ctx->text.mult = 1;
- ctx->text.showposition = True;
- ctx->text.from_left = -1;
- ctx->text.insertPos = insertPos;
- EndAction(ctx);
-}
-
-/*ARGSUSED*/
-static void
-MoveForwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdRight, XawstPositions, True);
-}
-
-/*ARGSUSED*/
-static void
-MoveBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdLeft, XawstPositions, True);
-}
-
-static void
-MoveForwardWord(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- if (*n && (p[0][0] == 'A' || p[0][0] == 'a'))
- Move((TextWidget)w, event, XawsdRight, XawstAlphaNumeric, False);
- else
- Move((TextWidget)w, event, XawsdRight, XawstWhiteSpace, False);
-}
-
-static void
-MoveBackwardWord(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- if (*n && (p[0][0] == 'A' || p[0][0] == 'a'))
- Move((TextWidget)w, event, XawsdLeft, XawstAlphaNumeric, False);
- else
- Move((TextWidget)w, event, XawsdLeft, XawstWhiteSpace, False);
-}
-
-static void
-MoveForwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition position = ctx->text.insertPos;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- ctx->text.mult = -mult;
- MoveBackwardParagraph(w, event, p, n);
- return;
- }
-
- while (mult--) {
- position = SrcScan(ctx->text.source, position,
- XawstEOL, XawsdRight, 1, False) - 1;
-
- while (position == SrcScan(ctx->text.source, position,
- XawstEOL, XawsdRight, 1, False))
- if (++position > ctx->text.lastPos) {
- mult = 0;
- break;
- }
-
- position = SrcScan(ctx->text.source, position,
- XawstParagraph, XawsdRight, 1, True);
- if (position != ctx->text.lastPos)
- position = SrcScan(ctx->text.source, position - 1,
- XawstEOL, XawsdLeft, 1, False);
- else
- break;
- }
-
- if (position != ctx->text.insertPos) {
- XawTextUnsetSelection(w);
- StartAction(ctx, event);
- ctx->text.showposition = True;
- ctx->text.from_left = -1;
- ctx->text.insertPos = position;
- EndAction(ctx);
- }
- else
- ctx->text.mult = 1;
-}
-
-/*ARGSUSED*/
-static void
-MoveBackwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition position = ctx->text.insertPos;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- ctx->text.mult = -mult;
- MoveForwardParagraph(w, event, p, n);
- return;
- }
-
- while (mult--) {
- position = SrcScan(ctx->text.source, position,
- XawstEOL, XawsdLeft, 1, False) + 1;
-
- while (position == SrcScan(ctx->text.source, position,
- XawstEOL, XawsdLeft, 1, False))
- if (--position < 0) {
- mult = 0;
- break;
- }
-
- position = SrcScan(ctx->text.source, position,
- XawstParagraph, XawsdLeft, 1, True);
- if (position > 0 && position < ctx->text.lastPos)
- ++position;
- else
- break;
- }
-
- if (position != ctx->text.insertPos) {
- XawTextUnsetSelection(w);
- StartAction(ctx, event);
- ctx->text.showposition = True;
- ctx->text.from_left = -1;
- ctx->text.insertPos = position;
- EndAction(ctx);
- }
- else
- ctx->text.mult = 1;
-}
-
-/*ARGSUSED*/
-static void
-MoveToLineEnd(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdRight, XawstEOL, False);
-}
-
-/*ARGSUSED*/
-static void
-MoveToLineStart(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdLeft, XawstEOL, False);
-}
-
-static void
-MoveLine(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
-{
- XawTextPosition cnew, next_line, ltemp;
- int itemp, from_left;
- short mult = MULT(ctx);
-
- StartAction(ctx, event);
-
- XawTextUnsetSelection((Widget)ctx);
-
- if (dir == XawsdLeft)
- mult = mult == 0 ? 5 : mult + 1;
-
- cnew = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstEOL, XawsdLeft, 1, False);
-
- if (ctx->text.from_left < 0)
- FindDist(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.insertPos,
- &ctx->text.from_left, <emp, &itemp);
-
- cnew = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir,
- mult, (dir == XawsdRight));
-
- next_line = SrcScan(ctx->text.source, cnew, XawstEOL, XawsdRight, 1, False);
-
- FindPos(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.from_left,
- False, &ctx->text.insertPos, &from_left, &itemp);
-
- if (from_left < ctx->text.from_left) {
- XawTextBlock block;
-
- XawTextSourceRead(ctx->text.source, ctx->text.insertPos, &block, 1);
- if (block.length) {
- if (XawTextFormat(ctx, XawFmtWide)) {
- if (*(wchar_t *)block.ptr == _Xaw_atowc(XawTAB))
- ++ctx->text.insertPos;
- }
- else if (block.ptr[0] == XawTAB)
- ++ctx->text.insertPos;
- }
- }
-
- if (ctx->text.insertPos > next_line)
- ctx->text.insertPos = next_line;
-
- EndAction(ctx);
-}
-
-static void
-MoveNextLine(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- ctx->text.mult = -mult;
- MovePreviousLine(w, event, p, n);
- return;
- }
-
- if (ctx->text.insertPos < ctx->text.lastPos)
- MoveLine(ctx, event, XawsdRight);
- else
- ctx->text.mult = 1;
-}
-
-static void
-MovePreviousLine(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- ctx->text.mult = -mult;
- MoveNextLine(w, event, p, n);
- return;
- }
-
- if (ctx->text.lt.top != 0 || (ctx->text.lt.lines > 1 &&
- ctx->text.insertPos >= ctx->text.lt.info[1].position))
- MoveLine(ctx, event, XawsdLeft);
- else
- ctx->text.mult = 1;
-}
-
-/*ARGSUSED*/
-static void
-MoveBeginningOfFile(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdLeft, XawstAll, True);
-}
-
-/*ARGSUSED*/
-static void
-MoveEndOfFile(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdRight, XawstAll, True);
-}
-
-static void
-Scroll(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
-{
- short mult = MULT(ctx);
-
- if (mult < 0) {
- mult = -mult;
- dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
- }
-
- if (ctx->text.lt.lines > 1
- && (dir == XawsdRight
- || ctx->text.lastPos >= ctx->text.lt.info[1].position)) {
- StartAction(ctx, event);
-
- if (dir == XawsdLeft)
- _XawTextVScroll(ctx, mult);
- else
- _XawTextVScroll(ctx, -mult);
-
- EndAction(ctx);
- }
- else {
- ctx->text.mult = 1;
-#ifndef OLDXAW
- ctx->text.numeric = False;
-#endif
- }
-}
-
-/*ARGSUSED*/
-static void
-ScrollOneLineUp(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Scroll((TextWidget)w, event, XawsdLeft);
-}
-
-/*ARGSUSED*/
-static void
-ScrollOneLineDown(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Scroll((TextWidget)w, event, XawsdRight);
-}
-
-static void
-MovePage(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
-{
- int scroll_val = 0;
- XawTextPosition old_pos;
-
- ctx->text.from_left = -1;
- switch (dir) {
- case XawsdLeft:
- if (ctx->text.lt.top != 0)
- scroll_val = -Max(1, ctx->text.lt.lines - 1);
- break;
- case XawsdRight:
- if (!IsPositionVisible(ctx, Max(0, ctx->text.lastPos)))
- scroll_val = Max(1, ctx->text.lt.lines - 1);
- break;
- }
-
- if (scroll_val)
- XawTextScroll(ctx, scroll_val,
- ctx->text.left_margin - ctx->text.r_margin.left);
-
- old_pos = ctx->text.insertPos;
- switch (dir) {
- case XawsdRight:
- if (IsPositionVisible(ctx, Max(0, ctx->text.lastPos)))
- ctx->text.insertPos = Max(0, ctx->text.lastPos);
- else
- ctx->text.insertPos = ctx->text.lt.top;
- if (ctx->text.insertPos < old_pos)
- ctx->text.insertPos = SrcScan(ctx->text.source, old_pos,
- XawstEOL, XawsdLeft, 1, False);
- break;
- case XawsdLeft:
- if (IsPositionVisible(ctx, 0))
- ctx->text.insertPos = 0;
- else if (ctx->text.lt.lines)
- ctx->text.insertPos =
- ctx->text.lt.info[ctx->text.lt.lines - 1].position;
- else
- ctx->text.insertPos = ctx->text.lt.top;
- if (ctx->text.insertPos > old_pos)
- ctx->text.insertPos = SrcScan(ctx->text.source, old_pos,
- XawstEOL, XawsdLeft, 1, False);
- break;
- }
-}
-
-static void
-MoveNextPage(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- ctx->text.mult = -mult;
- MovePreviousPage(w, event, p, n);
- return;
- }
-
- if (ctx->text.insertPos < ctx->text.lastPos) {
- XawTextUnsetSelection(w);
- StartAction(ctx, event);
- ctx->text.clear_to_eol = True;
- while (mult-- && ctx->text.insertPos < ctx->text.lastPos)
- MovePage(ctx, event, XawsdRight);
- EndAction(ctx);
- }
- else
- ctx->text.mult = 1;
-}
-
-/*ARGSUSED*/
-static void
-MovePreviousPage(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- ctx->text.mult = -mult;
- MoveNextPage(w, event, p, n);
- return;
- }
-
- if (ctx->text.insertPos > 0) {
- XawTextUnsetSelection(w);
- StartAction(ctx, event);
- ctx->text.clear_to_eol = True;
- while (mult-- && ctx->text.insertPos > 0)
- MovePage(ctx, event, XawsdLeft);
- EndAction(ctx);
- }
- else
- ctx->text.mult = 1;
-}
-
-/*
- * Delete Routines
- */
-static Bool
-MatchSelection(Atom selection, XawTextSelection *s)
-{
- Atom *match;
- int count;
-
- for (count = 0, match = s->selections; count < s->atom_count;
- match++, count++)
- if (*match == selection)
- return (True);
-
- return (False);
-}
-
-#define SrcCvtSel XawTextSourceConvertSelection
-
-static Boolean
-ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type,
- XtPointer *value, unsigned long *length, int *format)
-{
- Display *d = XtDisplay(w);
- TextWidget ctx = (TextWidget)w;
- Widget src = ctx->text.source;
- XawTextEditType edit_mode;
- Arg args[1];
- XawTextSelectionSalt *salt = NULL;
- XawTextSelection *s;
-
- if (*target == XA_TARGETS(d)) {
- Atom *targetP, *std_targets;
- unsigned long std_length;
-
- if (SrcCvtSel(src, selection, target, type, value, length, format))
- return (True);
-
- XtSetArg(args[0], XtNeditType,&edit_mode);
- XtGetValues(src, args, 1);
-
- XmuConvertStandardSelection(w, ctx->text.time, selection,
- target, type, (XPointer *)&std_targets,
- &std_length, format);
-
- *length = 7 + (edit_mode == XawtextEdit) + std_length;
- *value = XtMalloc((unsigned)sizeof(Atom)*(*length));
- targetP = *(Atom**)value;
- *targetP++ = XA_STRING;
- *targetP++ = XA_TEXT(d);
- *targetP++ = XA_UTF8_STRING(d);
- *targetP++ = XA_COMPOUND_TEXT(d);
- *targetP++ = XA_LENGTH(d);
- *targetP++ = XA_LIST_LENGTH(d);
- *targetP++ = XA_CHARACTER_POSITION(d);
- if (edit_mode == XawtextEdit) {
- *targetP++ = XA_DELETE(d);
- }
- memcpy((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length);
- XtFree((char*)std_targets);
- *type = XA_ATOM;
- *format = 32;
- return (True);
- }
-
- if (SrcCvtSel(src, selection, target, type, value, length, format))
- return (True);
-
- for (salt = ctx->text.salt2; salt; salt = salt->next)
- if (MatchSelection (*selection, &salt->s))
- break;
- if (!salt)
- return (False);
- s = &salt->s;
- if (*target == XA_STRING
- || *target == XA_TEXT(d)
- || *target == XA_UTF8_STRING(d)
- || *target == XA_COMPOUND_TEXT(d)) {
- if (*target == XA_TEXT(d)) {
- if (XawTextFormat(ctx, XawFmtWide))
- *type = XA_COMPOUND_TEXT(d);
- else
- *type = XA_STRING;
- }
- else
- *type = *target;
-
- /*
- * If salt is True, the salt->contents stores CT string,
- * its length is measured in bytes.
- * Refer to _XawTextSaltAwaySelection()
- *
- * by Li Yuhong, Mar. 20, 1991.
- */
- if (!salt) {
- *value = (char *)_XawTextGetSTRING(ctx, s->left, s->right);
- if (XawTextFormat(ctx, XawFmtWide)) {
- XTextProperty textprop;
- if (XwcTextListToTextProperty(d, (wchar_t**)value, 1,
- XCompoundTextStyle, &textprop)
- < Success) {
- XtFree(*value);
- return (False);
- }
- XtFree(*value);
- *value = (XtPointer)textprop.value;
- *length = textprop.nitems;
- }
- else
- *length = strlen(*value);
- }
- else {
- *value = XtMalloc((salt->length + 1) * sizeof(unsigned char));
- strcpy (*value, salt->contents);
- *length = salt->length;
- }
- /* Got *value,*length, now in COMPOUND_TEXT format. */
- if (XawTextFormat(ctx, XawFmtWide)) {
- if (*type == XA_STRING) {
- XTextProperty textprop;
- wchar_t **wlist;
- int count;
-
- textprop.encoding = XA_COMPOUND_TEXT(d);
- textprop.value = (unsigned char *)*value;
- textprop.nitems = strlen(*value);
- textprop.format = 8;
- if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count)
- < Success
- || count < 1) {
- XtFree(*value);
- return (False);
- }
- XtFree(*value);
- if (XwcTextListToTextProperty(d, wlist, 1, XStringStyle, &textprop)
- < Success) {
- XwcFreeStringList((wchar_t**)wlist);
- return (False);
- }
- *value = (XtPointer)textprop.value;
- *length = textprop.nitems;
- XwcFreeStringList((wchar_t**) wlist);
- }
- else if (*type == XA_UTF8_STRING(d)) {
- XTextProperty textprop;
- char **list;
- int count;
-
- textprop.encoding = XA_COMPOUND_TEXT(d);
- textprop.value = (unsigned char *)*value;
- textprop.nitems = strlen(*value);
- textprop.format = 8;
- if (Xutf8TextPropertyToTextList(d, &textprop, &list, &count)
- < Success
- || count < 1) {
- XtFree(*value);
- return (False);
- }
- XtFree(*value);
- *value = *list;
- *length = strlen(*list);
- XFree(list);
- }
- }
- *format = 8;
- return (True);
- }
-
- if (*target == XA_LIST_LENGTH(d) || *target == XA_LENGTH(d)) {
- long *temp;
-
- temp = (long *)XtMalloc(sizeof(long));
- if (*target == XA_LIST_LENGTH(d))
- *temp = 1L;
- else /* *target == XA_LENGTH(d) */
- *temp = (long)(s->right - s->left);
-
- *value = (XPointer)temp;
- *type = XA_INTEGER;
- *length = 1L;
- *format = 32;
- return (True);
- }
-
- if (*target == XA_CHARACTER_POSITION(d)) {
- long *temp;
-
- temp = (long *) XtMalloc(2 * sizeof(long));
- temp[0] = (long)(s->left + 1);
- temp[1] = s->right;
- *value = (XPointer)temp;
- *type = XA_SPAN(d);
- *length = 2L;
- *format = 32;
- return (True);
- }
-
- if (*target == XA_DELETE(d)) {
- if (!salt)
- _XawTextZapSelection(ctx, NULL, True);
- *value = NULL;
- *type = XA_NULL(d);
- *length = 0;
- *format = 32;
- return (True);
- }
-
- if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type,
- (XPointer *)value, length, format))
- return (True);
-
- return (False);
-}
-
-static void
-LoseSelection(Widget w, Atom *selection)
-{
- _LoseSelection(w, selection, NULL, NULL);
-}
-
-static void
-_LoseSelection(Widget w, Atom *selection, char **contents, int *length)
-{
- TextWidget ctx = (TextWidget)w;
- Atom *atomP;
- int i;
- XawTextSelectionSalt *salt, *prevSalt, *nextSalt;
-
- prevSalt = 0;
- for (salt = ctx->text.salt2; salt; salt = nextSalt) {
- atomP = salt->s.selections;
- nextSalt = salt->next;
- for (i = 0 ; i < salt->s.atom_count; i++, atomP++)
- if (*selection == *atomP)
- *atomP = (Atom)0;
-
- while (salt->s.atom_count
- && salt->s.selections[salt->s.atom_count-1] == 0)
- salt->s.atom_count--;
-
- /*
- * Must walk the selection list in opposite order from UnsetSelection.
- */
- atomP = salt->s.selections;
- for (i = 0 ; i < salt->s.atom_count; i++, atomP++)
- if (*atomP == (Atom)0) {
- *atomP = salt->s.selections[--salt->s.atom_count];
-
- while (salt->s.atom_count
- && salt->s.selections[salt->s.atom_count-1] == 0)
- salt->s.atom_count--;
- }
- if (salt->s.atom_count == 0) {
-#ifndef OLDXAW
- if (contents == NULL) {
- XawTextKillRing *kill_ring = XtNew(XawTextKillRing);
-
- kill_ring->next = xaw_text_kill_ring;
- kill_ring->contents = salt->contents;
- kill_ring->length = salt->length;
- kill_ring->format = XawFmt8Bit;
- xaw_text_kill_ring = kill_ring;
- kill_ring_prev.next = xaw_text_kill_ring;
-
- if (++num_kill_rings > MAX_KILL_RINGS) {
- XawTextKillRing *tail = NULL;
-
- while (kill_ring->next) {
- tail = kill_ring;
- kill_ring = kill_ring->next;
- }
- if (kill_ring->refcount == 0) {
- --num_kill_rings;
- tail->next = NULL;
- XtFree(kill_ring->contents);
- XtFree((char*)kill_ring);
- }
- }
- }
- else {
- *contents = salt->contents;
- *length = salt->length;
- }
-#endif
- if (prevSalt)
- prevSalt->next = nextSalt;
- else
- ctx->text.salt2 = nextSalt;
-
- XtFree((char *)salt->s.selections);
- XtFree((char *)salt);
- }
- else
- prevSalt = salt;
- }
-}
-
-static void
-_DeleteOrKill(TextWidget ctx, XawTextPosition from, XawTextPosition to,
- Bool kill)
-{
- XawTextBlock text;
-
-#ifndef OLDXAW
- if (ctx->text.kill_ring_ptr) {
- --ctx->text.kill_ring_ptr->refcount;
- ctx->text.kill_ring_ptr = NULL;
- }
-#endif
- if (kill && from < to) {
-#ifndef OLDXAW
- Bool append = False;
- char *ring = NULL;
- XawTextPosition old_from = from;
-#endif
- char *string;
- int size = 0, length;
- XawTextSelectionSalt *salt;
- Atom selection = XInternAtom(XtDisplay(ctx), "SECONDARY", False);
-
-#ifndef OLDXAW
- if (ctx->text.kill_ring == KILL_RING_APPEND) {
- old_from = ctx->text.salt2->s.left;
- append = True;
- }
- else
- ctx->text.kill_ring = KILL_RING_BEGIN;
-
- if (append)
- _LoseSelection((Widget)ctx, &selection, &ring, &size);
- else
-#endif
- LoseSelection((Widget)ctx, &selection);
-
- salt = (XawTextSelectionSalt*)XtMalloc(sizeof(XawTextSelectionSalt));
- salt->s.selections = (Atom *)XtMalloc(sizeof(Atom));
- salt->s.left = from;
- salt->s.right = to;
-
- string = (char *)_XawTextGetSTRING(ctx, from, to);
-
- if (XawTextFormat(ctx, XawFmtWide)) {
- XTextProperty textprop;
-
- if (XwcTextListToTextProperty(XtDisplay((Widget)ctx),
- (wchar_t**)(&string),
- 1, XCompoundTextStyle,
- &textprop) < Success) {
- XtFree(string);
- XtFree((char*)salt->s.selections);
- XtFree((char*)salt);
- return;
- }
- XtFree(string);
- string = (char *)textprop.value;
- length = textprop.nitems;
- }
- else
- length = strlen(string);
-
- salt->length = length + size;
-
-#ifndef OLDXAW
- if (!append)
- salt->contents = string;
- else {
- salt->contents = XtMalloc(length + size + 1);
- if (from >= old_from) {
- strncpy(salt->contents, ring, size);
- salt->contents[size] = '\0';
- strncat(salt->contents, string, length);
- }
- else {
- strncpy(salt->contents, string, length);
- salt->contents[length] = '\0';
- strncat(salt->contents, ring, size);
- }
- salt->contents[length + size] = '\0';
- XtFree(ring);
- XtFree(string);
- }
-
- kill_ring_prev.contents = salt->contents;
- kill_ring_prev.length = salt->length;
- kill_ring_prev.format = XawFmt8Bit;
-#else
- salt->contents = string;
-#endif
-
- salt->next = ctx->text.salt2;
- ctx->text.salt2 = salt;
-
-#ifndef OLDXAW
- if (append)
- ctx->text.kill_ring = KILL_RING_BEGIN;
-#endif
-
- salt->s.selections[0] = selection;
-
- XtOwnSelection((Widget)ctx, selection, ctx->text.time,
- ConvertSelection, LoseSelection, NULL);
- salt->s.atom_count = 1;
- }
- text.length = 0;
- text.firstPos = 0;
-
- text.format = _XawTextFormat(ctx);
- text.ptr = "";
-
- if (_XawTextReplace(ctx, from, to, &text)) {
- XBell(XtDisplay(ctx), 50);
- return;
- }
- ctx->text.from_left = -1;
- ctx->text.insertPos = from;
- ctx->text.showposition = TRUE;
-}
-
-static void
-DeleteOrKill(TextWidget ctx, XEvent *event, XawTextScanDirection dir,
- XawTextScanType type, Bool include, Bool kill)
-{
- XawTextPosition from, to;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- mult = -mult;
- dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
- }
-
- StartAction(ctx, event);
-#ifndef OLDXAW
- if (mult == 1)
- _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True);
-#endif
- to = SrcScan(ctx->text.source, ctx->text.insertPos,
- type, dir, mult, include);
-
- /*
- * If no movement actually happened, then bump the count and try again.
- * This causes the character position at the very beginning and end of
- * a boundary to act correctly
- */
- if (to == ctx->text.insertPos)
- to = SrcScan(ctx->text.source, ctx->text.insertPos,
- type, dir, mult + 1, include);
-
- if (dir == XawsdLeft) {
- from = to;
- to = ctx->text.insertPos;
- }
- else
- from = ctx->text.insertPos;
-
- _DeleteOrKill(ctx, from, to, kill);
- EndAction(ctx);
-}
-
-static void
-Delete(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
-
- if (ctx->text.s.left != ctx->text.s.right)
- DeleteCurrentSelection(w, event, p, n);
- else
- DeleteBackwardChar(w, event, p, n);
-}
-
-static void
-DeleteChar(Widget w, XEvent *event, XawTextScanDirection dir)
-{
- TextWidget ctx = (TextWidget)w;
- short mul = MULT(ctx);
-
- if (mul < 0) {
- ctx->text.mult = mul = -mul;
- dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
- }
- DeleteOrKill(ctx, event, dir, XawstPositions, True, False);
-#ifndef OLDXAW
- if (mul == 1)
- _XawSourceSetUndoErase((TextSrcObject)ctx->text.source,
- dir == XawsdLeft ? -1 : 1);
-#endif
-}
-
-/*ARGSUSED*/
-static void
-DeleteForwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- DeleteChar(w, event, XawsdRight);
-}
-
-/*ARGSUSED*/
-static void
-DeleteBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- DeleteChar(w, event, XawsdLeft);
-}
-
-static void
-DeleteForwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- XawTextScanType type;
-
- if (*num_params && (*params[0] == 'A' || *params[0] == 'a'))
- type = XawstAlphaNumeric;
- else
- type = XawstWhiteSpace;
-
- DeleteOrKill((TextWidget)w, event, XawsdRight, type, False, False);
-}
-
-static void
-DeleteBackwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- XawTextScanType type;
-
- if (*num_params && (*params[0] == 'A' || *params[0] == 'a'))
- type = XawstAlphaNumeric;
- else
- type = XawstWhiteSpace;
-
- DeleteOrKill((TextWidget)w, event, XawsdLeft, type, False, False);
-}
-
-static void
-KillForwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- XawTextScanType type;
-
- if (*num_params && (*params[0] == 'A' || *params[0] == 'a'))
- type = XawstAlphaNumeric;
- else
- type = XawstWhiteSpace;
-
- DeleteOrKill((TextWidget)w, event, XawsdRight, type, False, True);
-}
-
-static void
-KillBackwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- XawTextScanType type;
-
- if (*num_params && (*params[0] == 'A' || *params[0] == 'a'))
- type = XawstAlphaNumeric;
- else
- type = XawstWhiteSpace;
-
- DeleteOrKill((TextWidget) w, event, XawsdLeft, type, False, True);
-}
-
-/*ARGSUSED*/
-static void
-KillToEndOfLine(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition end_of_line;
- XawTextScanDirection dir = XawsdRight;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- dir = XawsdLeft;
- mult = -mult;
- }
-
- StartAction(ctx, event);
- end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL,
- dir, mult, False);
- if (end_of_line == ctx->text.insertPos)
- end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL,
- dir, mult, True);
-
- if (dir == XawsdRight)
- _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, True);
- else
- _DeleteOrKill(ctx, end_of_line, ctx->text.insertPos, True);
- EndAction(ctx);
-}
-
-/*ARGSUSED*/
-static void
-KillToEndOfParagraph(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- DeleteOrKill((TextWidget)w, event, XawsdRight, XawstParagraph, False, True);
-}
-
-void
-_XawTextZapSelection(TextWidget ctx, XEvent *event, Bool kill)
-{
- StartAction(ctx, event);
- _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill);
- EndAction(ctx);
-}
-
-/*ARGSUSED*/
-static void
-KillCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- _XawTextZapSelection((TextWidget) w, event, True);
-}
-
-#ifndef OLDXAW
-/*ARGSUSED*/
-static void
-KillRingYank(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition insertPos = ctx->text.insertPos;
- Bool first_yank = False;
-
- if (ctx->text.s.left != ctx->text.s.right)
- XawTextUnsetSelection((Widget)ctx);
-
- StartAction(ctx, event);
-
- if (ctx->text.kill_ring_ptr == NULL) {
- ctx->text.kill_ring_ptr = &kill_ring_prev;
- ++ctx->text.kill_ring_ptr->refcount;
- ctx->text.s.left = ctx->text.s.right = insertPos;
- first_yank = True;
- }
- if (ctx->text.kill_ring_ptr) {
- int mul = MULT(ctx);
- XawTextBlock text;
-
- if (!first_yank) {
- if (mul < 0)
- mul = 1;
- --ctx->text.kill_ring_ptr->refcount;
- while (mul--) {
- if ((ctx->text.kill_ring_ptr = ctx->text.kill_ring_ptr->next) == NULL)
- ctx->text.kill_ring_ptr = &kill_ring_null;
- }
- ++ctx->text.kill_ring_ptr->refcount;
- }
- text.firstPos = 0;
- text.length = ctx->text.kill_ring_ptr->length;
- text.ptr = ctx->text.kill_ring_ptr->contents;
- text.format = ctx->text.kill_ring_ptr->format;
-
- if (_XawTextReplace(ctx, ctx->text.s.left, insertPos, &text) == XawEditDone) {
- ctx->text.kill_ring = KILL_RING_YANK;
- ctx->text.insertPos = ctx->text.s.left + text.length;
- }
- }
- else
- XBell(XtDisplay(w), 0);
-
- EndAction(ctx);
-}
-#endif /* OLDXAW */
-
-/*ARGSUSED*/
-static void
-DeleteCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- _XawTextZapSelection((TextWidget)w, event, False);
-}
-
-#ifndef OLDXAW
-#define CHECK_SAVE() \
- if (save && !save->ptr) \
- save->ptr = _XawTextGetText(ctx, save->firstPos, \
- save->firstPos + save->length)
-static Bool
-StripSpaces(TextWidget ctx, XawTextPosition left, XawTextPosition right,
- XawTextPosition *pos, int num_pos, XawTextBlock *save)
-{
- Bool done, space;
- int i, cpos, count = 0;
- XawTextBlock block, text;
- XawTextPosition ipos, position = left, tmp = left;
-
- text.firstPos = 0;
- text.format = XawFmt8Bit;
- text.ptr = " ";
- text.length = 1;
-
- position = XawTextSourceRead(ctx->text.source, position,
- &block, right - left);
- done = False;
- space = False;
- /* convert tabs and returns to spaces */
- while (!done) {
- if (XawTextFormat(ctx, XawFmt8Bit)) {
- for (i = 0; i < block.length; i++)
- if (block.ptr[i] == '\t' || block.ptr[i] == '\n') {
- space = True;
- break;
- }
- }
- else {
- wchar_t *wptr = (wchar_t*)block.ptr;
- for (i = 0; i < block.length; i++)
- if (wptr[i] == _Xaw_atowc('\t') || wptr[i] == _Xaw_atowc('\n')) {
- space = True;
- break;
- }
- }
- if (space) {
- CHECK_SAVE();
- if (_XawTextReplace(ctx, tmp + i, tmp + i + 1, &text))
- return (False);
- space = False;
- }
- tmp += i;
- position = XawTextSourceRead(ctx->text.source, tmp,
- &block, right - tmp);
- if (block.length == 0 || tmp == position || tmp >= right)
- done = True;
- }
-
- text.ptr = "";
- text.length = 0;
- position = tmp = left;
- position = XawTextSourceRead(ctx->text.source, position,
- &block, right - left);
- ipos = ctx->text.insertPos;
- done = False;
- while (!done) {
- if (XawTextFormat(ctx, XawFmt8Bit)) {
- for (i = 0; i < block.length; i++)
- if (block.ptr[i] == ' ')
- ++count;
- else if (count == 1)
- count = 0;
- else if (count)
- break;
- }
- else {
- wchar_t *wptr = (wchar_t*)block.ptr;
- for (i = 0; i < block.length; i++)
- if (wptr[i] == _Xaw_atowc(' '))
- ++count;
- else if (count == 1)
- count = 0;
- else if (count)
- break;
- }
- if (--count > 0) {
- CHECK_SAVE();
- if (_XawTextReplace(ctx, tmp + i - count, tmp + i, &text))
- return (False);
- right -= count;
- if (num_pos) {
- for (cpos = 0; cpos < num_pos; cpos++) {
- if (tmp + i - count < pos[cpos]) {
- if (tmp + i < pos[cpos])
- pos[cpos] -= count;
- else
- pos[cpos] = tmp + i - count;
- }
- }
- }
- else {
- if (tmp + i - count < ipos) {
- if (tmp + i < ipos)
- ipos -= count;
- else
- ipos = tmp + i - count;
- }
- }
- tmp += i - count;
- }
- else
- tmp += i + 1;
- count = 0;
- position = XawTextSourceRead(ctx->text.source, tmp,
- &block, right - tmp);
- if (block.length == 0 || tmp == position || tmp >= right)
- done = True;
- }
- if (!num_pos)
- ctx->text.insertPos = ipos;
-
- return (True);
-}
-
-static Bool
-Tabify(TextWidget ctx, XawTextPosition left, XawTextPosition right,
- XawTextPosition *pos, int num_pos, XawTextBlock *save)
-{
- Bool done, zero;
- int i, cpos, count = 0, column = 0, offset = 0;
- XawTextBlock text, block;
- XawTextPosition ipos, position = left, tmp = left;
- TextSinkObject sink = (TextSinkObject)ctx->text.sink;
- short *char_tabs = sink->text_sink.char_tabs;
- int tab_count = sink->text_sink.tab_count;
- int tab_index = 0, tab_column = 0, TAB_SIZE = DEFAULT_TAB_SIZE;
-
- text.firstPos = 0;
- text.ptr = "\t";
- text.format = XawFmt8Bit;
- text.length = 1;
-
- position = XawTextSourceRead(ctx->text.source, position,
- &block, right - left);
- ipos = ctx->text.insertPos;
- done = zero = False;
- if (tab_count)
- TAB_SIZE = *char_tabs;
- while (!done) {
- if (XawTextFormat(ctx, XawFmt8Bit)) {
- for (i = 0; i < block.length; i++) {
- ++offset;
- ++column;
- if (tab_count) {
- if (column > tab_column + char_tabs[tab_index]) {
- TAB_SIZE = tab_index < tab_count - 1 ? char_tabs[tab_index + 1] - char_tabs[tab_index] : *char_tabs;
- if (++tab_index >= tab_count) {
- tab_column += char_tabs[tab_count - 1];
- tab_index = 0;
- }
- }
- }
- if (block.ptr[i] == ' ') {
- if (++count > TAB_SIZE)
- count %= TAB_SIZE;
- if ((tab_count && column == tab_column + char_tabs[tab_index]) ||
- (!tab_count && column % TAB_SIZE == 0)) {
- if (count % (TAB_SIZE + 1) > 1)
- break;
- else
- count = 0;
- }
- }
- else {
- if (block.ptr[i] == '\n') {
- zero = True;
- break;
- }
- count = 0;
- }
- }
- }
- else {
- wchar_t *wptr = (wchar_t*)block.ptr;
- for (i = 0; i < block.length; i++) {
- ++offset;
- ++column;
- if (tab_count) {
- if (column > tab_column + char_tabs[tab_index]) {
- TAB_SIZE = tab_index < tab_count - 1 ? char_tabs[tab_index + 1] - char_tabs[tab_index] : *char_tabs;
- if (++tab_index >= tab_count) {
- tab_column += char_tabs[tab_count - 1];
- tab_index = 0;
- }
- }
- }
- if (wptr[i] == _Xaw_atowc(' ')) {
- if (++count > TAB_SIZE)
- count %= TAB_SIZE;
- if ((tab_count && column == tab_column + char_tabs[tab_index]) ||
- (!tab_count && column % TAB_SIZE == 0)) {
- if (count % (TAB_SIZE + 1) > 1)
- break;
- else
- count = 0;
- }
- }
- else {
- if (wptr[i] == _Xaw_atowc('\n')) {
- zero = True;
- break;
- }
- count = 0;
- }
- }
- }
- count %= TAB_SIZE + 1;
- if (!zero && count > 1 && i < block.length) {
- CHECK_SAVE();
- if (_XawTextReplace(ctx, tmp + i - count + 1, tmp + i + 1, &text))
- return (False);
- right -= count - 1;
- offset -= count - 1;
- if (num_pos) {
- for (cpos = 0; cpos < num_pos; cpos++) {
- if (tmp + i - count + 1 < pos[cpos]) {
- if (tmp + i + 1 < pos[cpos])
- pos[cpos] -= count;
- else
- pos[cpos] = tmp + i - count + 1;
- ++pos[cpos];
- }
- }
- }
- else {
- if (tmp + i - count + 1 < ipos) {
- if (tmp + i + 1 < ipos)
- ipos -= count;
- else
- ipos = tmp + i - count + 1;
- ++ipos;
- }
- }
- }
- if (count)
- --count;
- if (zero) {
- count = column = 0;
- zero = False;
- if (tab_count) {
- tab_column = tab_index = 0;
- TAB_SIZE = *char_tabs;
- }
- }
- else if (i < block.length)
- count = 0;
- tmp = left + offset;
- position = XawTextSourceRead(ctx->text.source, tmp,
- &block, right - tmp);
- if (tmp == position || tmp >= right)
- done = True;
- }
- if (!num_pos)
- ctx->text.insertPos = ipos;
-
- return (True);
-}
-
-static Bool
-Untabify(TextWidget ctx, XawTextPosition left, XawTextPosition right,
- XawTextPosition *pos, int num_pos, XawTextBlock *save)
-{
- Bool done, zero;
- int i, cpos, count = 0, diff = 0;
- XawTextBlock block, text;
- XawTextPosition ipos, position = left, tmp = left;
- TextSinkObject sink = (TextSinkObject)ctx->text.sink;
- short *char_tabs = sink->text_sink.char_tabs;
- int tab_count = sink->text_sink.tab_count;
- int tab_index = 0, tab_column = 0, tab_base = 0;
- static char *tabs = " ";
-
- text.firstPos = 0;
- text.format = XawFmt8Bit;
- text.ptr = tabs;
-
- position = XawTextSourceRead(ctx->text.source, position,
- &block, right - left);
- ipos = ctx->text.insertPos;
- done = False;
- zero = False;
- while (!done) {
- if (XawTextFormat(ctx, XawFmt8Bit))
- for (i = 0; i < block.length; i++) {
- if (block.ptr[i] != '\t') {
- ++count;
- if (block.ptr[i] == '\n') {
- zero = True;
- break;
- }
- }
- else
- break;
- }
- else {
- wchar_t *wptr = (wchar_t*)block.ptr;
- for (i = 0; i < block.length; i++)
- if (wptr[i] != _Xaw_atowc('\t')) {
- ++count;
- if (wptr[i] != _Xaw_atowc('\n')) {
- zero = True;
- break;
- }
- }
- else
- break;
- }
- if (!zero && i < block.length) {
- if (tab_count) {
- while (tab_base + tab_column <= count) {
- for (; tab_index < tab_count; ++tab_index)
- if (tab_base + char_tabs[tab_index] > count) {
- tab_column = char_tabs[tab_index];
- break;
- }
- if (tab_index >= tab_count) {
- tab_base += char_tabs[tab_count - 1];
- tab_column = tab_index = 0;
- }
- }
- text.length = (tab_base + tab_column) - count;
- if (text.length > 8) {
- int j;
-
- text.ptr = XtMalloc(text.length);
- for (j = 0; j < text.length; j++)
- text.ptr[j] = ' ';
- }
- else
- text.ptr = tabs;
- }
- else
- text.length = DEFAULT_TAB_SIZE - (count % DEFAULT_TAB_SIZE);
- CHECK_SAVE();
- if (_XawTextReplace(ctx, tmp + i, tmp + i + 1, &text)) {
- if (tab_count && text.length > 8)
- XtFree(text.ptr);
- return (False);
- }
- if (tab_count && text.length > 8)
- XtFree(text.ptr);
- count += text.length;
- right += text.length - 1;
- if (num_pos) {
- for (cpos = 0; cpos < num_pos; cpos++) {
- if (tmp + i < pos[cpos]) {
- if (tmp + i + 1 < pos[cpos])
- --pos[cpos];
- else
- pos[cpos] = tmp + i;
- pos[cpos] += text.length;
- }
- }
- }
- else {
- if (tmp + i < ipos) {
- if (tmp + i + 1 < ipos)
- --ipos;
- else
- ipos = tmp + i;
- ipos += text.length;
- }
- }
- }
- tmp = left + count + diff;
- if (zero) {
- diff += count;
- count = 0;
- zero = False;
- if (tab_count)
- tab_base = tab_column = tab_index = 0;
- }
- position = XawTextSourceRead(ctx->text.source, tmp,
- &block, right - tmp);
- if (tmp == position || tmp >= right)
- done = True;
- }
- if (!num_pos)
- ctx->text.insertPos = ipos;
-
- return (True);
-}
-
-static int
-FormatText(TextWidget ctx, XawTextPosition left, Bool force,
- XawTextPosition *pos, int num_pos)
-{
- char *ptr = NULL;
- Bool freepos = False, undo, paragraph = pos != NULL;
- int i, result;
- XawTextBlock block, *text;
- XawTextPosition end = ctx->text.lastPos, buf[32];
- TextSrcObject src = (TextSrcObject)ctx->text.source;
- XawTextPosition right = SrcScan(ctx->text.source, left, XawstEOL,
- XawsdRight, 1, False);
-
- undo = src->textSrc.enable_undo && src->textSrc.undo_state == False;
- if (undo) {
- if (!pos) {
- num_pos = src->textSrc.num_text;
- pos = XawStackAlloc(sizeof(XawTextPosition) * num_pos, buf);
- for (i = 0; i < num_pos; i++)
- pos[i] = ((TextWidget)src->textSrc.text[i])->text.insertPos;
- freepos = True;
- }
- else
- freepos = False;
- src->textSrc.undo_state = True;
- block.ptr = NULL;
- block.firstPos = left;
- block.length = right - left;
- text = █
- }
- else
- text = NULL;
-
- result = DoFormatText(ctx, left, force, 1, text, pos, num_pos, paragraph);
- if (undo && result == XawEditDone && block.ptr) {
- char *lbuf, *rbuf;
- unsigned llen, rlen, size;
-
- ptr = lbuf = block.ptr;
- llen = block.length;
- rlen = llen + (ctx->text.lastPos - end);
-
- block.firstPos = 0;
- block.format = _XawTextFormat(ctx);
-
- rbuf = _XawTextGetText(ctx, left, left + rlen);
-
- size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char);
- if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) {
- block.ptr = lbuf;
- block.length = llen;
- _XawTextReplace(ctx, left, left + rlen, &block);
-
- src->textSrc.undo_state = False;
- block.ptr = rbuf;
- block.length = rlen;
- _XawTextReplace(ctx, left, left + llen, &block);
- }
- else
- src->textSrc.undo_state = False;
- XtFree(rbuf);
- }
- if (undo) {
- src->textSrc.undo_state = False;
- if (freepos) {
- for (i = 0; i < num_pos; i++) {
- TextWidget tw = (TextWidget)src->textSrc.text[i];
- tw->text.insertPos = XawMin(XawMax(0, pos[i]), tw->text.lastPos);
- }
- XawStackFree(pos, buf);
- }
- if (ptr)
- XtFree(ptr);
- }
-
- return (result);
-}
-
-static int
-DoFormatText(TextWidget ctx, XawTextPosition left, Bool force, int level,
- XawTextBlock *save, XawTextPosition *pos, int num_pos,
- Bool paragraph)
-{
- XawTextPosition right = SrcScan(ctx->text.source, left, XawstEOL,
- XawsdRight, 1, False);
- XawTextPosition position, tmp, ipos;
- XawTextBlock block, text;
- char buf[128];
- wchar_t *wptr;
- int i, count, cpos;
- Bool done, force2 = force, recurse = False;
-
- position = XawTextSourceRead(ctx->text.source, left, &block, right - left);
- if (block.length == 0 || left >= right ||
- (level == 1 && ((XawTextFormat(ctx, XawFmt8Bit) &&
- block.ptr[0] != ' ' &&
- block.ptr[0] != '\t' &&
- !isalnum(*(unsigned char*)block.ptr)) ||
- (XawTextFormat(ctx, XawFmtWide) &&
- _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr &&
- _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr &&
- !iswalnum(*(wchar_t*)block.ptr)))))
- return (XawEditDone);
-
- if (level == 1 && !paragraph) {
- tmp = ctx->text.lastPos;
- if (Untabify(ctx, left, right, pos, num_pos, save) == False)
- return (XawEditError);
- right += ctx->text.lastPos - tmp;
- position = XawTextSourceRead(ctx->text.source, left, &block,
- right - left);
- }
-
- text.firstPos = 0;
- text.format = XawFmt8Bit;
-
- ipos = ctx->text.insertPos;
- count = 0;
- done = False;
- while (!done) {
- if (XawTextFormat(ctx, XawFmt8Bit)) {
- for (i = 0; i < block.length; i++)
- if (block.ptr[i] == ' ')
- ++count;
- else {
- done = True;
- break;
- }
- }
- else {
- wptr = (wchar_t*)block.ptr;
- for (i = 0; i < block.length; i++)
- if (wptr[i] == _Xaw_atowc(' '))
- ++count;
- else {
- done = True;
- break;
- }
- }
- tmp = position;
- position = XawTextSourceRead(ctx->text.source, position,
- &block, right - position);
- if (tmp == position)
- done = True;
- }
- position = left + count;
- if (count < ctx->text.left_column) {
- int bytes = ctx->text.left_column - count;
-
- text.ptr = XawStackAlloc(bytes, buf);
- text.length = bytes;
- for (i = 0; i < bytes; i++)
- text.ptr[i] = ' ';
- CHECK_SAVE();
- if (_XawTextReplace(ctx, left, left, &text)) {
- XawStackFree(text.ptr, buf);
- return (XawEditError);
- }
- XawStackFree(text.ptr, buf);
- right += bytes;
- if (num_pos) {
- for (cpos = 0; cpos < num_pos; cpos++)
- if (pos[cpos] >= left)
- pos[cpos] += bytes;
- }
- if (ipos >= left)
- ipos += bytes;
- count += bytes;
- }
-
- done = False;
- if (!paragraph && level == 1
- && ipos <= right && ipos - left > ctx->text.right_column) {
- XawTextPosition len = ctx->text.lastPos;
- int skip = ctx->text.justify == XawjustifyRight
- || ctx->text.justify == XawjustifyCenter ?
- ctx->text.left_column : count;
-
- if (pos)
- for (i = 0; i < num_pos; i++)
- if (pos[i] == ipos)
- break;
-
- StripSpaces(ctx, left + skip, right, pos, num_pos, save);
- right += ctx->text.lastPos - len;
- if (pos && i < num_pos)
- ipos = pos[i];
- else
- ipos = ctx->text.insertPos;
- done = ipos - left > ctx->text.right_column;
- count = skip + (count == skip + 1);
- }
- if ((paragraph || done) && right - left > ctx->text.right_column) {
- position = tmp = right;
- XawTextSourceRead(ctx->text.source, position - 1, &block, 1);
- if (block.length &&
- ((XawTextFormat(ctx, XawFmt8Bit) &&
- block.ptr[0] == ' ') ||
- (XawTextFormat(ctx, XawFmtWide) &&
- _Xaw_atowc(XawSP) == *(wchar_t*)block.ptr)))
- --position;
- while (position - left > ctx->text.right_column) {
- tmp = position;
- position = SrcScan(ctx->text.source, position,
- XawstWhiteSpace, XawsdLeft, 1, True);
- }
- if (position <= left + ctx->text.left_column)
- position = tmp;
- if (position > left && position - left > ctx->text.left_column
- && position != right) {
- text.ptr = "\n";
- text.length = 1;
- CHECK_SAVE();
- if (_XawTextReplace(ctx, position, position + 1, &text))
- return (XawEditError);
- right = position;
- recurse = True;
- force = True;
- }
- }
-
- if (force) {
- if (ctx->text.justify == XawjustifyCenter)
- count = ctx->text.right_column - (count - ctx->text.left_column);
- else
- count = ctx->text.right_column;
- if (count > right - left)
- count -= right - left;
- else
- count = 0;
- }
- else
- count = 0;
- if (count > 0) {
- switch (ctx->text.justify) {
- case XawjustifyLeft:
- break;
- case XawjustifyRight:
- case XawjustifyCenter:
- if (ctx->text.justify == XawjustifyCenter) {
- int alnum = 0;
-
- if (!(count & 1)) {
- XawTextSourceRead(ctx->text.source, right, &block, 1);
- if ((XawTextFormat(ctx, XawFmt8Bit)
- && isalnum(*(unsigned char*)block.ptr)) ||
- (XawTextFormat(ctx, XawFmtWide)
- && iswalnum(*(wchar_t*)block.ptr)))
- alnum = 1;
- }
- count = (count + alnum) >> 1;
- }
- text.ptr = XawStackAlloc(count, buf);
- text.length = count;
- for (i = 0; i < count; i++)
- text.ptr[i] = ' ';
- CHECK_SAVE();
- if (_XawTextReplace(ctx, left, left, &text)) {
- XawStackFree(text.ptr, buf);
- return (XawEditError);
- }
- XawStackFree(text.ptr, buf);
- position += count;
- right += count;
- if (num_pos) {
- for (cpos = 0; cpos < num_pos; cpos++)
- if (pos[cpos] > left)
- pos[cpos] += count;
- }
- else if (ipos > left)
- ipos += count;
- break;
- case XawjustifyFull:
- i = 0;
- tmp = left;
- /*CONSTCOND*/
- while (True) {
- tmp = SrcScan(ctx->text.source, tmp, XawstWhiteSpace,
- XawsdRight, 1, True);
- if (tmp < right)
- ++i;
- else
- break;
- }
- if (i) {
- double inc, ii;
- int bytes, steps;
-
- bytes = count;
- inc = ii = (count + .5) / (double)i;
-
- steps = count;
- text.ptr = XawStackAlloc(steps, buf);
- for (i = 0; i < steps; i++)
- text.ptr[i] = ' ';
- tmp = left;
- CHECK_SAVE();
- while (bytes) {
- steps = 1;
- while (inc + ii < 1) {
- ++steps;
- inc += ii;
- }
- tmp = SrcScan(ctx->text.source, tmp, XawstWhiteSpace,
- XawsdRight, steps, True);
- if (bytes > inc)
- text.length = (int)inc;
- else
- text.length = bytes;
- bytes -= text.length;
- if (_XawTextReplace(ctx, tmp, tmp, &text)) {
- XawStackFree(buf, text.ptr);
- return (XawEditError);
- }
- if (num_pos) {
- for (cpos = 0; cpos < num_pos; cpos++)
- if (tmp <= pos[cpos])
- pos[cpos] += text.length;
- }
- else if (tmp <= ipos)
- ipos += text.length;
- inc -= (int)inc;
- inc += ii;
- }
- position += count;
- right += count;
- XawStackFree(buf, text.ptr);
- }
- break;
- }
- }
-
- if (!num_pos)
- ctx->text.insertPos = XawMin(ipos, ctx->text.lastPos);
-
- return (recurse ? DoFormatText(ctx, position + 1,
- ctx->text.justify != XawjustifyFull
- && (force2 || paragraph),
- ++level, save, pos, num_pos, paragraph)
- : XawEditDone);
-}
-#undef CHECK_SAVE
-
-/*ARGSUSED*/
-static void
-Indent(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- TextSrcObject src = (TextSrcObject)ctx->text.source;
- XawTextPosition from, to, tmp, end = 0, *pos, *posbuf[32];
- char buf[32];
- XawTextBlock text;
- int i, spaces = MULT(ctx);
- char *lbuf = NULL, *rbuf;
- unsigned llen = 0, rlen, size;
- Bool undo = src->textSrc.enable_undo && src->textSrc.undo_state == False;
- Bool format = ctx->text.auto_fill
- && ctx->text.left_column < ctx->text.right_column;
-
- text.firstPos = 0;
- text.format = XawFmt8Bit;
- text.ptr = "";
-
- StartAction(ctx, event);
-
- pos = XawStackAlloc(sizeof(XawTextPosition) * src->textSrc.num_text, posbuf);
- for (i = 0; i < src->textSrc.num_text; i++)
- pos[i] = ((TextWidget)src->textSrc.text[i])->text.insertPos;
-
- if (!GetBlockBoundaries(ctx, &from, &to)) {
- EndAction(ctx);
- XawStackFree(pos, posbuf);
- return;
- }
-
- if (undo) {
- llen = to - from;
- end = ctx->text.lastPos;
- lbuf = _XawTextGetText(ctx, from, to);
- src->textSrc.undo_state = True;
- }
-
- tmp = ctx->text.lastPos;
- if (!Untabify(ctx, from, to, pos, src->textSrc.num_text, NULL)) {
- XBell(XtDisplay(ctx), 0);
- EndAction(ctx);
- XawStackFree(pos, posbuf);
- if (undo) {
- src->textSrc.undo_state = True;
- XtFree(lbuf);
- }
- return;
- }
- to += ctx->text.lastPos - tmp;
-
- tmp = from;
-
- if (spaces > 0) {
- text.ptr = XawStackAlloc(spaces, buf);
- for (i = 0; i < spaces; i++)
- text.ptr[i] = ' ';
-
- text.length = spaces;
- while (tmp < to) {
- _XawTextReplace(ctx, tmp, tmp, &text);
-
- for (i = 0; i < src->textSrc.num_text; i++)
- if (tmp < pos[i])
- pos[i] += spaces;
-
- to += spaces;
- tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True);
- }
- XawStackFree(text.ptr, buf);
- }
- else {
- int min = 32767;
-
- text.length = 0;
- tmp = from;
-
- /* find the amount of spaces to cut */
- while (tmp < to) {
- (void)BlankLine(w, tmp, &i);
- if (i < min)
- min = i;
- tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True);
- }
- spaces = XawMin(-spaces, min);
-
- /* cut the spaces */
- tmp = from;
- while (tmp < to) {
- _XawTextReplace(ctx, tmp, tmp + spaces, &text);
-
- for (i = 0; i < src->textSrc.num_text; i++)
- if (tmp < pos[i]) {
- if (tmp + spaces < pos[i])
- pos[i] -= spaces;
- else
- pos[i] = tmp;
- }
-
- to -= spaces;
- tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True);
- }
- }
-
- if (!format)
- Tabify(ctx, from, to, pos, src->textSrc.num_text, NULL);
-
- if (undo) {
- rlen = llen + (ctx->text.lastPos - end);
- rbuf = _XawTextGetText(ctx, from, from + rlen);
-
- text.format = _XawTextFormat(ctx);
- size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char);
- if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) {
- text.ptr = lbuf;
- text.length = llen;
- _XawTextReplace(ctx, from, from + rlen, &text);
-
- src->textSrc.undo_state = False;
- text.ptr = rbuf;
- text.length = rlen;
- _XawTextReplace(ctx, from, from + llen, &text);
- }
- else
- src->textSrc.undo_state = False;
- XtFree(lbuf);
- XtFree(rbuf);
- }
-
- for (i = 0; i < src->textSrc.num_text; i++) {
- TextWidget tw = (TextWidget)src->textSrc.text[i];
-
- tw->text.insertPos = XawMin(XawMax(0, pos[i]), tw->text.lastPos);
- }
- XawStackFree(pos, posbuf);
- ctx->text.showposition = True;
-
- EndAction(ctx);
-}
-
-/*ARGSUSED*/
-static void
-ToggleOverwrite(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- ctx->text.overwrite = !ctx->text.overwrite;
-
- /* call information callback */
- _XawTextSetLineAndColumnNumber(ctx, True);
-}
-#endif /* OLDXAW */
-
-/*
- * Insertion Routines
- */
-static int
-InsertNewLineAndBackupInternal(TextWidget ctx)
-{
- int count, error = XawEditDone, mult = MULT(ctx);
-#ifndef OLDXAW
- XawTextPosition position;
-#endif
- XawTextBlock text;
- char buf[32];
-
- if (mult < 0) {
- ctx->text.mult = 1;
- return (XawEditError);
- }
-
- text.format = _XawTextFormat(ctx);
- text.length = mult;
- text.firstPos = 0;
-
- if (text.format == XawFmtWide) {
- wchar_t *wptr;
-
- text.ptr = XawStackAlloc(sizeof(wchar_t) * mult, buf);
- wptr = (wchar_t *)text.ptr;
- for (count = 0; count < mult; count++)
- wptr[count] = _Xaw_atowc(XawLF);
- }
- else {
- text.ptr = XawStackAlloc(sizeof(char) * mult, buf);
- for (count = 0; count < mult; count++)
- text.ptr[count] = XawLF;
- }
-
-#ifndef OLDXAW
- position = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstEOL, XawsdLeft, 1, False);
-#endif
- if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
- XBell( XtDisplay(ctx), 50);
- error = XawEditError;
- }
- else {
- ctx->text.showposition = TRUE;
- ctx->text.insertPos += text.length;
- }
-
- XawStackFree(text.ptr, buf);
-
-#ifndef OLDXAW
- if (ctx->text.auto_fill && error == XawEditDone)
- (void)FormatText(ctx, position, ctx->text.justify != XawjustifyFull,
- NULL, 0);
-#endif
-
- return (error);
-}
-
-/*ARGSUSED*/
-static void
-InsertNewLineAndBackup(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition insertPos = ctx->text.insertPos;
-
- StartAction((TextWidget)w, event);
- (void)InsertNewLineAndBackupInternal(ctx);
- ctx->text.insertPos = SrcScan(ctx->text.source, insertPos, XawstEOL,
- XawsdRight, 1, False);
- EndAction((TextWidget)w);
-}
-
-static int
-LocalInsertNewLine(TextWidget ctx, XEvent *event)
-{
- int error;
-
- StartAction(ctx, event);
- error = InsertNewLineAndBackupInternal(ctx);
- ctx->text.from_left = -1;
- EndAction(ctx);
-
- return (error);
-}
-
-/*ARGSUSED*/
-static void
-InsertNewLine(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- (void)LocalInsertNewLine((TextWidget)w, event);
-}
-
-/*ARGSUSED*/
-static void
-InsertNewLineAndIndent(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- XawTextBlock text;
- XawTextPosition pos1;
- int length;
- TextWidget ctx = (TextWidget)w;
- String line_to_ip;
-
- StartAction(ctx, event);
- pos1 = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstEOL, XawsdLeft, 1, False);
-
- line_to_ip = _XawTextGetText(ctx, pos1, ctx->text.insertPos);
-
- text.format = _XawTextFormat(ctx);
- text.firstPos = 0;
-
- if (text.format == XawFmtWide) {
- wchar_t *ptr;
-
- text.ptr = XtMalloc((2 + wcslen((wchar_t*)line_to_ip))
- * sizeof(wchar_t));
- ptr = (wchar_t*)text.ptr;
- ptr[0] = _Xaw_atowc(XawLF);
- wcscpy((wchar_t*)++ptr, (wchar_t*)line_to_ip);
-
- length = wcslen((wchar_t*)text.ptr);
- while (length && (iswspace(*ptr) || *ptr == _Xaw_atowc(XawTAB)))
- ptr++, length--;
- *ptr = (wchar_t)0;
- text.length = wcslen((wchar_t*)text.ptr);
- }
- else {
- char *ptr;
-
- length = strlen(line_to_ip);
- text.ptr = XtMalloc((2 + length) * sizeof(char));
- ptr = text.ptr;
- ptr[0] = XawLF;
- strcpy(++ptr, line_to_ip);
-
- length++;
- while (length && (isspace(*ptr) || (*ptr == XawTAB)))
- ptr++, length--;
- *ptr = '\0';
- text.length = strlen(text.ptr);
- }
- XtFree(line_to_ip);
-
- if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) {
- XBell(XtDisplay(ctx), 50);
- XtFree(text.ptr);
- EndAction(ctx);
- return;
- }
-
- XtFree(text.ptr);
- ctx->text.from_left = -1;
- ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert,
- XawstPositions, XawsdRight, text.length, True);
- EndAction(ctx);
-}
-
-/*
- * Selection Routines
- */
-static void
-SelectWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition l, r;
-
- StartAction(ctx, event);
- l = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstWhiteSpace, XawsdLeft, 1, False);
- r = SrcScan(ctx->text.source, l, XawstWhiteSpace, XawsdRight, 1, False);
- _XawTextSetSelection(ctx, l, r, params, *num_params);
- EndAction(ctx);
-}
-
-static void
-SelectAll(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- StartAction(ctx, event);
- _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params);
- EndAction(ctx);
-}
-
-static void
-ModifySelection(TextWidget ctx, XEvent *event,
- XawTextSelectionMode mode,
- XawTextSelectionAction action,
- String *params, Cardinal *num_params)
-{
-#ifndef OLDXAW
- int old_y = ctx->text.ev_y;
-#endif
-
- StartAction(ctx, event);
- NotePosition(ctx, event);
-
-#ifndef OLDXAW
- if (event->type == MotionNotify) {
- if (ctx->text.ev_y <= ctx->text.margin.top) {
- if (old_y >= ctx->text.ev_y)
- XawTextScroll(ctx, -1, 0);
- }
- else if (ctx->text.ev_y >= XtHeight(ctx) - ctx->text.margin.bottom) {
- if (old_y <= ctx->text.ev_y
- && !IsPositionVisible(ctx, ctx->text.lastPos))
- XawTextScroll(ctx, 1, 0);
- }
- }
-#endif
- ctx->text.from_left = -1;
- _XawTextAlterSelection(ctx, mode, action, params, num_params);
-
- EndAction(ctx);
-}
-
-static void
-SelectStart(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
-#ifndef OLDXAW
- if (!ctx->text.selection_state) {
- ctx->text.selection_state = True;
-#endif
- ModifySelection(ctx, event,
- XawsmTextSelect, XawactionStart, params, num_params);
-#ifndef OLDXAW
- }
-#endif
-}
-
-static void
-SelectAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
-#ifndef OLDXAW
- if (ctx->text.selection_state)
-#endif
- ModifySelection(ctx, event,
- XawsmTextSelect, XawactionAdjust, params, num_params);
-}
-
-static void
-SelectEnd(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
-#ifndef OLDXAW
- if (ctx->text.selection_state) {
- ctx->text.selection_state = False;
-#endif
- ModifySelection(ctx, event,
- XawsmTextSelect, XawactionEnd, params, num_params);
-#ifndef OLDXAW
- }
-#endif
-}
-
-static void
-ExtendStart(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
-#ifndef OLDXAW
- if (!ctx->text.selection_state) {
- ctx->text.selection_state = True;
-#endif
- ModifySelection(ctx, event,
- XawsmTextExtend, XawactionStart, params, num_params);
-#ifndef OLDXAW
- }
-#endif
-}
-
-static void
-ExtendAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
-#ifndef OLDXAW
- if (ctx->text.selection_state)
-#endif
- ModifySelection(ctx, event,
- XawsmTextExtend, XawactionAdjust, params, num_params);
-}
-
-static void
-ExtendEnd(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
-#ifndef OLDXAW
- if (ctx->text.selection_state) {
- ctx->text.selection_state = False;
-#endif
- ModifySelection(ctx, event,
- XawsmTextExtend, XawactionEnd, params, num_params);
-#ifndef OLDXAW
- }
-#endif
-}
-
-static void
-SelectSave(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- int num_atoms;
- Atom *sel;
- Display *dpy = XtDisplay(w);
- Atom selections[256];
-
- StartAction((TextWidget)w, event);
- num_atoms = *num_params;
- if (num_atoms > 256)
- num_atoms = 256;
- for (sel=selections; --num_atoms >= 0; sel++, params++)
- *sel = XInternAtom(dpy, *params, False);
- num_atoms = *num_params;
- _XawTextSaltAwaySelection((TextWidget)w, selections, num_atoms);
- EndAction((TextWidget)w);
-}
-
-/*
- * Misc. Routines
- */
-/*ARGSUSED*/
-static void
-SetKeyboardFocus(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- Widget shell, parent;
-
- shell = parent = w;
- while (parent) {
- if (XtIsShell(shell = parent))
- break;
- parent = XtParent(parent);
- }
- XtSetKeyboardFocus(shell, w);
-}
-
-/*ARGSUSED*/
-static void
-RedrawDisplay(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- StartAction((TextWidget)w, event);
- _XawTextClearAndCenterDisplay((TextWidget)w);
- EndAction((TextWidget)w);
-}
-
-/* This is kind of a hack, but, only one text widget can have focus at
- * a time on one display. There is a problem in the implementation of the
- * text widget, the scrollbars can not be adressed via editres, since they
- * are not children of a subclass of composite.
- * The focus variable is required to make sure only one text window will
- * show a block cursor at one time.
- */
-struct _focus { Display *display; Widget widget; };
-static struct _focus *focus;
-static Cardinal num_focus;
-
-/*ARGSUSED*/
-static void
-DestroyFocusCallback(Widget w, XtPointer user_data, XtPointer call_data)
-{
- struct _focus *f = (struct _focus*)(user_data);
-
- if (f->widget == w)
- f->widget = NULL;
-}
-
-/*ARGSUSED*/
-static void
-TextFocusIn(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- Bool display_caret = ctx->text.display_caret;
- int i;
-
- if (event->xfocus.detail == NotifyPointer)
- return;
-
- if (event->xfocus.send_event) {
- Window root, child;
- int rootx, rooty, x, y;
- unsigned int mask;
-
- if (ctx->text.hasfocus)
- return;
-
- if (XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child,
- &rootx, &rooty, &x, &y, &mask)) {
- if (child)
- return;
- }
- }
-
- /* Let the input method know focus has arrived. */
- _XawImSetFocusValues(w, NULL, 0);
-
- if (display_caret)
- StartAction(ctx, event);
- ctx->text.hasfocus = TRUE;
- if (display_caret)
- EndAction(ctx);
-
- for (i = 0; i < num_focus; i++)
- if (focus[i].display == XtDisplay(w))
- break;
- if (i >= num_focus) {
- focus = (struct _focus*)
- XtRealloc((XtPointer)focus, sizeof(struct _focus) * (num_focus + 1));
- i = num_focus;
- focus[i].widget = NULL;
- focus[i].display = XtDisplay(w);
- num_focus++;
- }
- if (focus[i].widget != w) {
- Widget old = focus[i].widget;
-
- focus[i].widget = w;
- if (old != NULL) {
- TextFocusOut(old, event, p, n);
- /* TextFocusOut may set it to NULL */
- focus[i].widget = w;
- }
- XtAddCallback(w, XtNdestroyCallback,
- DestroyFocusCallback, (XtPointer)&focus[i]);
- }
-}
-
-/*ARGSUSED*/
-static void
-TextFocusOut(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- Bool display_caret = ctx->text.display_caret;
- Widget shell;
- Window window;
- int i, revert;
-
- shell = w;
- while (shell) {
- if (XtIsShell(shell))
- break;
- shell = XtParent(shell);
- }
-
- for (i = 0; i < num_focus; i++)
- if (focus[i].display == XtDisplay(w))
- break;
- XGetInputFocus(XtDisplay(w), &window, &revert);
- if ((XtWindow(shell) == window &&
- (i < num_focus && focus[i].widget == w))
- || event->xfocus.detail == NotifyPointer)
- return;
-
- if (i < num_focus && focus[i].widget) {
- XtRemoveCallback(focus[i].widget, XtNdestroyCallback,
- DestroyFocusCallback, (XtPointer)&focus[i]);
- focus[i].widget = NULL;
- }
-
- /* Let the input method know focus has left.*/
- _XawImUnsetFocus(w);
-
- if (display_caret)
- StartAction(ctx, event);
- ctx->text.hasfocus = FALSE;
- if (display_caret)
- EndAction(ctx);
-}
-
-/*ARGSUSED*/
-static void
-TextEnterWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus
- && !ctx->text.hasfocus)
- _XawImSetFocusValues(w, NULL, 0);
-}
-
-/*ARGSUSED*/
-static void
-TextLeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus
- && !ctx->text.hasfocus)
- _XawImUnsetFocus(w);
-}
-
-/*
- * Function:
- * AutoFill
- * Arguments: ctx - The text widget.
- *
- * Description:
- * Breaks the line at the previous word boundry when
- * called inside InsertChar.
- */
-static void
-AutoFill(TextWidget ctx)
-{
- int width, height, x, line_num, max_width;
- XawTextPosition ret_pos;
- XawTextBlock text;
- XRectangle cursor;
- wchar_t wc_buf[2];
-
- for (line_num = 0; line_num < ctx->text.lt.lines ; line_num++)
- if (ctx->text.lt.info[line_num].position >= ctx->text.insertPos)
- break;
- if (line_num)
- line_num--; /* backup a line. */
-
- XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
- max_width = Max(0, (int)XtWidth(ctx) - RHMargins(ctx) - cursor.width);
-
- x = ctx->text.r_margin.left;
- XawTextSinkFindPosition(ctx->text.sink, ctx->text.lt.info[line_num].position,
- x, max_width, True, &ret_pos,
- &width, &height);
-
- if (ret_pos <= ctx->text.lt.info[line_num].position
- || ret_pos >= ctx->text.insertPos || ret_pos < 1)
- return;
-
- XawTextSourceRead(ctx->text.source, ret_pos - 1, &text, 1);
-
- if (XawTextFormat(ctx, XawFmtWide)) {
- wc_buf[0] = *(wchar_t *)text.ptr;
- if (wc_buf[0] != _Xaw_atowc(XawSP) && wc_buf[0] != _Xaw_atowc(XawTAB))
- /* Only eats white spaces */
- return;
-
- text.format = XawFmtWide;
- text.ptr = (char *)wc_buf;
- wc_buf[0] = _Xaw_atowc(XawLF);
- wc_buf[1] = 0;
- }
- else {
- if (text.ptr[0] != XawSP && text.ptr[0] != XawTAB)
- /* Only eats white spaces */
- return;
-
- text.format = XawFmt8Bit;
- text.ptr = "\n";
- }
- text.length = 1;
- text.firstPos = 0;
-
- if (_XawTextReplace(ctx, ret_pos - 1, ret_pos, &text))
- XBell(XtDisplay((Widget)ctx), 0);
-
- if (++ctx->text.insertPos > ctx->text.lastPos)
- ctx->text.insertPos = ctx->text.lastPos;
-}
-
-/*ARGSUSED*/
-static void
-InsertChar(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- char *ptr, strbuf[128], ptrbuf[512];
- int count, error, mult = MULT(ctx);
- KeySym keysym;
- XawTextBlock text;
-#ifndef OLDXAW
- Bool format = False;
-#endif
- XawTextPosition from, to;
-
- if (XtIsSubclass (ctx->text.source, (WidgetClass) multiSrcObjectClass))
- text.length = _XawImWcLookupString(w, &event->xkey, (wchar_t*)strbuf,
- sizeof(strbuf), &keysym);
- else
- text.length = _XawLookupString(w, (XKeyEvent*)event, strbuf,
- sizeof(strbuf), &keysym);
-
- if (text.length == 0)
- return;
-
- if (mult < 0) {
- ctx->text.mult = 1;
- return;
- }
-
- text.format = _XawTextFormat(ctx);
- if (text.format == XawFmtWide) {
- text.ptr = ptr = XawStackAlloc(sizeof(wchar_t) * text.length
- * mult, ptrbuf);
- for (count = 0; count < mult; count++) {
- memcpy((char*)ptr, (char *)strbuf, sizeof(wchar_t) * text.length);
- ptr += sizeof(wchar_t) * text.length;
- }
-#ifndef OLDXAW
- if (mult == 1)
- format = ctx->text.left_column < ctx->text.right_column;
-#endif
- }
- else { /* == XawFmt8Bit */
- text.ptr = ptr = XawStackAlloc(text.length * mult, ptrbuf);
- for (count = 0; count < mult; count++) {
- strncpy(ptr, strbuf, text.length);
- ptr += text.length;
- }
-#ifndef OLDXAW
- if (mult == 1)
- format = ctx->text.left_column < ctx->text.right_column;
-#endif
- }
-
- text.length = text.length * mult;
- text.firstPos = 0;
-
- StartAction(ctx, event);
-#ifndef OLDXAW
- if (mult == 1)
- _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True);
-#endif
-
- from = ctx->text.insertPos;
-#ifndef OLDXAW
- if (ctx->text.overwrite) {
- XawTextPosition tmp;
-
- to = from + mult;
- tmp = SrcScan(ctx->text.source, from, XawstEOL, XawsdRight, 1, False);
- if (to > tmp)
- to = tmp;
- }
- else
-#endif
- to = from;
-
- error = _XawTextReplace(ctx, from , to, &text);
-
- if (error == XawEditDone) {
- ctx->text.from_left = -1;
- ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert,
- XawstPositions, XawsdRight,
- text.length, True);
- if (ctx->text.auto_fill) {
-#ifndef OLDXAW
- if (format)
- (void)FormatText(ctx, SrcScan(ctx->text.source,
- ctx->text.insertPos, XawstEOL,
- XawsdLeft, 1, False), False,
- NULL, 0);
- else
-#endif
- AutoFill(ctx);
- }
- }
- else
- XBell(XtDisplay(ctx), 50);
-
- XawStackFree(text.ptr, ptrbuf);
- EndAction(ctx);
-
- if (error == XawEditDone && text.format == XawFmt8Bit && text.length == 1
- && (text.ptr[0] == ')' || text.ptr[0] == ']' || text.ptr[0] == '}')
- && ctx->text.display_caret) {
- static struct timeval tmval = {0, 500000};
- fd_set fds;
- Widget source = ctx->text.source;
- XawTextPosition insertPos = ctx->text.insertPos, pos, tmp, last;
- char left, right = text.ptr[0];
- int level = 0;
- XtAppContext app_context = XtWidgetToApplicationContext(w);
-
- left = right == ')' ? '(' : right == ']' ? '[' : '{';
-
- last = insertPos - 1;
- do {
- text.ptr[0] = left;
- pos = XawTextSourceSearch(source, last, XawsdLeft, &text);
- if (pos == XawTextSearchError || !IsPositionVisible(ctx, pos))
- return;
- text.ptr[0] = right;
- tmp = pos;
- do {
- tmp = XawTextSourceSearch(source, tmp, XawsdRight, &text);
- if (tmp == XawTextSearchError)
- return;
- if (tmp <= last)
- ++level;
- } while (++tmp <= last);
- --level;
- last = pos;
- } while (level);
-
- StartAction(ctx, NULL);
-#ifndef OLDXAW
- _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True);
-#endif
- ctx->text.insertPos = pos;
- EndAction(ctx);
-
- XSync(XtDisplay(w), False);
- while (XtAppPending(app_context) & XtIMXEvent) {
- XEvent ev;
- if (! XtAppPeekEvent(app_context, &ev))
- break;
- if (ev.type == KeyPress || ev.type == ButtonPress)
- break;
- XtAppProcessEvent(app_context, XtIMXEvent);
- }
- FD_ZERO(&fds);
- FD_SET(ConnectionNumber(XtDisplay(w)), &fds);
- (void)select(FD_SETSIZE, &fds, NULL, NULL, &tmval);
- if (tmval.tv_usec != 500000)
- usleep(40000);
-
- StartAction(ctx, NULL);
-#ifndef OLDXAW
- _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True);
-#endif
- ctx->text.insertPos = insertPos;
- EndAction(ctx);
- }
-}
-
-/* IfHexConvertHexElseReturnParam() - called by InsertString
- *
- * i18n requires the ability to specify multiple characters in a hexa-
- * decimal string at once. Since Insert was already too long, I made
- * this a seperate routine.
- *
- * A legal hex string in MBNF: '0' 'x' ( HEX-DIGIT HEX-DIGIT )+ '\0'
- *
- * WHEN: the passed param is a legal hex string
- * RETURNS: a pointer to that converted, null terminated hex string;
- * len_return holds the character count of conversion result
- *
- * WHEN: the passed param is not a legal hex string:
- * RETURNS: the parameter passed;
- * len_return holds the char count of param.
- *
- * NOTE: In neither case will there be strings to free. */
-static char *
-IfHexConvertHexElseReturnParam(char *param, int *len_return)
-{
- char *p; /* steps through param char by char */
- char c; /* holds the character pointed to by p */
- int ind; /* steps through hexval buffer char by char */
- static char hexval[XawTextActionMaxHexChars];
- Boolean first_digit;
-
- /* reject if it doesn't begin with 0x and at least one more character. */
- if ((param[0] != '0') || (param[1] != 'x') || (param[2] == '\0')) {
- *len_return = strlen(param);
- return(param);
- }
-
- /* Skip the 0x; go character by character shifting and adding. */
- first_digit = True;
- ind = 0;
- hexval[ind] = '\0';
-
- for (p = param+2; (c = *p) != '\0'; p++) {
- hexval[ind] *= 16;
- if (c >= '0' && c <= '9')
- hexval[ind] += c - '0';
- else if (c >= 'a' && c <= 'f')
- hexval[ind] += c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- hexval[ind] += c - 'A' + 10;
- else
- break;
-
- /* If we didn't break in preceding line, it was a good hex char. */
- if (first_digit)
- first_digit = False;
- else {
- first_digit = True;
- if (++ind < XawTextActionMaxHexChars)
- hexval[ind] = '\0';
- else {
- *len_return = strlen(param);
- return(param);
- }
- }
- }
-
- /* We quit the above loop becasue we hit a non hex. If that char is \0... */
- if ((c == '\0') && first_digit) {
- *len_return = strlen(hexval);
- return (hexval); /* ...it was a legal hex string, so return it */
- }
-
- /* Else, there were non-hex chars or odd digit count, so... */
-
- *len_return = strlen(param);
- return (param); /* ...return the verbatim string. */
-}
-
-/* InsertString() - action
- *
- * Mostly rewritten for R6 i18n.
- *
- * Each parameter, in turn, will be insert at the inputPos
- * and the inputPos advances to the insertion's end.
- *
- * The exception is that parameters composed of the two
- * characters 0x, followed only by an even number of
- * hexadecimal digits will be converted to characters */
-/*ARGSUSED*/
-static void
-InsertString(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- XtAppContext app_con = XtWidgetToApplicationContext(w);
- XawTextBlock text;
- int i;
-
- text.firstPos = 0;
- text.format = _XawTextFormat(ctx);
-
- StartAction(ctx, event);
- for (i = *num_params; i; i--, params++) { /* DO FOR EACH PARAMETER */
- text.ptr = IfHexConvertHexElseReturnParam(*params, &text.length);
-
- if (text.length == 0)
- continue;
-
- if (XawTextFormat(ctx, XawFmtWide)) { /* convert to WC */
- int temp_len;
-
- text.ptr = (char*)_XawTextMBToWC(XtDisplay(w), text.ptr,
- &text.length);
-
- if (text.ptr == NULL) { /* conversion error */
- XtAppWarningMsg(app_con,
- "insertString", "textAction", "XawError",
- "insert-string()'s parameter contents "
- "not legal in this locale.",
- NULL, NULL);
- ParameterError(w, *params);
- continue;
- }
-
- /* Double check that the new input is legal: try to convert to MB. */
-
- temp_len = text.length; /* _XawTextWCToMB's 3rd arg is in_out */
- if (_XawTextWCToMB(XtDisplay(w), (wchar_t*)text.ptr, &temp_len)
- == NULL) {
- XtAppWarningMsg( app_con,
- "insertString", "textAction", "XawError",
- "insert-string()'s parameter contents "
- "not legal in this locale.",
- NULL, NULL);
- ParameterError(w, *params);
- continue;
- }
- } /* convert to WC */
-
- if (_XawTextReplace(ctx, ctx->text.insertPos,
- ctx->text.insertPos, &text)) {
- XBell(XtDisplay(ctx), 50);
- EndAction(ctx);
- return;
- }
-
- ctx->text.from_left = -1;
- /* Advance insertPos to the end of the string we just inserted. */
- ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert,
- XawstPositions, XawsdRight, text.length,
- True);
-
- } /* DO FOR EACH PARAMETER */
-
- EndAction(ctx);
-}
-
-/* DisplayCaret() - action
- *
- * The parameter list should contain one boolean value. If the
- * argument is true, the cursor will be displayed. If false, not.
- *
- * The exception is that EnterNotify and LeaveNotify events may
- * have a second argument, "always". If they do not, the cursor
- * is only affected if the focus member of the event is true. */
-static void
-DisplayCaret(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- Bool display_caret = True;
-
- if ((event->type == EnterNotify || event->type == LeaveNotify)
- && ((*num_params >= 2) && (strcmp(params[1], "always") == 0))
- && (!event->xcrossing.focus))
- return;
-
- if (*num_params > 0) { /* default arg is "True" */
- XrmValue from, to;
- from.size = strlen(from.addr = params[0]);
- XtConvert(w, XtRString, &from, XtRBoolean, &to);
-
- if (to.addr != NULL)
- display_caret = *(Boolean*)to.addr;
- if (ctx->text.display_caret == display_caret)
- return;
- }
- StartAction(ctx, event);
- ctx->text.display_caret = display_caret;
- EndAction(ctx);
-}
-
-#ifndef OLDXAW
-static void
-Numeric(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- if (ctx->text.numeric) {
- long mult = ctx->text.mult;
-
- if (*num_params != 1 || strlen(params[0]) != 1
- || (!isdigit(params[0][0])
- && (params[0][0] != '-' || mult != 0))) {
- char err_buf[256];
-
- if (event && (event->type == KeyPress || event->type == KeyRelease)
- && params[0][0] == '-') {
- InsertChar(w, event, params, num_params);
- return;
- }
- XmuSnprintf(err_buf, sizeof(err_buf),
- "numeric: Invalid argument%s'%s'",
- *num_params ? ", " : "", *num_params ? params[0] : "");
- XtAppWarning(XtWidgetToApplicationContext(w), err_buf);
- ctx->text.numeric = False;
- ctx->text.mult = 1;
- return;
- }
- if (params[0][0] == '-') {
- ctx->text.mult = 32767;
- return;
- }
- else if (mult == 32767) {
- mult = ctx->text.mult = - (params[0][0] - '0');
- return;
- }
- else {
- mult = mult * 10 + (params[0][0] - '0') * (mult < 0 ? -1 : 1);
- ctx->text.mult = ctx->text.mult * 10 + (params[0][0] - '0') *
- (mult < 0 ? -1 : 1);
- }
- if (mult != ctx->text.mult || mult >= 32767) { /* checks for overflow */
- XBell(XtDisplay(w), 0);
- ctx->text.mult = 1;
- ctx->text.numeric = False;
- return;
- }
- }
- else
- InsertChar(w, event, params, num_params);
-}
-
-/*ARGSUSED*/
-static void
-KeyboardReset(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- ctx->text.numeric = False;
- ctx->text.mult = 1;
-
- (void)_XawTextSrcToggleUndo((TextSrcObject)ctx->text.source);
-
- if (ctx->text.kill_ring_ptr) {
- --ctx->text.kill_ring_ptr->refcount;
- ctx->text.kill_ring_ptr = NULL;
- }
- ctx->text.kill_ring = 0;
-
- XBell(XtDisplay(w), 0);
-}
-#endif /* OLDXAW */
-
-/* Multiply() - action
- *
- * The parameter list may contain either a number or the string 'Reset'.
- *
- * A number will multiply the current multiplication factor by that number.
- * Many of the text widget actions will will perform n actions, where n is
- * the multiplication factor.
- *
- * The string reset will reset the mutiplication factor to 1. */
-/*ARGSUSED*/
-static void
-Multiply(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- int mult;
-
- if (*num_params != 1) {
- XtAppError(XtWidgetToApplicationContext(w),
- "Xaw Text Widget: multiply() takes exactly one argument.");
- XBell(XtDisplay(w), 0);
- return;
- }
-
- if ((params[0][0] == 'r') || (params[0][0] == 'R')) {
- XBell(XtDisplay(w), 0);
-#ifndef OLDXAW
- ctx->text.numeric = False;
-#endif
- ctx->text.mult = 1;
- return;
- }
-
-#ifndef OLDXAW
- if (params[0][0] == 's' || params[0][0] == 'S') {
- ctx->text.numeric = True;
- ctx->text.mult = 0;
- return;
- }
- else
-#endif
- if ((mult = atoi(params[0])) == 0) {
- char buf[BUFSIZ];
-
- XmuSnprintf(buf, sizeof(buf),
- "%s %s", "Xaw Text Widget: multiply() argument",
- "must be a number greater than zero, or 'Reset'.");
- XtAppError(XtWidgetToApplicationContext(w), buf);
- XBell(XtDisplay(w), 50);
- return;
- }
-
- ctx->text.mult *= mult;
-}
-
-/* StripOutOldCRs() - called from FormRegion
- *
- * removes CRs in widget ctx, from from to to.
- *
- * RETURNS: the new ending location (we may add some characters),
- * or XawReplaceError if the widget can't be written to. */
-static XawTextPosition
-StripOutOldCRs(TextWidget ctx, XawTextPosition from, XawTextPosition to,
- XawTextPosition *pos, int num_pos)
-{
- XawTextPosition startPos, endPos, eop_begin, eop_end, temp;
- Widget src = ctx->text.source;
- XawTextBlock text;
- char *buf;
- static wchar_t wc_two_spaces[3];
- int idx;
-
- /* Initialize our TextBlock with two spaces. */
- text.firstPos = 0;
- text.format = _XawTextFormat(ctx);
- if (text.format == XawFmt8Bit)
- text.ptr= " ";
- else {
- wc_two_spaces[0] = _Xaw_atowc(XawSP);
- wc_two_spaces[1] = _Xaw_atowc(XawSP);
- wc_two_spaces[2] = 0;
- text.ptr = (char*)wc_two_spaces;
- }
-
- /* Strip out CR's. */
- eop_begin = eop_end = startPos = endPos = from;
-
- /* CONSTCOND */
- while (TRUE) {
- endPos=SrcScan(src, startPos, XawstEOL, XawsdRight, 1, False);
-
- temp = SrcScan(src, endPos, XawstWhiteSpace, XawsdLeft, 1, False);
- temp = SrcScan(src, temp, XawstWhiteSpace, XawsdRight,1, False);
-
- if (temp > startPos)
- endPos = temp;
-
- if (endPos >= to)
- break;
-
- if (endPos >= eop_begin) {
- startPos = eop_end;
- eop_begin=SrcScan(src, startPos, XawstParagraph,
- XawsdRight, 1,False);
- eop_end = SrcScan(src, startPos, XawstParagraph,
- XawsdRight, 1, True);
- }
- else {
- XawTextPosition periodPos, next_word;
- int i, len;
-
- periodPos = SrcScan(src, endPos, XawstPositions,
- XawsdLeft, 1, True);
- next_word = SrcScan(src, endPos, XawstWhiteSpace,
- XawsdRight, 1, False);
-
- len = next_word - periodPos;
-
- text.length = 1;
- buf = _XawTextGetText(ctx, periodPos, next_word);
- if (text.format == XawFmtWide) {
- if (periodPos < endPos && ((wchar_t*)buf)[0] == _Xaw_atowc('.'))
- text.length++;
- }
- else
- if (periodPos < endPos && buf[0] == '.')
- text.length++; /* Put in two spaces. */
-
- /*
- * Remove all extra spaces.
- */
- for (i = 1 ; i < len; i++)
- if (text.format == XawFmtWide) {
- if (!iswspace(((wchar_t*)buf)[i]) || ((periodPos + i) >= to))
- break;
- }
- else if (!isspace(buf[i]) || (periodPos + i) >= to)
- break;
-
- XtFree(buf);
-
- to -= (i - text.length - 1);
- startPos = SrcScan(src, periodPos, XawstPositions,
- XawsdRight, i, True);
- if (_XawTextReplace(ctx, endPos, startPos, &text) != XawEditDone)
- return (XawReplaceError);
-
- for (idx = 0; idx < num_pos; idx++) {
- if (endPos < pos[idx]) {
- if (startPos < pos[idx])
- pos[idx] -= startPos - endPos;
- else
- pos[idx] = endPos;
- pos[idx] += text.length;
- }
- }
-
- startPos -= i - text.length;
- }
- }
-
- return (to);
-}
-
-/* InsertNewCRs() - called from FormRegion
- *
- * inserts new CRs for FormRegion, thus for FormParagraph action */
-static void
-InsertNewCRs(TextWidget ctx, XawTextPosition from, XawTextPosition to,
- XawTextPosition *pos, int num_pos)
-{
- XawTextPosition startPos, endPos, space, eol;
- XawTextBlock text;
- int i, width, height, len, wwidth, idx;
- char *buf;
- static wchar_t wide_CR[2];
-
- text.firstPos = 0;
- text.length = 1;
- text.format = _XawTextFormat(ctx);
-
- if (text.format == XawFmt8Bit)
- text.ptr = "\n";
- else {
- wide_CR[0] = _Xaw_atowc(XawLF);
- wide_CR[1] = 0;
- text.ptr = (char*)wide_CR;
- }
-
- startPos = from;
-
- wwidth = (int)XtWidth(ctx) - (int)HMargins(ctx);
- if (ctx->text.wrap != XawtextWrapNever) {
- XRectangle cursor;
-
- XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
- wwidth -= (int)cursor.width;
- }
- wwidth = XawMax(0, wwidth);
-
- /* CONSTCOND */
- while (TRUE) {
- XawTextSinkFindPosition(ctx->text.sink, startPos,
- (int)ctx->text.r_margin.left, wwidth,
- True, &eol, &width, &height);
- if (eol == startPos)
- ++eol;
- if (eol >= to)
- break;
-
- eol = SrcScan(ctx->text.source, eol, XawstPositions,
- XawsdLeft, 1, True);
- space = SrcScan(ctx->text.source, eol, XawstWhiteSpace,
- XawsdRight,1, True);
-
- startPos = endPos = eol;
- if (eol == space)
- return;
-
- len = (int)(space - eol);
- buf = _XawTextGetText(ctx, eol, space);
- for (i = 0 ; i < len ; i++)
- if (text.format == XawFmtWide) {
- if (!iswspace(((wchar_t*)buf)[i]))
- break;
- }
- else if (!isspace(buf[i]))
- break;
-
- to -= (i - 1);
- endPos = SrcScan(ctx->text.source, endPos,
- XawstPositions, XawsdRight, i, True);
- XtFree(buf);
-
- if (_XawTextReplace(ctx, startPos, endPos, &text))
- return;
-
- for (idx = 0; idx < num_pos; idx++) {
- if (startPos < pos[idx]) {
- if (endPos < pos[idx])
- pos[idx] -= endPos - startPos;
- else
- pos[idx] = startPos;
- pos[idx] += text.length;
- }
- }
-
- startPos = SrcScan(ctx->text.source, startPos,
- XawstPositions, XawsdRight, 1, True);
- }
-}
-
-/* FormRegion() - called by FormParagraph
- *
- * oversees the work of paragraph-forming a region
- *
- * Return:
- * XawEditDone if successful, or XawReplaceError
- */
-static int
-FormRegion(TextWidget ctx, XawTextPosition from, XawTextPosition to,
- XawTextPosition *pos, int num_pos)
-{
-#ifndef OLDXAW
- Bool format = ctx->text.auto_fill
- && ctx->text.left_column < ctx->text.right_column;
-#endif
-
- if (from >= to)
- return (XawEditDone);
-
-#ifndef OLDXAW
- if (format) {
- XawTextPosition len = ctx->text.lastPos;
- int inc = 0;
-
- if (ctx->text.justify == XawjustifyLeft ||
- ctx->text.justify == XawjustifyFull) {
- Untabify(ctx, from, to, pos, num_pos, NULL);
- to += ctx->text.lastPos - len;
- len = ctx->text.insertPos;
- (void)BlankLine((Widget)ctx, from, &inc);
- if (from + inc >= to)
- return (XawEditDone);
- }
- if (!StripSpaces(ctx, from + inc, to, pos, num_pos, NULL))
- return (XawReplaceError);
- to += ctx->text.lastPos - len;
-
- FormatText(ctx, from, ctx->text.justify != XawjustifyFull, pos, num_pos);
- }
- else {
-#endif
- if ((to = StripOutOldCRs(ctx, from, to, pos, num_pos)) == XawReplaceError)
- return (XawReplaceError);
- InsertNewCRs(ctx, from, to, pos, num_pos);
-#ifndef OLDXAW
- }
-#endif
- ctx->text.from_left = -1;
-
- return (XawEditDone);
-}
-
-#ifndef OLDXAW
-static Bool
-BlankLine(Widget w, XawTextPosition pos, int *blanks_return)
-{
- int i, blanks = 0;
- XawTextBlock block;
- Widget src = XawTextGetSource(w);
- XawTextPosition l = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False);
- XawTextPosition r = SrcScan(src, pos, XawstEOL, XawsdRight, 1, False);
-
- while (l < r) {
- l = XawTextSourceRead(src, l, &block, r - l);
- if (block.length == 0) {
- if (blanks_return)
- *blanks_return = blanks;
- return (True);
- }
- if (XawTextFormat((TextWidget)w, XawFmt8Bit)) {
- for (i = 0; i < block.length; i++, blanks++)
- if (block.ptr[i] != ' ' &&
- block.ptr[i] != '\t') {
- if (blanks_return)
- *blanks_return = blanks;
- return (block.ptr[i] == '\n');
- }
- }
- else if (XawTextFormat((TextWidget)w, XawFmtWide)) {
- for (i = 0; i < block.length; i++, blanks++)
- if (_Xaw_atowc(XawSP) != ((wchar_t*)block.ptr)[i] &&
- _Xaw_atowc(XawTAB) != ((wchar_t*)block.ptr)[i]) {
- if (blanks_return)
- *blanks_return = blanks;
- return (_Xaw_atowc(XawLF) == ((wchar_t*)block.ptr)[i]);
- }
- }
- }
-
- return (True);
-}
-
-static Bool
-GetBlockBoundaries(TextWidget ctx,
- XawTextPosition *from_return, XawTextPosition *to_return)
-{
- XawTextPosition from, to;
-
- if (ctx->text.auto_fill && ctx->text.left_column < ctx->text.right_column) {
- if (ctx->text.s.left != ctx->text.s.right) {
- from = SrcScan(ctx->text.source,
- XawMin(ctx->text.s.left, ctx->text.s.right),
- XawstEOL, XawsdLeft, 1, False);
- to = SrcScan(ctx->text.source,
- XawMax(ctx->text.s.right, ctx->text.s.right),
- XawstEOL, XawsdRight, 1, False);
- }
- else {
- XawTextBlock block;
- XawTextPosition tmp;
- Bool first;
-
- from = to = ctx->text.insertPos;
-
- /* find from position */
- first = True;
- while (1) {
- tmp = from;
- from = SrcScan(ctx->text.source, from, XawstEOL, XawsdLeft,
- 1 + !first, False);
- XawTextSourceRead(ctx->text.source, from, &block, 1);
- if (block.length == 0 ||
- (XawTextFormat(ctx, XawFmt8Bit) &&
- block.ptr[0] != ' ' &&
- block.ptr[0] != '\t' &&
- !isalnum(*(unsigned char*)block.ptr)) ||
- (XawTextFormat(ctx, XawFmtWide) &&
- _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr &&
- _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr &&
- !iswalnum(*(wchar_t*)block.ptr)) ||
- BlankLine((Widget)ctx, from, NULL)) {
- from = tmp;
- break;
- }
- if (from == tmp && !first)
- break;
- first = False;
- }
- if (first)
- return (False);
-
- /* find to position */
- first = True;
- while (1) {
- tmp = to;
- to = SrcScan(ctx->text.source, to, XawstEOL, XawsdRight,
- 1 + !first, False);
- XawTextSourceRead(ctx->text.source, to + (to < ctx->text.lastPos),
- &block, 1);
- if (block.length == 0 ||
- (XawTextFormat(ctx, XawFmt8Bit) &&
- block.ptr[0] != ' ' &&
- block.ptr[0] != '\t' &&
- !isalnum(*(unsigned char*)block.ptr)) ||
- (XawTextFormat(ctx, XawFmtWide) &&
- _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr &&
- _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr &&
- !iswalnum(*(wchar_t*)block.ptr)) ||
- BlankLine((Widget)ctx, to, NULL))
- break;
- if (to == tmp && !first)
- break;
- first = False;
- }
- }
- }
- else {
- from = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL,
- XawsdLeft, 1, False);
- if (BlankLine((Widget)ctx, from, NULL))
- return (False);
- from = SrcScan(ctx->text.source, from, XawstParagraph,
- XawsdLeft, 1, False);
- if (BlankLine((Widget)ctx, from, NULL))
- from = SrcScan(ctx->text.source, from, XawstEOL,
- XawsdRight, 1, True);
- to = SrcScan(ctx->text.source, from, XawstParagraph,
- XawsdRight, 1, False);
- }
-
- if (from < to) {
- *from_return = from;
- *to_return = to;
- return (True);
- }
-
- return (False);
-}
-#endif /* OLDXAW */
-
-/* FormParagraph() - action
- *
- * removes and reinserts CRs to maximize line length without clipping */
-/*ARGSUSED*/
-static void
-FormParagraph(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition from, to, buf[32], *pos;
-#ifndef OLDXAW
- XawTextPosition endPos = 0;
- char *lbuf = NULL, *rbuf;
- TextSrcObject src = (TextSrcObject)ctx->text.source;
- Cardinal i;
- Bool undo = src->textSrc.enable_undo && src->textSrc.undo_state == False;
-#endif
-
- StartAction(ctx, event);
-
-#ifndef OLDXAW
- pos = XawStackAlloc(sizeof(XawTextPosition) * src->textSrc.num_text, buf);
- for (i = 0; i < src->textSrc.num_text; i++)
- pos[i] = ((TextWidget)src->textSrc.text[i])->text.old_insert;
-#else
- pos = buf;
- *pos = ctx->text.old_insert;
-#endif
-
-#ifndef OLDXAW
- if (!GetBlockBoundaries(ctx, &from, &to)) {
- EndAction(ctx);
- XawStackFree(pos, buf);
- return;
- }
-
- if (undo) {
- src->textSrc.undo_state = True;
- lbuf = _XawTextGetText(ctx, from, to);
- endPos = ctx->text.lastPos;
- }
-
- if (FormRegion(ctx, from, to, pos, src->textSrc.num_text) == XawReplaceError) {
-#else
- from = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstParagraph, XawsdLeft, 1, False);
- to = SrcScan(ctx->text.source, from,
- XawstParagraph, XawsdRight, 1, False);
-
- if (FormRegion(ctx, from, to, pos, 1) == XawReplaceError) {
-#endif
- XawStackFree(pos, buf);
- XBell(XtDisplay(w), 0);
-#ifndef OLDXAW
- if (undo) {
- src->textSrc.undo_state = False;
- XtFree(lbuf);
- }
-#endif
- }
-#ifndef OLDXAW
- else if (undo) {
- /* makes the form-paragraph only one undo/redo step */
- unsigned llen, rlen, size;
- XawTextBlock block;
-
- llen = to - from;
- rlen = llen + (ctx->text.lastPos - endPos);
-
- block.firstPos = 0;
- block.format = _XawTextFormat(ctx);
-
- rbuf = _XawTextGetText(ctx, from, from + rlen);
-
- size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char);
- if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) {
- block.ptr = lbuf;
- block.length = llen;
- _XawTextReplace(ctx, from, from + rlen, &block);
-
- src->textSrc.undo_state = False;
- block.ptr = rbuf;
- block.length = rlen;
- _XawTextReplace(ctx, from, from + llen, &block);
- }
- else
- src->textSrc.undo_state = False;
- XtFree(lbuf);
- XtFree(rbuf);
- }
-
- for (i = 0; i < src->textSrc.num_text; i++) {
- TextWidget tw = (TextWidget)src->textSrc.text[i];
-
- tw->text.old_insert = tw->text.insertPos = pos[i];
- _XawTextBuildLineTable(tw, SrcScan((Widget)src, tw->text.lt.top, XawstEOL,
- XawsdLeft, 1, False), False);
- tw->text.clear_to_eol = True;
- }
-#else
- ctx->text.old_insert = ctx->text.insertPos = *pos;
- _XawTextBuildLineTable(ctx, SrcScan(ctx->text.source, ctx->text.lt.top,
- XawstEOL, XawsdLeft, 1, False), False);
- ctx->text.clear_to_eol = True;
-#endif
- XawStackFree(pos, buf);
- ctx->text.showposition = True;
-
- EndAction(ctx);
-}
-
-/* TransposeCharacters() - action
- *
- * Swaps the character to the left of the mark
- * with the character to the right of the mark */
-/*ARGSUSED*/
-static void
-TransposeCharacters(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition start, end;
- XawTextBlock text;
- char *buf;
- int i, mult = MULT(ctx);
-
- if (mult < 0) {
- ctx->text.mult = 1;
- return;
- }
-
- StartAction(ctx, event);
-
- /* Get bounds. */
-
- start = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions,
- XawsdLeft, 1, True);
- end = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions,
- XawsdRight, mult, True);
-
- /* Make sure we aren't at the very beginning or end of the buffer. */
-
- if (start == ctx->text.insertPos || end == ctx->text.insertPos) {
- XBell(XtDisplay(w), 0); /* complain. */
- EndAction(ctx);
- return;
- }
-
- ctx->text.from_left = -1;
- ctx->text.insertPos = end;
-
- text.firstPos = 0;
- text.format = _XawTextFormat(ctx);
-
- /* Retrieve text and swap the characters. */
- if (text.format == XawFmtWide) {
- wchar_t wc;
- wchar_t *wbuf;
-
- wbuf = (wchar_t*)_XawTextGetText(ctx, start, end);
- text.length = wcslen(wbuf);
- wc = wbuf[0];
- for (i = 1; i < text.length; i++)
- wbuf[i - 1] = wbuf[i];
- wbuf[i - 1] = wc;
- buf = (char*)wbuf; /* so that it gets assigned and freed */
- }
- else { /* thus text.format == XawFmt8Bit */
- char c;
-
- buf = _XawTextGetText(ctx, start, end);
- text.length = strlen(buf);
- c = buf[0];
- for (i = 1; i < text.length; i++)
- buf[i - 1] = buf[i];
- buf[i - 1] = c;
- }
-
- text.ptr = buf;
-
- /* Store new text in source. */
-
- if (_XawTextReplace (ctx, start, end, &text))
- XBell(XtDisplay(w), 0);
- XtFree((char *)buf);
- EndAction(ctx);
-}
-
-#ifndef OLDXAW
-/*ARGSUSED*/
-static void
-Undo(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- int mul = MULT(ctx);
- Bool toggle = False;
-
- if (mul < 0) {
- toggle = True;
- _XawTextSrcToggleUndo((TextSrcObject)ctx->text.source);
- ctx->text.mult = mul = -mul;
- }
-
- StartAction(ctx, event);
- for (; mul; --mul)
- if (!_XawTextSrcUndo((TextSrcObject)ctx->text.source, &ctx->text.insertPos))
- break;
- ctx->text.showposition = True;
-
- if (toggle)
- _XawTextSrcToggleUndo((TextSrcObject)ctx->text.source);
- EndAction(ctx);
-}
-#endif
-
-/* NoOp() - action
- * This action performs no action, and allows the user or
- * application programmer to unbind a translation.
- *
- * Note: If the parameter list contains the string "RingBell" then
- * this action will ring the bell.
- */
-/*ARGSUSED*/
-static void
-NoOp(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- if (*num_params != 1)
- return;
-
- switch(params[0][0]) {
- case 'R':
- case 'r':
- XBell(XtDisplay(w), 0);
- /*FALLTROUGH*/
- default:
- break;
- }
-}
-
-/* Reconnect() - action
- * This reconnects to the input method. The user will typically call
- * this action if/when connection has been severed, or when the app
- * was started up before an IM was started up
- */
-/*ARGSUSED*/
-static void
-Reconnect(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- _XawImReconnect(w);
-}
-
-#define CAPITALIZE 1
-#define DOWNCASE 2
-#define UPCASE 3
-
-#ifdef NO_LIBC_I18N
-static int
-ToLower(int ch)
-{
- char buf[2];
-
- *buf = ch;
- XmuNCopyISOLatin1Lowered(buf, buf, sizeof(buf));
-
- return (*buf);
-}
-
-static int
-ToUpper(int ch)
-{
- char buf[2];
-
- *buf = ch;
- XmuNCopyISOLatin1Uppered(buf, buf, sizeof(buf));
-
- return (*buf);
-}
-
-static int
-IsAlnum(int ch)
-{
- return ((ch >= '0' && ch <= '9') || ToUpper(ch) != ch || ToLower(ch) != ch);
-}
-
-static int
-IsLower(int ch)
-{
- char upbuf[2];
- char lobuf[2];
-
- *upbuf = *lobuf = ch;
- XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf));
- XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf));
-
- return (*lobuf != *upbuf && ch == *lobuf);
-}
-
-static int
-IsUpper(int ch)
-{
- char upbuf[2];
- char lobuf[2];
-
- *upbuf = *lobuf = ch;
- XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf));
- XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf));
-
- return (*lobuf != *upbuf && ch == *upbuf);
-}
-#else
-#define ToLower tolower
-#define ToUpper toupper
-#define IsAlnum isalnum
-#define IsLower islower
-#define IsUpper isupper
-#endif
-
-static void
-CaseProc(Widget w, XEvent *event, int cmd)
-{
- TextWidget ctx = (TextWidget)w;
- short mul = MULT(ctx);
- XawTextPosition left, right;
- XawTextBlock block;
- Bool changed = False;
- unsigned char ch, mb[sizeof(wchar_t)];
- int i, count;
-
- if (mul > 0)
- right = SrcScan(ctx->text.source, left = ctx->text.insertPos,
- XawstAlphaNumeric, XawsdRight, mul, False);
- else
- left = SrcScan(ctx->text.source, right = ctx->text.insertPos,
- XawstAlphaNumeric, XawsdLeft, 1 + -mul, False);
- block.firstPos = 0;
- block.format = _XawTextFormat(ctx);
- block.length = right - left;
- block.ptr = _XawTextGetText(ctx, left, right);
-
- count = 0;
- if (block.format == XawFmt8Bit)
- for (i = 0; i < block.length; i++) {
- if (!IsAlnum(*mb = (unsigned char)block.ptr[i]))
- count = 0;
- else if (++count == 1 || cmd != CAPITALIZE) {
- ch = cmd == DOWNCASE ? ToLower(*mb) : ToUpper(*mb);
- if (ch != *mb) {
- changed = True;
- block.ptr[i] = ch;
- }
- }
- else if (cmd == CAPITALIZE) {
- if ((ch = ToLower(*mb)) != *mb) {
- changed = True;
- block.ptr[i] = ch;
- }
- }
- }
- else
- for (i = 0; i < block.length; i++) {
- wctomb((char*)mb, ((wchar_t*)block.ptr)[i]);
- if (!IsAlnum(*mb))
- count = 0;
- else if (++count == 1 || cmd != CAPITALIZE) {
- ch = cmd == DOWNCASE ? ToLower(*mb) : ToUpper(*mb);
- if (ch != *mb) {
- changed = True;
- ((wchar_t*)block.ptr)[i] = _Xaw_atowc(ch);
- }
- }
- else if (cmd == CAPITALIZE) {
- if ((ch = ToLower(*mb)) != *mb) {
- changed = True;
- ((wchar_t*)block.ptr)[i] = _Xaw_atowc(ch);
- }
- }
- }
-
- StartAction(ctx, event);
- if (changed && _XawTextReplace(ctx, left, right, &block) != XawEditDone)
- XBell(XtDisplay(ctx), 0);
- ctx->text.insertPos = right;
- EndAction(ctx);
-
- XtFree(block.ptr);
-}
-
-/*ARGSUSED*/
-static void
-CapitalizeWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CaseProc(w, event, CAPITALIZE);
-}
-
-/*ARGSUSED*/
-static void
-DowncaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CaseProc(w, event, DOWNCASE);
-}
-
-/*ARGSUSED*/
-static void
-UpcaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CaseProc(w, event, UPCASE);
-}
-#undef CAPITALIZE
-#undef DOWNCASE
-#undef UPCASE
-
-XtActionsRec _XawTextActionsTable[] = {
- /* motion */
- {"forward-character", MoveForwardChar},
- {"backward-character", MoveBackwardChar},
- {"forward-word", MoveForwardWord},
- {"backward-word", MoveBackwardWord},
- {"forward-paragraph", MoveForwardParagraph},
- {"backward-paragraph", MoveBackwardParagraph},
- {"beginning-of-line", MoveToLineStart},
- {"end-of-line", MoveToLineEnd},
- {"next-line", MoveNextLine},
- {"previous-line", MovePreviousLine},
- {"next-page", MoveNextPage},
- {"previous-page", MovePreviousPage},
- {"beginning-of-file", MoveBeginningOfFile},
- {"end-of-file", MoveEndOfFile},
- {"scroll-one-line-up", ScrollOneLineUp},
- {"scroll-one-line-down", ScrollOneLineDown},
-
- /* delete */
- {"delete-next-character", DeleteForwardChar},
- {"delete-previous-character", DeleteBackwardChar},
- {"delete-next-word", DeleteForwardWord},
- {"delete-previous-word", DeleteBackwardWord},
- {"delete-selection", DeleteCurrentSelection},
- {"delete", Delete},
-
- /* kill */
- {"kill-word", KillForwardWord},
- {"backward-kill-word", KillBackwardWord},
- {"kill-selection", KillCurrentSelection},
- {"kill-to-end-of-line", KillToEndOfLine},
- {"kill-to-end-of-paragraph", KillToEndOfParagraph},
-
- /* new line */
- {"newline-and-indent", InsertNewLineAndIndent},
- {"newline-and-backup", InsertNewLineAndBackup},
- {"newline", InsertNewLine},
-
- /* selection */
- {"select-word", SelectWord},
- {"select-all", SelectAll},
- {"select-start", SelectStart},
- {"select-adjust", SelectAdjust},
- {"select-end", SelectEnd},
- {"select-save", SelectSave},
- {"extend-start", ExtendStart},
- {"extend-adjust", ExtendAdjust},
- {"extend-end", ExtendEnd},
- {"insert-selection", InsertSelection},
-
- /* miscellaneous */
- {"redraw-display", RedrawDisplay},
- {"insert-file", _XawTextInsertFile},
- {"search", _XawTextSearch},
- {"insert-char", InsertChar},
- {"insert-string", InsertString},
- {"focus-in", TextFocusIn},
- {"focus-out", TextFocusOut},
- {"enter-window", TextEnterWindow},
- {"leave-window", TextLeaveWindow},
- {"display-caret", DisplayCaret},
- {"multiply", Multiply},
- {"form-paragraph", FormParagraph},
- {"transpose-characters", TransposeCharacters},
- {"set-keyboard-focus", SetKeyboardFocus},
-#ifndef OLDXAW
- {"numeric", Numeric},
- {"undo", Undo},
- {"keyboard-reset", KeyboardReset},
- {"kill-ring-yank", KillRingYank},
- {"toggle-overwrite", ToggleOverwrite},
- {"indent", Indent},
-#endif
- {"no-op", NoOp},
-
- /* case transformations */
- {"capitalize-word", CapitalizeWord},
- {"downcase-word", DowncaseWord},
- {"upcase-word", UpcaseWord},
-
- /* action to bind translations for text dialogs */
- {"InsertFileAction", _XawTextInsertFileAction},
- {"DoSearchAction", _XawTextDoSearchAction},
- {"DoReplaceAction", _XawTextDoReplaceAction},
- {"SetField", _XawTextSetField},
- {"PopdownSearchAction", _XawTextPopdownSearchAction},
-
- /* reconnect to Input Method */
- {"reconnect-im", Reconnect} /* Li Yuhong, Omron KK, 1991 */
-};
-
-Cardinal _XawTextActionsTableCount = XtNumber(_XawTextActionsTable);
+/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <X11/Xos.h> /* for select() and struct timeval */ +#include <ctype.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xatom.h> +#include <X11/Xfuncs.h> +#include <X11/Xutil.h> +#include <X11/Xwinsock.h> +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/StdSel.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/MultiSinkP.h> +#include <X11/Xaw/MultiSrcP.h> +#include <X11/Xaw/TextP.h> +#include <X11/Xaw/TextSrcP.h> +#include <X11/Xaw/XawImP.h> +#include "Private.h" +#include "XawI18n.h" + +#define SrcScan XawTextSourceScan +#define FindDist XawTextSinkFindDistance +#define FindPos XawTextSinkFindPosition +#define MULT(w) (w->text.mult == 0 ? 4 : \ + w->text.mult == 32767 ? -4 : w->text.mult) + +#define KILL_RING_APPEND 2 +#define KILL_RING_BEGIN 3 +#define KILL_RING_YANK 100 +#define KILL_RING_YANK_DONE 98 + +#define XawTextActionMaxHexChars 100 + +#ifdef _MSC_VER +#define usleep(time) Sleep(time) +#endif +/* + * Prototypes + */ +static void _DeleteOrKill(TextWidget, XawTextPosition, XawTextPosition, Bool); +static void _SelectionReceived(Widget, XtPointer, Atom*, Atom*, XtPointer, + unsigned long*, int*); +static void _LoseSelection(Widget, Atom*, char**, int*); +static void AutoFill(TextWidget); +static Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*, + unsigned long*, int*); +static void DeleteOrKill(TextWidget, XEvent*, XawTextScanDirection, + XawTextScanType, Bool, Bool); +static void EndAction(TextWidget); +#ifndef OLDXAW +static Bool BlankLine(Widget, XawTextPosition, int*); +static int DoFormatText(TextWidget, XawTextPosition, Bool, int, + XawTextBlock*, XawTextPosition*, int, Bool); +static int FormatText(TextWidget, XawTextPosition, Bool, + XawTextPosition*, int); +static Bool GetBlockBoundaries(TextWidget, XawTextPosition*, XawTextPosition*); +#endif +static int FormRegion(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int); +static void GetSelection(Widget, Time, String*, Cardinal); +static char *IfHexConvertHexElseReturnParam(char*, int*); +static void InsertNewCRs(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int); +static int InsertNewLineAndBackupInternal(TextWidget); +static int LocalInsertNewLine(TextWidget, XEvent*); +static void LoseSelection(Widget, Atom*); +static void ParameterError(Widget, String); +static Bool MatchSelection(Atom, XawTextSelection*); +static void ModifySelection(TextWidget, XEvent*, XawTextSelectionMode, + XawTextSelectionAction, String*, Cardinal*); +static void Move(TextWidget, XEvent*, XawTextScanDirection, XawTextScanType, + Bool); +static void NotePosition(TextWidget, XEvent*); +static void StartAction(TextWidget, XEvent*); +static XawTextPosition StripOutOldCRs(TextWidget, XawTextPosition, + XawTextPosition, XawTextPosition*, int); +#ifndef OLDXAW +static Bool StripSpaces(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int, XawTextBlock*); +static Bool Tabify(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int, XawTextBlock*); +static Bool Untabify(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int, XawTextBlock*); +#endif + +/* + * Actions + */ +static void CapitalizeWord(Widget, XEvent*, String*, Cardinal*); +static void DisplayCaret(Widget, XEvent*, String*, Cardinal*); +static void Delete(Widget, XEvent*, String*, Cardinal*); +static void DeleteBackwardChar(Widget, XEvent*, String*, Cardinal*); +static void DeleteBackwardWord(Widget, XEvent*, String*, Cardinal*); +static void DeleteCurrentSelection(Widget, XEvent*, String*, Cardinal*); +static void DeleteForwardChar(Widget, XEvent*, String*, Cardinal*); +static void DeleteForwardWord(Widget, XEvent*, String*, Cardinal*); +static void DowncaseWord(Widget, XEvent*, String*, Cardinal*); +static void ExtendAdjust(Widget, XEvent*, String*, Cardinal*); +static void ExtendEnd(Widget, XEvent*, String*, Cardinal*); +static void ExtendStart(Widget, XEvent*, String*, Cardinal*); +static void FormParagraph(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void Indent(Widget, XEvent*, String*, Cardinal*); +#endif +static void InsertChar(Widget, XEvent*, String*, Cardinal*); +static void InsertNewLine(Widget, XEvent*, String*, Cardinal*); +static void InsertNewLineAndBackup(Widget, XEvent*, String*, Cardinal*); +static void InsertNewLineAndIndent(Widget, XEvent*, String*, Cardinal*); +static void InsertSelection(Widget, XEvent*, String*, Cardinal*); +static void InsertString(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void KeyboardReset(Widget, XEvent*, String*, Cardinal*); +#endif +static void KillBackwardWord(Widget, XEvent*, String*, Cardinal*); +static void KillCurrentSelection(Widget, XEvent*, String*, Cardinal*); +static void KillForwardWord(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void KillRingYank(Widget, XEvent*, String*, Cardinal*); +#endif +static void KillToEndOfLine(Widget, XEvent*, String*, Cardinal*); +static void KillToEndOfParagraph(Widget, XEvent*, String*, Cardinal*); +static void MoveBackwardChar(Widget, XEvent*, String*, Cardinal*); +static void MoveBackwardWord(Widget, XEvent*, String*, Cardinal*); +static void MoveBackwardParagraph(Widget, XEvent*, String*, Cardinal*); +static void MoveBeginningOfFile(Widget, XEvent*, String*, Cardinal*); +static void MoveEndOfFile(Widget, XEvent*, String*, Cardinal*); +static void MoveForwardChar(Widget, XEvent*, String*, Cardinal*); +static void MoveForwardWord(Widget, XEvent*, String*, Cardinal*); +static void MoveForwardParagraph(Widget, XEvent*, String*, Cardinal*); +static void MoveNextLine(Widget, XEvent*, String*, Cardinal*); +static void MoveNextPage(Widget, XEvent*, String*, Cardinal*); +static void MovePage(TextWidget, XEvent*, XawTextScanDirection); +static void MovePreviousLine(Widget, XEvent*, String*, Cardinal*); +static void MovePreviousPage(Widget, XEvent*, String*, Cardinal*); +static void MoveLine(TextWidget, XEvent*, XawTextScanDirection); +static void MoveToLineEnd(Widget, XEvent*, String*, Cardinal*); +static void MoveToLineStart(Widget, XEvent*, String*, Cardinal*); +static void Multiply(Widget, XEvent*, String*, Cardinal*); +static void NoOp(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void Numeric(Widget, XEvent*, String*, Cardinal*); +#endif +static void Reconnect(Widget, XEvent*, String*, Cardinal*); +static void RedrawDisplay(Widget, XEvent*, String*, Cardinal*); +static void Scroll(TextWidget, XEvent*, XawTextScanDirection); +static void ScrollOneLineDown(Widget, XEvent*, String*, Cardinal*); +static void ScrollOneLineUp(Widget, XEvent*, String*, Cardinal*); +static void SelectAdjust(Widget, XEvent*, String*, Cardinal*); +static void SelectAll(Widget, XEvent*, String*, Cardinal*); +static void SelectEnd(Widget, XEvent*, String*, Cardinal*); +static void SelectSave(Widget, XEvent*, String*, Cardinal*); +static void SelectStart(Widget, XEvent*, String*, Cardinal*); +static void SelectWord(Widget, XEvent*, String*, Cardinal*); +static void SetKeyboardFocus(Widget, XEvent*, String*, Cardinal*); +static void TextEnterWindow(Widget, XEvent*, String*, Cardinal*); +static void TextFocusIn(Widget, XEvent*, String*, Cardinal*); +static void TextFocusOut(Widget, XEvent*, String*, Cardinal*); +static void TextLeaveWindow(Widget, XEvent*, String*, Cardinal*); +static void TransposeCharacters(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void ToggleOverwrite(Widget, XEvent*, String*, Cardinal*); +static void Undo(Widget, XEvent*, String*, Cardinal*); +#endif +static void UpcaseWord(Widget, XEvent*, String*, Cardinal*); +static void DestroyFocusCallback(Widget, XtPointer, XtPointer); + +/* + * External + */ +void _XawTextZapSelection(TextWidget, XEvent*, Bool); + +/* + * Defined in TextPop.c + */ +void _XawTextInsertFileAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextInsertFile(Widget, XEvent*, String*, Cardinal*); +void _XawTextSearch(Widget, XEvent*, String*, Cardinal*); +void _XawTextDoSearchAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextDoReplaceAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextSetField(Widget, XEvent*, String*, Cardinal*); +void _XawTextPopdownSearchAction(Widget, XEvent*, String*, Cardinal*); + +/* + * These are defined in Text.c + */ +void _XawTextAlterSelection(TextWidget, XawTextSelectionMode, + XawTextSelectionAction, String*, Cardinal*); +void _XawTextClearAndCenterDisplay(TextWidget); +void _XawTextExecuteUpdate(TextWidget); +char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); +void _XawTextPrepareToUpdate(TextWidget); +int _XawTextReplace(TextWidget, XawTextPosition, XawTextPosition, + XawTextBlock*); +Atom *_XawTextSelectionList(TextWidget, String*, Cardinal); +void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition, + String*, Cardinal); +void _XawTextVScroll(TextWidget, int); +void XawTextScroll(TextWidget, int, int); +void _XawTextSetLineAndColumnNumber(TextWidget, Bool); + +#ifndef OLDXAW +/* + * Defined in TextSrc.c + */ +Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*); +Bool _XawTextSrcToggleUndo(TextSrcObject); +void _XawSourceSetUndoErase(TextSrcObject, int); +void _XawSourceSetUndoMerge(TextSrcObject, Bool); +#endif /* OLDXAW */ + +/* + * Initialization + */ +#ifndef OLDXAW +#define MAX_KILL_RINGS 1024 +XawTextKillRing *xaw_text_kill_ring; +static XawTextKillRing kill_ring_prev, kill_ring_null = { &kill_ring_prev, }; +static unsigned num_kill_rings; +#endif + +/* + * Implementation + */ +static void +ParameterError(Widget w, String param) +{ + String params[2]; + Cardinal num_params = 2; + params[0] = XtName(w); + params[1] = param; + + XtAppWarningMsg(XtWidgetToApplicationContext(w), + "parameterError", "textAction", "XawError", + "Widget: %s Parameter: %s", + params, &num_params); + XBell(XtDisplay(w), 50); +} + +static void +StartAction(TextWidget ctx, XEvent *event) +{ +#ifndef OLDXAW + Cardinal i; + TextSrcObject src = (TextSrcObject)ctx->text.source; + + for (i = 0; i < src->textSrc.num_text; i++) + _XawTextPrepareToUpdate((TextWidget)src->textSrc.text[i]); + _XawSourceSetUndoMerge(src, False); +#else + _XawTextPrepareToUpdate(ctx); +#endif + + if (event != NULL) { + switch (event->type) { + case ButtonPress: + case ButtonRelease: + ctx->text.time = event->xbutton.time; + break; + case KeyPress: + case KeyRelease: + ctx->text.time = event->xkey.time; + break; + case MotionNotify: + ctx->text.time = event->xmotion.time; + break; + case EnterNotify: + case LeaveNotify: + ctx->text.time = event->xcrossing.time; + } + } +} + +static void +NotePosition(TextWidget ctx, XEvent *event) +{ + switch (event->type) { + case ButtonPress: + case ButtonRelease: + ctx->text.ev_x = event->xbutton.x; + ctx->text.ev_y = event->xbutton.y; + break; + case KeyPress: + case KeyRelease: { + XRectangle cursor; + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + ctx->text.ev_x = cursor.x + cursor.width / 2; + ctx->text.ev_y = cursor.y + cursor.height / 2; + } break; + case MotionNotify: + ctx->text.ev_x = event->xmotion.x; + ctx->text.ev_y = event->xmotion.y; + break; + case EnterNotify: + case LeaveNotify: + ctx->text.ev_x = event->xcrossing.x; + ctx->text.ev_y = event->xcrossing.y; + } +} + +static void +EndAction(TextWidget ctx) +{ +#ifndef OLDXAW + Cardinal i; + TextSrcObject src = (TextSrcObject)ctx->text.source; + + for (i = 0; i < src->textSrc.num_text; i++) + _XawTextExecuteUpdate((TextWidget)src->textSrc.text[i]); + + ctx->text.mult = 1; + ctx->text.numeric = False; + if (ctx->text.kill_ring) { + if (--ctx->text.kill_ring == KILL_RING_YANK_DONE) { + if (ctx->text.kill_ring_ptr) { + --ctx->text.kill_ring_ptr->refcount; + ctx->text.kill_ring_ptr = NULL; + } + } + } +#else + ctx->text.mult = 1; + _XawTextExecuteUpdate(ctx); +#endif /* OLDXAW */ +} + +struct _SelectionList { + String* params; + Cardinal count; + Time time; + int asked; /* which selection currently has been asked for: + 0 = UTF8_STRING, 1 = COMPOUND_TEXT, 2 = STRING */ + Atom selection; /* selection atom (normally XA_PRIMARY) */ +}; + +/*ARGSUSED*/ +static void +_SelectionReceived(Widget w, XtPointer client_data, Atom *selection, + Atom *type, XtPointer value, unsigned long *length, + int *format) +{ + Display *d = XtDisplay(w); + TextWidget ctx = (TextWidget)w; + XawTextBlock text; + + if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) { + struct _SelectionList* list = (struct _SelectionList*)client_data; + + if (list != NULL) { + if (list->asked == 0) { + /* If we just asked for XA_UTF8_STRING and got no response, + we'll ask again, this time for XA_COMPOUND_TEXT. */ + list->asked++; + XtGetSelectionValue(w, list->selection, XA_COMPOUND_TEXT(d), + _SelectionReceived, + (XtPointer)list, list->time); + } else if (list->asked == 1) { + /* If we just asked for XA_COMPOUND_TEXT and got no response, + we'll ask again, this time for XA_STRING. */ + list->asked++; + XtGetSelectionValue(w, list->selection, XA_STRING, + _SelectionReceived, + (XtPointer)list, list->time); + } else { + /* We tried all possible text targets in this param. + Recurse on the tail of the params list. */ + GetSelection(w, list->time, list->params, list->count); + XtFree(client_data); + } + } + return; + } + + StartAction(ctx, NULL); + if (XawTextFormat(ctx, XawFmtWide)) { + XTextProperty textprop; + wchar_t **wlist; + int count; + + textprop.encoding = *type; + textprop.value = (unsigned char *)value; + textprop.nitems = strlen(value); + textprop.format = 8; + + if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count) + != Success + || count < 1) { + XwcFreeStringList(wlist); + + /* Notify the user on strerr and in the insertion :) */ + fprintf(stderr, "Xaw Text Widget: An attempt was made to insert " + "an illegal selection.\n"); + + textprop.value = (unsigned char *)" >> ILLEGAL SELECTION << "; + textprop.nitems = strlen((char *) textprop.value); + if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count) + != Success + || count < 1) + return; + } + + XFree(value); + value = (XPointer)wlist[0]; + + *length = wcslen(wlist[0]); + XtFree((XtPointer)wlist); + text.format = XawFmtWide; + } + text.ptr = (char*)value; + text.firstPos = 0; + text.length = *length; + if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell(XtDisplay(ctx), 0); + EndAction(ctx); + return; + } + + ctx->text.from_left = -1; + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert, + XawstPositions, XawsdRight, text.length, True); + + EndAction(ctx); + XtFree(client_data); + XFree(value); /* the selection value should be freed with XFree */ +} + +static void +GetSelection(Widget w, Time timev, String *params, Cardinal num_params) +{ + Display *d = XtDisplay(w); + TextWidget ctx = (TextWidget)w; + Atom selection; + int buffer; + + selection = XInternAtom(XtDisplay(w), *params, False); + switch (selection) { + case XA_CUT_BUFFER0: buffer = 0; break; + case XA_CUT_BUFFER1: buffer = 1; break; + case XA_CUT_BUFFER2: buffer = 2; break; + case XA_CUT_BUFFER3: buffer = 3; break; + case XA_CUT_BUFFER4: buffer = 4; break; + case XA_CUT_BUFFER5: buffer = 5; break; + case XA_CUT_BUFFER6: buffer = 6; break; + case XA_CUT_BUFFER7: buffer = 7; break; + default: buffer = -1; + } + if (buffer >= 0) { + int nbytes; + unsigned long length; + int fmt8 = 8; + Atom type = XA_STRING; + char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer); + + if ((length = nbytes) != 0L) + _SelectionReceived(w, NULL, &selection, &type, line, &length, &fmt8); + else if (num_params > 1) + GetSelection(w, timev, params+1, num_params-1); + } + else { + struct _SelectionList* list; + + if (--num_params) { + list = XtNew(struct _SelectionList); + list->params = params + 1; + list->count = num_params; + list->time = timev; + list->asked = 0; + list->selection = selection; + } + else + list = NULL; + XtGetSelectionValue(w, selection, XawTextFormat(ctx, XawFmtWide) ? + XA_UTF8_STRING(d) : XA_TEXT(d), + _SelectionReceived, (XtPointer)list, timev); + } +} + +static void +InsertSelection(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + StartAction((TextWidget)w, event); /* Get Time. */ + GetSelection(w, ((TextWidget)w)->text.time, params, *num_params); + EndAction((TextWidget)w); +} + +/* + * Routines for Moving Around + */ +static void +Move(TextWidget ctx, XEvent *event, XawTextScanDirection dir, + XawTextScanType type, Bool include) +{ + XawTextPosition insertPos; + short mult = MULT(ctx); + + if (mult < 0) { + mult = -mult; + dir = dir == XawsdLeft ? XawsdRight : XawsdLeft; + } + + insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, mult, include); + + StartAction(ctx, event); + + if (ctx->text.s.left != ctx->text.s.right) + XawTextUnsetSelection((Widget)ctx); + +#ifndef OLDXAW + ctx->text.numeric = False; +#endif + ctx->text.mult = 1; + ctx->text.showposition = True; + ctx->text.from_left = -1; + ctx->text.insertPos = insertPos; + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +MoveForwardChar(Widget w, XEvent *event, String *p, Cardinal *n) +{ + Move((TextWidget)w, event, XawsdRight, XawstPositions, True); +} + +/*ARGSUSED*/ +static void +MoveBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n) +{ + Move((TextWidget)w, event, XawsdLeft, XawstPositions, True); +} + +static void +MoveForwardWord(Widget w, XEvent *event, String *p, Cardinal *n) +{ + if (*n && (p[0][0] == 'A' || p[0][0] == 'a')) + Move((TextWidget)w, event, XawsdRight, XawstAlphaNumeric, False); + else + Move((TextWidget)w, event, XawsdRight, XawstWhiteSpace, False); +} + +static void +MoveBackwardWord(Widget w, XEvent *event, String *p, Cardinal *n) +{ + if (*n && (p[0][0] == 'A' || p[0][0] == 'a')) + Move((TextWidget)w, event, XawsdLeft, XawstAlphaNumeric, False); + else + Move((TextWidget)w, event, XawsdLeft, XawstWhiteSpace, False); +} + +static void +MoveForwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition position = ctx->text.insertPos; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MoveBackwardParagraph(w, event, p, n); + return; + } + + while (mult--) { + position = SrcScan(ctx->text.source, position, + XawstEOL, XawsdRight, 1, False) - 1; + + while (position == SrcScan(ctx->text.source, position, + XawstEOL, XawsdRight, 1, False)) + if (++position > ctx->text.lastPos) { + mult = 0; + break; + } + + position = SrcScan(ctx->text.source, position, + XawstParagraph, XawsdRight, 1, True); + if (position != ctx->text.lastPos) + position = SrcScan(ctx->text.source, position - 1, + XawstEOL, XawsdLeft, 1, False); + else + break; + } + + if (position != ctx->text.insertPos) { + XawTextUnsetSelection(w); + StartAction(ctx, event); + ctx->text.showposition = True; + ctx->text.from_left = -1; + ctx->text.insertPos = position; + EndAction(ctx); + } + else + ctx->text.mult = 1; +} + +/*ARGSUSED*/ +static void +MoveBackwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition position = ctx->text.insertPos; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MoveForwardParagraph(w, event, p, n); + return; + } + + while (mult--) { + position = SrcScan(ctx->text.source, position, + XawstEOL, XawsdLeft, 1, False) + 1; + + while (position == SrcScan(ctx->text.source, position, + XawstEOL, XawsdLeft, 1, False)) + if (--position < 0) { + mult = 0; + break; + } + + position = SrcScan(ctx->text.source, position, + XawstParagraph, XawsdLeft, 1, True); + if (position > 0 && position < ctx->text.lastPos) + ++position; + else + break; + } + + if (position != ctx->text.insertPos) { + XawTextUnsetSelection(w); + StartAction(ctx, event); + ctx->text.showposition = True; + ctx->text.from_left = -1; + ctx->text.insertPos = position; + EndAction(ctx); + } + else + ctx->text.mult = 1; +} + +/*ARGSUSED*/ +static void +MoveToLineEnd(Widget w, XEvent *event, String *p, Cardinal *n) +{ + Move((TextWidget)w, event, XawsdRight, XawstEOL, False); +} + +/*ARGSUSED*/ +static void +MoveToLineStart(Widget w, XEvent *event, String *p, Cardinal *n) +{ + Move((TextWidget)w, event, XawsdLeft, XawstEOL, False); +} + +static void +MoveLine(TextWidget ctx, XEvent *event, XawTextScanDirection dir) +{ + XawTextPosition cnew, next_line, ltemp; + int itemp, from_left; + short mult = MULT(ctx); + + StartAction(ctx, event); + + XawTextUnsetSelection((Widget)ctx); + + if (dir == XawsdLeft) + mult = mult == 0 ? 5 : mult + 1; + + cnew = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, False); + + if (ctx->text.from_left < 0) + FindDist(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.insertPos, + &ctx->text.from_left, <emp, &itemp); + + cnew = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir, + mult, (dir == XawsdRight)); + + next_line = SrcScan(ctx->text.source, cnew, XawstEOL, XawsdRight, 1, False); + + FindPos(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.from_left, + False, &ctx->text.insertPos, &from_left, &itemp); + + if (from_left < ctx->text.from_left) { + XawTextBlock block; + + XawTextSourceRead(ctx->text.source, ctx->text.insertPos, &block, 1); + if (block.length) { + if (XawTextFormat(ctx, XawFmtWide)) { + if (*(wchar_t *)block.ptr == _Xaw_atowc(XawTAB)) + ++ctx->text.insertPos; + } + else if (block.ptr[0] == XawTAB) + ++ctx->text.insertPos; + } + } + + if (ctx->text.insertPos > next_line) + ctx->text.insertPos = next_line; + + EndAction(ctx); +} + +static void +MoveNextLine(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MovePreviousLine(w, event, p, n); + return; + } + + if (ctx->text.insertPos < ctx->text.lastPos) + MoveLine(ctx, event, XawsdRight); + else + ctx->text.mult = 1; +} + +static void +MovePreviousLine(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MoveNextLine(w, event, p, n); + return; + } + + if (ctx->text.lt.top != 0 || (ctx->text.lt.lines > 1 && + ctx->text.insertPos >= ctx->text.lt.info[1].position)) + MoveLine(ctx, event, XawsdLeft); + else + ctx->text.mult = 1; +} + +/*ARGSUSED*/ +static void +MoveBeginningOfFile(Widget w, XEvent *event, String *p, Cardinal *n) +{ + Move((TextWidget)w, event, XawsdLeft, XawstAll, True); +} + +/*ARGSUSED*/ +static void +MoveEndOfFile(Widget w, XEvent *event, String *p, Cardinal *n) +{ + Move((TextWidget)w, event, XawsdRight, XawstAll, True); +} + +static void +Scroll(TextWidget ctx, XEvent *event, XawTextScanDirection dir) +{ + short mult = MULT(ctx); + + if (mult < 0) { + mult = -mult; + dir = dir == XawsdLeft ? XawsdRight : XawsdLeft; + } + + if (ctx->text.lt.lines > 1 + && (dir == XawsdRight + || ctx->text.lastPos >= ctx->text.lt.info[1].position)) { + StartAction(ctx, event); + + if (dir == XawsdLeft) + _XawTextVScroll(ctx, mult); + else + _XawTextVScroll(ctx, -mult); + + EndAction(ctx); + } + else { + ctx->text.mult = 1; +#ifndef OLDXAW + ctx->text.numeric = False; +#endif + } +} + +/*ARGSUSED*/ +static void +ScrollOneLineUp(Widget w, XEvent *event, String *p, Cardinal *n) +{ + Scroll((TextWidget)w, event, XawsdLeft); +} + +/*ARGSUSED*/ +static void +ScrollOneLineDown(Widget w, XEvent *event, String *p, Cardinal *n) +{ + Scroll((TextWidget)w, event, XawsdRight); +} + +static void +MovePage(TextWidget ctx, XEvent *event, XawTextScanDirection dir) +{ + int scroll_val = 0; + XawTextPosition old_pos; + + ctx->text.from_left = -1; + switch (dir) { + case XawsdLeft: + if (ctx->text.lt.top != 0) + scroll_val = -Max(1, ctx->text.lt.lines - 1); + break; + case XawsdRight: + if (!IsPositionVisible(ctx, Max(0, ctx->text.lastPos))) + scroll_val = Max(1, ctx->text.lt.lines - 1); + break; + } + + if (scroll_val) + XawTextScroll(ctx, scroll_val, + ctx->text.left_margin - ctx->text.r_margin.left); + + old_pos = ctx->text.insertPos; + switch (dir) { + case XawsdRight: + if (IsPositionVisible(ctx, Max(0, ctx->text.lastPos))) + ctx->text.insertPos = Max(0, ctx->text.lastPos); + else + ctx->text.insertPos = ctx->text.lt.top; + if (ctx->text.insertPos < old_pos) + ctx->text.insertPos = SrcScan(ctx->text.source, old_pos, + XawstEOL, XawsdLeft, 1, False); + break; + case XawsdLeft: + if (IsPositionVisible(ctx, 0)) + ctx->text.insertPos = 0; + else if (ctx->text.lt.lines) + ctx->text.insertPos = + ctx->text.lt.info[ctx->text.lt.lines - 1].position; + else + ctx->text.insertPos = ctx->text.lt.top; + if (ctx->text.insertPos > old_pos) + ctx->text.insertPos = SrcScan(ctx->text.source, old_pos, + XawstEOL, XawsdLeft, 1, False); + break; + } +} + +static void +MoveNextPage(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MovePreviousPage(w, event, p, n); + return; + } + + if (ctx->text.insertPos < ctx->text.lastPos) { + XawTextUnsetSelection(w); + StartAction(ctx, event); + ctx->text.clear_to_eol = True; + while (mult-- && ctx->text.insertPos < ctx->text.lastPos) + MovePage(ctx, event, XawsdRight); + EndAction(ctx); + } + else + ctx->text.mult = 1; +} + +/*ARGSUSED*/ +static void +MovePreviousPage(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MoveNextPage(w, event, p, n); + return; + } + + if (ctx->text.insertPos > 0) { + XawTextUnsetSelection(w); + StartAction(ctx, event); + ctx->text.clear_to_eol = True; + while (mult-- && ctx->text.insertPos > 0) + MovePage(ctx, event, XawsdLeft); + EndAction(ctx); + } + else + ctx->text.mult = 1; +} + +/* + * Delete Routines + */ +static Bool +MatchSelection(Atom selection, XawTextSelection *s) +{ + Atom *match; + int count; + + for (count = 0, match = s->selections; count < s->atom_count; + match++, count++) + if (*match == selection) + return (True); + + return (False); +} + +#define SrcCvtSel XawTextSourceConvertSelection + +static Boolean +ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type, + XtPointer *value, unsigned long *length, int *format) +{ + Display *d = XtDisplay(w); + TextWidget ctx = (TextWidget)w; + Widget src = ctx->text.source; + XawTextEditType edit_mode; + Arg args[1]; + XawTextSelectionSalt *salt = NULL; + XawTextSelection *s; + + if (*target == XA_TARGETS(d)) { + Atom *targetP, *std_targets; + unsigned long std_length; + + if (SrcCvtSel(src, selection, target, type, value, length, format)) + return (True); + + XtSetArg(args[0], XtNeditType,&edit_mode); + XtGetValues(src, args, 1); + + XmuConvertStandardSelection(w, ctx->text.time, selection, + target, type, (XPointer *)&std_targets, + &std_length, format); + + *length = 7 + (edit_mode == XawtextEdit) + std_length; + *value = XtMalloc((unsigned)sizeof(Atom)*(*length)); + targetP = *(Atom**)value; + *targetP++ = XA_STRING; + *targetP++ = XA_TEXT(d); + *targetP++ = XA_UTF8_STRING(d); + *targetP++ = XA_COMPOUND_TEXT(d); + *targetP++ = XA_LENGTH(d); + *targetP++ = XA_LIST_LENGTH(d); + *targetP++ = XA_CHARACTER_POSITION(d); + if (edit_mode == XawtextEdit) { + *targetP++ = XA_DELETE(d); + } + memcpy((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); + XtFree((char*)std_targets); + *type = XA_ATOM; + *format = 32; + return (True); + } + + if (SrcCvtSel(src, selection, target, type, value, length, format)) + return (True); + + for (salt = ctx->text.salt2; salt; salt = salt->next) + if (MatchSelection (*selection, &salt->s)) + break; + if (!salt) + return (False); + s = &salt->s; + if (*target == XA_STRING + || *target == XA_TEXT(d) + || *target == XA_UTF8_STRING(d) + || *target == XA_COMPOUND_TEXT(d)) { + if (*target == XA_TEXT(d)) { + if (XawTextFormat(ctx, XawFmtWide)) + *type = XA_COMPOUND_TEXT(d); + else + *type = XA_STRING; + } + else + *type = *target; + + /* + * If salt is True, the salt->contents stores CT string, + * its length is measured in bytes. + * Refer to _XawTextSaltAwaySelection() + * + * by Li Yuhong, Mar. 20, 1991. + */ + if (!salt) { + *value = (char *)_XawTextGetSTRING(ctx, s->left, s->right); + if (XawTextFormat(ctx, XawFmtWide)) { + XTextProperty textprop; + if (XwcTextListToTextProperty(d, (wchar_t**)value, 1, + XCompoundTextStyle, &textprop) + < Success) { + XtFree(*value); + return (False); + } + XtFree(*value); + *value = (XtPointer)textprop.value; + *length = textprop.nitems; + } + else + *length = strlen(*value); + } + else { + *value = XtMalloc((salt->length + 1) * sizeof(unsigned char)); + strcpy (*value, salt->contents); + *length = salt->length; + } + /* Got *value,*length, now in COMPOUND_TEXT format. */ + if (XawTextFormat(ctx, XawFmtWide)) { + if (*type == XA_STRING) { + XTextProperty textprop; + wchar_t **wlist; + int count; + + textprop.encoding = XA_COMPOUND_TEXT(d); + textprop.value = (unsigned char *)*value; + textprop.nitems = strlen(*value); + textprop.format = 8; + if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count) + < Success + || count < 1) { + XtFree(*value); + return (False); + } + XtFree(*value); + if (XwcTextListToTextProperty(d, wlist, 1, XStringStyle, &textprop) + < Success) { + XwcFreeStringList((wchar_t**)wlist); + return (False); + } + *value = (XtPointer)textprop.value; + *length = textprop.nitems; + XwcFreeStringList((wchar_t**) wlist); + } + else if (*type == XA_UTF8_STRING(d)) { + XTextProperty textprop; + char **list; + int count; + + textprop.encoding = XA_COMPOUND_TEXT(d); + textprop.value = (unsigned char *)*value; + textprop.nitems = strlen(*value); + textprop.format = 8; + if (Xutf8TextPropertyToTextList(d, &textprop, &list, &count) + < Success + || count < 1) { + XtFree(*value); + return (False); + } + XtFree(*value); + *value = *list; + *length = strlen(*list); + XFree(list); + } + } + *format = 8; + return (True); + } + + if (*target == XA_LIST_LENGTH(d) || *target == XA_LENGTH(d)) { + long *temp; + + temp = (long *)XtMalloc(sizeof(long)); + if (*target == XA_LIST_LENGTH(d)) + *temp = 1L; + else /* *target == XA_LENGTH(d) */ + *temp = (long)(s->right - s->left); + + *value = (XPointer)temp; + *type = XA_INTEGER; + *length = 1L; + *format = 32; + return (True); + } + + if (*target == XA_CHARACTER_POSITION(d)) { + long *temp; + + temp = (long *) XtMalloc(2 * sizeof(long)); + temp[0] = (long)(s->left + 1); + temp[1] = s->right; + *value = (XPointer)temp; + *type = XA_SPAN(d); + *length = 2L; + *format = 32; + return (True); + } + + if (*target == XA_DELETE(d)) { + if (!salt) + _XawTextZapSelection(ctx, NULL, True); + *value = NULL; + *type = XA_NULL(d); + *length = 0; + *format = 32; + return (True); + } + + if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type, + (XPointer *)value, length, format)) + return (True); + + return (False); +} + +static void +LoseSelection(Widget w, Atom *selection) +{ + _LoseSelection(w, selection, NULL, NULL); +} + +static void +_LoseSelection(Widget w, Atom *selection, char **contents, int *length) +{ + TextWidget ctx = (TextWidget)w; + Atom *atomP; + int i; + XawTextSelectionSalt *salt, *prevSalt, *nextSalt; + + prevSalt = 0; + for (salt = ctx->text.salt2; salt; salt = nextSalt) { + atomP = salt->s.selections; + nextSalt = salt->next; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*selection == *atomP) + *atomP = (Atom)0; + + while (salt->s.atom_count + && salt->s.selections[salt->s.atom_count-1] == 0) + salt->s.atom_count--; + + /* + * Must walk the selection list in opposite order from UnsetSelection. + */ + atomP = salt->s.selections; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*atomP == (Atom)0) { + *atomP = salt->s.selections[--salt->s.atom_count]; + + while (salt->s.atom_count + && salt->s.selections[salt->s.atom_count-1] == 0) + salt->s.atom_count--; + } + if (salt->s.atom_count == 0) { +#ifndef OLDXAW + if (contents == NULL) { + XawTextKillRing *kill_ring = XtNew(XawTextKillRing); + + kill_ring->next = xaw_text_kill_ring; + kill_ring->contents = salt->contents; + kill_ring->length = salt->length; + kill_ring->format = XawFmt8Bit; + xaw_text_kill_ring = kill_ring; + kill_ring_prev.next = xaw_text_kill_ring; + + if (++num_kill_rings > MAX_KILL_RINGS) { + XawTextKillRing *tail = NULL; + + while (kill_ring->next) { + tail = kill_ring; + kill_ring = kill_ring->next; + } + if (kill_ring->refcount == 0) { + --num_kill_rings; + tail->next = NULL; + XtFree(kill_ring->contents); + XtFree((char*)kill_ring); + } + } + } + else { + *contents = salt->contents; + *length = salt->length; + } +#endif + if (prevSalt) + prevSalt->next = nextSalt; + else + ctx->text.salt2 = nextSalt; + + XtFree((char *)salt->s.selections); + XtFree((char *)salt); + } + else + prevSalt = salt; + } +} + +static void +_DeleteOrKill(TextWidget ctx, XawTextPosition from, XawTextPosition to, + Bool kill) +{ + XawTextBlock text; + +#ifndef OLDXAW + if (ctx->text.kill_ring_ptr) { + --ctx->text.kill_ring_ptr->refcount; + ctx->text.kill_ring_ptr = NULL; + } +#endif + if (kill && from < to) { +#ifndef OLDXAW + Bool append = False; + char *ring = NULL; + XawTextPosition old_from = from; +#endif + char *string; + int size = 0, length; + XawTextSelectionSalt *salt; + Atom selection = XInternAtom(XtDisplay(ctx), "SECONDARY", False); + +#ifndef OLDXAW + if (ctx->text.kill_ring == KILL_RING_APPEND) { + old_from = ctx->text.salt2->s.left; + append = True; + } + else + ctx->text.kill_ring = KILL_RING_BEGIN; + + if (append) + _LoseSelection((Widget)ctx, &selection, &ring, &size); + else +#endif + LoseSelection((Widget)ctx, &selection); + + salt = (XawTextSelectionSalt*)XtMalloc(sizeof(XawTextSelectionSalt)); + salt->s.selections = (Atom *)XtMalloc(sizeof(Atom)); + salt->s.left = from; + salt->s.right = to; + + string = (char *)_XawTextGetSTRING(ctx, from, to); + + if (XawTextFormat(ctx, XawFmtWide)) { + XTextProperty textprop; + + if (XwcTextListToTextProperty(XtDisplay((Widget)ctx), + (wchar_t**)(&string), + 1, XCompoundTextStyle, + &textprop) < Success) { + XtFree(string); + XtFree((char*)salt->s.selections); + XtFree((char*)salt); + return; + } + XtFree(string); + string = (char *)textprop.value; + length = textprop.nitems; + } + else + length = strlen(string); + + salt->length = length + size; + +#ifndef OLDXAW + if (!append) + salt->contents = string; + else { + salt->contents = XtMalloc(length + size + 1); + if (from >= old_from) { + strncpy(salt->contents, ring, size); + salt->contents[size] = '\0'; + strncat(salt->contents, string, length); + } + else { + strncpy(salt->contents, string, length); + salt->contents[length] = '\0'; + strncat(salt->contents, ring, size); + } + salt->contents[length + size] = '\0'; + XtFree(ring); + XtFree(string); + } + + kill_ring_prev.contents = salt->contents; + kill_ring_prev.length = salt->length; + kill_ring_prev.format = XawFmt8Bit; +#else + salt->contents = string; +#endif + + salt->next = ctx->text.salt2; + ctx->text.salt2 = salt; + +#ifndef OLDXAW + if (append) + ctx->text.kill_ring = KILL_RING_BEGIN; +#endif + + salt->s.selections[0] = selection; + + XtOwnSelection((Widget)ctx, selection, ctx->text.time, + ConvertSelection, LoseSelection, NULL); + salt->s.atom_count = 1; + } + text.length = 0; + text.firstPos = 0; + + text.format = _XawTextFormat(ctx); + text.ptr = ""; + + if (_XawTextReplace(ctx, from, to, &text)) { + XBell(XtDisplay(ctx), 50); + return; + } + ctx->text.from_left = -1; + ctx->text.insertPos = from; + ctx->text.showposition = TRUE; +} + +static void +DeleteOrKill(TextWidget ctx, XEvent *event, XawTextScanDirection dir, + XawTextScanType type, Bool include, Bool kill) +{ + XawTextPosition from, to; + short mult = MULT(ctx); + + if (mult < 0) { + mult = -mult; + dir = dir == XawsdLeft ? XawsdRight : XawsdLeft; + } + + StartAction(ctx, event); +#ifndef OLDXAW + if (mult == 1) + _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True); +#endif + to = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, mult, include); + + /* + * If no movement actually happened, then bump the count and try again. + * This causes the character position at the very beginning and end of + * a boundary to act correctly + */ + if (to == ctx->text.insertPos) + to = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, mult + 1, include); + + if (dir == XawsdLeft) { + from = to; + to = ctx->text.insertPos; + } + else + from = ctx->text.insertPos; + + _DeleteOrKill(ctx, from, to, kill); + EndAction(ctx); +} + +static void +Delete(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + + if (ctx->text.s.left != ctx->text.s.right) + DeleteCurrentSelection(w, event, p, n); + else + DeleteBackwardChar(w, event, p, n); +} + +static void +DeleteChar(Widget w, XEvent *event, XawTextScanDirection dir) +{ + TextWidget ctx = (TextWidget)w; + short mul = MULT(ctx); + + if (mul < 0) { + ctx->text.mult = mul = -mul; + dir = dir == XawsdLeft ? XawsdRight : XawsdLeft; + } + DeleteOrKill(ctx, event, dir, XawstPositions, True, False); +#ifndef OLDXAW + if (mul == 1) + _XawSourceSetUndoErase((TextSrcObject)ctx->text.source, + dir == XawsdLeft ? -1 : 1); +#endif +} + +/*ARGSUSED*/ +static void +DeleteForwardChar(Widget w, XEvent *event, String *p, Cardinal *n) +{ + DeleteChar(w, event, XawsdRight); +} + +/*ARGSUSED*/ +static void +DeleteBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n) +{ + DeleteChar(w, event, XawsdLeft); +} + +static void +DeleteForwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XawTextScanType type; + + if (*num_params && (*params[0] == 'A' || *params[0] == 'a')) + type = XawstAlphaNumeric; + else + type = XawstWhiteSpace; + + DeleteOrKill((TextWidget)w, event, XawsdRight, type, False, False); +} + +static void +DeleteBackwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XawTextScanType type; + + if (*num_params && (*params[0] == 'A' || *params[0] == 'a')) + type = XawstAlphaNumeric; + else + type = XawstWhiteSpace; + + DeleteOrKill((TextWidget)w, event, XawsdLeft, type, False, False); +} + +static void +KillForwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XawTextScanType type; + + if (*num_params && (*params[0] == 'A' || *params[0] == 'a')) + type = XawstAlphaNumeric; + else + type = XawstWhiteSpace; + + DeleteOrKill((TextWidget)w, event, XawsdRight, type, False, True); +} + +static void +KillBackwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XawTextScanType type; + + if (*num_params && (*params[0] == 'A' || *params[0] == 'a')) + type = XawstAlphaNumeric; + else + type = XawstWhiteSpace; + + DeleteOrKill((TextWidget) w, event, XawsdLeft, type, False, True); +} + +/*ARGSUSED*/ +static void +KillToEndOfLine(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition end_of_line; + XawTextScanDirection dir = XawsdRight; + short mult = MULT(ctx); + + if (mult < 0) { + dir = XawsdLeft; + mult = -mult; + } + + StartAction(ctx, event); + end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, + dir, mult, False); + if (end_of_line == ctx->text.insertPos) + end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, + dir, mult, True); + + if (dir == XawsdRight) + _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, True); + else + _DeleteOrKill(ctx, end_of_line, ctx->text.insertPos, True); + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +KillToEndOfParagraph(Widget w, XEvent *event, String *p, Cardinal *n) +{ + DeleteOrKill((TextWidget)w, event, XawsdRight, XawstParagraph, False, True); +} + +void +_XawTextZapSelection(TextWidget ctx, XEvent *event, Bool kill) +{ + StartAction(ctx, event); + _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill); + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +KillCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n) +{ + _XawTextZapSelection((TextWidget) w, event, True); +} + +#ifndef OLDXAW +/*ARGSUSED*/ +static void +KillRingYank(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition insertPos = ctx->text.insertPos; + Bool first_yank = False; + + if (ctx->text.s.left != ctx->text.s.right) + XawTextUnsetSelection((Widget)ctx); + + StartAction(ctx, event); + + if (ctx->text.kill_ring_ptr == NULL) { + ctx->text.kill_ring_ptr = &kill_ring_prev; + ++ctx->text.kill_ring_ptr->refcount; + ctx->text.s.left = ctx->text.s.right = insertPos; + first_yank = True; + } + if (ctx->text.kill_ring_ptr) { + int mul = MULT(ctx); + XawTextBlock text; + + if (!first_yank) { + if (mul < 0) + mul = 1; + --ctx->text.kill_ring_ptr->refcount; + while (mul--) { + if ((ctx->text.kill_ring_ptr = ctx->text.kill_ring_ptr->next) == NULL) + ctx->text.kill_ring_ptr = &kill_ring_null; + } + ++ctx->text.kill_ring_ptr->refcount; + } + text.firstPos = 0; + text.length = ctx->text.kill_ring_ptr->length; + text.ptr = ctx->text.kill_ring_ptr->contents; + text.format = ctx->text.kill_ring_ptr->format; + + if (_XawTextReplace(ctx, ctx->text.s.left, insertPos, &text) == XawEditDone) { + ctx->text.kill_ring = KILL_RING_YANK; + ctx->text.insertPos = ctx->text.s.left + text.length; + } + } + else + XBell(XtDisplay(w), 0); + + EndAction(ctx); +} +#endif /* OLDXAW */ + +/*ARGSUSED*/ +static void +DeleteCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n) +{ + _XawTextZapSelection((TextWidget)w, event, False); +} + +#ifndef OLDXAW +#define CHECK_SAVE() \ + if (save && !save->ptr) \ + save->ptr = _XawTextGetText(ctx, save->firstPos, \ + save->firstPos + save->length) +static Bool +StripSpaces(TextWidget ctx, XawTextPosition left, XawTextPosition right, + XawTextPosition *pos, int num_pos, XawTextBlock *save) +{ + Bool done, space; + int i, cpos, count = 0; + XawTextBlock block, text; + XawTextPosition ipos, position = left, tmp = left; + + text.firstPos = 0; + text.format = XawFmt8Bit; + text.ptr = " "; + text.length = 1; + + position = XawTextSourceRead(ctx->text.source, position, + &block, right - left); + done = False; + space = False; + /* convert tabs and returns to spaces */ + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) { + for (i = 0; i < block.length; i++) + if (block.ptr[i] == '\t' || block.ptr[i] == '\n') { + space = True; + break; + } + } + else { + wchar_t *wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) + if (wptr[i] == _Xaw_atowc('\t') || wptr[i] == _Xaw_atowc('\n')) { + space = True; + break; + } + } + if (space) { + CHECK_SAVE(); + if (_XawTextReplace(ctx, tmp + i, tmp + i + 1, &text)) + return (False); + space = False; + } + tmp += i; + position = XawTextSourceRead(ctx->text.source, tmp, + &block, right - tmp); + if (block.length == 0 || tmp == position || tmp >= right) + done = True; + } + + text.ptr = ""; + text.length = 0; + position = tmp = left; + position = XawTextSourceRead(ctx->text.source, position, + &block, right - left); + ipos = ctx->text.insertPos; + done = False; + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) { + for (i = 0; i < block.length; i++) + if (block.ptr[i] == ' ') + ++count; + else if (count == 1) + count = 0; + else if (count) + break; + } + else { + wchar_t *wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) + if (wptr[i] == _Xaw_atowc(' ')) + ++count; + else if (count == 1) + count = 0; + else if (count) + break; + } + if (--count > 0) { + CHECK_SAVE(); + if (_XawTextReplace(ctx, tmp + i - count, tmp + i, &text)) + return (False); + right -= count; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) { + if (tmp + i - count < pos[cpos]) { + if (tmp + i < pos[cpos]) + pos[cpos] -= count; + else + pos[cpos] = tmp + i - count; + } + } + } + else { + if (tmp + i - count < ipos) { + if (tmp + i < ipos) + ipos -= count; + else + ipos = tmp + i - count; + } + } + tmp += i - count; + } + else + tmp += i + 1; + count = 0; + position = XawTextSourceRead(ctx->text.source, tmp, + &block, right - tmp); + if (block.length == 0 || tmp == position || tmp >= right) + done = True; + } + if (!num_pos) + ctx->text.insertPos = ipos; + + return (True); +} + +static Bool +Tabify(TextWidget ctx, XawTextPosition left, XawTextPosition right, + XawTextPosition *pos, int num_pos, XawTextBlock *save) +{ + Bool done, zero; + int i, cpos, count = 0, column = 0, offset = 0; + XawTextBlock text, block; + XawTextPosition ipos, position = left, tmp = left; + TextSinkObject sink = (TextSinkObject)ctx->text.sink; + short *char_tabs = sink->text_sink.char_tabs; + int tab_count = sink->text_sink.tab_count; + int tab_index = 0, tab_column = 0, TAB_SIZE = DEFAULT_TAB_SIZE; + + text.firstPos = 0; + text.ptr = "\t"; + text.format = XawFmt8Bit; + text.length = 1; + + position = XawTextSourceRead(ctx->text.source, position, + &block, right - left); + ipos = ctx->text.insertPos; + done = zero = False; + if (tab_count) + TAB_SIZE = *char_tabs; + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) { + for (i = 0; i < block.length; i++) { + ++offset; + ++column; + if (tab_count) { + if (column > tab_column + char_tabs[tab_index]) { + TAB_SIZE = tab_index < tab_count - 1 ? char_tabs[tab_index + 1] - char_tabs[tab_index] : *char_tabs; + if (++tab_index >= tab_count) { + tab_column += char_tabs[tab_count - 1]; + tab_index = 0; + } + } + } + if (block.ptr[i] == ' ') { + if (++count > TAB_SIZE) + count %= TAB_SIZE; + if ((tab_count && column == tab_column + char_tabs[tab_index]) || + (!tab_count && column % TAB_SIZE == 0)) { + if (count % (TAB_SIZE + 1) > 1) + break; + else + count = 0; + } + } + else { + if (block.ptr[i] == '\n') { + zero = True; + break; + } + count = 0; + } + } + } + else { + wchar_t *wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) { + ++offset; + ++column; + if (tab_count) { + if (column > tab_column + char_tabs[tab_index]) { + TAB_SIZE = tab_index < tab_count - 1 ? char_tabs[tab_index + 1] - char_tabs[tab_index] : *char_tabs; + if (++tab_index >= tab_count) { + tab_column += char_tabs[tab_count - 1]; + tab_index = 0; + } + } + } + if (wptr[i] == _Xaw_atowc(' ')) { + if (++count > TAB_SIZE) + count %= TAB_SIZE; + if ((tab_count && column == tab_column + char_tabs[tab_index]) || + (!tab_count && column % TAB_SIZE == 0)) { + if (count % (TAB_SIZE + 1) > 1) + break; + else + count = 0; + } + } + else { + if (wptr[i] == _Xaw_atowc('\n')) { + zero = True; + break; + } + count = 0; + } + } + } + count %= TAB_SIZE + 1; + if (!zero && count > 1 && i < block.length) { + CHECK_SAVE(); + if (_XawTextReplace(ctx, tmp + i - count + 1, tmp + i + 1, &text)) + return (False); + right -= count - 1; + offset -= count - 1; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) { + if (tmp + i - count + 1 < pos[cpos]) { + if (tmp + i + 1 < pos[cpos]) + pos[cpos] -= count; + else + pos[cpos] = tmp + i - count + 1; + ++pos[cpos]; + } + } + } + else { + if (tmp + i - count + 1 < ipos) { + if (tmp + i + 1 < ipos) + ipos -= count; + else + ipos = tmp + i - count + 1; + ++ipos; + } + } + } + if (count) + --count; + if (zero) { + count = column = 0; + zero = False; + if (tab_count) { + tab_column = tab_index = 0; + TAB_SIZE = *char_tabs; + } + } + else if (i < block.length) + count = 0; + tmp = left + offset; + position = XawTextSourceRead(ctx->text.source, tmp, + &block, right - tmp); + if (tmp == position || tmp >= right) + done = True; + } + if (!num_pos) + ctx->text.insertPos = ipos; + + return (True); +} + +static Bool +Untabify(TextWidget ctx, XawTextPosition left, XawTextPosition right, + XawTextPosition *pos, int num_pos, XawTextBlock *save) +{ + Bool done, zero; + int i, cpos, count = 0, diff = 0; + XawTextBlock block, text; + XawTextPosition ipos, position = left, tmp = left; + TextSinkObject sink = (TextSinkObject)ctx->text.sink; + short *char_tabs = sink->text_sink.char_tabs; + int tab_count = sink->text_sink.tab_count; + int tab_index = 0, tab_column = 0, tab_base = 0; + static char *tabs = " "; + + text.firstPos = 0; + text.format = XawFmt8Bit; + text.ptr = tabs; + + position = XawTextSourceRead(ctx->text.source, position, + &block, right - left); + ipos = ctx->text.insertPos; + done = False; + zero = False; + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) + for (i = 0; i < block.length; i++) { + if (block.ptr[i] != '\t') { + ++count; + if (block.ptr[i] == '\n') { + zero = True; + break; + } + } + else + break; + } + else { + wchar_t *wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) + if (wptr[i] != _Xaw_atowc('\t')) { + ++count; + if (wptr[i] != _Xaw_atowc('\n')) { + zero = True; + break; + } + } + else + break; + } + if (!zero && i < block.length) { + if (tab_count) { + while (tab_base + tab_column <= count) { + for (; tab_index < tab_count; ++tab_index) + if (tab_base + char_tabs[tab_index] > count) { + tab_column = char_tabs[tab_index]; + break; + } + if (tab_index >= tab_count) { + tab_base += char_tabs[tab_count - 1]; + tab_column = tab_index = 0; + } + } + text.length = (tab_base + tab_column) - count; + if (text.length > 8) { + int j; + + text.ptr = XtMalloc(text.length); + for (j = 0; j < text.length; j++) + text.ptr[j] = ' '; + } + else + text.ptr = tabs; + } + else + text.length = DEFAULT_TAB_SIZE - (count % DEFAULT_TAB_SIZE); + CHECK_SAVE(); + if (_XawTextReplace(ctx, tmp + i, tmp + i + 1, &text)) { + if (tab_count && text.length > 8) + XtFree(text.ptr); + return (False); + } + if (tab_count && text.length > 8) + XtFree(text.ptr); + count += text.length; + right += text.length - 1; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) { + if (tmp + i < pos[cpos]) { + if (tmp + i + 1 < pos[cpos]) + --pos[cpos]; + else + pos[cpos] = tmp + i; + pos[cpos] += text.length; + } + } + } + else { + if (tmp + i < ipos) { + if (tmp + i + 1 < ipos) + --ipos; + else + ipos = tmp + i; + ipos += text.length; + } + } + } + tmp = left + count + diff; + if (zero) { + diff += count; + count = 0; + zero = False; + if (tab_count) + tab_base = tab_column = tab_index = 0; + } + position = XawTextSourceRead(ctx->text.source, tmp, + &block, right - tmp); + if (tmp == position || tmp >= right) + done = True; + } + if (!num_pos) + ctx->text.insertPos = ipos; + + return (True); +} + +static int +FormatText(TextWidget ctx, XawTextPosition left, Bool force, + XawTextPosition *pos, int num_pos) +{ + char *ptr = NULL; + Bool freepos = False, undo, paragraph = pos != NULL; + int i, result; + XawTextBlock block, *text; + XawTextPosition end = ctx->text.lastPos, buf[32]; + TextSrcObject src = (TextSrcObject)ctx->text.source; + XawTextPosition right = SrcScan(ctx->text.source, left, XawstEOL, + XawsdRight, 1, False); + + undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; + if (undo) { + if (!pos) { + num_pos = src->textSrc.num_text; + pos = XawStackAlloc(sizeof(XawTextPosition) * num_pos, buf); + for (i = 0; i < num_pos; i++) + pos[i] = ((TextWidget)src->textSrc.text[i])->text.insertPos; + freepos = True; + } + else + freepos = False; + src->textSrc.undo_state = True; + block.ptr = NULL; + block.firstPos = left; + block.length = right - left; + text = █ + } + else + text = NULL; + + result = DoFormatText(ctx, left, force, 1, text, pos, num_pos, paragraph); + if (undo && result == XawEditDone && block.ptr) { + char *lbuf, *rbuf; + unsigned llen, rlen, size; + + ptr = lbuf = block.ptr; + llen = block.length; + rlen = llen + (ctx->text.lastPos - end); + + block.firstPos = 0; + block.format = _XawTextFormat(ctx); + + rbuf = _XawTextGetText(ctx, left, left + rlen); + + size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char); + if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) { + block.ptr = lbuf; + block.length = llen; + _XawTextReplace(ctx, left, left + rlen, &block); + + src->textSrc.undo_state = False; + block.ptr = rbuf; + block.length = rlen; + _XawTextReplace(ctx, left, left + llen, &block); + } + else + src->textSrc.undo_state = False; + XtFree(rbuf); + } + if (undo) { + src->textSrc.undo_state = False; + if (freepos) { + for (i = 0; i < num_pos; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + tw->text.insertPos = XawMin(XawMax(0, pos[i]), tw->text.lastPos); + } + XawStackFree(pos, buf); + } + if (ptr) + XtFree(ptr); + } + + return (result); +} + +static int +DoFormatText(TextWidget ctx, XawTextPosition left, Bool force, int level, + XawTextBlock *save, XawTextPosition *pos, int num_pos, + Bool paragraph) +{ + XawTextPosition right = SrcScan(ctx->text.source, left, XawstEOL, + XawsdRight, 1, False); + XawTextPosition position, tmp, ipos; + XawTextBlock block, text; + char buf[128]; + wchar_t *wptr; + int i, count, cpos; + Bool done, force2 = force, recurse = False; + + position = XawTextSourceRead(ctx->text.source, left, &block, right - left); + if (block.length == 0 || left >= right || + (level == 1 && ((XawTextFormat(ctx, XawFmt8Bit) && + block.ptr[0] != ' ' && + block.ptr[0] != '\t' && + !isalnum(*(unsigned char*)block.ptr)) || + (XawTextFormat(ctx, XawFmtWide) && + _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr && + _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr && + !iswalnum(*(wchar_t*)block.ptr))))) + return (XawEditDone); + + if (level == 1 && !paragraph) { + tmp = ctx->text.lastPos; + if (Untabify(ctx, left, right, pos, num_pos, save) == False) + return (XawEditError); + right += ctx->text.lastPos - tmp; + position = XawTextSourceRead(ctx->text.source, left, &block, + right - left); + } + + text.firstPos = 0; + text.format = XawFmt8Bit; + + ipos = ctx->text.insertPos; + count = 0; + done = False; + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) { + for (i = 0; i < block.length; i++) + if (block.ptr[i] == ' ') + ++count; + else { + done = True; + break; + } + } + else { + wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) + if (wptr[i] == _Xaw_atowc(' ')) + ++count; + else { + done = True; + break; + } + } + tmp = position; + position = XawTextSourceRead(ctx->text.source, position, + &block, right - position); + if (tmp == position) + done = True; + } + position = left + count; + if (count < ctx->text.left_column) { + int bytes = ctx->text.left_column - count; + + text.ptr = XawStackAlloc(bytes, buf); + text.length = bytes; + for (i = 0; i < bytes; i++) + text.ptr[i] = ' '; + CHECK_SAVE(); + if (_XawTextReplace(ctx, left, left, &text)) { + XawStackFree(text.ptr, buf); + return (XawEditError); + } + XawStackFree(text.ptr, buf); + right += bytes; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) + if (pos[cpos] >= left) + pos[cpos] += bytes; + } + if (ipos >= left) + ipos += bytes; + count += bytes; + } + + done = False; + if (!paragraph && level == 1 + && ipos <= right && ipos - left > ctx->text.right_column) { + XawTextPosition len = ctx->text.lastPos; + int skip = ctx->text.justify == XawjustifyRight + || ctx->text.justify == XawjustifyCenter ? + ctx->text.left_column : count; + + if (pos) + for (i = 0; i < num_pos; i++) + if (pos[i] == ipos) + break; + + StripSpaces(ctx, left + skip, right, pos, num_pos, save); + right += ctx->text.lastPos - len; + if (pos && i < num_pos) + ipos = pos[i]; + else + ipos = ctx->text.insertPos; + done = ipos - left > ctx->text.right_column; + count = skip + (count == skip + 1); + } + if ((paragraph || done) && right - left > ctx->text.right_column) { + position = tmp = right; + XawTextSourceRead(ctx->text.source, position - 1, &block, 1); + if (block.length && + ((XawTextFormat(ctx, XawFmt8Bit) && + block.ptr[0] == ' ') || + (XawTextFormat(ctx, XawFmtWide) && + _Xaw_atowc(XawSP) == *(wchar_t*)block.ptr))) + --position; + while (position - left > ctx->text.right_column) { + tmp = position; + position = SrcScan(ctx->text.source, position, + XawstWhiteSpace, XawsdLeft, 1, True); + } + if (position <= left + ctx->text.left_column) + position = tmp; + if (position > left && position - left > ctx->text.left_column + && position != right) { + text.ptr = "\n"; + text.length = 1; + CHECK_SAVE(); + if (_XawTextReplace(ctx, position, position + 1, &text)) + return (XawEditError); + right = position; + recurse = True; + force = True; + } + } + + if (force) { + if (ctx->text.justify == XawjustifyCenter) + count = ctx->text.right_column - (count - ctx->text.left_column); + else + count = ctx->text.right_column; + if (count > right - left) + count -= right - left; + else + count = 0; + } + else + count = 0; + if (count > 0) { + switch (ctx->text.justify) { + case XawjustifyLeft: + break; + case XawjustifyRight: + case XawjustifyCenter: + if (ctx->text.justify == XawjustifyCenter) { + int alnum = 0; + + if (!(count & 1)) { + XawTextSourceRead(ctx->text.source, right, &block, 1); + if ((XawTextFormat(ctx, XawFmt8Bit) + && isalnum(*(unsigned char*)block.ptr)) || + (XawTextFormat(ctx, XawFmtWide) + && iswalnum(*(wchar_t*)block.ptr))) + alnum = 1; + } + count = (count + alnum) >> 1; + } + text.ptr = XawStackAlloc(count, buf); + text.length = count; + for (i = 0; i < count; i++) + text.ptr[i] = ' '; + CHECK_SAVE(); + if (_XawTextReplace(ctx, left, left, &text)) { + XawStackFree(text.ptr, buf); + return (XawEditError); + } + XawStackFree(text.ptr, buf); + position += count; + right += count; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) + if (pos[cpos] > left) + pos[cpos] += count; + } + else if (ipos > left) + ipos += count; + break; + case XawjustifyFull: + i = 0; + tmp = left; + /*CONSTCOND*/ + while (True) { + tmp = SrcScan(ctx->text.source, tmp, XawstWhiteSpace, + XawsdRight, 1, True); + if (tmp < right) + ++i; + else + break; + } + if (i) { + double inc, ii; + int bytes, steps; + + bytes = count; + inc = ii = (count + .5) / (double)i; + + steps = count; + text.ptr = XawStackAlloc(steps, buf); + for (i = 0; i < steps; i++) + text.ptr[i] = ' '; + tmp = left; + CHECK_SAVE(); + while (bytes) { + steps = 1; + while (inc + ii < 1) { + ++steps; + inc += ii; + } + tmp = SrcScan(ctx->text.source, tmp, XawstWhiteSpace, + XawsdRight, steps, True); + if (bytes > inc) + text.length = (int)inc; + else + text.length = bytes; + bytes -= text.length; + if (_XawTextReplace(ctx, tmp, tmp, &text)) { + XawStackFree(buf, text.ptr); + return (XawEditError); + } + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) + if (tmp <= pos[cpos]) + pos[cpos] += text.length; + } + else if (tmp <= ipos) + ipos += text.length; + inc -= (int)inc; + inc += ii; + } + position += count; + right += count; + XawStackFree(buf, text.ptr); + } + break; + } + } + + if (!num_pos) + ctx->text.insertPos = XawMin(ipos, ctx->text.lastPos); + + return (recurse ? DoFormatText(ctx, position + 1, + ctx->text.justify != XawjustifyFull + && (force2 || paragraph), + ++level, save, pos, num_pos, paragraph) + : XawEditDone); +} +#undef CHECK_SAVE + +/*ARGSUSED*/ +static void +Indent(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + TextSrcObject src = (TextSrcObject)ctx->text.source; + XawTextPosition from, to, tmp, end = 0, *pos, *posbuf[32]; + char buf[32]; + XawTextBlock text; + int i, spaces = MULT(ctx); + char *lbuf = NULL, *rbuf; + unsigned llen = 0, rlen, size; + Bool undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; + Bool format = ctx->text.auto_fill + && ctx->text.left_column < ctx->text.right_column; + + text.firstPos = 0; + text.format = XawFmt8Bit; + text.ptr = ""; + + StartAction(ctx, event); + + pos = XawStackAlloc(sizeof(XawTextPosition) * src->textSrc.num_text, posbuf); + for (i = 0; i < src->textSrc.num_text; i++) + pos[i] = ((TextWidget)src->textSrc.text[i])->text.insertPos; + + if (!GetBlockBoundaries(ctx, &from, &to)) { + EndAction(ctx); + XawStackFree(pos, posbuf); + return; + } + + if (undo) { + llen = to - from; + end = ctx->text.lastPos; + lbuf = _XawTextGetText(ctx, from, to); + src->textSrc.undo_state = True; + } + + tmp = ctx->text.lastPos; + if (!Untabify(ctx, from, to, pos, src->textSrc.num_text, NULL)) { + XBell(XtDisplay(ctx), 0); + EndAction(ctx); + XawStackFree(pos, posbuf); + if (undo) { + src->textSrc.undo_state = True; + XtFree(lbuf); + } + return; + } + to += ctx->text.lastPos - tmp; + + tmp = from; + + if (spaces > 0) { + text.ptr = XawStackAlloc(spaces, buf); + for (i = 0; i < spaces; i++) + text.ptr[i] = ' '; + + text.length = spaces; + while (tmp < to) { + _XawTextReplace(ctx, tmp, tmp, &text); + + for (i = 0; i < src->textSrc.num_text; i++) + if (tmp < pos[i]) + pos[i] += spaces; + + to += spaces; + tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True); + } + XawStackFree(text.ptr, buf); + } + else { + int min = 32767; + + text.length = 0; + tmp = from; + + /* find the amount of spaces to cut */ + while (tmp < to) { + (void)BlankLine(w, tmp, &i); + if (i < min) + min = i; + tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True); + } + spaces = XawMin(-spaces, min); + + /* cut the spaces */ + tmp = from; + while (tmp < to) { + _XawTextReplace(ctx, tmp, tmp + spaces, &text); + + for (i = 0; i < src->textSrc.num_text; i++) + if (tmp < pos[i]) { + if (tmp + spaces < pos[i]) + pos[i] -= spaces; + else + pos[i] = tmp; + } + + to -= spaces; + tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True); + } + } + + if (!format) + Tabify(ctx, from, to, pos, src->textSrc.num_text, NULL); + + if (undo) { + rlen = llen + (ctx->text.lastPos - end); + rbuf = _XawTextGetText(ctx, from, from + rlen); + + text.format = _XawTextFormat(ctx); + size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char); + if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) { + text.ptr = lbuf; + text.length = llen; + _XawTextReplace(ctx, from, from + rlen, &text); + + src->textSrc.undo_state = False; + text.ptr = rbuf; + text.length = rlen; + _XawTextReplace(ctx, from, from + llen, &text); + } + else + src->textSrc.undo_state = False; + XtFree(lbuf); + XtFree(rbuf); + } + + for (i = 0; i < src->textSrc.num_text; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + + tw->text.insertPos = XawMin(XawMax(0, pos[i]), tw->text.lastPos); + } + XawStackFree(pos, posbuf); + ctx->text.showposition = True; + + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +ToggleOverwrite(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + + ctx->text.overwrite = !ctx->text.overwrite; + + /* call information callback */ + _XawTextSetLineAndColumnNumber(ctx, True); +} +#endif /* OLDXAW */ + +/* + * Insertion Routines + */ +static int +InsertNewLineAndBackupInternal(TextWidget ctx) +{ + int count, error = XawEditDone, mult = MULT(ctx); +#ifndef OLDXAW + XawTextPosition position; +#endif + XawTextBlock text; + char buf[32]; + + if (mult < 0) { + ctx->text.mult = 1; + return (XawEditError); + } + + text.format = _XawTextFormat(ctx); + text.length = mult; + text.firstPos = 0; + + if (text.format == XawFmtWide) { + wchar_t *wptr; + + text.ptr = XawStackAlloc(sizeof(wchar_t) * mult, buf); + wptr = (wchar_t *)text.ptr; + for (count = 0; count < mult; count++) + wptr[count] = _Xaw_atowc(XawLF); + } + else { + text.ptr = XawStackAlloc(sizeof(char) * mult, buf); + for (count = 0; count < mult; count++) + text.ptr[count] = XawLF; + } + +#ifndef OLDXAW + position = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, False); +#endif + if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell( XtDisplay(ctx), 50); + error = XawEditError; + } + else { + ctx->text.showposition = TRUE; + ctx->text.insertPos += text.length; + } + + XawStackFree(text.ptr, buf); + +#ifndef OLDXAW + if (ctx->text.auto_fill && error == XawEditDone) + (void)FormatText(ctx, position, ctx->text.justify != XawjustifyFull, + NULL, 0); +#endif + + return (error); +} + +/*ARGSUSED*/ +static void +InsertNewLineAndBackup(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition insertPos = ctx->text.insertPos; + + StartAction((TextWidget)w, event); + (void)InsertNewLineAndBackupInternal(ctx); + ctx->text.insertPos = SrcScan(ctx->text.source, insertPos, XawstEOL, + XawsdRight, 1, False); + EndAction((TextWidget)w); +} + +static int +LocalInsertNewLine(TextWidget ctx, XEvent *event) +{ + int error; + + StartAction(ctx, event); + error = InsertNewLineAndBackupInternal(ctx); + ctx->text.from_left = -1; + EndAction(ctx); + + return (error); +} + +/*ARGSUSED*/ +static void +InsertNewLine(Widget w, XEvent *event, String *p, Cardinal *n) +{ + (void)LocalInsertNewLine((TextWidget)w, event); +} + +/*ARGSUSED*/ +static void +InsertNewLineAndIndent(Widget w, XEvent *event, String *p, Cardinal *n) +{ + XawTextBlock text; + XawTextPosition pos1; + int length; + TextWidget ctx = (TextWidget)w; + String line_to_ip; + + StartAction(ctx, event); + pos1 = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, False); + + line_to_ip = _XawTextGetText(ctx, pos1, ctx->text.insertPos); + + text.format = _XawTextFormat(ctx); + text.firstPos = 0; + + if (text.format == XawFmtWide) { + wchar_t *ptr; + + text.ptr = XtMalloc((2 + wcslen((wchar_t*)line_to_ip)) + * sizeof(wchar_t)); + ptr = (wchar_t*)text.ptr; + ptr[0] = _Xaw_atowc(XawLF); + wcscpy((wchar_t*)++ptr, (wchar_t*)line_to_ip); + + length = wcslen((wchar_t*)text.ptr); + while (length && (iswspace(*ptr) || *ptr == _Xaw_atowc(XawTAB))) + ptr++, length--; + *ptr = (wchar_t)0; + text.length = wcslen((wchar_t*)text.ptr); + } + else { + char *ptr; + + length = strlen(line_to_ip); + text.ptr = XtMalloc((2 + length) * sizeof(char)); + ptr = text.ptr; + ptr[0] = XawLF; + strcpy(++ptr, line_to_ip); + + length++; + while (length && (isspace(*ptr) || (*ptr == XawTAB))) + ptr++, length--; + *ptr = '\0'; + text.length = strlen(text.ptr); + } + XtFree(line_to_ip); + + if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell(XtDisplay(ctx), 50); + XtFree(text.ptr); + EndAction(ctx); + return; + } + + XtFree(text.ptr); + ctx->text.from_left = -1; + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert, + XawstPositions, XawsdRight, text.length, True); + EndAction(ctx); +} + +/* + * Selection Routines + */ +static void +SelectWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition l, r; + + StartAction(ctx, event); + l = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstWhiteSpace, XawsdLeft, 1, False); + r = SrcScan(ctx->text.source, l, XawstWhiteSpace, XawsdRight, 1, False); + _XawTextSetSelection(ctx, l, r, params, *num_params); + EndAction(ctx); +} + +static void +SelectAll(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + + StartAction(ctx, event); + _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params); + EndAction(ctx); +} + +static void +ModifySelection(TextWidget ctx, XEvent *event, + XawTextSelectionMode mode, + XawTextSelectionAction action, + String *params, Cardinal *num_params) +{ +#ifndef OLDXAW + int old_y = ctx->text.ev_y; +#endif + + StartAction(ctx, event); + NotePosition(ctx, event); + +#ifndef OLDXAW + if (event->type == MotionNotify) { + if (ctx->text.ev_y <= ctx->text.margin.top) { + if (old_y >= ctx->text.ev_y) + XawTextScroll(ctx, -1, 0); + } + else if (ctx->text.ev_y >= XtHeight(ctx) - ctx->text.margin.bottom) { + if (old_y <= ctx->text.ev_y + && !IsPositionVisible(ctx, ctx->text.lastPos)) + XawTextScroll(ctx, 1, 0); + } + } +#endif + ctx->text.from_left = -1; + _XawTextAlterSelection(ctx, mode, action, params, num_params); + + EndAction(ctx); +} + +static void +SelectStart(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (!ctx->text.selection_state) { + ctx->text.selection_state = True; +#endif + ModifySelection(ctx, event, + XawsmTextSelect, XawactionStart, params, num_params); +#ifndef OLDXAW + } +#endif +} + +static void +SelectAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (ctx->text.selection_state) +#endif + ModifySelection(ctx, event, + XawsmTextSelect, XawactionAdjust, params, num_params); +} + +static void +SelectEnd(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (ctx->text.selection_state) { + ctx->text.selection_state = False; +#endif + ModifySelection(ctx, event, + XawsmTextSelect, XawactionEnd, params, num_params); +#ifndef OLDXAW + } +#endif +} + +static void +ExtendStart(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (!ctx->text.selection_state) { + ctx->text.selection_state = True; +#endif + ModifySelection(ctx, event, + XawsmTextExtend, XawactionStart, params, num_params); +#ifndef OLDXAW + } +#endif +} + +static void +ExtendAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (ctx->text.selection_state) +#endif + ModifySelection(ctx, event, + XawsmTextExtend, XawactionAdjust, params, num_params); +} + +static void +ExtendEnd(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (ctx->text.selection_state) { + ctx->text.selection_state = False; +#endif + ModifySelection(ctx, event, + XawsmTextExtend, XawactionEnd, params, num_params); +#ifndef OLDXAW + } +#endif +} + +static void +SelectSave(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + int num_atoms; + Atom *sel; + Display *dpy = XtDisplay(w); + Atom selections[256]; + + StartAction((TextWidget)w, event); + num_atoms = *num_params; + if (num_atoms > 256) + num_atoms = 256; + for (sel=selections; --num_atoms >= 0; sel++, params++) + *sel = XInternAtom(dpy, *params, False); + num_atoms = *num_params; + _XawTextSaltAwaySelection((TextWidget)w, selections, num_atoms); + EndAction((TextWidget)w); +} + +/* + * Misc. Routines + */ +/*ARGSUSED*/ +static void +SetKeyboardFocus(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + Widget shell, parent; + + shell = parent = w; + while (parent) { + if (XtIsShell(shell = parent)) + break; + parent = XtParent(parent); + } + XtSetKeyboardFocus(shell, w); +} + +/*ARGSUSED*/ +static void +RedrawDisplay(Widget w, XEvent *event, String *p, Cardinal *n) +{ + StartAction((TextWidget)w, event); + _XawTextClearAndCenterDisplay((TextWidget)w); + EndAction((TextWidget)w); +} + +/* This is kind of a hack, but, only one text widget can have focus at + * a time on one display. There is a problem in the implementation of the + * text widget, the scrollbars can not be adressed via editres, since they + * are not children of a subclass of composite. + * The focus variable is required to make sure only one text window will + * show a block cursor at one time. + */ +struct _focus { Display *display; Widget widget; }; +static struct _focus *focus; +static Cardinal num_focus; + +/*ARGSUSED*/ +static void +DestroyFocusCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + struct _focus *f = (struct _focus*)(user_data); + + if (f->widget == w) + f->widget = NULL; +} + +/*ARGSUSED*/ +static void +TextFocusIn(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + Bool display_caret = ctx->text.display_caret; + int i; + + if (event->xfocus.detail == NotifyPointer) + return; + + if (event->xfocus.send_event) { + Window root, child; + int rootx, rooty, x, y; + unsigned int mask; + + if (ctx->text.hasfocus) + return; + + if (XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, + &rootx, &rooty, &x, &y, &mask)) { + if (child) + return; + } + } + + /* Let the input method know focus has arrived. */ + _XawImSetFocusValues(w, NULL, 0); + + if (display_caret) + StartAction(ctx, event); + ctx->text.hasfocus = TRUE; + if (display_caret) + EndAction(ctx); + + for (i = 0; i < num_focus; i++) + if (focus[i].display == XtDisplay(w)) + break; + if (i >= num_focus) { + focus = (struct _focus*) + XtRealloc((XtPointer)focus, sizeof(struct _focus) * (num_focus + 1)); + i = num_focus; + focus[i].widget = NULL; + focus[i].display = XtDisplay(w); + num_focus++; + } + if (focus[i].widget != w) { + Widget old = focus[i].widget; + + focus[i].widget = w; + if (old != NULL) { + TextFocusOut(old, event, p, n); + /* TextFocusOut may set it to NULL */ + focus[i].widget = w; + } + XtAddCallback(w, XtNdestroyCallback, + DestroyFocusCallback, (XtPointer)&focus[i]); + } +} + +/*ARGSUSED*/ +static void +TextFocusOut(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + Bool display_caret = ctx->text.display_caret; + Widget shell; + Window window; + int i, revert; + + shell = w; + while (shell) { + if (XtIsShell(shell)) + break; + shell = XtParent(shell); + } + + for (i = 0; i < num_focus; i++) + if (focus[i].display == XtDisplay(w)) + break; + XGetInputFocus(XtDisplay(w), &window, &revert); + if ((XtWindow(shell) == window && + (i < num_focus && focus[i].widget == w)) + || event->xfocus.detail == NotifyPointer) + return; + + if (i < num_focus && focus[i].widget) { + XtRemoveCallback(focus[i].widget, XtNdestroyCallback, + DestroyFocusCallback, (XtPointer)&focus[i]); + focus[i].widget = NULL; + } + + /* Let the input method know focus has left.*/ + _XawImUnsetFocus(w); + + if (display_caret) + StartAction(ctx, event); + ctx->text.hasfocus = FALSE; + if (display_caret) + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +TextEnterWindow(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + + if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus + && !ctx->text.hasfocus) + _XawImSetFocusValues(w, NULL, 0); +} + +/*ARGSUSED*/ +static void +TextLeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + + if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus + && !ctx->text.hasfocus) + _XawImUnsetFocus(w); +} + +/* + * Function: + * AutoFill + * Arguments: ctx - The text widget. + * + * Description: + * Breaks the line at the previous word boundry when + * called inside InsertChar. + */ +static void +AutoFill(TextWidget ctx) +{ + int width, height, x, line_num, max_width; + XawTextPosition ret_pos; + XawTextBlock text; + XRectangle cursor; + wchar_t wc_buf[2]; + + for (line_num = 0; line_num < ctx->text.lt.lines ; line_num++) + if (ctx->text.lt.info[line_num].position >= ctx->text.insertPos) + break; + if (line_num) + line_num--; /* backup a line. */ + + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + max_width = Max(0, (int)XtWidth(ctx) - RHMargins(ctx) - cursor.width); + + x = ctx->text.r_margin.left; + XawTextSinkFindPosition(ctx->text.sink, ctx->text.lt.info[line_num].position, + x, max_width, True, &ret_pos, + &width, &height); + + if (ret_pos <= ctx->text.lt.info[line_num].position + || ret_pos >= ctx->text.insertPos || ret_pos < 1) + return; + + XawTextSourceRead(ctx->text.source, ret_pos - 1, &text, 1); + + if (XawTextFormat(ctx, XawFmtWide)) { + wc_buf[0] = *(wchar_t *)text.ptr; + if (wc_buf[0] != _Xaw_atowc(XawSP) && wc_buf[0] != _Xaw_atowc(XawTAB)) + /* Only eats white spaces */ + return; + + text.format = XawFmtWide; + text.ptr = (char *)wc_buf; + wc_buf[0] = _Xaw_atowc(XawLF); + wc_buf[1] = 0; + } + else { + if (text.ptr[0] != XawSP && text.ptr[0] != XawTAB) + /* Only eats white spaces */ + return; + + text.format = XawFmt8Bit; + text.ptr = "\n"; + } + text.length = 1; + text.firstPos = 0; + + if (_XawTextReplace(ctx, ret_pos - 1, ret_pos, &text)) + XBell(XtDisplay((Widget)ctx), 0); + + if (++ctx->text.insertPos > ctx->text.lastPos) + ctx->text.insertPos = ctx->text.lastPos; +} + +/*ARGSUSED*/ +static void +InsertChar(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + char *ptr, strbuf[128], ptrbuf[512]; + int count, error, mult = MULT(ctx); + KeySym keysym; + XawTextBlock text; +#ifndef OLDXAW + Bool format = False; +#endif + XawTextPosition from, to; + + if (XtIsSubclass (ctx->text.source, (WidgetClass) multiSrcObjectClass)) + text.length = _XawImWcLookupString(w, &event->xkey, (wchar_t*)strbuf, + sizeof(strbuf), &keysym); + else + text.length = _XawLookupString(w, (XKeyEvent*)event, strbuf, + sizeof(strbuf), &keysym); + + if (text.length == 0) + return; + + if (mult < 0) { + ctx->text.mult = 1; + return; + } + + text.format = _XawTextFormat(ctx); + if (text.format == XawFmtWide) { + text.ptr = ptr = XawStackAlloc(sizeof(wchar_t) * text.length + * mult, ptrbuf); + for (count = 0; count < mult; count++) { + memcpy((char*)ptr, (char *)strbuf, sizeof(wchar_t) * text.length); + ptr += sizeof(wchar_t) * text.length; + } +#ifndef OLDXAW + if (mult == 1) + format = ctx->text.left_column < ctx->text.right_column; +#endif + } + else { /* == XawFmt8Bit */ + text.ptr = ptr = XawStackAlloc(text.length * mult, ptrbuf); + for (count = 0; count < mult; count++) { + strncpy(ptr, strbuf, text.length); + ptr += text.length; + } +#ifndef OLDXAW + if (mult == 1) + format = ctx->text.left_column < ctx->text.right_column; +#endif + } + + text.length = text.length * mult; + text.firstPos = 0; + + StartAction(ctx, event); +#ifndef OLDXAW + if (mult == 1) + _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True); +#endif + + from = ctx->text.insertPos; +#ifndef OLDXAW + if (ctx->text.overwrite) { + XawTextPosition tmp; + + to = from + mult; + tmp = SrcScan(ctx->text.source, from, XawstEOL, XawsdRight, 1, False); + if (to > tmp) + to = tmp; + } + else +#endif + to = from; + + error = _XawTextReplace(ctx, from , to, &text); + + if (error == XawEditDone) { + ctx->text.from_left = -1; + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert, + XawstPositions, XawsdRight, + text.length, True); + if (ctx->text.auto_fill) { +#ifndef OLDXAW + if (format) + (void)FormatText(ctx, SrcScan(ctx->text.source, + ctx->text.insertPos, XawstEOL, + XawsdLeft, 1, False), False, + NULL, 0); + else +#endif + AutoFill(ctx); + } + } + else + XBell(XtDisplay(ctx), 50); + + XawStackFree(text.ptr, ptrbuf); + EndAction(ctx); + + if (error == XawEditDone && text.format == XawFmt8Bit && text.length == 1 + && (text.ptr[0] == ')' || text.ptr[0] == ']' || text.ptr[0] == '}') + && ctx->text.display_caret) { + static struct timeval tmval = {0, 500000}; + fd_set fds; + Widget source = ctx->text.source; + XawTextPosition insertPos = ctx->text.insertPos, pos, tmp, last; + char left, right = text.ptr[0]; + int level = 0; + XtAppContext app_context = XtWidgetToApplicationContext(w); + + left = right == ')' ? '(' : right == ']' ? '[' : '{'; + + last = insertPos - 1; + do { + text.ptr[0] = left; + pos = XawTextSourceSearch(source, last, XawsdLeft, &text); + if (pos == XawTextSearchError || !IsPositionVisible(ctx, pos)) + return; + text.ptr[0] = right; + tmp = pos; + do { + tmp = XawTextSourceSearch(source, tmp, XawsdRight, &text); + if (tmp == XawTextSearchError) + return; + if (tmp <= last) + ++level; + } while (++tmp <= last); + --level; + last = pos; + } while (level); + + StartAction(ctx, NULL); +#ifndef OLDXAW + _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True); +#endif + ctx->text.insertPos = pos; + EndAction(ctx); + + XSync(XtDisplay(w), False); + while (XtAppPending(app_context) & XtIMXEvent) { + XEvent ev; + if (! XtAppPeekEvent(app_context, &ev)) + break; + if (ev.type == KeyPress || ev.type == ButtonPress) + break; + XtAppProcessEvent(app_context, XtIMXEvent); + } + FD_ZERO(&fds); + FD_SET(ConnectionNumber(XtDisplay(w)), &fds); + (void)select(FD_SETSIZE, &fds, NULL, NULL, &tmval); + if (tmval.tv_usec != 500000) + usleep(40000); + + StartAction(ctx, NULL); +#ifndef OLDXAW + _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True); +#endif + ctx->text.insertPos = insertPos; + EndAction(ctx); + } +} + +/* IfHexConvertHexElseReturnParam() - called by InsertString + * + * i18n requires the ability to specify multiple characters in a hexa- + * decimal string at once. Since Insert was already too long, I made + * this a seperate routine. + * + * A legal hex string in MBNF: '0' 'x' ( HEX-DIGIT HEX-DIGIT )+ '\0' + * + * WHEN: the passed param is a legal hex string + * RETURNS: a pointer to that converted, null terminated hex string; + * len_return holds the character count of conversion result + * + * WHEN: the passed param is not a legal hex string: + * RETURNS: the parameter passed; + * len_return holds the char count of param. + * + * NOTE: In neither case will there be strings to free. */ +static char * +IfHexConvertHexElseReturnParam(char *param, int *len_return) +{ + char *p; /* steps through param char by char */ + char c; /* holds the character pointed to by p */ + int ind; /* steps through hexval buffer char by char */ + static char hexval[XawTextActionMaxHexChars]; + Boolean first_digit; + + /* reject if it doesn't begin with 0x and at least one more character. */ + if ((param[0] != '0') || (param[1] != 'x') || (param[2] == '\0')) { + *len_return = strlen(param); + return(param); + } + + /* Skip the 0x; go character by character shifting and adding. */ + first_digit = True; + ind = 0; + hexval[ind] = '\0'; + + for (p = param+2; (c = *p) != '\0'; p++) { + hexval[ind] *= 16; + if (c >= '0' && c <= '9') + hexval[ind] += c - '0'; + else if (c >= 'a' && c <= 'f') + hexval[ind] += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + hexval[ind] += c - 'A' + 10; + else + break; + + /* If we didn't break in preceding line, it was a good hex char. */ + if (first_digit) + first_digit = False; + else { + first_digit = True; + if (++ind < XawTextActionMaxHexChars) + hexval[ind] = '\0'; + else { + *len_return = strlen(param); + return(param); + } + } + } + + /* We quit the above loop becasue we hit a non hex. If that char is \0... */ + if ((c == '\0') && first_digit) { + *len_return = strlen(hexval); + return (hexval); /* ...it was a legal hex string, so return it */ + } + + /* Else, there were non-hex chars or odd digit count, so... */ + + *len_return = strlen(param); + return (param); /* ...return the verbatim string. */ +} + +/* InsertString() - action + * + * Mostly rewritten for R6 i18n. + * + * Each parameter, in turn, will be insert at the inputPos + * and the inputPos advances to the insertion's end. + * + * The exception is that parameters composed of the two + * characters 0x, followed only by an even number of + * hexadecimal digits will be converted to characters */ +/*ARGSUSED*/ +static void +InsertString(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + XtAppContext app_con = XtWidgetToApplicationContext(w); + XawTextBlock text; + int i; + + text.firstPos = 0; + text.format = _XawTextFormat(ctx); + + StartAction(ctx, event); + for (i = *num_params; i; i--, params++) { /* DO FOR EACH PARAMETER */ + text.ptr = IfHexConvertHexElseReturnParam(*params, &text.length); + + if (text.length == 0) + continue; + + if (XawTextFormat(ctx, XawFmtWide)) { /* convert to WC */ + int temp_len; + + text.ptr = (char*)_XawTextMBToWC(XtDisplay(w), text.ptr, + &text.length); + + if (text.ptr == NULL) { /* conversion error */ + XtAppWarningMsg(app_con, + "insertString", "textAction", "XawError", + "insert-string()'s parameter contents " + "not legal in this locale.", + NULL, NULL); + ParameterError(w, *params); + continue; + } + + /* Double check that the new input is legal: try to convert to MB. */ + + temp_len = text.length; /* _XawTextWCToMB's 3rd arg is in_out */ + if (_XawTextWCToMB(XtDisplay(w), (wchar_t*)text.ptr, &temp_len) + == NULL) { + XtAppWarningMsg( app_con, + "insertString", "textAction", "XawError", + "insert-string()'s parameter contents " + "not legal in this locale.", + NULL, NULL); + ParameterError(w, *params); + continue; + } + } /* convert to WC */ + + if (_XawTextReplace(ctx, ctx->text.insertPos, + ctx->text.insertPos, &text)) { + XBell(XtDisplay(ctx), 50); + EndAction(ctx); + return; + } + + ctx->text.from_left = -1; + /* Advance insertPos to the end of the string we just inserted. */ + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert, + XawstPositions, XawsdRight, text.length, + True); + + } /* DO FOR EACH PARAMETER */ + + EndAction(ctx); +} + +/* DisplayCaret() - action + * + * The parameter list should contain one boolean value. If the + * argument is true, the cursor will be displayed. If false, not. + * + * The exception is that EnterNotify and LeaveNotify events may + * have a second argument, "always". If they do not, the cursor + * is only affected if the focus member of the event is true. */ +static void +DisplayCaret(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + Bool display_caret = True; + + if ((event->type == EnterNotify || event->type == LeaveNotify) + && ((*num_params >= 2) && (strcmp(params[1], "always") == 0)) + && (!event->xcrossing.focus)) + return; + + if (*num_params > 0) { /* default arg is "True" */ + XrmValue from, to; + from.size = strlen(from.addr = params[0]); + XtConvert(w, XtRString, &from, XtRBoolean, &to); + + if (to.addr != NULL) + display_caret = *(Boolean*)to.addr; + if (ctx->text.display_caret == display_caret) + return; + } + StartAction(ctx, event); + ctx->text.display_caret = display_caret; + EndAction(ctx); +} + +#ifndef OLDXAW +static void +Numeric(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + + if (ctx->text.numeric) { + long mult = ctx->text.mult; + + if (*num_params != 1 || strlen(params[0]) != 1 + || (!isdigit(params[0][0]) + && (params[0][0] != '-' || mult != 0))) { + char err_buf[256]; + + if (event && (event->type == KeyPress || event->type == KeyRelease) + && params[0][0] == '-') { + InsertChar(w, event, params, num_params); + return; + } + XmuSnprintf(err_buf, sizeof(err_buf), + "numeric: Invalid argument%s'%s'", + *num_params ? ", " : "", *num_params ? params[0] : ""); + XtAppWarning(XtWidgetToApplicationContext(w), err_buf); + ctx->text.numeric = False; + ctx->text.mult = 1; + return; + } + if (params[0][0] == '-') { + ctx->text.mult = 32767; + return; + } + else if (mult == 32767) { + mult = ctx->text.mult = - (params[0][0] - '0'); + return; + } + else { + mult = mult * 10 + (params[0][0] - '0') * (mult < 0 ? -1 : 1); + ctx->text.mult = ctx->text.mult * 10 + (params[0][0] - '0') * + (mult < 0 ? -1 : 1); + } + if (mult != ctx->text.mult || mult >= 32767) { /* checks for overflow */ + XBell(XtDisplay(w), 0); + ctx->text.mult = 1; + ctx->text.numeric = False; + return; + } + } + else + InsertChar(w, event, params, num_params); +} + +/*ARGSUSED*/ +static void +KeyboardReset(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + + ctx->text.numeric = False; + ctx->text.mult = 1; + + (void)_XawTextSrcToggleUndo((TextSrcObject)ctx->text.source); + + if (ctx->text.kill_ring_ptr) { + --ctx->text.kill_ring_ptr->refcount; + ctx->text.kill_ring_ptr = NULL; + } + ctx->text.kill_ring = 0; + + XBell(XtDisplay(w), 0); +} +#endif /* OLDXAW */ + +/* Multiply() - action + * + * The parameter list may contain either a number or the string 'Reset'. + * + * A number will multiply the current multiplication factor by that number. + * Many of the text widget actions will will perform n actions, where n is + * the multiplication factor. + * + * The string reset will reset the mutiplication factor to 1. */ +/*ARGSUSED*/ +static void +Multiply(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + int mult; + + if (*num_params != 1) { + XtAppError(XtWidgetToApplicationContext(w), + "Xaw Text Widget: multiply() takes exactly one argument."); + XBell(XtDisplay(w), 0); + return; + } + + if ((params[0][0] == 'r') || (params[0][0] == 'R')) { + XBell(XtDisplay(w), 0); +#ifndef OLDXAW + ctx->text.numeric = False; +#endif + ctx->text.mult = 1; + return; + } + +#ifndef OLDXAW + if (params[0][0] == 's' || params[0][0] == 'S') { + ctx->text.numeric = True; + ctx->text.mult = 0; + return; + } + else +#endif + if ((mult = atoi(params[0])) == 0) { + char buf[BUFSIZ]; + + XmuSnprintf(buf, sizeof(buf), + "%s %s", "Xaw Text Widget: multiply() argument", + "must be a number greater than zero, or 'Reset'."); + XtAppError(XtWidgetToApplicationContext(w), buf); + XBell(XtDisplay(w), 50); + return; + } + + ctx->text.mult *= mult; +} + +/* StripOutOldCRs() - called from FormRegion + * + * removes CRs in widget ctx, from from to to. + * + * RETURNS: the new ending location (we may add some characters), + * or XawReplaceError if the widget can't be written to. */ +static XawTextPosition +StripOutOldCRs(TextWidget ctx, XawTextPosition from, XawTextPosition to, + XawTextPosition *pos, int num_pos) +{ + XawTextPosition startPos, endPos, eop_begin, eop_end, temp; + Widget src = ctx->text.source; + XawTextBlock text; + char *buf; + static wchar_t wc_two_spaces[3]; + int idx; + + /* Initialize our TextBlock with two spaces. */ + text.firstPos = 0; + text.format = _XawTextFormat(ctx); + if (text.format == XawFmt8Bit) + text.ptr= " "; + else { + wc_two_spaces[0] = _Xaw_atowc(XawSP); + wc_two_spaces[1] = _Xaw_atowc(XawSP); + wc_two_spaces[2] = 0; + text.ptr = (char*)wc_two_spaces; + } + + /* Strip out CR's. */ + eop_begin = eop_end = startPos = endPos = from; + + /* CONSTCOND */ + while (TRUE) { + endPos=SrcScan(src, startPos, XawstEOL, XawsdRight, 1, False); + + temp = SrcScan(src, endPos, XawstWhiteSpace, XawsdLeft, 1, False); + temp = SrcScan(src, temp, XawstWhiteSpace, XawsdRight,1, False); + + if (temp > startPos) + endPos = temp; + + if (endPos >= to) + break; + + if (endPos >= eop_begin) { + startPos = eop_end; + eop_begin=SrcScan(src, startPos, XawstParagraph, + XawsdRight, 1,False); + eop_end = SrcScan(src, startPos, XawstParagraph, + XawsdRight, 1, True); + } + else { + XawTextPosition periodPos, next_word; + int i, len; + + periodPos = SrcScan(src, endPos, XawstPositions, + XawsdLeft, 1, True); + next_word = SrcScan(src, endPos, XawstWhiteSpace, + XawsdRight, 1, False); + + len = next_word - periodPos; + + text.length = 1; + buf = _XawTextGetText(ctx, periodPos, next_word); + if (text.format == XawFmtWide) { + if (periodPos < endPos && ((wchar_t*)buf)[0] == _Xaw_atowc('.')) + text.length++; + } + else + if (periodPos < endPos && buf[0] == '.') + text.length++; /* Put in two spaces. */ + + /* + * Remove all extra spaces. + */ + for (i = 1 ; i < len; i++) + if (text.format == XawFmtWide) { + if (!iswspace(((wchar_t*)buf)[i]) || ((periodPos + i) >= to)) + break; + } + else if (!isspace(buf[i]) || (periodPos + i) >= to) + break; + + XtFree(buf); + + to -= (i - text.length - 1); + startPos = SrcScan(src, periodPos, XawstPositions, + XawsdRight, i, True); + if (_XawTextReplace(ctx, endPos, startPos, &text) != XawEditDone) + return (XawReplaceError); + + for (idx = 0; idx < num_pos; idx++) { + if (endPos < pos[idx]) { + if (startPos < pos[idx]) + pos[idx] -= startPos - endPos; + else + pos[idx] = endPos; + pos[idx] += text.length; + } + } + + startPos -= i - text.length; + } + } + + return (to); +} + +/* InsertNewCRs() - called from FormRegion + * + * inserts new CRs for FormRegion, thus for FormParagraph action */ +static void +InsertNewCRs(TextWidget ctx, XawTextPosition from, XawTextPosition to, + XawTextPosition *pos, int num_pos) +{ + XawTextPosition startPos, endPos, space, eol; + XawTextBlock text; + int i, width, height, len, wwidth, idx; + char *buf; + static wchar_t wide_CR[2]; + + text.firstPos = 0; + text.length = 1; + text.format = _XawTextFormat(ctx); + + if (text.format == XawFmt8Bit) + text.ptr = "\n"; + else { + wide_CR[0] = _Xaw_atowc(XawLF); + wide_CR[1] = 0; + text.ptr = (char*)wide_CR; + } + + startPos = from; + + wwidth = (int)XtWidth(ctx) - (int)HMargins(ctx); + if (ctx->text.wrap != XawtextWrapNever) { + XRectangle cursor; + + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + wwidth -= (int)cursor.width; + } + wwidth = XawMax(0, wwidth); + + /* CONSTCOND */ + while (TRUE) { + XawTextSinkFindPosition(ctx->text.sink, startPos, + (int)ctx->text.r_margin.left, wwidth, + True, &eol, &width, &height); + if (eol == startPos) + ++eol; + if (eol >= to) + break; + + eol = SrcScan(ctx->text.source, eol, XawstPositions, + XawsdLeft, 1, True); + space = SrcScan(ctx->text.source, eol, XawstWhiteSpace, + XawsdRight,1, True); + + startPos = endPos = eol; + if (eol == space) + return; + + len = (int)(space - eol); + buf = _XawTextGetText(ctx, eol, space); + for (i = 0 ; i < len ; i++) + if (text.format == XawFmtWide) { + if (!iswspace(((wchar_t*)buf)[i])) + break; + } + else if (!isspace(buf[i])) + break; + + to -= (i - 1); + endPos = SrcScan(ctx->text.source, endPos, + XawstPositions, XawsdRight, i, True); + XtFree(buf); + + if (_XawTextReplace(ctx, startPos, endPos, &text)) + return; + + for (idx = 0; idx < num_pos; idx++) { + if (startPos < pos[idx]) { + if (endPos < pos[idx]) + pos[idx] -= endPos - startPos; + else + pos[idx] = startPos; + pos[idx] += text.length; + } + } + + startPos = SrcScan(ctx->text.source, startPos, + XawstPositions, XawsdRight, 1, True); + } +} + +/* FormRegion() - called by FormParagraph + * + * oversees the work of paragraph-forming a region + * + * Return: + * XawEditDone if successful, or XawReplaceError + */ +static int +FormRegion(TextWidget ctx, XawTextPosition from, XawTextPosition to, + XawTextPosition *pos, int num_pos) +{ +#ifndef OLDXAW + Bool format = ctx->text.auto_fill + && ctx->text.left_column < ctx->text.right_column; +#endif + + if (from >= to) + return (XawEditDone); + +#ifndef OLDXAW + if (format) { + XawTextPosition len = ctx->text.lastPos; + int inc = 0; + + if (ctx->text.justify == XawjustifyLeft || + ctx->text.justify == XawjustifyFull) { + Untabify(ctx, from, to, pos, num_pos, NULL); + to += ctx->text.lastPos - len; + len = ctx->text.insertPos; + (void)BlankLine((Widget)ctx, from, &inc); + if (from + inc >= to) + return (XawEditDone); + } + if (!StripSpaces(ctx, from + inc, to, pos, num_pos, NULL)) + return (XawReplaceError); + to += ctx->text.lastPos - len; + + FormatText(ctx, from, ctx->text.justify != XawjustifyFull, pos, num_pos); + } + else { +#endif + if ((to = StripOutOldCRs(ctx, from, to, pos, num_pos)) == XawReplaceError) + return (XawReplaceError); + InsertNewCRs(ctx, from, to, pos, num_pos); +#ifndef OLDXAW + } +#endif + ctx->text.from_left = -1; + + return (XawEditDone); +} + +#ifndef OLDXAW +static Bool +BlankLine(Widget w, XawTextPosition pos, int *blanks_return) +{ + int i, blanks = 0; + XawTextBlock block; + Widget src = XawTextGetSource(w); + XawTextPosition l = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False); + XawTextPosition r = SrcScan(src, pos, XawstEOL, XawsdRight, 1, False); + + while (l < r) { + l = XawTextSourceRead(src, l, &block, r - l); + if (block.length == 0) { + if (blanks_return) + *blanks_return = blanks; + return (True); + } + if (XawTextFormat((TextWidget)w, XawFmt8Bit)) { + for (i = 0; i < block.length; i++, blanks++) + if (block.ptr[i] != ' ' && + block.ptr[i] != '\t') { + if (blanks_return) + *blanks_return = blanks; + return (block.ptr[i] == '\n'); + } + } + else if (XawTextFormat((TextWidget)w, XawFmtWide)) { + for (i = 0; i < block.length; i++, blanks++) + if (_Xaw_atowc(XawSP) != ((wchar_t*)block.ptr)[i] && + _Xaw_atowc(XawTAB) != ((wchar_t*)block.ptr)[i]) { + if (blanks_return) + *blanks_return = blanks; + return (_Xaw_atowc(XawLF) == ((wchar_t*)block.ptr)[i]); + } + } + } + + return (True); +} + +static Bool +GetBlockBoundaries(TextWidget ctx, + XawTextPosition *from_return, XawTextPosition *to_return) +{ + XawTextPosition from, to; + + if (ctx->text.auto_fill && ctx->text.left_column < ctx->text.right_column) { + if (ctx->text.s.left != ctx->text.s.right) { + from = SrcScan(ctx->text.source, + XawMin(ctx->text.s.left, ctx->text.s.right), + XawstEOL, XawsdLeft, 1, False); + to = SrcScan(ctx->text.source, + XawMax(ctx->text.s.right, ctx->text.s.right), + XawstEOL, XawsdRight, 1, False); + } + else { + XawTextBlock block; + XawTextPosition tmp; + Bool first; + + from = to = ctx->text.insertPos; + + /* find from position */ + first = True; + while (1) { + tmp = from; + from = SrcScan(ctx->text.source, from, XawstEOL, XawsdLeft, + 1 + !first, False); + XawTextSourceRead(ctx->text.source, from, &block, 1); + if (block.length == 0 || + (XawTextFormat(ctx, XawFmt8Bit) && + block.ptr[0] != ' ' && + block.ptr[0] != '\t' && + !isalnum(*(unsigned char*)block.ptr)) || + (XawTextFormat(ctx, XawFmtWide) && + _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr && + _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr && + !iswalnum(*(wchar_t*)block.ptr)) || + BlankLine((Widget)ctx, from, NULL)) { + from = tmp; + break; + } + if (from == tmp && !first) + break; + first = False; + } + if (first) + return (False); + + /* find to position */ + first = True; + while (1) { + tmp = to; + to = SrcScan(ctx->text.source, to, XawstEOL, XawsdRight, + 1 + !first, False); + XawTextSourceRead(ctx->text.source, to + (to < ctx->text.lastPos), + &block, 1); + if (block.length == 0 || + (XawTextFormat(ctx, XawFmt8Bit) && + block.ptr[0] != ' ' && + block.ptr[0] != '\t' && + !isalnum(*(unsigned char*)block.ptr)) || + (XawTextFormat(ctx, XawFmtWide) && + _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr && + _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr && + !iswalnum(*(wchar_t*)block.ptr)) || + BlankLine((Widget)ctx, to, NULL)) + break; + if (to == tmp && !first) + break; + first = False; + } + } + } + else { + from = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, + XawsdLeft, 1, False); + if (BlankLine((Widget)ctx, from, NULL)) + return (False); + from = SrcScan(ctx->text.source, from, XawstParagraph, + XawsdLeft, 1, False); + if (BlankLine((Widget)ctx, from, NULL)) + from = SrcScan(ctx->text.source, from, XawstEOL, + XawsdRight, 1, True); + to = SrcScan(ctx->text.source, from, XawstParagraph, + XawsdRight, 1, False); + } + + if (from < to) { + *from_return = from; + *to_return = to; + return (True); + } + + return (False); +} +#endif /* OLDXAW */ + +/* FormParagraph() - action + * + * removes and reinserts CRs to maximize line length without clipping */ +/*ARGSUSED*/ +static void +FormParagraph(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition from, to, buf[32], *pos; +#ifndef OLDXAW + XawTextPosition endPos = 0; + char *lbuf = NULL, *rbuf; + TextSrcObject src = (TextSrcObject)ctx->text.source; + Cardinal i; + Bool undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; +#endif + + StartAction(ctx, event); + +#ifndef OLDXAW + pos = XawStackAlloc(sizeof(XawTextPosition) * src->textSrc.num_text, buf); + for (i = 0; i < src->textSrc.num_text; i++) + pos[i] = ((TextWidget)src->textSrc.text[i])->text.old_insert; +#else + pos = buf; + *pos = ctx->text.old_insert; +#endif + +#ifndef OLDXAW + if (!GetBlockBoundaries(ctx, &from, &to)) { + EndAction(ctx); + XawStackFree(pos, buf); + return; + } + + if (undo) { + src->textSrc.undo_state = True; + lbuf = _XawTextGetText(ctx, from, to); + endPos = ctx->text.lastPos; + } + + if (FormRegion(ctx, from, to, pos, src->textSrc.num_text) == XawReplaceError) { +#else + from = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstParagraph, XawsdLeft, 1, False); + to = SrcScan(ctx->text.source, from, + XawstParagraph, XawsdRight, 1, False); + + if (FormRegion(ctx, from, to, pos, 1) == XawReplaceError) { +#endif + XawStackFree(pos, buf); + XBell(XtDisplay(w), 0); +#ifndef OLDXAW + if (undo) { + src->textSrc.undo_state = False; + XtFree(lbuf); + } +#endif + } +#ifndef OLDXAW + else if (undo) { + /* makes the form-paragraph only one undo/redo step */ + unsigned llen, rlen, size; + XawTextBlock block; + + llen = to - from; + rlen = llen + (ctx->text.lastPos - endPos); + + block.firstPos = 0; + block.format = _XawTextFormat(ctx); + + rbuf = _XawTextGetText(ctx, from, from + rlen); + + size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char); + if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) { + block.ptr = lbuf; + block.length = llen; + _XawTextReplace(ctx, from, from + rlen, &block); + + src->textSrc.undo_state = False; + block.ptr = rbuf; + block.length = rlen; + _XawTextReplace(ctx, from, from + llen, &block); + } + else + src->textSrc.undo_state = False; + XtFree(lbuf); + XtFree(rbuf); + } + + for (i = 0; i < src->textSrc.num_text; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + + tw->text.old_insert = tw->text.insertPos = pos[i]; + _XawTextBuildLineTable(tw, SrcScan((Widget)src, tw->text.lt.top, XawstEOL, + XawsdLeft, 1, False), False); + tw->text.clear_to_eol = True; + } +#else + ctx->text.old_insert = ctx->text.insertPos = *pos; + _XawTextBuildLineTable(ctx, SrcScan(ctx->text.source, ctx->text.lt.top, + XawstEOL, XawsdLeft, 1, False), False); + ctx->text.clear_to_eol = True; +#endif + XawStackFree(pos, buf); + ctx->text.showposition = True; + + EndAction(ctx); +} + +/* TransposeCharacters() - action + * + * Swaps the character to the left of the mark + * with the character to the right of the mark */ +/*ARGSUSED*/ +static void +TransposeCharacters(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition start, end; + XawTextBlock text; + char *buf; + int i, mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = 1; + return; + } + + StartAction(ctx, event); + + /* Get bounds. */ + + start = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, + XawsdLeft, 1, True); + end = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, + XawsdRight, mult, True); + + /* Make sure we aren't at the very beginning or end of the buffer. */ + + if (start == ctx->text.insertPos || end == ctx->text.insertPos) { + XBell(XtDisplay(w), 0); /* complain. */ + EndAction(ctx); + return; + } + + ctx->text.from_left = -1; + ctx->text.insertPos = end; + + text.firstPos = 0; + text.format = _XawTextFormat(ctx); + + /* Retrieve text and swap the characters. */ + if (text.format == XawFmtWide) { + wchar_t wc; + wchar_t *wbuf; + + wbuf = (wchar_t*)_XawTextGetText(ctx, start, end); + text.length = wcslen(wbuf); + wc = wbuf[0]; + for (i = 1; i < text.length; i++) + wbuf[i - 1] = wbuf[i]; + wbuf[i - 1] = wc; + buf = (char*)wbuf; /* so that it gets assigned and freed */ + } + else { /* thus text.format == XawFmt8Bit */ + char c; + + buf = _XawTextGetText(ctx, start, end); + text.length = strlen(buf); + c = buf[0]; + for (i = 1; i < text.length; i++) + buf[i - 1] = buf[i]; + buf[i - 1] = c; + } + + text.ptr = buf; + + /* Store new text in source. */ + + if (_XawTextReplace (ctx, start, end, &text)) + XBell(XtDisplay(w), 0); + XtFree((char *)buf); + EndAction(ctx); +} + +#ifndef OLDXAW +/*ARGSUSED*/ +static void +Undo(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + int mul = MULT(ctx); + Bool toggle = False; + + if (mul < 0) { + toggle = True; + _XawTextSrcToggleUndo((TextSrcObject)ctx->text.source); + ctx->text.mult = mul = -mul; + } + + StartAction(ctx, event); + for (; mul; --mul) + if (!_XawTextSrcUndo((TextSrcObject)ctx->text.source, &ctx->text.insertPos)) + break; + ctx->text.showposition = True; + + if (toggle) + _XawTextSrcToggleUndo((TextSrcObject)ctx->text.source); + EndAction(ctx); +} +#endif + +/* NoOp() - action + * This action performs no action, and allows the user or + * application programmer to unbind a translation. + * + * Note: If the parameter list contains the string "RingBell" then + * this action will ring the bell. + */ +/*ARGSUSED*/ +static void +NoOp(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + if (*num_params != 1) + return; + + switch(params[0][0]) { + case 'R': + case 'r': + XBell(XtDisplay(w), 0); + /*FALLTROUGH*/ + default: + break; + } +} + +/* Reconnect() - action + * This reconnects to the input method. The user will typically call + * this action if/when connection has been severed, or when the app + * was started up before an IM was started up + */ +/*ARGSUSED*/ +static void +Reconnect(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + _XawImReconnect(w); +} + +#define CAPITALIZE 1 +#define DOWNCASE 2 +#define UPCASE 3 + +#ifdef NO_LIBC_I18N +static int +ToLower(int ch) +{ + char buf[2]; + + *buf = ch; + XmuNCopyISOLatin1Lowered(buf, buf, sizeof(buf)); + + return (*buf); +} + +static int +ToUpper(int ch) +{ + char buf[2]; + + *buf = ch; + XmuNCopyISOLatin1Uppered(buf, buf, sizeof(buf)); + + return (*buf); +} + +static int +IsAlnum(int ch) +{ + return ((ch >= '0' && ch <= '9') || ToUpper(ch) != ch || ToLower(ch) != ch); +} + +static int +IsLower(int ch) +{ + char upbuf[2]; + char lobuf[2]; + + *upbuf = *lobuf = ch; + XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf)); + XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf)); + + return (*lobuf != *upbuf && ch == *lobuf); +} + +static int +IsUpper(int ch) +{ + char upbuf[2]; + char lobuf[2]; + + *upbuf = *lobuf = ch; + XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf)); + XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf)); + + return (*lobuf != *upbuf && ch == *upbuf); +} +#else +#define ToLower tolower +#define ToUpper toupper +#define IsAlnum isalnum +#define IsLower islower +#define IsUpper isupper +#endif + +static void +CaseProc(Widget w, XEvent *event, int cmd) +{ + TextWidget ctx = (TextWidget)w; + short mul = MULT(ctx); + XawTextPosition left, right; + XawTextBlock block; + Bool changed = False; + unsigned char ch, mb[sizeof(wchar_t)]; + int i, count; + + if (mul > 0) + right = SrcScan(ctx->text.source, left = ctx->text.insertPos, + XawstAlphaNumeric, XawsdRight, mul, False); + else + left = SrcScan(ctx->text.source, right = ctx->text.insertPos, + XawstAlphaNumeric, XawsdLeft, 1 + -mul, False); + block.firstPos = 0; + block.format = _XawTextFormat(ctx); + block.length = right - left; + block.ptr = _XawTextGetText(ctx, left, right); + + count = 0; + if (block.format == XawFmt8Bit) + for (i = 0; i < block.length; i++) { + if (!IsAlnum(*mb = (unsigned char)block.ptr[i])) + count = 0; + else if (++count == 1 || cmd != CAPITALIZE) { + ch = cmd == DOWNCASE ? ToLower(*mb) : ToUpper(*mb); + if (ch != *mb) { + changed = True; + block.ptr[i] = ch; + } + } + else if (cmd == CAPITALIZE) { + if ((ch = ToLower(*mb)) != *mb) { + changed = True; + block.ptr[i] = ch; + } + } + } + else + for (i = 0; i < block.length; i++) { + wctomb((char*)mb, ((wchar_t*)block.ptr)[i]); + if (!IsAlnum(*mb)) + count = 0; + else if (++count == 1 || cmd != CAPITALIZE) { + ch = cmd == DOWNCASE ? ToLower(*mb) : ToUpper(*mb); + if (ch != *mb) { + changed = True; + ((wchar_t*)block.ptr)[i] = _Xaw_atowc(ch); + } + } + else if (cmd == CAPITALIZE) { + if ((ch = ToLower(*mb)) != *mb) { + changed = True; + ((wchar_t*)block.ptr)[i] = _Xaw_atowc(ch); + } + } + } + + StartAction(ctx, event); + if (changed && _XawTextReplace(ctx, left, right, &block) != XawEditDone) + XBell(XtDisplay(ctx), 0); + ctx->text.insertPos = right; + EndAction(ctx); + + XtFree(block.ptr); +} + +/*ARGSUSED*/ +static void +CapitalizeWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CaseProc(w, event, CAPITALIZE); +} + +/*ARGSUSED*/ +static void +DowncaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CaseProc(w, event, DOWNCASE); +} + +/*ARGSUSED*/ +static void +UpcaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CaseProc(w, event, UPCASE); +} +#undef CAPITALIZE +#undef DOWNCASE +#undef UPCASE + +XtActionsRec _XawTextActionsTable[] = { + /* motion */ + {"forward-character", MoveForwardChar}, + {"backward-character", MoveBackwardChar}, + {"forward-word", MoveForwardWord}, + {"backward-word", MoveBackwardWord}, + {"forward-paragraph", MoveForwardParagraph}, + {"backward-paragraph", MoveBackwardParagraph}, + {"beginning-of-line", MoveToLineStart}, + {"end-of-line", MoveToLineEnd}, + {"next-line", MoveNextLine}, + {"previous-line", MovePreviousLine}, + {"next-page", MoveNextPage}, + {"previous-page", MovePreviousPage}, + {"beginning-of-file", MoveBeginningOfFile}, + {"end-of-file", MoveEndOfFile}, + {"scroll-one-line-up", ScrollOneLineUp}, + {"scroll-one-line-down", ScrollOneLineDown}, + + /* delete */ + {"delete-next-character", DeleteForwardChar}, + {"delete-previous-character", DeleteBackwardChar}, + {"delete-next-word", DeleteForwardWord}, + {"delete-previous-word", DeleteBackwardWord}, + {"delete-selection", DeleteCurrentSelection}, + {"delete", Delete}, + + /* kill */ + {"kill-word", KillForwardWord}, + {"backward-kill-word", KillBackwardWord}, + {"kill-selection", KillCurrentSelection}, + {"kill-to-end-of-line", KillToEndOfLine}, + {"kill-to-end-of-paragraph", KillToEndOfParagraph}, + + /* new line */ + {"newline-and-indent", InsertNewLineAndIndent}, + {"newline-and-backup", InsertNewLineAndBackup}, + {"newline", InsertNewLine}, + + /* selection */ + {"select-word", SelectWord}, + {"select-all", SelectAll}, + {"select-start", SelectStart}, + {"select-adjust", SelectAdjust}, + {"select-end", SelectEnd}, + {"select-save", SelectSave}, + {"extend-start", ExtendStart}, + {"extend-adjust", ExtendAdjust}, + {"extend-end", ExtendEnd}, + {"insert-selection", InsertSelection}, + + /* miscellaneous */ + {"redraw-display", RedrawDisplay}, + {"insert-file", _XawTextInsertFile}, + {"search", _XawTextSearch}, + {"insert-char", InsertChar}, + {"insert-string", InsertString}, + {"focus-in", TextFocusIn}, + {"focus-out", TextFocusOut}, + {"enter-window", TextEnterWindow}, + {"leave-window", TextLeaveWindow}, + {"display-caret", DisplayCaret}, + {"multiply", Multiply}, + {"form-paragraph", FormParagraph}, + {"transpose-characters", TransposeCharacters}, + {"set-keyboard-focus", SetKeyboardFocus}, +#ifndef OLDXAW + {"numeric", Numeric}, + {"undo", Undo}, + {"keyboard-reset", KeyboardReset}, + {"kill-ring-yank", KillRingYank}, + {"toggle-overwrite", ToggleOverwrite}, + {"indent", Indent}, +#endif + {"no-op", NoOp}, + + /* case transformations */ + {"capitalize-word", CapitalizeWord}, + {"downcase-word", DowncaseWord}, + {"upcase-word", UpcaseWord}, + + /* action to bind translations for text dialogs */ + {"InsertFileAction", _XawTextInsertFileAction}, + {"DoSearchAction", _XawTextDoSearchAction}, + {"DoReplaceAction", _XawTextDoReplaceAction}, + {"SetField", _XawTextSetField}, + {"PopdownSearchAction", _XawTextPopdownSearchAction}, + + /* reconnect to Input Method */ + {"reconnect-im", Reconnect} /* Li Yuhong, Omron KK, 1991 */ +}; + +Cardinal _XawTextActionsTableCount = XtNumber(_XawTextActionsTable); diff --git a/libXaw/src/TextPop.c b/libXaw/src/TextPop.c index b96752aa0..4775c25d0 100644 --- a/libXaw/src/TextPop.c +++ b/libXaw/src/TextPop.c @@ -1,1550 +1,1550 @@ -/*
-
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-/*
- * This file is broken up into three sections one dealing with
- * each of the three popups created here:
- *
- * FileInsert, Search, and Replace.
- *
- * There is also a section at the end for utility functions
- * used by all more than one of these dialogs.
- *
- * The following functions are the only non-static ones defined
- * in this module. They are located at the begining of the
- * section that contains this dialog box that uses them.
- *
- * void _XawTextInsertFileAction(w, event, params, num_params);
- * void _XawTextDoSearchAction(w, event, params, num_params);
- * void _XawTextDoReplaceAction(w, event, params, num_params);
- * void _XawTextInsertFile(w, event, params, num_params);
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <errno.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Shell.h>
-#include <X11/Xos.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/TextP.h>
-#include <X11/Xaw/AsciiText.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/Command.h>
-#include <X11/Xaw/Form.h>
-#include <X11/Xaw/Toggle.h>
-#include "XawI18n.h"
-
-static char* INSERT_FILE = "Enter Filename:";
-static char* SEARCH_LABEL_1 = "Use <Tab> to change fields.";
-static char* SEARCH_LABEL_2 = "Use ^q<Tab> for <Tab>.";
-static char* DISMISS_NAME = "cancel";
-#define DISMISS_NAME_LEN 6
-static char* FORM_NAME = "form";
-static char* LABEL_NAME = "label";
-static char* TEXT_NAME = "text";
-
-#define R_OFFSET 1
-
-typedef void (*AddFunc)(Widget, char*, Widget);
-
-/*
- * Prototypes
- */
-static void _SetField(Widget, Widget);
-static void AddSearchChildren(Widget, char*, Widget);
-static void AddInsertFileChildren(Widget, char*, Widget);
-static void CenterWidgetOnPoint(Widget, XEvent*);
-static Widget CreateDialog(Widget, String, String, AddFunc);
-static void DoInsert(Widget, XtPointer, XtPointer);
-static void DoReplaceAll(Widget, XtPointer, XtPointer);
-static void DoReplaceOne(Widget, XtPointer, XtPointer);
-static Bool DoSearch(struct SearchAndReplace*);
-static Widget GetShell(Widget);
-static String GetString(Widget);
-static String GetStringRaw(Widget);
-static void InitializeSearchWidget(struct SearchAndReplace*,
- XawTextScanDirection, Bool);
-static Bool InParams(String, String*, unsigned int);
-static Bool InsertFileNamed(Widget, char*);
-static void PopdownFileInsert(Widget, XtPointer, XtPointer);
-static void PopdownSearch(Widget, XtPointer, XtPointer);
-static Bool Replace(struct SearchAndReplace*, Bool, Bool);
-static void SearchButton(Widget, XtPointer, XtPointer);
-static void SetResource(Widget, char*, XtArgVal);
-static Bool SetResourceByName(Widget, char*, char*, XtArgVal);
-static void SetSearchLabels(struct SearchAndReplace*, String, String, Bool);
-static void SetWMProtocolTranslations(Widget);
-
-/*
- * Actions
- */
-static void WMProtocols(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * External Actions
- */
-void _XawTextDoReplaceAction(Widget, XEvent*, String*, Cardinal*);
-void _XawTextDoSearchAction(Widget, XEvent*, String*, Cardinal*);
-void _XawTextInsertFile(Widget, XEvent*, String*, Cardinal*);
-void _XawTextInsertFileAction(Widget, XEvent*, String*, Cardinal*);
-void _XawTextPopdownSearchAction(Widget, XEvent*, String*, Cardinal*);
-void _XawTextSearch(Widget, XEvent*, String*, Cardinal*);
-void _XawTextSetField(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * From Text.c
- */
-char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition);
-void _XawTextShowPosition(TextWidget);
-
-/*
- * Initialization
- */
-static char radio_trans_string[] =
-"<Btn1Down>,<Btn1Up>:" "set() notify()\n"
-;
-
-static char search_text_trans[] =
-"~s<Key>Return:" "DoSearchAction(Popdown)\n"
-"s<Key>Return:" "DoSearchAction() SetField(Replace)\n"
-"c<Key>c:" "PopdownSearchAction()\n"
-"<Btn1Down>:" "select-start() SetField(Search)\n"
-"<Key>Tab:" "DoSearchAction() SetField(Replace)\n"
-;
-
-static char rep_text_trans[] =
-"~s<Key>Return:" "DoReplaceAction(Popdown)\n"
-"s<Key>Return:" "SetField(Search)\n"
-"c<Key>c:" "PopdownSearchAction()\n"
-"<Btn1Down>:" "select-start() DoSearchAction() SetField(Replace)\n"
-"<Key>Tab:" "SetField(Search)\n"
-;
-
-/*
- * Implementation
- */
-/*
- * This section of the file contains all the functions that
- * the file insert dialog box uses
- */
-
-/*
- * Function:
- * _XawTextInsertFileAction
- *
- * Description:
- * Action routine that can be bound to dialog box's Text Widget
- * that will insert a file into the main Text Widget.
- */
-/*ARGSUSED*/
-void
-_XawTextInsertFileAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- DoInsert(w, (XtPointer)XtParent(XtParent(XtParent(w))), NULL);
-}
-
-/*
- * Function:
- * _XawTextInsertFile
- *
- * Parameters:
- * w - text widget
- * event - X Event (used to get x and y location)
- * params - parameter list
- * num_params - ""
- *
- * Description:
- * Action routine that can be bound to the text widget
- * it will popup the insert file dialog box.
- *
- * Note:
- * The parameter list may contain one entry
- *
- * Entry:
- * This entry is optional and contains the value of the default
- * file to insert
- */
-void
-_XawTextInsertFile(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- char *ptr;
- XawTextEditType edit_mode;
- Arg args[1];
-
- XtSetArg(args[0], XtNeditType, &edit_mode);
- XtGetValues(ctx->text.source, args, 1);
-
- if (edit_mode != XawtextEdit) {
- XBell(XtDisplay(w), 0);
- return;
- }
-
- if (*num_params == 0)
- ptr = "";
- else
- ptr = params[0];
-
- if (!ctx->text.file_insert) {
- ctx->text.file_insert = CreateDialog(w, ptr, "insertFile",
- AddInsertFileChildren);
- XtRealizeWidget(ctx->text.file_insert);
- SetWMProtocolTranslations(ctx->text.file_insert);
- }
-
- CenterWidgetOnPoint(ctx->text.file_insert, event);
- XtPopup(ctx->text.file_insert, XtGrabNone);
-}
-
-/*
- * Function:
- * PopdownFileInsert
- *
- * Parameters:
- * w - widget that caused this action
- * closure - pointer to the main text widget that popped up this dialog
- * call_data - (not used)
- *
- * Description:
- * Pops down the file insert button
- */
-/*ARGSUSED*/
-static void
-PopdownFileInsert(Widget w, XtPointer closure, XtPointer call_data)
-{
- TextWidget ctx = (TextWidget)closure;
-
- XtPopdown(ctx->text.file_insert);
- (void)SetResourceByName(ctx->text.file_insert, LABEL_NAME,
- XtNlabel, (XtArgVal)INSERT_FILE);
-}
-
-/*
- * Function:
- * DoInsert
- *
- * Parameters:
- * w - widget that activated this callback
- * closure - pointer to the text widget to insert the file into
- *
- * Description:
- * Actually insert the file named in the text widget of the file dialog
- */
-/*ARGSUSED*/
-static void
-DoInsert(Widget w, XtPointer closure, XtPointer call_data)
-{
- TextWidget ctx = (TextWidget)closure;
- char buf[BUFSIZ], msg[BUFSIZ];
- Widget temp_widget;
-
- (void)XmuSnprintf(buf, sizeof(buf), "%s.%s", FORM_NAME, TEXT_NAME);
- if ((temp_widget = XtNameToWidget(ctx->text.file_insert, buf)) == NULL) {
- (void)strcpy(msg,
- "Error: Could not get text widget from file insert popup");
- }
- else if (InsertFileNamed((Widget)ctx, GetString(temp_widget))) {
- PopdownFileInsert(w, closure, call_data);
- return;
- }
- else
- (void)XmuSnprintf(msg, sizeof(msg), "Error: %s", strerror(errno));
-
- (void)SetResourceByName(ctx->text.file_insert,
- LABEL_NAME, XtNlabel, (XtArgVal)msg);
- XBell(XtDisplay(w), 0);
-}
-
-/*
- * Function:
- * InsertFileNamed
- *
- * Parameters:
- * tw - text widget to insert this file into
- * str - name of the file to insert
- *
- * Description:
- * Inserts a file into the text widget.
- *
- * Returns:
- * True if the insert was sucessful, False otherwise.
- */
-static Bool
-InsertFileNamed(Widget tw, char *str)
-{
- FILE *file;
- XawTextBlock text;
- XawTextPosition pos;
-
- if (str == NULL || strlen(str) == 0 || (file = fopen(str, "r")) == NULL)
- return (False);
-
- pos = XawTextGetInsertionPoint(tw);
-
- fseek(file, 0L, 2);
-
- text.firstPos = 0;
- text.length = ftell(file);
- text.ptr = XtMalloc(text.length + 1);
- text.format = XawFmt8Bit;
-
- fseek(file, 0L, 0);
- if (fread(text.ptr, 1, text.length, file) != text.length)
- XtErrorMsg("readError", "insertFileNamed", "XawError",
- "fread returned error", NULL, NULL);
-
- if (XawTextReplace(tw, pos, pos, &text) != XawEditDone) {
- XtFree(text.ptr);
- fclose(file);
- return (False);
- }
- pos += text.length;
- XtFree(text.ptr);
- fclose(file);
- XawTextSetInsertionPoint(tw, pos);
- _XawTextShowPosition((TextWidget)tw);
-
- return (True);
-}
-
-/*
- * Function:
- * AddInsertFileChildren
- *
- * Parameters:
- * form - form widget for the insert dialog widget
- * ptr - pointer to the initial string for the Text Widget
- * tw - main text widget
- *
- * Description:
- * Adds all children to the InsertFile dialog widget.
- */
-static void
-AddInsertFileChildren(Widget form, char *ptr, Widget tw)
-{
- Arg args[10];
- Cardinal num_args;
- Widget label, text, cancel, insert;
- XtTranslations trans;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, INSERT_FILE); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNresizable, True); num_args++;
- XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
- label = XtCreateManagedWidget(LABEL_NAME, labelWidgetClass, form,
- args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNfromVert, label); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainRight); num_args++;
- XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++;
- XtSetArg(args[num_args], XtNresizable, True); num_args++;
- XtSetArg(args[num_args], XtNstring, ptr); num_args++;
- text = XtCreateManagedWidget(TEXT_NAME, asciiTextWidgetClass, form,
- args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Insert File"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, text); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- insert = XtCreateManagedWidget("insert", commandWidgetClass, form,
- args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, text); num_args++;
- XtSetArg(args[num_args], XtNfromHoriz, insert); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form,
- args, num_args);
-
- XtAddCallback(cancel, XtNcallback, PopdownFileInsert, (XtPointer)tw);
- XtAddCallback(insert, XtNcallback, DoInsert, (XtPointer)tw);
-
- XtSetKeyboardFocus(form, text);
-
- /*
- * Bind <CR> to insert file
- */
- trans = XtParseTranslationTable("<Key>Return:InsertFileAction()");
- XtOverrideTranslations(text, trans);
-}
-
-/*
- * This section of the file contains all the functions that
- * the search dialog box uses
- */
-/*
- * Function:
- * _XawTextDoSearchAction
- *
- * Description:
- * Action routine that can be bound to dialog box's Text Widget that
- * will search for a string in the main Text Widget.
- *
- * Note:
- * If the search was sucessful and the argument popdown is passed to
- * this action routine then the widget will automatically popdown the
- * search widget
- */
-/*ARGSUSED*/
-void
-_XawTextDoSearchAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- TextWidget tw = (TextWidget)XtParent(XtParent(XtParent(w)));
- Bool popdown = False;
-
- if (*num_params == 1 && (params[0][0] == 'p' || params[0][0] == 'P'))
- popdown = True;
-
- if (DoSearch(tw->text.search) && popdown)
- PopdownSearch(w, (XtPointer)tw->text.search, NULL);
-}
-
-/*
- * Function:
- * _XawTextPopdownSearchAction
- *
- * Description:
- * Action routine that can be bound to dialog box's Text Widget that
- * will popdown the search widget.
- */
-/*ARGSUSED*/
-void
-_XawTextPopdownSearchAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- TextWidget tw = (TextWidget)XtParent(XtParent(XtParent(w)));
-
- PopdownSearch(w, (XtPointer)tw->text.search, NULL);
-}
-
-/*
- * Function:
- * PopdownSearch
- *
- * Parameters:
- * w - (not used)
- * closure - pointer to the search structure
- * call_data - (not used)
- *
- * Description:
- * Pops down the search widget and resets it
- */
-/*ARGSUSED*/
-static void
-PopdownSearch(Widget w, XtPointer closure, XtPointer call_data)
-{
- struct SearchAndReplace *search = (struct SearchAndReplace *)closure;
-
- XtPopdown(search->search_popup);
- SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, False);
-}
-
-/*
- * Function:
- * SearchButton
- *
- * Arguments:
- * w - (not used)
- * closure - pointer to the search info
- * call_data - (not used)
- *
- * Description:
- * Performs a search when the button is clicked.
- */
-/*ARGSUSED*/
-static void
-SearchButton(Widget w, XtPointer closure, XtPointer call_data)
-{
- (void)DoSearch((struct SearchAndReplace *)closure);
-}
-
-/*
- * Function:
- * _XawTextSearch
- *
- * Parameters:
- * w - text widget
- * event - X Event (used to get x and y location)
- * params - parameter list
- * num_params - ""
- *
- * Description:
- * Action routine that can be bound to the text widget
- * it will popup the search dialog box.
- *
- * Note:
- * The parameter list contains one or two entries that may be
- * the following.
- *
- * First Entry:
- * The first entry is the direction to search by default.
- * This arguement must be specified and may have a value of
- * "left" or "right".
- *
- * Second Entry:
- * This entry is optional and contains the value of the default
- * string to search for.
- */
-
-#define SEARCH_HEADER "Text Widget - Search():"
-void
-_XawTextSearch(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextScanDirection dir;
- char *ptr, buf[BUFSIZ];
- XawTextEditType edit_mode;
- Arg args[1];
- wchar_t wcs[1];
-
- if (*num_params < 1 || *num_params > 2) {
- (void)XmuSnprintf(buf, sizeof(buf), "%s %s\n%s", SEARCH_HEADER,
- "This action must have only",
- "one or two parameters");
- XtAppWarning(XtWidgetToApplicationContext(w), buf);
- return;
- }
-
- if (*num_params == 2)
- ptr = params[1];
- else if (XawTextFormat(ctx, XawFmtWide)) {
- /* This just does the equivalent of
- ptr = ""L, a waste because params[1] isnt W aligned */
- ptr = (char *)wcs;
- wcs[0] = 0;
- }
- else
- ptr = "";
-
- switch(params[0][0]) {
- case 'b': /* Left */
- case 'B':
- dir = XawsdLeft;
- break;
- case 'f': /* Right */
- case 'F':
- dir = XawsdRight;
- break;
- default:
- (void)XmuSnprintf(buf, sizeof(buf), "%s %s\n%s", SEARCH_HEADER,
- "The first parameter must be",
- "Either 'backward' or 'forward'");
- XtAppWarning(XtWidgetToApplicationContext(w), buf);
- return;
- }
-
- if (ctx->text.search== NULL) {
- ctx->text.search = XtNew(struct SearchAndReplace);
- ctx->text.search->search_popup = CreateDialog(w, ptr, "search",
- AddSearchChildren);
- XtRealizeWidget(ctx->text.search->search_popup);
- SetWMProtocolTranslations(ctx->text.search->search_popup);
- }
- else if (*num_params > 1)
- XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL);
-
- XtSetArg(args[0], XtNeditType,&edit_mode);
- XtGetValues(ctx->text.source, args, 1);
-
- InitializeSearchWidget(ctx->text.search, dir, (edit_mode == XawtextEdit));
-
- CenterWidgetOnPoint(ctx->text.search->search_popup, event);
- XtPopup(ctx->text.search->search_popup, XtGrabNone);
-}
-
-/*
- * Function:
- * InitializeSearchWidget
- *
- * Parameters:
- * search - search widget structure
- * dir - direction to search
- * replace_active - state of the sensitivity for the replace button
- *
- * Description:
- * This function initializes the search widget and
- * is called each time the search widget is poped up.
- */
-static void
-InitializeSearchWidget(struct SearchAndReplace *search,
- XawTextScanDirection dir, Bool replace_active)
-{
- SetResource(search->rep_one, XtNsensitive, (XtArgVal)replace_active);
- SetResource(search->rep_all, XtNsensitive, (XtArgVal)replace_active);
- SetResource(search->rep_label, XtNsensitive, (XtArgVal)replace_active);
- SetResource(search->rep_text, XtNsensitive, (XtArgVal)replace_active);
-
- switch (dir) {
- case XawsdLeft:
- SetResource(search->left_toggle, XtNstate, (XtArgVal)True);
- break;
- case XawsdRight:
- SetResource(search->right_toggle, XtNstate, (XtArgVal)True);
- break;
- }
-}
-
-/*
- * Function:
- * AddSearchChildren
- *
- * Parameters:
- * form - form widget for the search widget
- * ptr - pointer to the initial string for the Text Widget
- * tw - main text widget
- *
- * Description:
- * Adds all children to the Search Dialog Widget.
- */
-static void
-AddSearchChildren(Widget form, char *ptr, Widget tw)
-{
- Arg args[10];
- Cardinal num_args;
- Widget cancel, search_button, s_label, s_text, r_text;
- XtTranslations trans;
- struct SearchAndReplace *search = ((TextWidget)tw)->text.search;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNresizable, True); num_args++;
- XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
- search->label1 = XtCreateManagedWidget("label1", labelWidgetClass, form,
- args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNresizable, True); num_args++;
- XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
- search->label2 = XtCreateManagedWidget("label2", labelWidgetClass, form,
- args, num_args);
-
- /*
- * We need to add R_OFFSET to the radio_data, because the value zero (0)
- * has special meaning
- */
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Backward"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNradioData, (XPointer)XawsdLeft + R_OFFSET);
- num_args++;
- search->left_toggle = XtCreateManagedWidget("backwards", toggleWidgetClass,
- form, args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Forward"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++;
- XtSetArg(args[num_args], XtNfromHoriz, search->left_toggle); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNradioGroup, search->left_toggle); num_args++;
- XtSetArg(args[num_args], XtNradioData, (XPointer)XawsdRight + R_OFFSET);
- num_args++;
- search->right_toggle = XtCreateManagedWidget("forwards", toggleWidgetClass,
- form, args, num_args);
-
- {
- XtTranslations radio_translations;
-
- radio_translations = XtParseTranslationTable(radio_trans_string);
- XtOverrideTranslations(search->left_toggle, radio_translations);
- XtOverrideTranslations(search->right_toggle, radio_translations);
- }
-
-#ifndef OLDXAW
- if (XawTextFormat((TextWidget)tw, XawFmt8Bit)) {
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Case Sensitive"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++;
- XtSetArg(args[num_args], XtNfromHoriz, search->right_toggle); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNstate, True); num_args++;
- search->case_sensitive = XtCreateManagedWidget("case", toggleWidgetClass,
- form, args, num_args);
- }
- else
- search->case_sensitive = NULL;
-#endif
-
- num_args = 0;
- XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++;
- XtSetArg(args[num_args], XtNlabel, "Search for: "); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++;
- s_label = XtCreateManagedWidget("searchLabel", labelWidgetClass, form,
- args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++;
- XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainRight); num_args++;
- XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++;
- XtSetArg(args[num_args], XtNresizable, True); num_args++;
- XtSetArg(args[num_args], XtNstring, ptr); num_args++;
- s_text = XtCreateManagedWidget("searchText", asciiTextWidgetClass, form,
- args, num_args);
- search->search_text = s_text;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNfromVert, s_text); num_args++;
- XtSetArg(args[num_args], XtNlabel, "Replace with:"); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
- search->rep_label = XtCreateManagedWidget("replaceLabel", labelWidgetClass,
- form, args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++;
- XtSetArg(args[num_args], XtNfromVert, s_text); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainRight); num_args++;
- XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++;
- XtSetArg(args[num_args], XtNresizable, True); num_args++;
- XtSetArg(args[num_args], XtNstring, ""); num_args++;
- r_text = XtCreateManagedWidget("replaceText", asciiTextWidgetClass,
- form, args, num_args);
- search->rep_text = r_text;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Search"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, r_text); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- search_button = XtCreateManagedWidget("search", commandWidgetClass, form,
- args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Replace"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, r_text); num_args++;
- XtSetArg(args[num_args], XtNfromHoriz, search_button); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- search->rep_one = XtCreateManagedWidget("replaceOne", commandWidgetClass,
- form, args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Replace All"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, r_text); num_args++;
- XtSetArg(args[num_args], XtNfromHoriz, search->rep_one); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- search->rep_all = XtCreateManagedWidget("replaceAll", commandWidgetClass,
- form, args, num_args);
-
- num_args = 0;
- XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++;
- XtSetArg(args[num_args], XtNfromVert, r_text); num_args++;
- XtSetArg(args[num_args], XtNfromHoriz, search->rep_all); num_args++;
- XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
- XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
- cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form,
- args, num_args);
-
- XtAddCallback(search_button, XtNcallback, SearchButton, (XtPointer)search);
- XtAddCallback(search->rep_one, XtNcallback, DoReplaceOne, (XtPointer)search);
- XtAddCallback(search->rep_all, XtNcallback, DoReplaceAll, (XtPointer)search);
- XtAddCallback(cancel, XtNcallback, PopdownSearch, (XtPointer)search);
-
- /*
- * Initialize the text entry fields
- */
- {
- Pixel color;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNbackground, &color); num_args++;
- XtGetValues(search->rep_text, args, num_args);
- num_args = 0;
- XtSetArg(args[num_args], XtNborderColor, color); num_args++;
- XtSetValues(search->rep_text, args, num_args);
- XtSetKeyboardFocus(form, search->search_text);
- }
-
- SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, False);
-
- /*
- * Bind Extra translations
- */
- trans = XtParseTranslationTable(search_text_trans);
- XtOverrideTranslations(search->search_text, trans);
-
- trans = XtParseTranslationTable(rep_text_trans);
- XtOverrideTranslations(search->rep_text, trans);
-}
-
-/*
- * Function:
- * DoSearch
- *
- * Parameters:
- * search - search structure
- *
- * Description:
- * Performs a search
- *
- * Returns:
- * True if sucessful
- */
-/*ARGSUSED*/
-static Bool
-DoSearch(struct SearchAndReplace *search)
-{
- char msg[37];
- Widget tw = XtParent(search->search_popup);
- XawTextPosition pos;
- XawTextScanDirection dir;
- XawTextBlock text;
- TextWidget ctx = (TextWidget)tw;
-
- text.firstPos = 0;
- text.ptr = GetStringRaw(search->search_text);
- if ((text.format = _XawTextFormat(ctx)) == XawFmtWide)
- text.length = wcslen((wchar_t*)text.ptr);
- else {
- text.length = strlen(text.ptr);
-
-#ifndef OLDXAW
- if (search->case_sensitive) {
- /* text.firstPos isn't useful here, so I'll use it as an
- * options flag.
- */
- Arg args[1];
- Boolean case_sensitive;
-
- XtSetArg(args[0], XtNstate, &case_sensitive);
- XtGetValues(search->case_sensitive, args, 1);
- text.firstPos = !case_sensitive;
- }
-#endif /* OLDXAW */
- }
-
- dir = (XawTextScanDirection)(unsigned long)
- ((XPointer)XawToggleGetCurrent(search->left_toggle) - R_OFFSET);
-
- pos = XawTextSearch(tw, dir, &text);
-
- /* The Raw string in find.ptr may be WC I can't use here, so I re - call
- GetString to get a tame version */
-
- if (pos == XawTextSearchError) {
- char *ptr;
- int len;
-
- ptr = GetString(search->search_text);
- len = strlen(ptr);
- (void)XmuSnprintf(msg, sizeof(msg), "%s", ptr);
-
- ptr = strchr(msg, '\n');
- if (ptr != NULL || sizeof(msg) - 1 < len) {
- if (ptr != NULL)
- len = ptr - msg + 4;
- else
- len = strlen(msg);
-
- if (len < 4)
- strcpy(msg, "...");
- else
- strcpy(msg + len - 4, "...");
- }
- XawTextUnsetSelection(tw);
- SetSearchLabels(search, "Could not find string", msg, True);
-
- return (False);
- }
- XawTextDisableRedisplay(tw);
- XawTextSetSelection(tw, pos, pos + text.length);
- search->selection_changed = False; /* selection is good */
-
- if (dir == XawsdRight)
- XawTextSetInsertionPoint(tw, pos + text.length);
- else
- XawTextSetInsertionPoint(tw, pos);
- _XawTextShowPosition(ctx);
- XawTextEnableRedisplay(tw);
-
- return (True);
-}
-
-/*
- * This section of the file contains all the functions that
- * the replace dialog box uses
- */
-/*
- * Function:
- * _XawTextDoReplaceAction
- *
- * Description:
- * Action routine that can be bound to dialog box's
- * Text Widget that will replace a string in the main Text Widget.
- */
-/*ARGSUSED*/
-void
-_XawTextDoReplaceAction(Widget w, XEvent *event,
- String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)XtParent(XtParent(XtParent(w)));
- Bool popdown = False;
-
- if (*num_params == 1 && (params[0][0] == 'p' || params[0][0] == 'P'))
- popdown = True;
-
- if (Replace( ctx->text.search, True, popdown) && popdown)
- PopdownSearch(w, (XtPointer)ctx->text.search, NULL);
-}
-
-/*
- * Function:
- * DoReplaceOne
- *
- * Arguments:
- * w - *** Not Used ***
- * closure - a pointer to the search structure
- * call_data - *** Not Used ***
- *
- * Description:
- * Replaces the first instance of the string in the search
- * dialog's text widget with the one in the replace dialog's text widget.
- */
-/*ARGSUSED*/
-static void
-DoReplaceOne(Widget w, XtPointer closure, XtPointer call_data)
-{
- Replace((struct SearchAndReplace *)closure, True, False);
-}
-
-/*
- * Function:
- * DoReplaceAll
- *
- * Parameters:
- * w - (not used)
- * closure - pointer to the search structure
- * call_data - (not used)
- *
- * Description:
- * Replaces every instance of the string in the search dialog's
- * text widget with the one in the replace dialog's text widget.
- */
-/*ARGSUSED*/
-static void
-DoReplaceAll(Widget w, XtPointer closure, XtPointer call_data)
-{
- Replace((struct SearchAndReplace *)closure, False, False);
-}
-
-/*
- * Function:
- * Replace
- *
- * Parameters:
- * tw - Text Widget to replce the string in
- * once_only - if True then only replace the first one found,
- * else replace all of them
- * show_current - if true then leave the selection on the
- * string that was just replaced, otherwise
- * move it onto the next one
- *
- * Description:
- * This is the function that does the real work of
- * replacing strings in the main text widget.
- */
-static Bool
-Replace(struct SearchAndReplace *search, Bool once_only, Bool show_current)
-{
- XawTextPosition pos, new_pos, end_pos, ipos;
- XawTextScanDirection dir;
- XawTextBlock find, replace;
- Widget tw = XtParent(search->search_popup);
- int count = 0;
- TextWidget ctx = (TextWidget)tw;
- Bool redisplay;
-
- find.ptr = GetStringRaw(search->search_text);
- if ((find.format = _XawTextFormat(ctx)) == XawFmtWide)
- find.length = (XawTextPosition)wcslen((wchar_t*)find.ptr);
- else
- find.length = (XawTextPosition)strlen(find.ptr);
- find.firstPos = 0;
-
- replace.ptr = GetStringRaw(search->rep_text);
- replace.firstPos = 0;
- if ((replace.format = _XawTextFormat(ctx)) == XawFmtWide)
- replace.length = wcslen((wchar_t*)replace.ptr);
- else
- replace.length = strlen(replace.ptr);
-
- dir = (XawTextScanDirection)(unsigned long)
- ((XPointer)XawToggleGetCurrent(search->left_toggle) - R_OFFSET);
-
- redisplay = !once_only || (once_only && !show_current);
- ipos = XawTextGetInsertionPoint(tw);
- if (redisplay)
- XawTextDisableRedisplay(tw);
- /*CONSTCOND*/
- while (True) {
- if (count != 0) {
- new_pos = XawTextSearch(tw, dir, &find);
-
- if (new_pos == XawTextSearchError) {
- if (count == 0) {
- char msg[37];
- char *ptr;
- int len;
-
- ptr = GetString(search->search_text);
- len = strlen(ptr);
- (void)XmuSnprintf(msg, sizeof(msg), "%s", ptr);
- ptr = strchr(msg, '\n');
- if (ptr != NULL || sizeof(msg) - 1 < len) {
- if (ptr != NULL)
- len = ptr - msg + 4;
- else
- len = strlen(msg);
-
- if (len < 4)
- strcpy(msg, "...");
- else
- strcpy(msg + len - 4, "...");
- }
- SetSearchLabels(search, "Could not find string", msg, True);
-
- if (redisplay) {
- XawTextSetInsertionPoint(tw, ipos);
- _XawTextShowPosition(ctx);
- XawTextEnableRedisplay(tw);
- }
-
- return (False);
- }
- else
- break;
- }
- pos = new_pos;
- end_pos = pos + find.length;
- }
- else {
- XawTextGetSelectionPos(tw, &pos, &end_pos);
-
- if (search->selection_changed) {
- SetSearchLabels(search, "Selection modified, aborting.",
- "", True);
- if (redisplay) {
- XawTextSetInsertionPoint(tw, ipos);
- XawTextEnableRedisplay(tw);
- }
-
- return (False);
- }
- if (pos == end_pos) {
- if (redisplay) {
- XawTextSetInsertionPoint(tw, ipos);
- XawTextEnableRedisplay(tw);
- }
-
- return (False);
- }
- }
-
- if (XawTextReplace(tw, pos, end_pos, &replace) != XawEditDone) {
- SetSearchLabels(search, "Error while replacing.", "", True);
- if (redisplay) {
- XawTextSetInsertionPoint(tw, ipos);
- XawTextEnableRedisplay(tw);
- }
-
- return (False);
- }
-
- if (dir == XawsdRight)
- ipos = pos + replace.length;
- else
- ipos = pos;
-
- if (once_only) {
- if (show_current)
- break;
- else {
- DoSearch(search);
- XawTextEnableRedisplay(tw);
-
- return (True);
- }
- }
- else
- ctx->text.insertPos = ipos;
- count++;
- }
-
- if (replace.length == 0)
- XawTextUnsetSelection(tw);
- else
- XawTextSetSelection(tw, pos, pos + replace.length);
-
- XawTextSetInsertionPoint(tw, ipos);
- _XawTextShowPosition(ctx);
- XawTextEnableRedisplay(tw);
-
- return (True);
-}
-
-/*
- * Function:
- * SetSearchLabels
- *
- * Parameters:
- * search - search structure
- * msg1 - message to put in each search label
- * msg2 - ""
- * bell - if True then ring bell
- *
- * Description:
- * Sets both the search labels, and also rings the bell.
- */
-static void
-SetSearchLabels(struct SearchAndReplace *search, String msg1, String msg2,
- Bool bell)
-{
- (void)SetResource(search->label1, XtNlabel, (XtArgVal)msg1);
- (void)SetResource(search->label2, XtNlabel, (XtArgVal)msg2);
- if (bell)
- XBell(XtDisplay(search->search_popup), 0);
-}
-
-/*
- * This section of the file contains utility routines used by
- * other functions in this file
- */
-/*
- * Function:
- * _XawTextSetField
- *
- * Description:
- * Action routine that can be bound to dialog box's
- * Text Widget that will send input to the field specified.
- */
-/*ARGSUSED*/
-void
-_XawTextSetField(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- struct SearchAndReplace *search;
- Widget cnew, old;
-
- search = ((TextWidget)XtParent(XtParent(XtParent(w))))->text.search;
-
- if (*num_params != 1) {
- SetSearchLabels(search, "Error: SetField Action must have",
- "exactly one argument", True);
- return;
- }
- switch (params[0][0]) {
- case 's':
- case 'S':
- cnew = search->search_text;
- old = search->rep_text;
- break;
- case 'r':
- case 'R':
- old = search->search_text;
- cnew = search->rep_text;
- break;
- default:
- SetSearchLabels(search,
- "Error: SetField Action's first Argument must",
- "be either 'Search' or 'Replace'", True);
- return;
- }
- _SetField(cnew, old);
-}
-
-/*
- * Function:
- * _SetField
- *
- * Parameters:
- * cnew - new and old text fields
- * old - ""
- *
- * Description:
- * Sets the current text field.
- */
-static void
-_SetField(Widget cnew, Widget old)
-{
- Arg args[2];
- Pixel new_border, old_border, old_bg;
-
- if (!XtIsSensitive(cnew)) {
- XBell(XtDisplay(old), 0); /* Don't set field to an inactive Widget */
- return;
- }
-
- XtSetKeyboardFocus(XtParent(cnew), cnew);
-
- XtSetArg(args[0], XtNborderColor, &old_border);
- XtSetArg(args[1], XtNbackground, &old_bg);
- XtGetValues(cnew, args, 2);
-
- XtSetArg(args[0], XtNborderColor, &new_border);
- XtGetValues(old, args, 1);
-
- if (old_border != old_bg) /* Colors are already correct, return */
- return;
-
- SetResource(old, XtNborderColor, (XtArgVal)old_border);
- SetResource(cnew, XtNborderColor, (XtArgVal)new_border);
-}
-
-/*
- * Function:
- * SetResourceByName
- *
- * Parameters:
- * shell - shell widget of the popup
- * name - name of the child
- * res_name - name of the resource
- * value - value of the resource
- *
- * Description:
- * Sets a resource in any of the dialog children given
- * name of the child and the shell widget of the dialog.
- *
- * Returns:
- * True if sucessful
- */
-static Bool
-SetResourceByName(Widget shell, char *name, char *res_name, XtArgVal value)
-{
- Widget temp_widget;
- char buf[BUFSIZ];
-
- (void)XmuSnprintf(buf, sizeof(buf), "%s.%s", FORM_NAME, name);
-
- if ((temp_widget = XtNameToWidget(shell, buf)) != NULL) {
- SetResource(temp_widget, res_name, value);
- return (True);
- }
- return (False);
-}
-
-/*
- * Function:
- * SetResource
- *
- * Parameters:
- * w - widget
- * res_name - name of the resource
- * value - value of the resource
- *
- * Description:
- * Sets a resource in a widget
- */
-static void
-SetResource(Widget w, char *res_name, XtArgVal value)
-{
- Arg args[1];
-
- XtSetArg(args[0], res_name, value);
- XtSetValues( w, args, 1);
-}
-
-/*
- * Function:
- * GetString{Raw}
- *
- * Parameters:
- * text - text widget whose string we will get
- *
- * Description:
- * Gets the value for the string in the popup.
- *
- * Returns:
- * GetString: the string as a MB
- * GetStringRaw: the exact buffer contents suitable for a search
- */
-static String
-GetString(Widget text)
-{
- String string;
- Arg args[1];
-
- XtSetArg(args[0], XtNstring, &string);
- XtGetValues(text, args, 1);
-
- return (string);
-}
-
-static String
-GetStringRaw(Widget tw)
-{
- TextWidget ctx = (TextWidget)tw;
- XawTextPosition last;
-
- last = XawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight,
- ctx->text.mult, True);
- return (_XawTextGetText(ctx, 0, last));
-}
-
-/*
- * Function:
- * CenterWidgetOnPoint
- *
- * Parameters:
- * w - shell widget
- * event - event containing the location of the point
- *
- * Description:
- * Centers a shell widget on a point relative to the root window.
- *
- * Note:
- * The widget is not allowed to go off the screen
- */
-static void
-CenterWidgetOnPoint(Widget w, XEvent *event)
-{
- Arg args[3];
- Cardinal num_args;
- Dimension width, height, b_width;
- Position x, y, max_x, max_y;
-
- if (event != NULL) {
- switch (event->type) {
- case ButtonPress:
- case ButtonRelease:
- x = event->xbutton.x_root;
- y = event->xbutton.y_root;
- break;
- case KeyPress:
- case KeyRelease:
- x = event->xkey.x_root;
- y = event->xkey.y_root;
- break;
- default:
- return;
- }
- }
- else
- return;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNwidth, &width); num_args++;
- XtSetArg(args[num_args], XtNheight, &height); num_args++;
- XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
- XtGetValues(w, args, num_args);
-
- width += b_width << 1;
- height += b_width << 1;
-
- x -= (Position)(width >> 1);
- if (x < 0)
- x = 0;
- if (x > (max_x = (Position)(XtScreen(w)->width - width)))
- x = max_x;
-
- y -= (Position)(height >> 1);
- if (y < 0)
- y = 0;
- if (y > (max_y = (Position)(XtScreen(w)->height - height)))
- y = max_y;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNx, x); num_args++;
- XtSetArg(args[num_args], XtNy, y); num_args++;
- XtSetValues(w, args, num_args);
-}
-
-/*
- * Function:
- * CreateDialog
- *
- * Parameters:
- * parent - parent of the dialog - the main text widget
- * ptr - initial_string for the dialog
- * name - name of the dialog
- * func - function to create the children of the dialog
- *
- * Returns:
- * Popup shell of the dialog
- *
- * Note:
- * The function argument is passed the following arguments:
- * form - from widget that is the dialog
- * ptr - initial string for the dialog's text widget
- * parent - parent of the dialog - the main text widget
- */
-static Widget
-CreateDialog(Widget parent, String ptr, String name, AddFunc func)
-{
- Widget popup, form;
- Arg args[5];
- Cardinal num_args;
-
- num_args = 0;
- XtSetArg(args[num_args], XtNiconName, name); num_args++;
- XtSetArg(args[num_args], XtNgeometry, NULL); num_args++;
- XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
- XtSetArg(args[num_args], XtNtransientFor, GetShell(parent));num_args++;
- popup = XtCreatePopupShell(name, transientShellWidgetClass,
- parent, args, num_args);
-
- form = XtCreateManagedWidget(FORM_NAME, formWidgetClass, popup, NULL, 0);
- XtManageChild (form);
-
- (*func)(form, ptr, parent);
-
- return (popup);
-}
-
-/*
- * Function
- * GetShell
- * nearest shell widget.
- *
- * Parameters:
- * w - widget whose parent shell should be returned
- *
- * Returns:
- * The shell widget among the ancestors of w that is the
- * fewest levels up in the widget hierarchy.
- *
- * Description:
- * Walks up the widget hierarchy to find the topmost shell widget.
- */
-static Widget
-GetShell(Widget w)
-{
- while (w != NULL && !XtIsShell(w))
- w = XtParent(w);
-
- return (w);
-}
-
-static Bool
-InParams(String str, String *p, unsigned int n)
-{
- unsigned int i;
-
- for (i = 0; i < n; p++, i++)
- if (!XmuCompareISOLatin1(*p, str))
- return (True);
- return (False);
-}
-
-static char *WM_DELETE_WINDOW = "WM_DELETE_WINDOW";
-
-static void
-WMProtocols(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- Atom wm_delete_window;
- Atom wm_protocols;
-
- wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, True);
- wm_protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", True);
-
- /* Respond to a recognized WM protocol request if
- * event type is ClientMessage and no parameters are passed, or
- * event type is ClientMessage and event data is matched to parameters, or
- * event type isn't ClientMessage and parameters make a request
- */
-#define DO_DELETE_WINDOW InParams(WM_DELETE_WINDOW, params, *num_params)
-
- if ((event->type == ClientMessage
- && event->xclient.message_type == wm_protocols
- && event->xclient.data.l[0] == wm_delete_window
- && (*num_params == 0 || DO_DELETE_WINDOW))
- || (event->type != ClientMessage && DO_DELETE_WINDOW)) {
-#undef DO_DELETE_WINDOW
- Widget cancel;
- char descendant[DISMISS_NAME_LEN + 2];
-
- (void)XmuSnprintf(descendant, sizeof(descendant), "*%s", DISMISS_NAME);
- cancel = XtNameToWidget(w, descendant);
- if (cancel)
- XtCallCallbacks(cancel, XtNcallback, NULL);
- }
-}
-
-static void
-SetWMProtocolTranslations(Widget w)
-{
- static XtTranslations compiled_table;
- static XtAppContext *app_context_list;
- static Cardinal list_size;
-
- unsigned int i;
- XtAppContext app_context;
- Atom wm_delete_window;
-
- app_context = XtWidgetToApplicationContext(w);
-
- /* parse translation table once */
- if (!compiled_table)
- compiled_table =
- XtParseTranslationTable("<Message>WM_PROTOCOLS:XawWMProtocols()\n");
-
- /* add actions once per application context */
- for (i = 0; i < list_size && app_context_list[i] != app_context; i++)
- ;
- if (i == list_size) {
- XtActionsRec actions[1];
-
- actions[0].string = "XawWMProtocols";
- actions[0].proc = WMProtocols;
- list_size++;
- app_context_list = (XtAppContext *)XtRealloc
- ((char *)app_context_list, list_size * sizeof(XtAppContext));
- XtAppAddActions(app_context, actions, 1);
- app_context_list[i] = app_context;
- }
-
- /* establish communication between the window manager and each shell */
- XtAugmentTranslations(w, compiled_table);
- wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, False);
- (void)XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_delete_window, 1);
-}
+/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * This file is broken up into three sections one dealing with + * each of the three popups created here: + * + * FileInsert, Search, and Replace. + * + * There is also a section at the end for utility functions + * used by all more than one of these dialogs. + * + * The following functions are the only non-static ones defined + * in this module. They are located at the begining of the + * section that contains this dialog box that uses them. + * + * void _XawTextInsertFileAction(w, event, params, num_params); + * void _XawTextDoSearchAction(w, event, params, num_params); + * void _XawTextDoReplaceAction(w, event, params, num_params); + * void _XawTextInsertFile(w, event, params, num_params); + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <errno.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <X11/Xos.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/TextP.h> +#include <X11/Xaw/AsciiText.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/Command.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Toggle.h> +#include "XawI18n.h" + +static char* INSERT_FILE = "Enter Filename:"; +static char* SEARCH_LABEL_1 = "Use <Tab> to change fields."; +static char* SEARCH_LABEL_2 = "Use ^q<Tab> for <Tab>."; +static char* DISMISS_NAME = "cancel"; +#define DISMISS_NAME_LEN 6 +static char* FORM_NAME = "form"; +static char* LABEL_NAME = "label"; +static char* TEXT_NAME = "text"; + +#define R_OFFSET 1 + +typedef void (*AddFunc)(Widget, char*, Widget); + +/* + * Prototypes + */ +static void _SetField(Widget, Widget); +static void AddSearchChildren(Widget, char*, Widget); +static void AddInsertFileChildren(Widget, char*, Widget); +static void CenterWidgetOnPoint(Widget, XEvent*); +static Widget CreateDialog(Widget, String, String, AddFunc); +static void DoInsert(Widget, XtPointer, XtPointer); +static void DoReplaceAll(Widget, XtPointer, XtPointer); +static void DoReplaceOne(Widget, XtPointer, XtPointer); +static Bool DoSearch(struct SearchAndReplace*); +static Widget GetShell(Widget); +static String GetString(Widget); +static String GetStringRaw(Widget); +static void InitializeSearchWidget(struct SearchAndReplace*, + XawTextScanDirection, Bool); +static Bool InParams(String, String*, unsigned int); +static Bool InsertFileNamed(Widget, char*); +static void PopdownFileInsert(Widget, XtPointer, XtPointer); +static void PopdownSearch(Widget, XtPointer, XtPointer); +static Bool Replace(struct SearchAndReplace*, Bool, Bool); +static void SearchButton(Widget, XtPointer, XtPointer); +static void SetResource(Widget, char*, XtArgVal); +static Bool SetResourceByName(Widget, char*, char*, XtArgVal); +static void SetSearchLabels(struct SearchAndReplace*, String, String, Bool); +static void SetWMProtocolTranslations(Widget); + +/* + * Actions + */ +static void WMProtocols(Widget, XEvent*, String*, Cardinal*); + +/* + * External Actions + */ +void _XawTextDoReplaceAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextDoSearchAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextInsertFile(Widget, XEvent*, String*, Cardinal*); +void _XawTextInsertFileAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextPopdownSearchAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextSearch(Widget, XEvent*, String*, Cardinal*); +void _XawTextSetField(Widget, XEvent*, String*, Cardinal*); + +/* + * From Text.c + */ +char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); +void _XawTextShowPosition(TextWidget); + +/* + * Initialization + */ +static char radio_trans_string[] = +"<Btn1Down>,<Btn1Up>:" "set() notify()\n" +; + +static char search_text_trans[] = +"~s<Key>Return:" "DoSearchAction(Popdown)\n" +"s<Key>Return:" "DoSearchAction() SetField(Replace)\n" +"c<Key>c:" "PopdownSearchAction()\n" +"<Btn1Down>:" "select-start() SetField(Search)\n" +"<Key>Tab:" "DoSearchAction() SetField(Replace)\n" +; + +static char rep_text_trans[] = +"~s<Key>Return:" "DoReplaceAction(Popdown)\n" +"s<Key>Return:" "SetField(Search)\n" +"c<Key>c:" "PopdownSearchAction()\n" +"<Btn1Down>:" "select-start() DoSearchAction() SetField(Replace)\n" +"<Key>Tab:" "SetField(Search)\n" +; + +/* + * Implementation + */ +/* + * This section of the file contains all the functions that + * the file insert dialog box uses + */ + +/* + * Function: + * _XawTextInsertFileAction + * + * Description: + * Action routine that can be bound to dialog box's Text Widget + * that will insert a file into the main Text Widget. + */ +/*ARGSUSED*/ +void +_XawTextInsertFileAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + DoInsert(w, (XtPointer)XtParent(XtParent(XtParent(w))), NULL); +} + +/* + * Function: + * _XawTextInsertFile + * + * Parameters: + * w - text widget + * event - X Event (used to get x and y location) + * params - parameter list + * num_params - "" + * + * Description: + * Action routine that can be bound to the text widget + * it will popup the insert file dialog box. + * + * Note: + * The parameter list may contain one entry + * + * Entry: + * This entry is optional and contains the value of the default + * file to insert + */ +void +_XawTextInsertFile(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + char *ptr; + XawTextEditType edit_mode; + Arg args[1]; + + XtSetArg(args[0], XtNeditType, &edit_mode); + XtGetValues(ctx->text.source, args, 1); + + if (edit_mode != XawtextEdit) { + XBell(XtDisplay(w), 0); + return; + } + + if (*num_params == 0) + ptr = ""; + else + ptr = params[0]; + + if (!ctx->text.file_insert) { + ctx->text.file_insert = CreateDialog(w, ptr, "insertFile", + AddInsertFileChildren); + XtRealizeWidget(ctx->text.file_insert); + SetWMProtocolTranslations(ctx->text.file_insert); + } + + CenterWidgetOnPoint(ctx->text.file_insert, event); + XtPopup(ctx->text.file_insert, XtGrabNone); +} + +/* + * Function: + * PopdownFileInsert + * + * Parameters: + * w - widget that caused this action + * closure - pointer to the main text widget that popped up this dialog + * call_data - (not used) + * + * Description: + * Pops down the file insert button + */ +/*ARGSUSED*/ +static void +PopdownFileInsert(Widget w, XtPointer closure, XtPointer call_data) +{ + TextWidget ctx = (TextWidget)closure; + + XtPopdown(ctx->text.file_insert); + (void)SetResourceByName(ctx->text.file_insert, LABEL_NAME, + XtNlabel, (XtArgVal)INSERT_FILE); +} + +/* + * Function: + * DoInsert + * + * Parameters: + * w - widget that activated this callback + * closure - pointer to the text widget to insert the file into + * + * Description: + * Actually insert the file named in the text widget of the file dialog + */ +/*ARGSUSED*/ +static void +DoInsert(Widget w, XtPointer closure, XtPointer call_data) +{ + TextWidget ctx = (TextWidget)closure; + char buf[BUFSIZ], msg[BUFSIZ]; + Widget temp_widget; + + (void)XmuSnprintf(buf, sizeof(buf), "%s.%s", FORM_NAME, TEXT_NAME); + if ((temp_widget = XtNameToWidget(ctx->text.file_insert, buf)) == NULL) { + (void)strcpy(msg, + "Error: Could not get text widget from file insert popup"); + } + else if (InsertFileNamed((Widget)ctx, GetString(temp_widget))) { + PopdownFileInsert(w, closure, call_data); + return; + } + else + (void)XmuSnprintf(msg, sizeof(msg), "Error: %s", strerror(errno)); + + (void)SetResourceByName(ctx->text.file_insert, + LABEL_NAME, XtNlabel, (XtArgVal)msg); + XBell(XtDisplay(w), 0); +} + +/* + * Function: + * InsertFileNamed + * + * Parameters: + * tw - text widget to insert this file into + * str - name of the file to insert + * + * Description: + * Inserts a file into the text widget. + * + * Returns: + * True if the insert was sucessful, False otherwise. + */ +static Bool +InsertFileNamed(Widget tw, char *str) +{ + FILE *file; + XawTextBlock text; + XawTextPosition pos; + + if (str == NULL || strlen(str) == 0 || (file = fopen(str, "r")) == NULL) + return (False); + + pos = XawTextGetInsertionPoint(tw); + + fseek(file, 0L, 2); + + text.firstPos = 0; + text.length = ftell(file); + text.ptr = XtMalloc(text.length + 1); + text.format = XawFmt8Bit; + + fseek(file, 0L, 0); + if (fread(text.ptr, 1, text.length, file) != text.length) + XtErrorMsg("readError", "insertFileNamed", "XawError", + "fread returned error", NULL, NULL); + + if (XawTextReplace(tw, pos, pos, &text) != XawEditDone) { + XtFree(text.ptr); + fclose(file); + return (False); + } + pos += text.length; + XtFree(text.ptr); + fclose(file); + XawTextSetInsertionPoint(tw, pos); + _XawTextShowPosition((TextWidget)tw); + + return (True); +} + +/* + * Function: + * AddInsertFileChildren + * + * Parameters: + * form - form widget for the insert dialog widget + * ptr - pointer to the initial string for the Text Widget + * tw - main text widget + * + * Description: + * Adds all children to the InsertFile dialog widget. + */ +static void +AddInsertFileChildren(Widget form, char *ptr, Widget tw) +{ + Arg args[10]; + Cardinal num_args; + Widget label, text, cancel, insert; + XtTranslations trans; + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, INSERT_FILE); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNresizable, True); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; + label = XtCreateManagedWidget(LABEL_NAME, labelWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, label); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; + XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; + XtSetArg(args[num_args], XtNresizable, True); num_args++; + XtSetArg(args[num_args], XtNstring, ptr); num_args++; + text = XtCreateManagedWidget(TEXT_NAME, asciiTextWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Insert File"); num_args++; + XtSetArg(args[num_args], XtNfromVert, text); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + insert = XtCreateManagedWidget("insert", commandWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++; + XtSetArg(args[num_args], XtNfromVert, text); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, insert); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form, + args, num_args); + + XtAddCallback(cancel, XtNcallback, PopdownFileInsert, (XtPointer)tw); + XtAddCallback(insert, XtNcallback, DoInsert, (XtPointer)tw); + + XtSetKeyboardFocus(form, text); + + /* + * Bind <CR> to insert file + */ + trans = XtParseTranslationTable("<Key>Return:InsertFileAction()"); + XtOverrideTranslations(text, trans); +} + +/* + * This section of the file contains all the functions that + * the search dialog box uses + */ +/* + * Function: + * _XawTextDoSearchAction + * + * Description: + * Action routine that can be bound to dialog box's Text Widget that + * will search for a string in the main Text Widget. + * + * Note: + * If the search was sucessful and the argument popdown is passed to + * this action routine then the widget will automatically popdown the + * search widget + */ +/*ARGSUSED*/ +void +_XawTextDoSearchAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + TextWidget tw = (TextWidget)XtParent(XtParent(XtParent(w))); + Bool popdown = False; + + if (*num_params == 1 && (params[0][0] == 'p' || params[0][0] == 'P')) + popdown = True; + + if (DoSearch(tw->text.search) && popdown) + PopdownSearch(w, (XtPointer)tw->text.search, NULL); +} + +/* + * Function: + * _XawTextPopdownSearchAction + * + * Description: + * Action routine that can be bound to dialog box's Text Widget that + * will popdown the search widget. + */ +/*ARGSUSED*/ +void +_XawTextPopdownSearchAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + TextWidget tw = (TextWidget)XtParent(XtParent(XtParent(w))); + + PopdownSearch(w, (XtPointer)tw->text.search, NULL); +} + +/* + * Function: + * PopdownSearch + * + * Parameters: + * w - (not used) + * closure - pointer to the search structure + * call_data - (not used) + * + * Description: + * Pops down the search widget and resets it + */ +/*ARGSUSED*/ +static void +PopdownSearch(Widget w, XtPointer closure, XtPointer call_data) +{ + struct SearchAndReplace *search = (struct SearchAndReplace *)closure; + + XtPopdown(search->search_popup); + SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, False); +} + +/* + * Function: + * SearchButton + * + * Arguments: + * w - (not used) + * closure - pointer to the search info + * call_data - (not used) + * + * Description: + * Performs a search when the button is clicked. + */ +/*ARGSUSED*/ +static void +SearchButton(Widget w, XtPointer closure, XtPointer call_data) +{ + (void)DoSearch((struct SearchAndReplace *)closure); +} + +/* + * Function: + * _XawTextSearch + * + * Parameters: + * w - text widget + * event - X Event (used to get x and y location) + * params - parameter list + * num_params - "" + * + * Description: + * Action routine that can be bound to the text widget + * it will popup the search dialog box. + * + * Note: + * The parameter list contains one or two entries that may be + * the following. + * + * First Entry: + * The first entry is the direction to search by default. + * This arguement must be specified and may have a value of + * "left" or "right". + * + * Second Entry: + * This entry is optional and contains the value of the default + * string to search for. + */ + +#define SEARCH_HEADER "Text Widget - Search():" +void +_XawTextSearch(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + XawTextScanDirection dir; + char *ptr, buf[BUFSIZ]; + XawTextEditType edit_mode; + Arg args[1]; + wchar_t wcs[1]; + + if (*num_params < 1 || *num_params > 2) { + (void)XmuSnprintf(buf, sizeof(buf), "%s %s\n%s", SEARCH_HEADER, + "This action must have only", + "one or two parameters"); + XtAppWarning(XtWidgetToApplicationContext(w), buf); + return; + } + + if (*num_params == 2) + ptr = params[1]; + else if (XawTextFormat(ctx, XawFmtWide)) { + /* This just does the equivalent of + ptr = ""L, a waste because params[1] isnt W aligned */ + ptr = (char *)wcs; + wcs[0] = 0; + } + else + ptr = ""; + + switch(params[0][0]) { + case 'b': /* Left */ + case 'B': + dir = XawsdLeft; + break; + case 'f': /* Right */ + case 'F': + dir = XawsdRight; + break; + default: + (void)XmuSnprintf(buf, sizeof(buf), "%s %s\n%s", SEARCH_HEADER, + "The first parameter must be", + "Either 'backward' or 'forward'"); + XtAppWarning(XtWidgetToApplicationContext(w), buf); + return; + } + + if (ctx->text.search== NULL) { + ctx->text.search = XtNew(struct SearchAndReplace); + ctx->text.search->search_popup = CreateDialog(w, ptr, "search", + AddSearchChildren); + XtRealizeWidget(ctx->text.search->search_popup); + SetWMProtocolTranslations(ctx->text.search->search_popup); + } + else if (*num_params > 1) + XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL); + + XtSetArg(args[0], XtNeditType,&edit_mode); + XtGetValues(ctx->text.source, args, 1); + + InitializeSearchWidget(ctx->text.search, dir, (edit_mode == XawtextEdit)); + + CenterWidgetOnPoint(ctx->text.search->search_popup, event); + XtPopup(ctx->text.search->search_popup, XtGrabNone); +} + +/* + * Function: + * InitializeSearchWidget + * + * Parameters: + * search - search widget structure + * dir - direction to search + * replace_active - state of the sensitivity for the replace button + * + * Description: + * This function initializes the search widget and + * is called each time the search widget is poped up. + */ +static void +InitializeSearchWidget(struct SearchAndReplace *search, + XawTextScanDirection dir, Bool replace_active) +{ + SetResource(search->rep_one, XtNsensitive, (XtArgVal)replace_active); + SetResource(search->rep_all, XtNsensitive, (XtArgVal)replace_active); + SetResource(search->rep_label, XtNsensitive, (XtArgVal)replace_active); + SetResource(search->rep_text, XtNsensitive, (XtArgVal)replace_active); + + switch (dir) { + case XawsdLeft: + SetResource(search->left_toggle, XtNstate, (XtArgVal)True); + break; + case XawsdRight: + SetResource(search->right_toggle, XtNstate, (XtArgVal)True); + break; + } +} + +/* + * Function: + * AddSearchChildren + * + * Parameters: + * form - form widget for the search widget + * ptr - pointer to the initial string for the Text Widget + * tw - main text widget + * + * Description: + * Adds all children to the Search Dialog Widget. + */ +static void +AddSearchChildren(Widget form, char *ptr, Widget tw) +{ + Arg args[10]; + Cardinal num_args; + Widget cancel, search_button, s_label, s_text, r_text; + XtTranslations trans; + struct SearchAndReplace *search = ((TextWidget)tw)->text.search; + + num_args = 0; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNresizable, True); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; + search->label1 = XtCreateManagedWidget("label1", labelWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNresizable, True); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; + search->label2 = XtCreateManagedWidget("label2", labelWidgetClass, form, + args, num_args); + + /* + * We need to add R_OFFSET to the radio_data, because the value zero (0) + * has special meaning + */ + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Backward"); num_args++; + XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNradioData, (XPointer)XawsdLeft + R_OFFSET); + num_args++; + search->left_toggle = XtCreateManagedWidget("backwards", toggleWidgetClass, + form, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Forward"); num_args++; + XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search->left_toggle); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNradioGroup, search->left_toggle); num_args++; + XtSetArg(args[num_args], XtNradioData, (XPointer)XawsdRight + R_OFFSET); + num_args++; + search->right_toggle = XtCreateManagedWidget("forwards", toggleWidgetClass, + form, args, num_args); + + { + XtTranslations radio_translations; + + radio_translations = XtParseTranslationTable(radio_trans_string); + XtOverrideTranslations(search->left_toggle, radio_translations); + XtOverrideTranslations(search->right_toggle, radio_translations); + } + +#ifndef OLDXAW + if (XawTextFormat((TextWidget)tw, XawFmt8Bit)) { + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Case Sensitive"); num_args++; + XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search->right_toggle); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNstate, True); num_args++; + search->case_sensitive = XtCreateManagedWidget("case", toggleWidgetClass, + form, args, num_args); + } + else + search->case_sensitive = NULL; +#endif + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++; + XtSetArg(args[num_args], XtNlabel, "Search for: "); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++; + s_label = XtCreateManagedWidget("searchLabel", labelWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; + XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; + XtSetArg(args[num_args], XtNresizable, True); num_args++; + XtSetArg(args[num_args], XtNstring, ptr); num_args++; + s_text = XtCreateManagedWidget("searchText", asciiTextWidgetClass, form, + args, num_args); + search->search_text = s_text; + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, s_text); num_args++; + XtSetArg(args[num_args], XtNlabel, "Replace with:"); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; + search->rep_label = XtCreateManagedWidget("replaceLabel", labelWidgetClass, + form, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++; + XtSetArg(args[num_args], XtNfromVert, s_text); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; + XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; + XtSetArg(args[num_args], XtNresizable, True); num_args++; + XtSetArg(args[num_args], XtNstring, ""); num_args++; + r_text = XtCreateManagedWidget("replaceText", asciiTextWidgetClass, + form, args, num_args); + search->rep_text = r_text; + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Search"); num_args++; + XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + search_button = XtCreateManagedWidget("search", commandWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Replace"); num_args++; + XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search_button); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + search->rep_one = XtCreateManagedWidget("replaceOne", commandWidgetClass, + form, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Replace All"); num_args++; + XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search->rep_one); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + search->rep_all = XtCreateManagedWidget("replaceAll", commandWidgetClass, + form, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++; + XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search->rep_all); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form, + args, num_args); + + XtAddCallback(search_button, XtNcallback, SearchButton, (XtPointer)search); + XtAddCallback(search->rep_one, XtNcallback, DoReplaceOne, (XtPointer)search); + XtAddCallback(search->rep_all, XtNcallback, DoReplaceAll, (XtPointer)search); + XtAddCallback(cancel, XtNcallback, PopdownSearch, (XtPointer)search); + + /* + * Initialize the text entry fields + */ + { + Pixel color; + + num_args = 0; + XtSetArg(args[num_args], XtNbackground, &color); num_args++; + XtGetValues(search->rep_text, args, num_args); + num_args = 0; + XtSetArg(args[num_args], XtNborderColor, color); num_args++; + XtSetValues(search->rep_text, args, num_args); + XtSetKeyboardFocus(form, search->search_text); + } + + SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, False); + + /* + * Bind Extra translations + */ + trans = XtParseTranslationTable(search_text_trans); + XtOverrideTranslations(search->search_text, trans); + + trans = XtParseTranslationTable(rep_text_trans); + XtOverrideTranslations(search->rep_text, trans); +} + +/* + * Function: + * DoSearch + * + * Parameters: + * search - search structure + * + * Description: + * Performs a search + * + * Returns: + * True if sucessful + */ +/*ARGSUSED*/ +static Bool +DoSearch(struct SearchAndReplace *search) +{ + char msg[37]; + Widget tw = XtParent(search->search_popup); + XawTextPosition pos; + XawTextScanDirection dir; + XawTextBlock text; + TextWidget ctx = (TextWidget)tw; + + text.firstPos = 0; + text.ptr = GetStringRaw(search->search_text); + if ((text.format = _XawTextFormat(ctx)) == XawFmtWide) + text.length = wcslen((wchar_t*)text.ptr); + else { + text.length = strlen(text.ptr); + +#ifndef OLDXAW + if (search->case_sensitive) { + /* text.firstPos isn't useful here, so I'll use it as an + * options flag. + */ + Arg args[1]; + Boolean case_sensitive; + + XtSetArg(args[0], XtNstate, &case_sensitive); + XtGetValues(search->case_sensitive, args, 1); + text.firstPos = !case_sensitive; + } +#endif /* OLDXAW */ + } + + dir = (XawTextScanDirection)(unsigned long) + ((XPointer)XawToggleGetCurrent(search->left_toggle) - R_OFFSET); + + pos = XawTextSearch(tw, dir, &text); + + /* The Raw string in find.ptr may be WC I can't use here, so I re - call + GetString to get a tame version */ + + if (pos == XawTextSearchError) { + char *ptr; + int len; + + ptr = GetString(search->search_text); + len = strlen(ptr); + (void)XmuSnprintf(msg, sizeof(msg), "%s", ptr); + + ptr = strchr(msg, '\n'); + if (ptr != NULL || sizeof(msg) - 1 < len) { + if (ptr != NULL) + len = ptr - msg + 4; + else + len = strlen(msg); + + if (len < 4) + strcpy(msg, "..."); + else + strcpy(msg + len - 4, "..."); + } + XawTextUnsetSelection(tw); + SetSearchLabels(search, "Could not find string", msg, True); + + return (False); + } + XawTextDisableRedisplay(tw); + XawTextSetSelection(tw, pos, pos + text.length); + search->selection_changed = False; /* selection is good */ + + if (dir == XawsdRight) + XawTextSetInsertionPoint(tw, pos + text.length); + else + XawTextSetInsertionPoint(tw, pos); + _XawTextShowPosition(ctx); + XawTextEnableRedisplay(tw); + + return (True); +} + +/* + * This section of the file contains all the functions that + * the replace dialog box uses + */ +/* + * Function: + * _XawTextDoReplaceAction + * + * Description: + * Action routine that can be bound to dialog box's + * Text Widget that will replace a string in the main Text Widget. + */ +/*ARGSUSED*/ +void +_XawTextDoReplaceAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)XtParent(XtParent(XtParent(w))); + Bool popdown = False; + + if (*num_params == 1 && (params[0][0] == 'p' || params[0][0] == 'P')) + popdown = True; + + if (Replace( ctx->text.search, True, popdown) && popdown) + PopdownSearch(w, (XtPointer)ctx->text.search, NULL); +} + +/* + * Function: + * DoReplaceOne + * + * Arguments: + * w - *** Not Used *** + * closure - a pointer to the search structure + * call_data - *** Not Used *** + * + * Description: + * Replaces the first instance of the string in the search + * dialog's text widget with the one in the replace dialog's text widget. + */ +/*ARGSUSED*/ +static void +DoReplaceOne(Widget w, XtPointer closure, XtPointer call_data) +{ + Replace((struct SearchAndReplace *)closure, True, False); +} + +/* + * Function: + * DoReplaceAll + * + * Parameters: + * w - (not used) + * closure - pointer to the search structure + * call_data - (not used) + * + * Description: + * Replaces every instance of the string in the search dialog's + * text widget with the one in the replace dialog's text widget. + */ +/*ARGSUSED*/ +static void +DoReplaceAll(Widget w, XtPointer closure, XtPointer call_data) +{ + Replace((struct SearchAndReplace *)closure, False, False); +} + +/* + * Function: + * Replace + * + * Parameters: + * tw - Text Widget to replce the string in + * once_only - if True then only replace the first one found, + * else replace all of them + * show_current - if true then leave the selection on the + * string that was just replaced, otherwise + * move it onto the next one + * + * Description: + * This is the function that does the real work of + * replacing strings in the main text widget. + */ +static Bool +Replace(struct SearchAndReplace *search, Bool once_only, Bool show_current) +{ + XawTextPosition pos, new_pos, end_pos, ipos; + XawTextScanDirection dir; + XawTextBlock find, replace; + Widget tw = XtParent(search->search_popup); + int count = 0; + TextWidget ctx = (TextWidget)tw; + Bool redisplay; + + find.ptr = GetStringRaw(search->search_text); + if ((find.format = _XawTextFormat(ctx)) == XawFmtWide) + find.length = (XawTextPosition)wcslen((wchar_t*)find.ptr); + else + find.length = (XawTextPosition)strlen(find.ptr); + find.firstPos = 0; + + replace.ptr = GetStringRaw(search->rep_text); + replace.firstPos = 0; + if ((replace.format = _XawTextFormat(ctx)) == XawFmtWide) + replace.length = wcslen((wchar_t*)replace.ptr); + else + replace.length = strlen(replace.ptr); + + dir = (XawTextScanDirection)(unsigned long) + ((XPointer)XawToggleGetCurrent(search->left_toggle) - R_OFFSET); + + redisplay = !once_only || (once_only && !show_current); + ipos = XawTextGetInsertionPoint(tw); + if (redisplay) + XawTextDisableRedisplay(tw); + /*CONSTCOND*/ + while (True) { + if (count != 0) { + new_pos = XawTextSearch(tw, dir, &find); + + if (new_pos == XawTextSearchError) { + if (count == 0) { + char msg[37]; + char *ptr; + int len; + + ptr = GetString(search->search_text); + len = strlen(ptr); + (void)XmuSnprintf(msg, sizeof(msg), "%s", ptr); + ptr = strchr(msg, '\n'); + if (ptr != NULL || sizeof(msg) - 1 < len) { + if (ptr != NULL) + len = ptr - msg + 4; + else + len = strlen(msg); + + if (len < 4) + strcpy(msg, "..."); + else + strcpy(msg + len - 4, "..."); + } + SetSearchLabels(search, "Could not find string", msg, True); + + if (redisplay) { + XawTextSetInsertionPoint(tw, ipos); + _XawTextShowPosition(ctx); + XawTextEnableRedisplay(tw); + } + + return (False); + } + else + break; + } + pos = new_pos; + end_pos = pos + find.length; + } + else { + XawTextGetSelectionPos(tw, &pos, &end_pos); + + if (search->selection_changed) { + SetSearchLabels(search, "Selection modified, aborting.", + "", True); + if (redisplay) { + XawTextSetInsertionPoint(tw, ipos); + XawTextEnableRedisplay(tw); + } + + return (False); + } + if (pos == end_pos) { + if (redisplay) { + XawTextSetInsertionPoint(tw, ipos); + XawTextEnableRedisplay(tw); + } + + return (False); + } + } + + if (XawTextReplace(tw, pos, end_pos, &replace) != XawEditDone) { + SetSearchLabels(search, "Error while replacing.", "", True); + if (redisplay) { + XawTextSetInsertionPoint(tw, ipos); + XawTextEnableRedisplay(tw); + } + + return (False); + } + + if (dir == XawsdRight) + ipos = pos + replace.length; + else + ipos = pos; + + if (once_only) { + if (show_current) + break; + else { + DoSearch(search); + XawTextEnableRedisplay(tw); + + return (True); + } + } + else + ctx->text.insertPos = ipos; + count++; + } + + if (replace.length == 0) + XawTextUnsetSelection(tw); + else + XawTextSetSelection(tw, pos, pos + replace.length); + + XawTextSetInsertionPoint(tw, ipos); + _XawTextShowPosition(ctx); + XawTextEnableRedisplay(tw); + + return (True); +} + +/* + * Function: + * SetSearchLabels + * + * Parameters: + * search - search structure + * msg1 - message to put in each search label + * msg2 - "" + * bell - if True then ring bell + * + * Description: + * Sets both the search labels, and also rings the bell. + */ +static void +SetSearchLabels(struct SearchAndReplace *search, String msg1, String msg2, + Bool bell) +{ + (void)SetResource(search->label1, XtNlabel, (XtArgVal)msg1); + (void)SetResource(search->label2, XtNlabel, (XtArgVal)msg2); + if (bell) + XBell(XtDisplay(search->search_popup), 0); +} + +/* + * This section of the file contains utility routines used by + * other functions in this file + */ +/* + * Function: + * _XawTextSetField + * + * Description: + * Action routine that can be bound to dialog box's + * Text Widget that will send input to the field specified. + */ +/*ARGSUSED*/ +void +_XawTextSetField(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + struct SearchAndReplace *search; + Widget cnew, old; + + search = ((TextWidget)XtParent(XtParent(XtParent(w))))->text.search; + + if (*num_params != 1) { + SetSearchLabels(search, "Error: SetField Action must have", + "exactly one argument", True); + return; + } + switch (params[0][0]) { + case 's': + case 'S': + cnew = search->search_text; + old = search->rep_text; + break; + case 'r': + case 'R': + old = search->search_text; + cnew = search->rep_text; + break; + default: + SetSearchLabels(search, + "Error: SetField Action's first Argument must", + "be either 'Search' or 'Replace'", True); + return; + } + _SetField(cnew, old); +} + +/* + * Function: + * _SetField + * + * Parameters: + * cnew - new and old text fields + * old - "" + * + * Description: + * Sets the current text field. + */ +static void +_SetField(Widget cnew, Widget old) +{ + Arg args[2]; + Pixel new_border, old_border, old_bg; + + if (!XtIsSensitive(cnew)) { + XBell(XtDisplay(old), 0); /* Don't set field to an inactive Widget */ + return; + } + + XtSetKeyboardFocus(XtParent(cnew), cnew); + + XtSetArg(args[0], XtNborderColor, &old_border); + XtSetArg(args[1], XtNbackground, &old_bg); + XtGetValues(cnew, args, 2); + + XtSetArg(args[0], XtNborderColor, &new_border); + XtGetValues(old, args, 1); + + if (old_border != old_bg) /* Colors are already correct, return */ + return; + + SetResource(old, XtNborderColor, (XtArgVal)old_border); + SetResource(cnew, XtNborderColor, (XtArgVal)new_border); +} + +/* + * Function: + * SetResourceByName + * + * Parameters: + * shell - shell widget of the popup + * name - name of the child + * res_name - name of the resource + * value - value of the resource + * + * Description: + * Sets a resource in any of the dialog children given + * name of the child and the shell widget of the dialog. + * + * Returns: + * True if sucessful + */ +static Bool +SetResourceByName(Widget shell, char *name, char *res_name, XtArgVal value) +{ + Widget temp_widget; + char buf[BUFSIZ]; + + (void)XmuSnprintf(buf, sizeof(buf), "%s.%s", FORM_NAME, name); + + if ((temp_widget = XtNameToWidget(shell, buf)) != NULL) { + SetResource(temp_widget, res_name, value); + return (True); + } + return (False); +} + +/* + * Function: + * SetResource + * + * Parameters: + * w - widget + * res_name - name of the resource + * value - value of the resource + * + * Description: + * Sets a resource in a widget + */ +static void +SetResource(Widget w, char *res_name, XtArgVal value) +{ + Arg args[1]; + + XtSetArg(args[0], res_name, value); + XtSetValues( w, args, 1); +} + +/* + * Function: + * GetString{Raw} + * + * Parameters: + * text - text widget whose string we will get + * + * Description: + * Gets the value for the string in the popup. + * + * Returns: + * GetString: the string as a MB + * GetStringRaw: the exact buffer contents suitable for a search + */ +static String +GetString(Widget text) +{ + String string; + Arg args[1]; + + XtSetArg(args[0], XtNstring, &string); + XtGetValues(text, args, 1); + + return (string); +} + +static String +GetStringRaw(Widget tw) +{ + TextWidget ctx = (TextWidget)tw; + XawTextPosition last; + + last = XawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight, + ctx->text.mult, True); + return (_XawTextGetText(ctx, 0, last)); +} + +/* + * Function: + * CenterWidgetOnPoint + * + * Parameters: + * w - shell widget + * event - event containing the location of the point + * + * Description: + * Centers a shell widget on a point relative to the root window. + * + * Note: + * The widget is not allowed to go off the screen + */ +static void +CenterWidgetOnPoint(Widget w, XEvent *event) +{ + Arg args[3]; + Cardinal num_args; + Dimension width, height, b_width; + Position x, y, max_x, max_y; + + if (event != NULL) { + switch (event->type) { + case ButtonPress: + case ButtonRelease: + x = event->xbutton.x_root; + y = event->xbutton.y_root; + break; + case KeyPress: + case KeyRelease: + x = event->xkey.x_root; + y = event->xkey.y_root; + break; + default: + return; + } + } + else + return; + + num_args = 0; + XtSetArg(args[num_args], XtNwidth, &width); num_args++; + XtSetArg(args[num_args], XtNheight, &height); num_args++; + XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++; + XtGetValues(w, args, num_args); + + width += b_width << 1; + height += b_width << 1; + + x -= (Position)(width >> 1); + if (x < 0) + x = 0; + if (x > (max_x = (Position)(XtScreen(w)->width - width))) + x = max_x; + + y -= (Position)(height >> 1); + if (y < 0) + y = 0; + if (y > (max_y = (Position)(XtScreen(w)->height - height))) + y = max_y; + + num_args = 0; + XtSetArg(args[num_args], XtNx, x); num_args++; + XtSetArg(args[num_args], XtNy, y); num_args++; + XtSetValues(w, args, num_args); +} + +/* + * Function: + * CreateDialog + * + * Parameters: + * parent - parent of the dialog - the main text widget + * ptr - initial_string for the dialog + * name - name of the dialog + * func - function to create the children of the dialog + * + * Returns: + * Popup shell of the dialog + * + * Note: + * The function argument is passed the following arguments: + * form - from widget that is the dialog + * ptr - initial string for the dialog's text widget + * parent - parent of the dialog - the main text widget + */ +static Widget +CreateDialog(Widget parent, String ptr, String name, AddFunc func) +{ + Widget popup, form; + Arg args[5]; + Cardinal num_args; + + num_args = 0; + XtSetArg(args[num_args], XtNiconName, name); num_args++; + XtSetArg(args[num_args], XtNgeometry, NULL); num_args++; + XtSetArg(args[num_args], XtNallowShellResize, True); num_args++; + XtSetArg(args[num_args], XtNtransientFor, GetShell(parent));num_args++; + popup = XtCreatePopupShell(name, transientShellWidgetClass, + parent, args, num_args); + + form = XtCreateManagedWidget(FORM_NAME, formWidgetClass, popup, NULL, 0); + XtManageChild (form); + + (*func)(form, ptr, parent); + + return (popup); +} + +/* + * Function + * GetShell + * nearest shell widget. + * + * Parameters: + * w - widget whose parent shell should be returned + * + * Returns: + * The shell widget among the ancestors of w that is the + * fewest levels up in the widget hierarchy. + * + * Description: + * Walks up the widget hierarchy to find the topmost shell widget. + */ +static Widget +GetShell(Widget w) +{ + while (w != NULL && !XtIsShell(w)) + w = XtParent(w); + + return (w); +} + +static Bool +InParams(String str, String *p, unsigned int n) +{ + unsigned int i; + + for (i = 0; i < n; p++, i++) + if (!XmuCompareISOLatin1(*p, str)) + return (True); + return (False); +} + +static char *WM_DELETE_WINDOW = "WM_DELETE_WINDOW"; + +static void +WMProtocols(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + Atom wm_delete_window; + Atom wm_protocols; + + wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, True); + wm_protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", True); + + /* Respond to a recognized WM protocol request if + * event type is ClientMessage and no parameters are passed, or + * event type is ClientMessage and event data is matched to parameters, or + * event type isn't ClientMessage and parameters make a request + */ +#define DO_DELETE_WINDOW InParams(WM_DELETE_WINDOW, params, *num_params) + + if ((event->type == ClientMessage + && event->xclient.message_type == wm_protocols + && event->xclient.data.l[0] == wm_delete_window + && (*num_params == 0 || DO_DELETE_WINDOW)) + || (event->type != ClientMessage && DO_DELETE_WINDOW)) { +#undef DO_DELETE_WINDOW + Widget cancel; + char descendant[DISMISS_NAME_LEN + 2]; + + (void)XmuSnprintf(descendant, sizeof(descendant), "*%s", DISMISS_NAME); + cancel = XtNameToWidget(w, descendant); + if (cancel) + XtCallCallbacks(cancel, XtNcallback, NULL); + } +} + +static void +SetWMProtocolTranslations(Widget w) +{ + static XtTranslations compiled_table; + static XtAppContext *app_context_list; + static Cardinal list_size; + + unsigned int i; + XtAppContext app_context; + Atom wm_delete_window; + + app_context = XtWidgetToApplicationContext(w); + + /* parse translation table once */ + if (!compiled_table) + compiled_table = + XtParseTranslationTable("<Message>WM_PROTOCOLS:XawWMProtocols()\n"); + + /* add actions once per application context */ + for (i = 0; i < list_size && app_context_list[i] != app_context; i++) + ; + if (i == list_size) { + XtActionsRec actions[1]; + + actions[0].string = "XawWMProtocols"; + actions[0].proc = WMProtocols; + list_size++; + app_context_list = (XtAppContext *)XtRealloc + ((char *)app_context_list, list_size * sizeof(XtAppContext)); + XtAppAddActions(app_context, actions, 1); + app_context_list[i] = app_context; + } + + /* establish communication between the window manager and each shell */ + XtAugmentTranslations(w, compiled_table); + wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, False); + (void)XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_delete_window, 1); +} diff --git a/libXaw/src/TextSink.c b/libXaw/src/TextSink.c index 424e4cf3c..b47c7b80a 100644 --- a/libXaw/src/TextSink.c +++ b/libXaw/src/TextSink.c @@ -1,1827 +1,1827 @@ -/*
-
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-/*
- * Author: Chris Peterson, MIT X Consortium.
- *
- * Much code taken from X11R3 AsciiSink.
- */
-
-/*
- * TextSink.c - TextSink object. (For use with the text widget).
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/TextP.h>
-#include <X11/Xaw/TextSinkP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * Prototypes
- */
-static void XawTextSinkClassPartInitialize(WidgetClass);
-static void XawTextSinkInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawTextSinkDestroy(Widget);
-static Boolean XawTextSinkSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-static int MaxLines(Widget, unsigned int);
-static int MaxHeight(Widget, int);
-static void DisplayText(Widget, int, int, XawTextPosition, XawTextPosition,
- Bool);
-static void InsertCursor(Widget, int, int, XawTextInsertState);
-static void ClearToBackground(Widget, int, int, unsigned int, unsigned int);
-static void FindPosition(Widget, XawTextPosition, int, int, Bool,
- XawTextPosition*, int*, int*);
-static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*,
- XawTextPosition*, int*);
-static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*);
-static void SetTabs(Widget, int, short*);
-static void GetCursorBounds(Widget, XRectangle*);
-
-#ifndef OLDXAW
-static Boolean CvtStringToPropertyList(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Boolean CvtPropertyListToString(Display*, XrmValue*, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static Bool BeginPaint(Widget);
-static Bool EndPaint(Widget);
-static void SetXlfdDefaults(Display*, XawTextProperty*);
-#endif
-
-/*
- * External
- */
-void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
-void _XawTextSinkDisplayText(Widget, int, int, XawTextPosition, XawTextPosition,
- Bool);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(TextSinkRec, text_sink.field)
-static XtResource resources[] = {
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(foreground),
- XtRString,
- XtDefaultForeground
- },
- {
- XtNbackground,
- XtCBackground,
- XtRPixel,
- sizeof(Pixel),
- offset(background),
- XtRString,
- XtDefaultBackground
- },
-#ifndef OLDXAW
- {
- XtNcursorColor,
- XtCColor,
- XtRPixel,
- sizeof(Pixel),
- offset(cursor_color),
- XtRString,
- XtDefaultForeground
- },
- {
- XawNtextProperties,
- XawCTextProperties,
- XawRTextProperties,
- sizeof(XawTextPropertyList*),
- offset(properties),
- XtRImmediate,
- NULL
- },
-#endif
-};
-#undef offset
-
-#ifndef OLDXAW
-static TextSinkExtRec extension_rec = {
- NULL, /* next_extension */
- NULLQUARK, /* record_type */
- 1, /* version */
- sizeof(TextSinkExtRec), /* record_size */
- BeginPaint,
- NULL,
- NULL,
- EndPaint
-};
-
-static XrmQuark Qdefault;
-#endif
-
-#define Superclass (&objectClassRec)
-TextSinkClassRec textSinkClassRec = {
- /* object */
- {
- (WidgetClass)Superclass, /* superclass */
- "TextSink", /* class_name */
- sizeof(TextSinkRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- XawTextSinkClassPartInitialize, /* class_part_initialize */
- False, /* class_inited */
- XawTextSinkInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* obj1 */
- NULL, /* obj2 */
- 0, /* obj3 */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* obj4 */
- False, /* obj5 */
- False, /* obj6 */
- False, /* obj7 */
- XawTextSinkDestroy, /* destroy */
- NULL, /* obj8 */
- NULL, /* obj9 */
- XawTextSinkSetValues, /* set_values */
- NULL, /* set_values_hook */
- NULL, /* obj10 */
- NULL, /* get_values_hook */
- NULL, /* obj11 */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* obj12 */
- NULL, /* obj13 */
- NULL, /* obj14 */
- NULL, /* extension */
- },
- /* text_sink */
- {
- DisplayText, /* DisplayText */
- InsertCursor, /* InsertCursor */
- ClearToBackground, /* ClearToBackground */
- FindPosition, /* FindPosition */
- FindDistance, /* FindDistance */
- Resolve, /* Resolve */
- MaxLines, /* MaxLines */
- MaxHeight, /* MaxHeight */
- SetTabs, /* SetTabs */
- GetCursorBounds, /* GetCursorBounds */
- },
-};
-
-WidgetClass textSinkObjectClass = (WidgetClass)&textSinkClassRec;
-
-/*
- * Implementation
- */
-static void
-XawTextSinkClassPartInitialize(WidgetClass wc)
-{
- TextSinkObjectClass t_src, superC;
-#ifndef OLDXAW
- static XtConvertArgRec CvtArgs[] = {
- {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.self),
- sizeof(Widget)},
- };
-#endif
-
- t_src = (TextSinkObjectClass) wc;
- superC = (TextSinkObjectClass) t_src->object_class.superclass;
-
-#ifndef OLDXAW
- extension_rec.record_type = XrmPermStringToQuark("TextSink");
- extension_rec.next_extension = (XtPointer)t_src->text_sink_class.extension;
- t_src->text_sink_class.extension = &extension_rec;
-
- Qdefault = XrmPermStringToQuark("default");
-#endif
-
- /*
- * We don't need to check for null super since we'll get to TextSink
- * eventually.
- */
- if (t_src->text_sink_class.DisplayText == XtInheritDisplayText)
- t_src->text_sink_class.DisplayText =
- superC->text_sink_class.DisplayText;
-
- if (t_src->text_sink_class.InsertCursor == XtInheritInsertCursor)
- t_src->text_sink_class.InsertCursor =
- superC->text_sink_class.InsertCursor;
-
- if (t_src->text_sink_class.ClearToBackground== XtInheritClearToBackground)
- t_src->text_sink_class.ClearToBackground =
- superC->text_sink_class.ClearToBackground;
-
- if (t_src->text_sink_class.FindPosition == XtInheritFindPosition)
- t_src->text_sink_class.FindPosition =
- superC->text_sink_class.FindPosition;
-
- if (t_src->text_sink_class.FindDistance == XtInheritFindDistance)
- t_src->text_sink_class.FindDistance =
- superC->text_sink_class.FindDistance;
-
- if (t_src->text_sink_class.Resolve == XtInheritResolve)
- t_src->text_sink_class.Resolve =
- superC->text_sink_class.Resolve;
-
- if (t_src->text_sink_class.MaxLines == XtInheritMaxLines)
- t_src->text_sink_class.MaxLines =
- superC->text_sink_class.MaxLines;
-
- if (t_src->text_sink_class.MaxHeight == XtInheritMaxHeight)
- t_src->text_sink_class.MaxHeight =
- superC->text_sink_class.MaxHeight;
-
- if (t_src->text_sink_class.SetTabs == XtInheritSetTabs)
- t_src->text_sink_class.SetTabs =
- superC->text_sink_class.SetTabs;
-
- if (t_src->text_sink_class.GetCursorBounds == XtInheritGetCursorBounds)
- t_src->text_sink_class.GetCursorBounds =
- superC->text_sink_class.GetCursorBounds;
-
-#ifndef OLDXAW
- XtSetTypeConverter(XtRString, XawRTextProperties, CvtStringToPropertyList,
- &CvtArgs[0], XtNumber(CvtArgs), XtCacheNone, NULL);
- XtSetTypeConverter(XawRTextProperties, XtRString, CvtPropertyListToString,
- NULL, 0, XtCacheNone, NULL);
-#endif
-}
-
-/*
- * Function:
- * XawTextSinkInitialize
- *
- * Parameters:
- * request - requested and new values for the object instance
- * cnew - ""
- *
- * Description:
- * Initializes the TextSink Object.
- */
-/*ARGSUSED*/
-static void
-XawTextSinkInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- TextSinkObject sink = (TextSinkObject)cnew;
-
- sink->text_sink.tab_count = 0; /* Initialize the tab stops. */
- sink->text_sink.tabs = NULL;
- sink->text_sink.char_tabs = NULL;
-#ifndef OLDXAW
- sink->text_sink.paint = NULL;
-#endif
-}
-
-/*
- * Function:
- * XawTextSinkDestroy
- *
- * Parameters:
- * w - TextSink Object
- *
- * Description:
- * This function cleans up when the object is destroyed.
- */
-static void
-XawTextSinkDestroy(Widget w)
-{
- TextSinkObject sink = (TextSinkObject) w;
-
- XtFree((char *)sink->text_sink.tabs);
- XtFree((char *)sink->text_sink.char_tabs);
-}
-
-/*
- * Function:
- * XawTextSinkSetValues
- *
- * Parameters:
- * current - current state of the object
- * request - what was requested
- * cnew - what the object will become
- *
- * Description:
- * Sets the values for the TextSink.
- *
- * Returns:
- * True if redisplay is needed
- */
-/*ARGSUSED*/
-static Boolean
-XawTextSinkSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- TextSinkObject w = (TextSinkObject)cnew;
- TextSinkObject old_w = (TextSinkObject)current;
-
- if (w->text_sink.foreground != old_w->text_sink.foreground)
- ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
-
- return (False);
-}
-
-/*
- * Function:
- * DisplayText
- *
- * Parameters:
- * w - TextSink Object
- * x - location to start drawing text
- * y - ""
- * pos1 - location of starting and ending points in the text buffer
- * pos2 - ""
- * highlight - hightlight this text?
- *
- * Description:
- * Stub function that in subclasses will display text.
- */
-/*ARGSUSED*/
-static void
-DisplayText(Widget w, int x, int y,
- XawTextPosition pos1, XawTextPosition pos2, Bool highlight)
-{
- return;
-}
-
-/*
- * Function:
- * InsertCursor
- *
- * Parameters:
- * w - TextSink Object
- * x - location for the cursor
- * y - ""
- * state - whether to turn the cursor on, or off
- *
- * Description:
- * Places the InsertCursor.
- */
-/*ARGSUSED*/
-static void
-InsertCursor(Widget w, int x, int y, XawTextInsertState state)
-{
- return;
-}
-
-/*
- * Function:
- * ClearToBackground
- *
- * Parameters:
- * w - TextSink Object
- * x - location of area to clear
- * y - ""
- * width - size of area to clear
- * height - ""
- *
- * Description:
- * Clears a region of the sink to the background color.
- */
-/*ARGSUSED*/
-static void
-ClearToBackground(Widget w, int x, int y,
- unsigned int width, unsigned int height)
-{
- /*
- * Don't clear in height or width are zero
- * XClearArea() has special semantic for these values
- */
- TextWidget xaw = (TextWidget)XtParent(w);
- Position x1, y1, x2, y2;
-
- x1 = XawMax(x, xaw->text.r_margin.left);
- y1 = XawMax(y, xaw->text.r_margin.top);
- x2 = XawMin(x + (int)width, (int)XtWidth(xaw) - xaw->text.r_margin.right);
- y2 = XawMin(y + (int)height, (int)XtHeight(xaw) - xaw->text.r_margin.bottom);
-
- x = x1;
- y = y1;
- width = XawMax(0, x2 - x1);
- height = XawMax(0, y2 - y1);
-
- if (height != 0 && width != 0)
- XClearArea(XtDisplayOfObject(w), XtWindowOfObject(w),
- x, y, width, height, False);
-}
-
-/*
- * Function:
- * FindPosition
- *
- * Parameters:
- * w - TextSink Object
- * fromPos - reference position
- * fromX - reference location
- * width - width of section to paint text
- * stopAtWordBreak - returned position is a word break?
- * resPos - position found (return)
- * resWidth - Width actually used (return)
- * resHeight - Height actually used (return)
- *
- * Description:
- * Finds a position in the text.
- */
-/*ARGSUSED*/
-static void
-FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
- Bool stopAtWordBreak, XawTextPosition *resPos,
- int *resWidth, int *resHeight)
-{
- *resPos = fromPos;
- *resHeight = *resWidth = 0;
-}
-
-/*
- * Function:
- * FindDistance
- *
- * Parameters:
- * w - TextSink Object
- * fromPos - starting Position
- * fromX - x location of starting Position
- * toPos - end Position
- * resWidth - Distance between fromPos and toPos
- * resPos - Acutal toPos used
- * resHeight - Height required by this text
- *
- * Description:
- * Find the Pixel Distance between two text Positions.
- */
-/*ARGSUSED*/
-static void
-FindDistance(Widget w, XawTextPosition fromPos, int fromx,
- XawTextPosition toPos, int *resWidth,
- XawTextPosition *resPos, int *resHeight)
-{
- *resWidth = *resHeight = 0;
- *resPos = fromPos;
-}
-
-/*
- * Function:
- * Resolve
- *
- * Parameters:
- * w - TextSink Object
- * pos - reference Position
- * fromx - reference Location
- * width - width to move
- * resPos - resulting position
- *
- * Description:
- * Resloves a location to a position.
- */
-/*ARGSUSED*/
-static void
-Resolve(Widget w, XawTextPosition pos, int fromx, int width,
- XawTextPosition *resPos)
-{
- *resPos = pos;
-}
-
-/*
- * Function:
- * MaxLines
- *
- * Parameters:
- * w - TextSink Object
- * height - height to fit lines into
- *
- * Description:
- * Finds the Maximum number of lines that will fit in a given height.
- *
- * Returns:
- * Number of lines that will fit
- */
-/*ARGSUSED*/
-static int
-MaxLines(Widget w, unsigned int height)
-{
- /*
- * The fontset has gone down to descent Sink Widget, so
- * the functions such MaxLines, SetTabs... are bound to the descent.
- *
- * by Li Yuhong, Jan. 15, 1991
- */
- return (0);
-}
-
-/*
- * Function:
- * MaxHeight
- *
- * Parameters:
- * w - TextSink Object
- * lines - number of lines
- *
- * Description:
- * Finds the Minium height that will contain a given number lines.
- *
- * Returns:
- * the height
- */
-/*ARGSUSED*/
-static int
-MaxHeight(Widget w, int lines)
-{
- return (0);
-}
-
-/*
- * Function:
- * SetTabs
- *
- * Parameters:
- * w - TextSink Object
- * tab_count - the number of tabs in the list
- * tabs - text positions of the tabs
- * Description:
- * Sets the Tab stops.
- */
-/*ARGSUSED*/
-static void
-SetTabs(Widget w, int tab_count, short *tabs)
-{
- return;
-}
-
-/*
- * Function:
- * GetCursorBounds
- *
- * Parameters:
- * w - TextSinkObject.
- * rect - X rectangle containing the cursor bounds
- *
- * Description:
- * Finds the bounding box for the insert cursor (caret)
- */
-/*ARGSUSED*/
-static void
-GetCursorBounds(Widget w, XRectangle *rect)
-{
- rect->x = rect->y = rect->width = rect->height = 0;
-}
-
-/*
- * Public Functions
- */
-/*
- * Function:
- * XawTextSinkDisplayText
- *
- * Parameters:
- * w - TextSink Object
- * x - location to start drawing text
- * y - ""
- * pos1 - location of starting and ending points in the text buffer
- * pos2 - ""
- * highlight - hightlight this text?
- */
-/*ARGSUSED*/
-void
-XawTextSinkDisplayText(Widget w,
-#if NeedWidePrototypes
- int x, int y,
-#else
- Position x, Position y,
-#endif
- XawTextPosition pos1, XawTextPosition pos2,
-#if NeedWidePrototypes
- int highlight
-#else
- Boolean highlight
-#endif
-)
-{
- _XawTextSinkDisplayText(w, x, y, pos1, pos2, highlight);
-}
-
-void
-_XawTextSinkDisplayText(Widget w, int x, int y,
- XawTextPosition pos1, XawTextPosition pos2,
- Bool highlight)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- (*cclass->text_sink_class.DisplayText)(w, x, y, pos1, pos2, highlight);
-}
-
-/*
- * Function:
- * XawTextSinkInsertCursor
- *
- * Parameters:
- * w - TextSink Object
- * x - location for the cursor
- * y - ""
- * state - whether to turn the cursor on, or off
- *
- * Description:
- * Places the InsertCursor.
- */
-/*ARGSUSED*/
-void
-#if NeedWidePrototypes
-XawTextSinkInsertCursor(Widget w, int x, int y, int state)
-#else
-XawTextSinkInsertCursor(Widget w, Position x, Position y, XawTextInsertState state)
-#endif
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- (*cclass->text_sink_class.InsertCursor)(w, x, y, state);
-}
-
-/*
- * Function:
- * XawTextSinkClearToBackground
- *
- * Parameters:
- * w - TextSink Object
- * x - location of area to clear
- * y - ""
- * width - size of area to clear
- * height - ""
- *
- * Description:
- * Clears a region of the sink to the background color.
- */
-/*ARGSUSED*/
-void
-XawTextSinkClearToBackground(Widget w,
-#if NeedWidePrototypes
- int x, int y,
- unsigned int width, unsigned int height
-#else
- Position x, Position y,
- Dimension width, Dimension height
-#endif
-)
-{
- _XawTextSinkClearToBackground(w, x, y, width, height);
-}
-
-void
-_XawTextSinkClearToBackground(Widget w,
- int x, int y,
- unsigned int width, unsigned int height)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- (*cclass->text_sink_class.ClearToBackground)(w, x, y, width, height);
-}
-
-/*
- * Function:
- * XawTextSinkFindPosition
- *
- * Parameters:
- * w - TextSink Object
- * fromPos - reference position
- * fromX - reference location
- * width - width of section to paint text
- * stopAtWordBreak - returned position is a word break?
- * resPos - position found (return)
- * resWidth - Width actually used (return)
- * resHeight - Height actually used (return)
- *
- * Description:
- * Finds a position in the text.
- */
-/*ARGSUSED*/
-void
-XawTextSinkFindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
-#if NeedWidePrototypes
- int stopAtWordBreak,
-#else
- Boolean stopAtWordBreak,
-#endif
- XawTextPosition *resPos, int *resWidth, int *resHeight)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- (*cclass->text_sink_class.FindPosition)(w, fromPos, fromx, width,
- stopAtWordBreak,
- resPos, resWidth, resHeight);
-}
-
-/*
- * Function:
- * XawTextSinkFindDistance
- *
- * Parameters:
- * w - TextSink Object
- * fromPos - starting Position
- * fromX - x location of starting Position
- * toPos - end Position
- * resWidth - Distance between fromPos and toPos
- * resPos - Acutal toPos used
- * resHeight - Height required by this text
- *
- * Description:
- * Find the Pixel Distance between two text Positions.
- */
-/*ARGSUSED*/
-void
-XawTextSinkFindDistance(Widget w, XawTextPosition fromPos, int fromx,
- XawTextPosition toPos, int *resWidth,
- XawTextPosition *resPos, int *resHeight)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- (*cclass->text_sink_class.FindDistance)(w, fromPos, fromx, toPos,
- resWidth, resPos, resHeight);
-}
-
-/*
- * Function:
- * XawTextSinkResolve
- *
- * Parameters:
- * w - TextSink Object
- * pos - reference Position
- * fromx - reference Location
- * width - width to move
- * resPos - resulting position
- *
- * Description:
- * Resloves a location to a position.
- */
-/*ARGSUSED*/
-void
-XawTextSinkResolve(Widget w, XawTextPosition pos, int fromx, int width,
- XawTextPosition *resPos)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass) w->core.widget_class;
-
- (*cclass->text_sink_class.Resolve)(w, pos, fromx, width, resPos);
-}
-
-/*
- * Function:
- * XawTextSinkMaxLines
- *
- * Parameters:
- * w - TextSink Object
- * height - height to fit lines into
- *
- * Description:
- * Finds the Maximum number of lines that will fit in a given height.
- *
- * Returns:
- * Number of lines that will fit
- */
-/*ARGSUSED*/
-int
-#if NeedWidePrototypes
-XawTextSinkMaxLines(Widget w, unsigned int height)
-#else
-XawTextSinkMaxLines(Widget w, Dimension height)
-#endif
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- return((*cclass->text_sink_class.MaxLines)(w, height));
-}
-
-/*
- * Function:
- * XawTextSinkMaxHeight
- *
- * Parameters:
- * w - TextSink Object
- * lines - number of lines
- *
- * Description:
- * Finds the Minium height that will contain a given number lines.
- *
- * Returns:
- * the height
- */
-/*ARGSUSED*/
-int
-XawTextSinkMaxHeight(Widget w, int lines)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- return((*cclass->text_sink_class.MaxHeight)(w, lines));
-}
-
-/*
- * Function:
- * XawTextSinkSetTabs
- *
- * Parameters:
- * w - TextSink Object
- * tab_count - the number of tabs in the list
- * tabs - text positions of the tabs
- * Description:
- * Sets the Tab stops.
- */
-void
-XawTextSinkSetTabs(Widget w, int tab_count, int *tabs)
-{
- if (tab_count > 0) {
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
- short *char_tabs = (short*)XtMalloc((unsigned)tab_count * sizeof(short));
- short *tab, len = 0;
- int i;
-
- for (i = tab_count, tab = char_tabs; i; i--) {
- if ((short)*tabs > len)
- *tab++ = (len = (short)*tabs++);
- else {
- tabs++;
- --tab_count;
- }
- }
-
- if (tab_count > 0)
- (*cclass->text_sink_class.SetTabs)(w, tab_count, char_tabs);
- XtFree((char *)char_tabs);
- }
-}
-
-/*
- * Function:
- * XawTextSinkGetCursorBounds
- *
- * Parameters:
- * w - TextSinkObject
- * rect - X rectance containing the cursor bounds
- *
- * Description:
- * Finds the bounding box for the insert cursor (caret).
- */
-/*ARGSUSED*/
-void
-XawTextSinkGetCursorBounds(Widget w, XRectangle *rect)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- (*cclass->text_sink_class.GetCursorBounds)(w, rect);
-}
-
-#ifndef OLDXAW
-Bool
-XawTextSinkBeginPaint(Widget w)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- if (cclass->text_sink_class.extension->BeginPaint == NULL ||
- cclass->text_sink_class.extension->PreparePaint == NULL ||
- cclass->text_sink_class.extension->DoPaint == NULL ||
- cclass->text_sink_class.extension->EndPaint == NULL)
- return (False);
-
- return ((*cclass->text_sink_class.extension->BeginPaint)(w));
-}
-
-static Bool
-BeginPaint(Widget w)
-{
- TextSinkObject sink = (TextSinkObject)w;
-
- if (sink->text_sink.paint != NULL)
- return (False);
-
- sink->text_sink.paint = XtNew(XawTextPaintList);
- sink->text_sink.paint->clip = XmuCreateArea();
- sink->text_sink.paint->hightabs = NULL;
- sink->text_sink.paint->paint = NULL;
- sink->text_sink.paint->bearings = NULL;
-
- return (True);
-}
-
-void
-XawTextSinkPreparePaint(Widget w, int y, int line, XawTextPosition from,
- XawTextPosition to, Bool highlight)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- (*cclass->text_sink_class.extension->PreparePaint)
- (w, y, line, from, to, highlight);
-}
-
-#if 0
-/*ARGSUSED*/
-static void
-PreparePaint(Widget w, int y, int line, XawTextPosition from, XawTextPosition to,
- Bool highlight)
-{
-}
-#endif
-
-void
-XawTextSinkDoPaint(Widget w)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- (*cclass->text_sink_class.extension->DoPaint)(w);
-}
-
-#if 0
-/*ARGSUSED*/
-static void
-DoPaint(Widget w)
-{
-}
-#endif
-
-Bool
-XawTextSinkEndPaint(Widget w)
-{
- TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
-
- return ((*cclass->text_sink_class.extension->EndPaint)(w));
-}
-
-static Bool
-EndPaint(Widget w)
-{
- TextSinkObject sink = (TextSinkObject)w;
- XawTextPaintStruct *paint, *next;
-
- if (sink->text_sink.paint == NULL)
- return (False);
-
- XmuDestroyArea(sink->text_sink.paint->clip);
- if (sink->text_sink.paint->hightabs)
- XmuDestroyArea(sink->text_sink.paint->hightabs);
- paint = sink->text_sink.paint->paint;
- while (paint) {
- next = paint->next;
- if (paint->text)
- XtFree((XtPointer)paint->text);
- if (paint->backtabs)
- XmuDestroyArea(paint->backtabs);
- XtFree((XtPointer)paint);
- paint = next;
- }
-
- paint = sink->text_sink.paint->bearings;
- while (paint) {
- next = paint->next;
- if (paint->text)
- XtFree((XtPointer)paint->text);
- XtFree((XtPointer)paint);
- paint = next;
- }
-
- XtFree((XtPointer)sink->text_sink.paint);
- sink->text_sink.paint = NULL;
- return (True);
-}
-
-static XawTextPropertyList **prop_lists;
-static Cardinal num_prop_lists;
-
-static int
-bcmp_qident(_Xconst void *left, _Xconst void *right)
-{
- return ((long)left - (*(XawTextProperty**)right)->identifier);
-}
-
-static int
-qcmp_qident(_Xconst void *left, _Xconst void *right)
-{
- return ((*(XawTextProperty**)left)->identifier -
- (*(XawTextProperty**)right)->identifier);
-}
-
-static void
-SetXlfdDefaults(Display *display, XawTextProperty *property)
-{
- Atom atom = XInternAtom(display, "FONT", True);
- unsigned long value;
- char *str;
-
- if (XGetFontProperty(property->font, atom, &value)) {
- char *xlfd = XGetAtomName(display, value);
-
- if (xlfd) {
- char *sep = xlfd + 1;
- char *name = sep;
-
- property->xlfd = XrmStringToQuark(xlfd);
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->foundry = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->family = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->weight = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->slant = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->setwidth = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->addstyle = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->pixel_size = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->point_size = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->res_x = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->res_y = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->spacing = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->avgwidth = XrmStringToQuark(name);
- name = sep;
-
- sep = strchr(sep, '-'); *sep++ = '\0';
- property->registry = XrmStringToQuark(name);
- name = sep;
-
- property->encoding = XrmStringToQuark(name);
-
- XFree(xlfd);
- }
- }
-
- atom = XInternAtom(display, "UNDERLINE_THICKNESS", True);
- if (XGetFontProperty(property->font, atom, &value) &&
- (str = XGetAtomName(display, value)) != NULL) {
- property->underline_thickness = atoi(str);
- XFree(str);
- }
- else {
- /* XLFD says:
- * CapStemWidth = average width of the stems of capitals
- * if (UNDERLINE_THICKNESS undefined) then
- * UNDERLINE_THICKNESS = CapStemWidth
- *
- * How do I know the value of CapStemWidth??
- */
- if (property->pixel_size != NULLQUARK) {
- property->underline_thickness =
- atoi(XrmQuarkToString(property->pixel_size)) / 10;
- property->underline_thickness =
- XawMax(1, property->underline_thickness);
- }
- else
- property->underline_thickness = 1;
- }
-
- atom = XInternAtom(display, "UNDERLINE_POSITION", True);
- if (XGetFontProperty(property->font, atom, &value) &&
- (str = XGetAtomName(display, value)) != NULL) {
- property->underline_position = atoi(str);
- XFree(str);
- }
- else
- /* XLFD says:
- * if (UNDERLINE_POSITION undefined) then
- * UNDERLINE_POSITION = ROUND((maximum_descent) / 2)
- */
- property->underline_position =
- property->font->max_bounds.descent >> 1;
-
- /* I am assuming xlfd does not consider that lines are
- * centered in the path */
- property->underline_position += property->underline_thickness >> 1;
-
-}
-
-static void
-DestroyTextPropertyList(XawTextPropertyList *list)
-{
- int i;
-
- for (i = 0; i < list->num_properties; i++) {
- if (list->properties[i]->font)
- XFreeFont(DisplayOfScreen(list->screen), list->properties[i]->font);
- XtFree((char*)list->properties[i]);
- }
- if (list->properties)
- XtFree((char*)list->properties);
- XtFree((char*)list);
-}
-
-static XawTextProperty *
-_XawTextSinkGetProperty(XawTextPropertyList *list, XrmQuark property)
-{
- if (property != NULLQUARK && list && list->properties) {
- XawTextProperty **ptr = (XawTextProperty**)
- bsearch((void*)(long)property,
- list->properties, list->num_properties,
- sizeof(XawTextProperty*), bcmp_qident);
-
- if (ptr)
- return (*ptr);
- }
-
- return (NULL);
-}
-
-XawTextProperty *
-XawTextSinkGetProperty(Widget w, XrmQuark property)
-{
- TextSinkObject sink = (TextSinkObject)w;
- XawTextPropertyList *list = sink->text_sink.properties;
-
- return (_XawTextSinkGetProperty(list, property));
-}
-
-XawTextProperty *
-XawTextSinkCopyProperty(Widget w, XrmQuark property)
-{
- XawTextProperty *cur, *ret;
-
- if ((cur = XawTextSinkGetProperty(w, property)) == NULL)
- cur = XawTextSinkGetProperty(w, Qdefault);
- ret = (XawTextProperty*)XtCalloc(1, sizeof(XawTextProperty));
- if (cur)
- memcpy(ret, cur, sizeof(XawTextProperty));
- ret->identifier = NULLQUARK;
- ret->mask &= ~XAW_TPROP_FONT;
-
- return (ret);
-}
-
-static XawTextProperty *
-_XawTextSinkAddProperty(XawTextPropertyList *list, XawTextProperty *property,
- Bool replace)
-{
- XawTextProperty *result;
- XColor color;
- char identifier[1024];
- char foreground[16];
- char background[16];
- char *foundry, *family, *weight, *slant, *setwidth, *addstyle, *pixel_size,
- *point_size, *res_x, *res_y, *spacing, *avgwidth, *registry, *encoding;
- char *xlfd;
- static char *asterisk = "*", *null = "";
- XrmQuark quark;
-
- if (list == NULL || property == NULL)
- return (NULL);
-
- if (property->mask & XAW_TPROP_FOREGROUND) {
- color.pixel = property->foreground;
- XQueryColor(DisplayOfScreen(list->screen), list->colormap, &color);
- XmuSnprintf(foreground, sizeof(foreground), "%04x%04x%04x",
- color.red, color.green, color.blue);
- }
- else
- strcpy(foreground, asterisk);
- if (property->mask & XAW_TPROP_BACKGROUND) {
- color.pixel = property->background;
- XQueryColor(DisplayOfScreen(list->screen), list->colormap, &color);
- XmuSnprintf(background, sizeof(background), "%04x%04x%04x",
- color.red, color.green, color.blue);
- }
- else
- strcpy(background, asterisk);
-
- if (property->xlfd_mask & XAW_TPROP_FOUNDRY)
- foundry = XrmQuarkToString(property->foundry);
- else
- foundry = asterisk;
-
- /* use default, or what was requested */
- if (property->family != NULLQUARK)
- family = XrmQuarkToString(property->family);
- else
- family = asterisk;
- if (property->weight != NULLQUARK)
- weight = XrmQuarkToString(property->weight);
- else
- weight = asterisk;
- if (property->slant != NULLQUARK) {
- slant = XrmQuarkToString(property->slant);
- if (toupper(*slant) != 'R')
- slant = asterisk; /* X defaults to italics, so, don't
- care in resolving between `I' and `O' */
- }
- else
- slant = asterisk;
-
- if (property->xlfd_mask & XAW_TPROP_SETWIDTH)
- setwidth = XrmQuarkToString(property->setwidth);
- else
- setwidth = asterisk;
- if (property->xlfd_mask & XAW_TPROP_ADDSTYLE)
- addstyle = XrmQuarkToString(property->addstyle);
- else
- addstyle = null;
-
- /* use default, or what was requested */
- if (!(property->mask & XAW_TPROP_POINTSIZE) &&
- property->pixel_size != NULLQUARK)
- pixel_size = XrmQuarkToString(property->pixel_size);
- else
- pixel_size = asterisk;
-
- if (property->xlfd_mask & XAW_TPROP_POINTSIZE)
- point_size = XrmQuarkToString(property->point_size);
- else
- point_size = asterisk;
- if (property->xlfd_mask & XAW_TPROP_RESX)
- res_x = XrmQuarkToString(property->res_x);
- else
- res_x = asterisk;
- if (property->xlfd_mask & XAW_TPROP_RESY)
- res_y = XrmQuarkToString(property->res_y);
- else
- res_y = asterisk;
- if (property->xlfd_mask & XAW_TPROP_SPACING)
- spacing = XrmQuarkToString(property->spacing);
- else
- spacing = asterisk;
- if (property->xlfd_mask & XAW_TPROP_AVGWIDTH)
- avgwidth = XrmQuarkToString(property->avgwidth);
- else
- avgwidth = asterisk;
-
- /* use default, or what that was requested */
- if (property->registry != NULLQUARK)
- registry = XrmQuarkToString(property->registry);
- else
- registry = asterisk;
- if (property->encoding != NULLQUARK)
- encoding = XrmQuarkToString(property->encoding);
- else
- encoding = asterisk;
-
- if (replace) {
- result = XtNew(XawTextProperty);
- memcpy(result, property, sizeof(XawTextProperty));
- }
- else
- result = property;
-
- /* XXX should do the best to load a suitable font here */
- if (!(result->mask & XAW_TPROP_FONT)) {
- XmuSnprintf(identifier, sizeof(identifier),
- "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
- foundry, family, weight, slant, setwidth, addstyle, pixel_size,
- point_size, res_x, res_y, spacing, avgwidth, registry, encoding);
- if ((result->font = XLoadQueryFont(DisplayOfScreen(list->screen),
- identifier)) != NULL) {
- result->mask |= XAW_TPROP_FONT;
- SetXlfdDefaults(DisplayOfScreen(list->screen), result);
- }
- else
- result->mask &= ~XAW_TPROP_FONT;
- }
-
- if (result->font)
- xlfd = XrmQuarkToString(result->xlfd);
- else
- xlfd = null;
-
- XmuSnprintf(identifier, sizeof(identifier), "%08lx%08lx%s%s%d%d%d%d%s",
- property->mask, property->xlfd_mask,
- foreground, background,
- (result->mask & XAW_TPROP_UNDERLINE) != 0,
- (result->mask & XAW_TPROP_OVERSTRIKE) != 0,
- (result->mask & XAW_TPROP_SUBSCRIPT) != 0,
- (result->mask & XAW_TPROP_SUPERSCRIPT) != 0,
- xlfd);
-
- quark = XrmStringToQuark(identifier);
- if (result->identifier == NULLQUARK)
- result->identifier = quark;
- result->code = quark;
-
- if ((property = _XawTextSinkGetProperty(list, result->identifier)) != NULL) {
- if (result->font)
- XFreeFont(DisplayOfScreen(list->screen), result->font);
- if (replace)
- XtFree((XtPointer)result);
-
- return (property);
- }
-
- list->properties = (XawTextProperty**)
- XtRealloc((XtPointer)list->properties, sizeof(XawTextProperty*) *
- (list->num_properties + 1));
- list->properties[list->num_properties++] = result;
- qsort((void*)list->properties, list->num_properties,
- sizeof(XawTextProperty*), qcmp_qident);
-
- return (result);
-}
-
-XawTextProperty *
-XawTextSinkAddProperty(Widget w, XawTextProperty *property)
-{
- TextSinkObject sink = (TextSinkObject)w;
- XawTextPropertyList *list = sink->text_sink.properties;
-
- return (_XawTextSinkAddProperty(list, property, True));
-}
-
-XawTextProperty *
-XawTextSinkCombineProperty(Widget w,
- XawTextProperty *property, XawTextProperty *combine,
- Bool override)
-{
- if (property == NULL || combine == NULL)
- return (property);
-
- if ((override || !(property->mask & XAW_TPROP_FOREGROUND)) &&
- (combine->mask & XAW_TPROP_FOREGROUND)) {
- property->mask |= XAW_TPROP_FOREGROUND;
- property->foreground = combine->foreground;
- }
- if ((override || !(property->mask & XAW_TPROP_BACKGROUND)) &&
- (combine->mask & XAW_TPROP_BACKGROUND)) {
- property->mask |= XAW_TPROP_BACKGROUND;
- property->background = combine->background;
- }
- if ((override || !(property->mask & XAW_TPROP_FPIXMAP)) &&
- (combine->mask & XAW_TPROP_FPIXMAP)) {
- property->mask |= XAW_TPROP_FPIXMAP;
- property->foreground_pixmap = combine->foreground_pixmap;
- }
- if ((override || !(property->mask & XAW_TPROP_BPIXMAP)) &&
- (combine->mask & XAW_TPROP_BPIXMAP)) {
- property->mask |= XAW_TPROP_BPIXMAP;
- property->background_pixmap = combine->background_pixmap;
- }
- if (combine->mask & XAW_TPROP_UNDERLINE)
- property->mask |= XAW_TPROP_UNDERLINE;
- if (combine->mask & XAW_TPROP_OVERSTRIKE)
- property->mask |= XAW_TPROP_OVERSTRIKE;
- if ((override || !(property->mask & XAW_TPROP_SUPERSCRIPT)) &&
- (combine->mask & XAW_TPROP_SUBSCRIPT))
- property->mask |= XAW_TPROP_SUBSCRIPT;
- if ((property->mask & XAW_TPROP_SUBSCRIPT) &&
- (combine->mask & XAW_TPROP_SUPERSCRIPT))
- property->mask |= XAW_TPROP_SUPERSCRIPT;
- if ((override || !(property->xlfd_mask & XAW_TPROP_FOUNDRY)) &&
- (combine->xlfd_mask & XAW_TPROP_FOUNDRY)) {
- property->xlfd_mask |= XAW_TPROP_FOUNDRY;
- property->foundry = combine->foundry;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_FAMILY)) &&
- (combine->xlfd_mask & XAW_TPROP_FAMILY)) {
- property->xlfd_mask |= XAW_TPROP_FAMILY;
- property->family = combine->family;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_WEIGHT)) &&
- (combine->xlfd_mask & XAW_TPROP_WEIGHT)) {
- property->xlfd_mask |= XAW_TPROP_WEIGHT;
- property->weight = combine->weight;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_SLANT)) &&
- (combine->xlfd_mask & XAW_TPROP_SLANT)) {
- property->xlfd_mask |= XAW_TPROP_SLANT;
- property->slant = combine->slant;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_SETWIDTH)) &&
- (combine->xlfd_mask & XAW_TPROP_SETWIDTH)) {
- property->xlfd_mask |= XAW_TPROP_SETWIDTH;
- property->setwidth = combine->setwidth;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_ADDSTYLE)) &&
- (combine->xlfd_mask & XAW_TPROP_ADDSTYLE)) {
- property->xlfd_mask |= XAW_TPROP_ADDSTYLE;
- property->addstyle = combine->addstyle;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_PIXELSIZE)) &&
- (combine->xlfd_mask & XAW_TPROP_PIXELSIZE)) {
- property->xlfd_mask |= XAW_TPROP_PIXELSIZE;
- property->pixel_size = combine->pixel_size;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_POINTSIZE)) &&
- (combine->xlfd_mask & XAW_TPROP_POINTSIZE)) {
- property->xlfd_mask |= XAW_TPROP_POINTSIZE;
- property->point_size = combine->point_size;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_RESX)) &&
- (combine->xlfd_mask & XAW_TPROP_RESX)) {
- property->xlfd_mask |= XAW_TPROP_RESX;
- property->res_x = combine->res_x;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_RESY)) &&
- (combine->xlfd_mask & XAW_TPROP_RESY)) {
- property->xlfd_mask |= XAW_TPROP_RESY;
- property->res_y = combine->res_y;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_SPACING)) &&
- (combine->xlfd_mask & XAW_TPROP_SPACING)) {
- property->xlfd_mask |= XAW_TPROP_SPACING;
- property->spacing = combine->spacing;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_AVGWIDTH)) &&
- (combine->xlfd_mask & XAW_TPROP_AVGWIDTH)) {
- property->xlfd_mask |= XAW_TPROP_AVGWIDTH;
- property->avgwidth = combine->avgwidth;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_REGISTRY)) &&
- (combine->xlfd_mask & XAW_TPROP_REGISTRY)) {
- property->xlfd_mask |= XAW_TPROP_REGISTRY;
- property->registry = combine->registry;
- }
- if ((override || !(property->xlfd_mask & XAW_TPROP_ENCODING)) &&
- (combine->xlfd_mask & XAW_TPROP_ENCODING)) {
- property->xlfd_mask |= XAW_TPROP_ENCODING;
- property->encoding = combine->encoding;
- }
-
- return (property);
-}
-
-/*
- * The default property must be defined first, if the code is willing to
- * combine properties.
- */
-XawTextPropertyList *
-XawTextSinkConvertPropertyList(String name, String spec, Screen *screen,
- Colormap colormap, int depth)
-{
- XrmQuark qname = XrmStringToQuark(name);
- XawTextPropertyList **ptr = NULL;
- XawTextPropertyList *propl, *prev = NULL;
- XawTextProperty *def_prop = NULL;
- String str, tok, tmp;
- char buffer[BUFSIZ];
-
- if (prop_lists) ptr = (XawTextPropertyList**)
- bsearch((void*)(long)qname, prop_lists, num_prop_lists,
- sizeof(XawTextPropertyList*), bcmp_qident);
- if (ptr) {
- propl = *ptr;
- while (propl) {
- prev = propl;
- if (propl->screen == screen &&
- propl->colormap == colormap &&
- propl->depth == depth)
- return (propl);
- propl = propl->next;
- }
- }
-
- propl = XtNew(XawTextPropertyList);
- propl->identifier = qname;
- propl->screen = screen;
- propl->colormap = colormap;
- propl->depth = depth;
- propl->next = NULL;
-
- if (prev)
- prev->next = propl;
-
- propl->properties = NULL;
- propl->num_properties = 0;
-
- str = XtNewString(spec);
- for (tok = str; tok; tok = tmp) {
- XawTextProperty *prop;
- XawParams *params;
- XrmQuark ident;
- XawArgVal *argval;
- XColor color, exact;
-
- if (def_prop == NULL && propl->num_properties)
- def_prop = _XawTextSinkGetProperty(propl, Qdefault);
- tmp = strchr(tok, ',');
- if (tmp) {
- *tmp = '\0';
- if (*++tmp == '\0')
- tmp = NULL;
- }
- params = XawParseParamsString(tok);
- ident = XrmStringToQuark(params->name);
- if (ident == NULLQUARK) {
- XmuSnprintf(buffer, sizeof(buffer),
- "Bad text property name \"%s\".", params->name);
- XtAppWarning(XtDisplayToApplicationContext
- (DisplayOfScreen(screen)), buffer);
- DestroyTextPropertyList(propl);
- if (prev)
- prev->next = NULL;
- XawFreeParamsStruct(params);
- return (NULL);
- }
- else if (_XawTextSinkGetProperty(propl, ident) != NULL) {
- XawFreeParamsStruct(params);
- continue;
- }
-
- prop = (XawTextProperty*)XtCalloc(1, sizeof(XawTextProperty));
- prop->identifier = ident;
-
- if ((argval = XawFindArgVal(params, "font")) != NULL &&
- argval->value) {
-
- if ((prop->font = XLoadQueryFont(DisplayOfScreen(screen),
- argval->value)) == NULL) {
- XmuSnprintf(buffer, sizeof(buffer),
- "Cannot load font \"%s\".", argval->value);
- XtAppWarning(XtDisplayToApplicationContext
- (DisplayOfScreen(screen)), buffer);
- DestroyTextPropertyList(propl);
- if (prev)
- prev->next = NULL;
- XawFreeParamsStruct(params);
- return (NULL);
- }
- prop->mask |= XAW_TPROP_FONT;
- SetXlfdDefaults(DisplayOfScreen(screen), prop);
- }
- /* fontset processing here */
-
- if ((argval = XawFindArgVal(params, "foreground")) != NULL &&
- argval->value) {
- if (!XAllocNamedColor(DisplayOfScreen(screen), colormap,
- argval->value, &color, &exact)) {
- XmuSnprintf(buffer, sizeof(buffer),
- "Cannot allocate color \"%s\".", argval->value);
- XtAppWarning(XtDisplayToApplicationContext
- (DisplayOfScreen(screen)), buffer);
- DestroyTextPropertyList(propl);
- if (prev)
- prev->next = NULL;
- XawFreeParamsStruct(params);
- return (NULL);
- }
- prop->foreground = color.pixel;
- prop->mask |= XAW_TPROP_FOREGROUND;
- }
- if ((argval = XawFindArgVal(params, "background")) != NULL &&
- argval->value) {
- if (!XAllocNamedColor(DisplayOfScreen(screen), colormap,
- argval->value, &color, &exact)) {
- XmuSnprintf(buffer, sizeof(buffer),
- "Cannot allocate color \"%s\".", argval->value);
- XtAppWarning(XtDisplayToApplicationContext
- (DisplayOfScreen(screen)), buffer);
- DestroyTextPropertyList(propl);
- if (prev)
- prev->next = NULL;
- XawFreeParamsStruct(params);
- return (NULL);
- }
- prop->background = color.pixel;
- prop->mask |= XAW_TPROP_BACKGROUND;
- }
- /* foreground_pixmap and background_pixmap processing here */
-
- if (XawFindArgVal(params, "underline"))
- prop->mask |= XAW_TPROP_UNDERLINE;
- if (XawFindArgVal(params, "overstrike"))
- prop->mask |= XAW_TPROP_OVERSTRIKE;
-
- if (XawFindArgVal(params, "subscript"))
- prop->mask |= XAW_TPROP_SUBSCRIPT;
- else if (XawFindArgVal(params, "superscript"))
- prop->mask |= XAW_TPROP_SUPERSCRIPT;
-
- /* xlfd */
- if ((argval = XawFindArgVal(params, "foundry")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_FOUNDRY;
- prop->foundry = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "family")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_FAMILY;
- prop->family = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "weight")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_WEIGHT;
- prop->weight = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "slant")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_SLANT;
- prop->slant = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "setwidth")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_SETWIDTH;
- prop->setwidth = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "addstyle")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_ADDSTYLE;
- prop->addstyle = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "pixelsize")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_PIXELSIZE;
- prop->pixel_size = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "pointsize")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_POINTSIZE;
- prop->point_size = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "resx")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_RESX;
- prop->res_x = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "resy")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_RESY;
- prop->res_y = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "spacing")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_SPACING;
- prop->spacing = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "avgwidth")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_AVGWIDTH;
- prop->avgwidth = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "registry")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_REGISTRY;
- prop->registry = XrmStringToQuark(argval->value);
- }
- if ((argval = XawFindArgVal(params, "encoding")) != NULL &&
- argval->value) {
- prop->xlfd_mask |= XAW_TPROP_ENCODING;
- prop->encoding = XrmStringToQuark(argval->value);
- }
-
- if (def_prop)
- (void)XawTextSinkCombineProperty(NULL, prop, def_prop, False);
- (void)_XawTextSinkAddProperty(propl, prop, False);
-
- XawFreeParamsStruct(params);
- }
-
- prop_lists = (XawTextPropertyList**)
- XtRealloc((XtPointer)prop_lists, sizeof(XawTextPropertyList*) *
- (num_prop_lists + 1));
- prop_lists[num_prop_lists++] = propl;
- qsort((void*)prop_lists, num_prop_lists, sizeof(XawTextPropertyList*),
- qcmp_qident);
-
- XtFree(str);
-
- return (propl);
-}
-
-/*ARGSUSED*/
-static Boolean
-CvtStringToPropertyList(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- XawTextPropertyList *propl = NULL;
- String name;
- Widget w;
-
- if (*num_args != 1) {
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- "wrongParameters", "cvtStringToTextProperties",
- "ToolkitError",
- "String to textProperties conversion needs widget argument",
- NULL, NULL);
- return (False);
- }
-
- w = *(Widget*)args[0].addr;
- while (w && !XtIsWidget(w))
- w = XtParent(w);
-
- name = (String)(fromVal[0].addr);
-
- if (w) {
- XawTextPropertyList **ptr = NULL;
- if (prop_lists) ptr = (XawTextPropertyList**)
- bsearch((void*)(long)XrmStringToQuark(name),
- prop_lists, num_prop_lists,
- sizeof(XawTextPropertyList*), bcmp_qident);
-
- if (ptr) {
- Screen *screen = w->core.screen;
- Colormap colormap = w->core.colormap;
- int depth = w->core.depth;
-
- propl = *ptr;
- while (propl) {
- if (propl->screen == screen &&
- propl->colormap == colormap &&
- propl->depth == depth)
- break;
- propl = propl->next;
- }
- }
- }
-
- if (!propl) {
- XtDisplayStringConversionWarning(dpy, (String)fromVal->addr,
- XawRTextProperties);
- toVal->addr = NULL;
- toVal->size = sizeof(XawTextPropertyList*);
- return (False);
- }
-
- if (toVal->addr != NULL) {
- if (toVal->size < sizeof(XawTextPropertyList*)) {
- toVal->size = sizeof(XawTextPropertyList*);
- return (False);
- }
- *(XawTextPropertyList**)(toVal->addr) = propl;
- }
- else {
- static XawTextPropertyList *static_val;
-
- static_val = propl;
- toVal->addr = (XPointer)&static_val;
- }
- toVal->size = sizeof(XawTextProperty*);
-
- return (True);
-}
-
-/*ARGSUSED*/
-static Boolean
-CvtPropertyListToString(Display *dpy, XrmValue *args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *converter_data)
-{
- static char *buffer;
- Cardinal size;
- XawTextPropertyList *propl;
-
- propl = *(XawTextPropertyList**)fromVal[0].addr;
-
- buffer = XrmQuarkToString(propl->identifier);
- size = strlen(buffer) + 1;
-
- if (toVal->addr != NULL) {
- if (toVal->size < size) {
- toVal->size = size;
- return (False);
- }
- strcpy((char *)toVal->addr, buffer);
- }
- else
- toVal->addr = buffer;
- toVal->size = size;
-
- return (True);
-}
-#endif
+/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Chris Peterson, MIT X Consortium. + * + * Much code taken from X11R3 AsciiSink. + */ + +/* + * TextSink.c - TextSink object. (For use with the text widget). + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/TextP.h> +#include <X11/Xaw/TextSinkP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * Prototypes + */ +static void XawTextSinkClassPartInitialize(WidgetClass); +static void XawTextSinkInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawTextSinkDestroy(Widget); +static Boolean XawTextSinkSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +static int MaxLines(Widget, unsigned int); +static int MaxHeight(Widget, int); +static void DisplayText(Widget, int, int, XawTextPosition, XawTextPosition, + Bool); +static void InsertCursor(Widget, int, int, XawTextInsertState); +static void ClearToBackground(Widget, int, int, unsigned int, unsigned int); +static void FindPosition(Widget, XawTextPosition, int, int, Bool, + XawTextPosition*, int*, int*); +static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*, + XawTextPosition*, int*); +static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*); +static void SetTabs(Widget, int, short*); +static void GetCursorBounds(Widget, XRectangle*); + +#ifndef OLDXAW +static Boolean CvtStringToPropertyList(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Boolean CvtPropertyListToString(Display*, XrmValue*, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static Bool BeginPaint(Widget); +static Bool EndPaint(Widget); +static void SetXlfdDefaults(Display*, XawTextProperty*); +#endif + +/* + * External + */ +void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned); +void _XawTextSinkDisplayText(Widget, int, int, XawTextPosition, XawTextPosition, + Bool); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(TextSinkRec, text_sink.field) +static XtResource resources[] = { + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(foreground), + XtRString, + XtDefaultForeground + }, + { + XtNbackground, + XtCBackground, + XtRPixel, + sizeof(Pixel), + offset(background), + XtRString, + XtDefaultBackground + }, +#ifndef OLDXAW + { + XtNcursorColor, + XtCColor, + XtRPixel, + sizeof(Pixel), + offset(cursor_color), + XtRString, + XtDefaultForeground + }, + { + XawNtextProperties, + XawCTextProperties, + XawRTextProperties, + sizeof(XawTextPropertyList*), + offset(properties), + XtRImmediate, + NULL + }, +#endif +}; +#undef offset + +#ifndef OLDXAW +static TextSinkExtRec extension_rec = { + NULL, /* next_extension */ + NULLQUARK, /* record_type */ + 1, /* version */ + sizeof(TextSinkExtRec), /* record_size */ + BeginPaint, + NULL, + NULL, + EndPaint +}; + +static XrmQuark Qdefault; +#endif + +#define Superclass (&objectClassRec) +TextSinkClassRec textSinkClassRec = { + /* object */ + { + (WidgetClass)Superclass, /* superclass */ + "TextSink", /* class_name */ + sizeof(TextSinkRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + XawTextSinkClassPartInitialize, /* class_part_initialize */ + False, /* class_inited */ + XawTextSinkInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* obj1 */ + NULL, /* obj2 */ + 0, /* obj3 */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* obj4 */ + False, /* obj5 */ + False, /* obj6 */ + False, /* obj7 */ + XawTextSinkDestroy, /* destroy */ + NULL, /* obj8 */ + NULL, /* obj9 */ + XawTextSinkSetValues, /* set_values */ + NULL, /* set_values_hook */ + NULL, /* obj10 */ + NULL, /* get_values_hook */ + NULL, /* obj11 */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* obj12 */ + NULL, /* obj13 */ + NULL, /* obj14 */ + NULL, /* extension */ + }, + /* text_sink */ + { + DisplayText, /* DisplayText */ + InsertCursor, /* InsertCursor */ + ClearToBackground, /* ClearToBackground */ + FindPosition, /* FindPosition */ + FindDistance, /* FindDistance */ + Resolve, /* Resolve */ + MaxLines, /* MaxLines */ + MaxHeight, /* MaxHeight */ + SetTabs, /* SetTabs */ + GetCursorBounds, /* GetCursorBounds */ + }, +}; + +WidgetClass textSinkObjectClass = (WidgetClass)&textSinkClassRec; + +/* + * Implementation + */ +static void +XawTextSinkClassPartInitialize(WidgetClass wc) +{ + TextSinkObjectClass t_src, superC; +#ifndef OLDXAW + static XtConvertArgRec CvtArgs[] = { + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.self), + sizeof(Widget)}, + }; +#endif + + t_src = (TextSinkObjectClass) wc; + superC = (TextSinkObjectClass) t_src->object_class.superclass; + +#ifndef OLDXAW + extension_rec.record_type = XrmPermStringToQuark("TextSink"); + extension_rec.next_extension = (XtPointer)t_src->text_sink_class.extension; + t_src->text_sink_class.extension = &extension_rec; + + Qdefault = XrmPermStringToQuark("default"); +#endif + + /* + * We don't need to check for null super since we'll get to TextSink + * eventually. + */ + if (t_src->text_sink_class.DisplayText == XtInheritDisplayText) + t_src->text_sink_class.DisplayText = + superC->text_sink_class.DisplayText; + + if (t_src->text_sink_class.InsertCursor == XtInheritInsertCursor) + t_src->text_sink_class.InsertCursor = + superC->text_sink_class.InsertCursor; + + if (t_src->text_sink_class.ClearToBackground== XtInheritClearToBackground) + t_src->text_sink_class.ClearToBackground = + superC->text_sink_class.ClearToBackground; + + if (t_src->text_sink_class.FindPosition == XtInheritFindPosition) + t_src->text_sink_class.FindPosition = + superC->text_sink_class.FindPosition; + + if (t_src->text_sink_class.FindDistance == XtInheritFindDistance) + t_src->text_sink_class.FindDistance = + superC->text_sink_class.FindDistance; + + if (t_src->text_sink_class.Resolve == XtInheritResolve) + t_src->text_sink_class.Resolve = + superC->text_sink_class.Resolve; + + if (t_src->text_sink_class.MaxLines == XtInheritMaxLines) + t_src->text_sink_class.MaxLines = + superC->text_sink_class.MaxLines; + + if (t_src->text_sink_class.MaxHeight == XtInheritMaxHeight) + t_src->text_sink_class.MaxHeight = + superC->text_sink_class.MaxHeight; + + if (t_src->text_sink_class.SetTabs == XtInheritSetTabs) + t_src->text_sink_class.SetTabs = + superC->text_sink_class.SetTabs; + + if (t_src->text_sink_class.GetCursorBounds == XtInheritGetCursorBounds) + t_src->text_sink_class.GetCursorBounds = + superC->text_sink_class.GetCursorBounds; + +#ifndef OLDXAW + XtSetTypeConverter(XtRString, XawRTextProperties, CvtStringToPropertyList, + &CvtArgs[0], XtNumber(CvtArgs), XtCacheNone, NULL); + XtSetTypeConverter(XawRTextProperties, XtRString, CvtPropertyListToString, + NULL, 0, XtCacheNone, NULL); +#endif +} + +/* + * Function: + * XawTextSinkInitialize + * + * Parameters: + * request - requested and new values for the object instance + * cnew - "" + * + * Description: + * Initializes the TextSink Object. + */ +/*ARGSUSED*/ +static void +XawTextSinkInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + TextSinkObject sink = (TextSinkObject)cnew; + + sink->text_sink.tab_count = 0; /* Initialize the tab stops. */ + sink->text_sink.tabs = NULL; + sink->text_sink.char_tabs = NULL; +#ifndef OLDXAW + sink->text_sink.paint = NULL; +#endif +} + +/* + * Function: + * XawTextSinkDestroy + * + * Parameters: + * w - TextSink Object + * + * Description: + * This function cleans up when the object is destroyed. + */ +static void +XawTextSinkDestroy(Widget w) +{ + TextSinkObject sink = (TextSinkObject) w; + + XtFree((char *)sink->text_sink.tabs); + XtFree((char *)sink->text_sink.char_tabs); +} + +/* + * Function: + * XawTextSinkSetValues + * + * Parameters: + * current - current state of the object + * request - what was requested + * cnew - what the object will become + * + * Description: + * Sets the values for the TextSink. + * + * Returns: + * True if redisplay is needed + */ +/*ARGSUSED*/ +static Boolean +XawTextSinkSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + TextSinkObject w = (TextSinkObject)cnew; + TextSinkObject old_w = (TextSinkObject)current; + + if (w->text_sink.foreground != old_w->text_sink.foreground) + ((TextWidget)XtParent(cnew))->text.redisplay_needed = True; + + return (False); +} + +/* + * Function: + * DisplayText + * + * Parameters: + * w - TextSink Object + * x - location to start drawing text + * y - "" + * pos1 - location of starting and ending points in the text buffer + * pos2 - "" + * highlight - hightlight this text? + * + * Description: + * Stub function that in subclasses will display text. + */ +/*ARGSUSED*/ +static void +DisplayText(Widget w, int x, int y, + XawTextPosition pos1, XawTextPosition pos2, Bool highlight) +{ + return; +} + +/* + * Function: + * InsertCursor + * + * Parameters: + * w - TextSink Object + * x - location for the cursor + * y - "" + * state - whether to turn the cursor on, or off + * + * Description: + * Places the InsertCursor. + */ +/*ARGSUSED*/ +static void +InsertCursor(Widget w, int x, int y, XawTextInsertState state) +{ + return; +} + +/* + * Function: + * ClearToBackground + * + * Parameters: + * w - TextSink Object + * x - location of area to clear + * y - "" + * width - size of area to clear + * height - "" + * + * Description: + * Clears a region of the sink to the background color. + */ +/*ARGSUSED*/ +static void +ClearToBackground(Widget w, int x, int y, + unsigned int width, unsigned int height) +{ + /* + * Don't clear in height or width are zero + * XClearArea() has special semantic for these values + */ + TextWidget xaw = (TextWidget)XtParent(w); + Position x1, y1, x2, y2; + + x1 = XawMax(x, xaw->text.r_margin.left); + y1 = XawMax(y, xaw->text.r_margin.top); + x2 = XawMin(x + (int)width, (int)XtWidth(xaw) - xaw->text.r_margin.right); + y2 = XawMin(y + (int)height, (int)XtHeight(xaw) - xaw->text.r_margin.bottom); + + x = x1; + y = y1; + width = XawMax(0, x2 - x1); + height = XawMax(0, y2 - y1); + + if (height != 0 && width != 0) + XClearArea(XtDisplayOfObject(w), XtWindowOfObject(w), + x, y, width, height, False); +} + +/* + * Function: + * FindPosition + * + * Parameters: + * w - TextSink Object + * fromPos - reference position + * fromX - reference location + * width - width of section to paint text + * stopAtWordBreak - returned position is a word break? + * resPos - position found (return) + * resWidth - Width actually used (return) + * resHeight - Height actually used (return) + * + * Description: + * Finds a position in the text. + */ +/*ARGSUSED*/ +static void +FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width, + Bool stopAtWordBreak, XawTextPosition *resPos, + int *resWidth, int *resHeight) +{ + *resPos = fromPos; + *resHeight = *resWidth = 0; +} + +/* + * Function: + * FindDistance + * + * Parameters: + * w - TextSink Object + * fromPos - starting Position + * fromX - x location of starting Position + * toPos - end Position + * resWidth - Distance between fromPos and toPos + * resPos - Acutal toPos used + * resHeight - Height required by this text + * + * Description: + * Find the Pixel Distance between two text Positions. + */ +/*ARGSUSED*/ +static void +FindDistance(Widget w, XawTextPosition fromPos, int fromx, + XawTextPosition toPos, int *resWidth, + XawTextPosition *resPos, int *resHeight) +{ + *resWidth = *resHeight = 0; + *resPos = fromPos; +} + +/* + * Function: + * Resolve + * + * Parameters: + * w - TextSink Object + * pos - reference Position + * fromx - reference Location + * width - width to move + * resPos - resulting position + * + * Description: + * Resloves a location to a position. + */ +/*ARGSUSED*/ +static void +Resolve(Widget w, XawTextPosition pos, int fromx, int width, + XawTextPosition *resPos) +{ + *resPos = pos; +} + +/* + * Function: + * MaxLines + * + * Parameters: + * w - TextSink Object + * height - height to fit lines into + * + * Description: + * Finds the Maximum number of lines that will fit in a given height. + * + * Returns: + * Number of lines that will fit + */ +/*ARGSUSED*/ +static int +MaxLines(Widget w, unsigned int height) +{ + /* + * The fontset has gone down to descent Sink Widget, so + * the functions such MaxLines, SetTabs... are bound to the descent. + * + * by Li Yuhong, Jan. 15, 1991 + */ + return (0); +} + +/* + * Function: + * MaxHeight + * + * Parameters: + * w - TextSink Object + * lines - number of lines + * + * Description: + * Finds the Minium height that will contain a given number lines. + * + * Returns: + * the height + */ +/*ARGSUSED*/ +static int +MaxHeight(Widget w, int lines) +{ + return (0); +} + +/* + * Function: + * SetTabs + * + * Parameters: + * w - TextSink Object + * tab_count - the number of tabs in the list + * tabs - text positions of the tabs + * Description: + * Sets the Tab stops. + */ +/*ARGSUSED*/ +static void +SetTabs(Widget w, int tab_count, short *tabs) +{ + return; +} + +/* + * Function: + * GetCursorBounds + * + * Parameters: + * w - TextSinkObject. + * rect - X rectangle containing the cursor bounds + * + * Description: + * Finds the bounding box for the insert cursor (caret) + */ +/*ARGSUSED*/ +static void +GetCursorBounds(Widget w, XRectangle *rect) +{ + rect->x = rect->y = rect->width = rect->height = 0; +} + +/* + * Public Functions + */ +/* + * Function: + * XawTextSinkDisplayText + * + * Parameters: + * w - TextSink Object + * x - location to start drawing text + * y - "" + * pos1 - location of starting and ending points in the text buffer + * pos2 - "" + * highlight - hightlight this text? + */ +/*ARGSUSED*/ +void +XawTextSinkDisplayText(Widget w, +#if NeedWidePrototypes + int x, int y, +#else + Position x, Position y, +#endif + XawTextPosition pos1, XawTextPosition pos2, +#if NeedWidePrototypes + int highlight +#else + Boolean highlight +#endif +) +{ + _XawTextSinkDisplayText(w, x, y, pos1, pos2, highlight); +} + +void +_XawTextSinkDisplayText(Widget w, int x, int y, + XawTextPosition pos1, XawTextPosition pos2, + Bool highlight) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + (*cclass->text_sink_class.DisplayText)(w, x, y, pos1, pos2, highlight); +} + +/* + * Function: + * XawTextSinkInsertCursor + * + * Parameters: + * w - TextSink Object + * x - location for the cursor + * y - "" + * state - whether to turn the cursor on, or off + * + * Description: + * Places the InsertCursor. + */ +/*ARGSUSED*/ +void +#if NeedWidePrototypes +XawTextSinkInsertCursor(Widget w, int x, int y, int state) +#else +XawTextSinkInsertCursor(Widget w, Position x, Position y, XawTextInsertState state) +#endif +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + (*cclass->text_sink_class.InsertCursor)(w, x, y, state); +} + +/* + * Function: + * XawTextSinkClearToBackground + * + * Parameters: + * w - TextSink Object + * x - location of area to clear + * y - "" + * width - size of area to clear + * height - "" + * + * Description: + * Clears a region of the sink to the background color. + */ +/*ARGSUSED*/ +void +XawTextSinkClearToBackground(Widget w, +#if NeedWidePrototypes + int x, int y, + unsigned int width, unsigned int height +#else + Position x, Position y, + Dimension width, Dimension height +#endif +) +{ + _XawTextSinkClearToBackground(w, x, y, width, height); +} + +void +_XawTextSinkClearToBackground(Widget w, + int x, int y, + unsigned int width, unsigned int height) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + (*cclass->text_sink_class.ClearToBackground)(w, x, y, width, height); +} + +/* + * Function: + * XawTextSinkFindPosition + * + * Parameters: + * w - TextSink Object + * fromPos - reference position + * fromX - reference location + * width - width of section to paint text + * stopAtWordBreak - returned position is a word break? + * resPos - position found (return) + * resWidth - Width actually used (return) + * resHeight - Height actually used (return) + * + * Description: + * Finds a position in the text. + */ +/*ARGSUSED*/ +void +XawTextSinkFindPosition(Widget w, XawTextPosition fromPos, int fromx, int width, +#if NeedWidePrototypes + int stopAtWordBreak, +#else + Boolean stopAtWordBreak, +#endif + XawTextPosition *resPos, int *resWidth, int *resHeight) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + (*cclass->text_sink_class.FindPosition)(w, fromPos, fromx, width, + stopAtWordBreak, + resPos, resWidth, resHeight); +} + +/* + * Function: + * XawTextSinkFindDistance + * + * Parameters: + * w - TextSink Object + * fromPos - starting Position + * fromX - x location of starting Position + * toPos - end Position + * resWidth - Distance between fromPos and toPos + * resPos - Acutal toPos used + * resHeight - Height required by this text + * + * Description: + * Find the Pixel Distance between two text Positions. + */ +/*ARGSUSED*/ +void +XawTextSinkFindDistance(Widget w, XawTextPosition fromPos, int fromx, + XawTextPosition toPos, int *resWidth, + XawTextPosition *resPos, int *resHeight) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + (*cclass->text_sink_class.FindDistance)(w, fromPos, fromx, toPos, + resWidth, resPos, resHeight); +} + +/* + * Function: + * XawTextSinkResolve + * + * Parameters: + * w - TextSink Object + * pos - reference Position + * fromx - reference Location + * width - width to move + * resPos - resulting position + * + * Description: + * Resloves a location to a position. + */ +/*ARGSUSED*/ +void +XawTextSinkResolve(Widget w, XawTextPosition pos, int fromx, int width, + XawTextPosition *resPos) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass) w->core.widget_class; + + (*cclass->text_sink_class.Resolve)(w, pos, fromx, width, resPos); +} + +/* + * Function: + * XawTextSinkMaxLines + * + * Parameters: + * w - TextSink Object + * height - height to fit lines into + * + * Description: + * Finds the Maximum number of lines that will fit in a given height. + * + * Returns: + * Number of lines that will fit + */ +/*ARGSUSED*/ +int +#if NeedWidePrototypes +XawTextSinkMaxLines(Widget w, unsigned int height) +#else +XawTextSinkMaxLines(Widget w, Dimension height) +#endif +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + return((*cclass->text_sink_class.MaxLines)(w, height)); +} + +/* + * Function: + * XawTextSinkMaxHeight + * + * Parameters: + * w - TextSink Object + * lines - number of lines + * + * Description: + * Finds the Minium height that will contain a given number lines. + * + * Returns: + * the height + */ +/*ARGSUSED*/ +int +XawTextSinkMaxHeight(Widget w, int lines) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + return((*cclass->text_sink_class.MaxHeight)(w, lines)); +} + +/* + * Function: + * XawTextSinkSetTabs + * + * Parameters: + * w - TextSink Object + * tab_count - the number of tabs in the list + * tabs - text positions of the tabs + * Description: + * Sets the Tab stops. + */ +void +XawTextSinkSetTabs(Widget w, int tab_count, int *tabs) +{ + if (tab_count > 0) { + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + short *char_tabs = (short*)XtMalloc((unsigned)tab_count * sizeof(short)); + short *tab, len = 0; + int i; + + for (i = tab_count, tab = char_tabs; i; i--) { + if ((short)*tabs > len) + *tab++ = (len = (short)*tabs++); + else { + tabs++; + --tab_count; + } + } + + if (tab_count > 0) + (*cclass->text_sink_class.SetTabs)(w, tab_count, char_tabs); + XtFree((char *)char_tabs); + } +} + +/* + * Function: + * XawTextSinkGetCursorBounds + * + * Parameters: + * w - TextSinkObject + * rect - X rectance containing the cursor bounds + * + * Description: + * Finds the bounding box for the insert cursor (caret). + */ +/*ARGSUSED*/ +void +XawTextSinkGetCursorBounds(Widget w, XRectangle *rect) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + (*cclass->text_sink_class.GetCursorBounds)(w, rect); +} + +#ifndef OLDXAW +Bool +XawTextSinkBeginPaint(Widget w) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + if (cclass->text_sink_class.extension->BeginPaint == NULL || + cclass->text_sink_class.extension->PreparePaint == NULL || + cclass->text_sink_class.extension->DoPaint == NULL || + cclass->text_sink_class.extension->EndPaint == NULL) + return (False); + + return ((*cclass->text_sink_class.extension->BeginPaint)(w)); +} + +static Bool +BeginPaint(Widget w) +{ + TextSinkObject sink = (TextSinkObject)w; + + if (sink->text_sink.paint != NULL) + return (False); + + sink->text_sink.paint = XtNew(XawTextPaintList); + sink->text_sink.paint->clip = XmuCreateArea(); + sink->text_sink.paint->hightabs = NULL; + sink->text_sink.paint->paint = NULL; + sink->text_sink.paint->bearings = NULL; + + return (True); +} + +void +XawTextSinkPreparePaint(Widget w, int y, int line, XawTextPosition from, + XawTextPosition to, Bool highlight) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + (*cclass->text_sink_class.extension->PreparePaint) + (w, y, line, from, to, highlight); +} + +#if 0 +/*ARGSUSED*/ +static void +PreparePaint(Widget w, int y, int line, XawTextPosition from, XawTextPosition to, + Bool highlight) +{ +} +#endif + +void +XawTextSinkDoPaint(Widget w) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + (*cclass->text_sink_class.extension->DoPaint)(w); +} + +#if 0 +/*ARGSUSED*/ +static void +DoPaint(Widget w) +{ +} +#endif + +Bool +XawTextSinkEndPaint(Widget w) +{ + TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class; + + return ((*cclass->text_sink_class.extension->EndPaint)(w)); +} + +static Bool +EndPaint(Widget w) +{ + TextSinkObject sink = (TextSinkObject)w; + XawTextPaintStruct *paint, *next; + + if (sink->text_sink.paint == NULL) + return (False); + + XmuDestroyArea(sink->text_sink.paint->clip); + if (sink->text_sink.paint->hightabs) + XmuDestroyArea(sink->text_sink.paint->hightabs); + paint = sink->text_sink.paint->paint; + while (paint) { + next = paint->next; + if (paint->text) + XtFree((XtPointer)paint->text); + if (paint->backtabs) + XmuDestroyArea(paint->backtabs); + XtFree((XtPointer)paint); + paint = next; + } + + paint = sink->text_sink.paint->bearings; + while (paint) { + next = paint->next; + if (paint->text) + XtFree((XtPointer)paint->text); + XtFree((XtPointer)paint); + paint = next; + } + + XtFree((XtPointer)sink->text_sink.paint); + sink->text_sink.paint = NULL; + return (True); +} + +static XawTextPropertyList **prop_lists; +static Cardinal num_prop_lists; + +static int +bcmp_qident(_Xconst void *left, _Xconst void *right) +{ + return ((long)left - (*(XawTextProperty**)right)->identifier); +} + +static int +qcmp_qident(_Xconst void *left, _Xconst void *right) +{ + return ((*(XawTextProperty**)left)->identifier - + (*(XawTextProperty**)right)->identifier); +} + +static void +SetXlfdDefaults(Display *display, XawTextProperty *property) +{ + Atom atom = XInternAtom(display, "FONT", True); + unsigned long value; + char *str; + + if (XGetFontProperty(property->font, atom, &value)) { + char *xlfd = XGetAtomName(display, value); + + if (xlfd) { + char *sep = xlfd + 1; + char *name = sep; + + property->xlfd = XrmStringToQuark(xlfd); + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->foundry = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->family = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->weight = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->slant = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->setwidth = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->addstyle = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->pixel_size = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->point_size = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->res_x = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->res_y = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->spacing = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->avgwidth = XrmStringToQuark(name); + name = sep; + + sep = strchr(sep, '-'); *sep++ = '\0'; + property->registry = XrmStringToQuark(name); + name = sep; + + property->encoding = XrmStringToQuark(name); + + XFree(xlfd); + } + } + + atom = XInternAtom(display, "UNDERLINE_THICKNESS", True); + if (XGetFontProperty(property->font, atom, &value) && + (str = XGetAtomName(display, value)) != NULL) { + property->underline_thickness = atoi(str); + XFree(str); + } + else { + /* XLFD says: + * CapStemWidth = average width of the stems of capitals + * if (UNDERLINE_THICKNESS undefined) then + * UNDERLINE_THICKNESS = CapStemWidth + * + * How do I know the value of CapStemWidth?? + */ + if (property->pixel_size != NULLQUARK) { + property->underline_thickness = + atoi(XrmQuarkToString(property->pixel_size)) / 10; + property->underline_thickness = + XawMax(1, property->underline_thickness); + } + else + property->underline_thickness = 1; + } + + atom = XInternAtom(display, "UNDERLINE_POSITION", True); + if (XGetFontProperty(property->font, atom, &value) && + (str = XGetAtomName(display, value)) != NULL) { + property->underline_position = atoi(str); + XFree(str); + } + else + /* XLFD says: + * if (UNDERLINE_POSITION undefined) then + * UNDERLINE_POSITION = ROUND((maximum_descent) / 2) + */ + property->underline_position = + property->font->max_bounds.descent >> 1; + + /* I am assuming xlfd does not consider that lines are + * centered in the path */ + property->underline_position += property->underline_thickness >> 1; + +} + +static void +DestroyTextPropertyList(XawTextPropertyList *list) +{ + int i; + + for (i = 0; i < list->num_properties; i++) { + if (list->properties[i]->font) + XFreeFont(DisplayOfScreen(list->screen), list->properties[i]->font); + XtFree((char*)list->properties[i]); + } + if (list->properties) + XtFree((char*)list->properties); + XtFree((char*)list); +} + +static XawTextProperty * +_XawTextSinkGetProperty(XawTextPropertyList *list, XrmQuark property) +{ + if (property != NULLQUARK && list && list->properties) { + XawTextProperty **ptr = (XawTextProperty**) + bsearch((void*)(long)property, + list->properties, list->num_properties, + sizeof(XawTextProperty*), bcmp_qident); + + if (ptr) + return (*ptr); + } + + return (NULL); +} + +XawTextProperty * +XawTextSinkGetProperty(Widget w, XrmQuark property) +{ + TextSinkObject sink = (TextSinkObject)w; + XawTextPropertyList *list = sink->text_sink.properties; + + return (_XawTextSinkGetProperty(list, property)); +} + +XawTextProperty * +XawTextSinkCopyProperty(Widget w, XrmQuark property) +{ + XawTextProperty *cur, *ret; + + if ((cur = XawTextSinkGetProperty(w, property)) == NULL) + cur = XawTextSinkGetProperty(w, Qdefault); + ret = (XawTextProperty*)XtCalloc(1, sizeof(XawTextProperty)); + if (cur) + memcpy(ret, cur, sizeof(XawTextProperty)); + ret->identifier = NULLQUARK; + ret->mask &= ~XAW_TPROP_FONT; + + return (ret); +} + +static XawTextProperty * +_XawTextSinkAddProperty(XawTextPropertyList *list, XawTextProperty *property, + Bool replace) +{ + XawTextProperty *result; + XColor color; + char identifier[1024]; + char foreground[16]; + char background[16]; + char *foundry, *family, *weight, *slant, *setwidth, *addstyle, *pixel_size, + *point_size, *res_x, *res_y, *spacing, *avgwidth, *registry, *encoding; + char *xlfd; + static char *asterisk = "*", *null = ""; + XrmQuark quark; + + if (list == NULL || property == NULL) + return (NULL); + + if (property->mask & XAW_TPROP_FOREGROUND) { + color.pixel = property->foreground; + XQueryColor(DisplayOfScreen(list->screen), list->colormap, &color); + XmuSnprintf(foreground, sizeof(foreground), "%04x%04x%04x", + color.red, color.green, color.blue); + } + else + strcpy(foreground, asterisk); + if (property->mask & XAW_TPROP_BACKGROUND) { + color.pixel = property->background; + XQueryColor(DisplayOfScreen(list->screen), list->colormap, &color); + XmuSnprintf(background, sizeof(background), "%04x%04x%04x", + color.red, color.green, color.blue); + } + else + strcpy(background, asterisk); + + if (property->xlfd_mask & XAW_TPROP_FOUNDRY) + foundry = XrmQuarkToString(property->foundry); + else + foundry = asterisk; + + /* use default, or what was requested */ + if (property->family != NULLQUARK) + family = XrmQuarkToString(property->family); + else + family = asterisk; + if (property->weight != NULLQUARK) + weight = XrmQuarkToString(property->weight); + else + weight = asterisk; + if (property->slant != NULLQUARK) { + slant = XrmQuarkToString(property->slant); + if (toupper(*slant) != 'R') + slant = asterisk; /* X defaults to italics, so, don't + care in resolving between `I' and `O' */ + } + else + slant = asterisk; + + if (property->xlfd_mask & XAW_TPROP_SETWIDTH) + setwidth = XrmQuarkToString(property->setwidth); + else + setwidth = asterisk; + if (property->xlfd_mask & XAW_TPROP_ADDSTYLE) + addstyle = XrmQuarkToString(property->addstyle); + else + addstyle = null; + + /* use default, or what was requested */ + if (!(property->mask & XAW_TPROP_POINTSIZE) && + property->pixel_size != NULLQUARK) + pixel_size = XrmQuarkToString(property->pixel_size); + else + pixel_size = asterisk; + + if (property->xlfd_mask & XAW_TPROP_POINTSIZE) + point_size = XrmQuarkToString(property->point_size); + else + point_size = asterisk; + if (property->xlfd_mask & XAW_TPROP_RESX) + res_x = XrmQuarkToString(property->res_x); + else + res_x = asterisk; + if (property->xlfd_mask & XAW_TPROP_RESY) + res_y = XrmQuarkToString(property->res_y); + else + res_y = asterisk; + if (property->xlfd_mask & XAW_TPROP_SPACING) + spacing = XrmQuarkToString(property->spacing); + else + spacing = asterisk; + if (property->xlfd_mask & XAW_TPROP_AVGWIDTH) + avgwidth = XrmQuarkToString(property->avgwidth); + else + avgwidth = asterisk; + + /* use default, or what that was requested */ + if (property->registry != NULLQUARK) + registry = XrmQuarkToString(property->registry); + else + registry = asterisk; + if (property->encoding != NULLQUARK) + encoding = XrmQuarkToString(property->encoding); + else + encoding = asterisk; + + if (replace) { + result = XtNew(XawTextProperty); + memcpy(result, property, sizeof(XawTextProperty)); + } + else + result = property; + + /* XXX should do the best to load a suitable font here */ + if (!(result->mask & XAW_TPROP_FONT)) { + XmuSnprintf(identifier, sizeof(identifier), + "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", + foundry, family, weight, slant, setwidth, addstyle, pixel_size, + point_size, res_x, res_y, spacing, avgwidth, registry, encoding); + if ((result->font = XLoadQueryFont(DisplayOfScreen(list->screen), + identifier)) != NULL) { + result->mask |= XAW_TPROP_FONT; + SetXlfdDefaults(DisplayOfScreen(list->screen), result); + } + else + result->mask &= ~XAW_TPROP_FONT; + } + + if (result->font) + xlfd = XrmQuarkToString(result->xlfd); + else + xlfd = null; + + XmuSnprintf(identifier, sizeof(identifier), "%08lx%08lx%s%s%d%d%d%d%s", + property->mask, property->xlfd_mask, + foreground, background, + (result->mask & XAW_TPROP_UNDERLINE) != 0, + (result->mask & XAW_TPROP_OVERSTRIKE) != 0, + (result->mask & XAW_TPROP_SUBSCRIPT) != 0, + (result->mask & XAW_TPROP_SUPERSCRIPT) != 0, + xlfd); + + quark = XrmStringToQuark(identifier); + if (result->identifier == NULLQUARK) + result->identifier = quark; + result->code = quark; + + if ((property = _XawTextSinkGetProperty(list, result->identifier)) != NULL) { + if (result->font) + XFreeFont(DisplayOfScreen(list->screen), result->font); + if (replace) + XtFree((XtPointer)result); + + return (property); + } + + list->properties = (XawTextProperty**) + XtRealloc((XtPointer)list->properties, sizeof(XawTextProperty*) * + (list->num_properties + 1)); + list->properties[list->num_properties++] = result; + qsort((void*)list->properties, list->num_properties, + sizeof(XawTextProperty*), qcmp_qident); + + return (result); +} + +XawTextProperty * +XawTextSinkAddProperty(Widget w, XawTextProperty *property) +{ + TextSinkObject sink = (TextSinkObject)w; + XawTextPropertyList *list = sink->text_sink.properties; + + return (_XawTextSinkAddProperty(list, property, True)); +} + +XawTextProperty * +XawTextSinkCombineProperty(Widget w, + XawTextProperty *property, XawTextProperty *combine, + Bool override) +{ + if (property == NULL || combine == NULL) + return (property); + + if ((override || !(property->mask & XAW_TPROP_FOREGROUND)) && + (combine->mask & XAW_TPROP_FOREGROUND)) { + property->mask |= XAW_TPROP_FOREGROUND; + property->foreground = combine->foreground; + } + if ((override || !(property->mask & XAW_TPROP_BACKGROUND)) && + (combine->mask & XAW_TPROP_BACKGROUND)) { + property->mask |= XAW_TPROP_BACKGROUND; + property->background = combine->background; + } + if ((override || !(property->mask & XAW_TPROP_FPIXMAP)) && + (combine->mask & XAW_TPROP_FPIXMAP)) { + property->mask |= XAW_TPROP_FPIXMAP; + property->foreground_pixmap = combine->foreground_pixmap; + } + if ((override || !(property->mask & XAW_TPROP_BPIXMAP)) && + (combine->mask & XAW_TPROP_BPIXMAP)) { + property->mask |= XAW_TPROP_BPIXMAP; + property->background_pixmap = combine->background_pixmap; + } + if (combine->mask & XAW_TPROP_UNDERLINE) + property->mask |= XAW_TPROP_UNDERLINE; + if (combine->mask & XAW_TPROP_OVERSTRIKE) + property->mask |= XAW_TPROP_OVERSTRIKE; + if ((override || !(property->mask & XAW_TPROP_SUPERSCRIPT)) && + (combine->mask & XAW_TPROP_SUBSCRIPT)) + property->mask |= XAW_TPROP_SUBSCRIPT; + if ((property->mask & XAW_TPROP_SUBSCRIPT) && + (combine->mask & XAW_TPROP_SUPERSCRIPT)) + property->mask |= XAW_TPROP_SUPERSCRIPT; + if ((override || !(property->xlfd_mask & XAW_TPROP_FOUNDRY)) && + (combine->xlfd_mask & XAW_TPROP_FOUNDRY)) { + property->xlfd_mask |= XAW_TPROP_FOUNDRY; + property->foundry = combine->foundry; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_FAMILY)) && + (combine->xlfd_mask & XAW_TPROP_FAMILY)) { + property->xlfd_mask |= XAW_TPROP_FAMILY; + property->family = combine->family; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_WEIGHT)) && + (combine->xlfd_mask & XAW_TPROP_WEIGHT)) { + property->xlfd_mask |= XAW_TPROP_WEIGHT; + property->weight = combine->weight; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_SLANT)) && + (combine->xlfd_mask & XAW_TPROP_SLANT)) { + property->xlfd_mask |= XAW_TPROP_SLANT; + property->slant = combine->slant; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_SETWIDTH)) && + (combine->xlfd_mask & XAW_TPROP_SETWIDTH)) { + property->xlfd_mask |= XAW_TPROP_SETWIDTH; + property->setwidth = combine->setwidth; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_ADDSTYLE)) && + (combine->xlfd_mask & XAW_TPROP_ADDSTYLE)) { + property->xlfd_mask |= XAW_TPROP_ADDSTYLE; + property->addstyle = combine->addstyle; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_PIXELSIZE)) && + (combine->xlfd_mask & XAW_TPROP_PIXELSIZE)) { + property->xlfd_mask |= XAW_TPROP_PIXELSIZE; + property->pixel_size = combine->pixel_size; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_POINTSIZE)) && + (combine->xlfd_mask & XAW_TPROP_POINTSIZE)) { + property->xlfd_mask |= XAW_TPROP_POINTSIZE; + property->point_size = combine->point_size; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_RESX)) && + (combine->xlfd_mask & XAW_TPROP_RESX)) { + property->xlfd_mask |= XAW_TPROP_RESX; + property->res_x = combine->res_x; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_RESY)) && + (combine->xlfd_mask & XAW_TPROP_RESY)) { + property->xlfd_mask |= XAW_TPROP_RESY; + property->res_y = combine->res_y; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_SPACING)) && + (combine->xlfd_mask & XAW_TPROP_SPACING)) { + property->xlfd_mask |= XAW_TPROP_SPACING; + property->spacing = combine->spacing; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_AVGWIDTH)) && + (combine->xlfd_mask & XAW_TPROP_AVGWIDTH)) { + property->xlfd_mask |= XAW_TPROP_AVGWIDTH; + property->avgwidth = combine->avgwidth; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_REGISTRY)) && + (combine->xlfd_mask & XAW_TPROP_REGISTRY)) { + property->xlfd_mask |= XAW_TPROP_REGISTRY; + property->registry = combine->registry; + } + if ((override || !(property->xlfd_mask & XAW_TPROP_ENCODING)) && + (combine->xlfd_mask & XAW_TPROP_ENCODING)) { + property->xlfd_mask |= XAW_TPROP_ENCODING; + property->encoding = combine->encoding; + } + + return (property); +} + +/* + * The default property must be defined first, if the code is willing to + * combine properties. + */ +XawTextPropertyList * +XawTextSinkConvertPropertyList(String name, String spec, Screen *screen, + Colormap colormap, int depth) +{ + XrmQuark qname = XrmStringToQuark(name); + XawTextPropertyList **ptr = NULL; + XawTextPropertyList *propl, *prev = NULL; + XawTextProperty *def_prop = NULL; + String str, tok, tmp; + char buffer[BUFSIZ]; + + if (prop_lists) ptr = (XawTextPropertyList**) + bsearch((void*)(long)qname, prop_lists, num_prop_lists, + sizeof(XawTextPropertyList*), bcmp_qident); + if (ptr) { + propl = *ptr; + while (propl) { + prev = propl; + if (propl->screen == screen && + propl->colormap == colormap && + propl->depth == depth) + return (propl); + propl = propl->next; + } + } + + propl = XtNew(XawTextPropertyList); + propl->identifier = qname; + propl->screen = screen; + propl->colormap = colormap; + propl->depth = depth; + propl->next = NULL; + + if (prev) + prev->next = propl; + + propl->properties = NULL; + propl->num_properties = 0; + + str = XtNewString(spec); + for (tok = str; tok; tok = tmp) { + XawTextProperty *prop; + XawParams *params; + XrmQuark ident; + XawArgVal *argval; + XColor color, exact; + + if (def_prop == NULL && propl->num_properties) + def_prop = _XawTextSinkGetProperty(propl, Qdefault); + tmp = strchr(tok, ','); + if (tmp) { + *tmp = '\0'; + if (*++tmp == '\0') + tmp = NULL; + } + params = XawParseParamsString(tok); + ident = XrmStringToQuark(params->name); + if (ident == NULLQUARK) { + XmuSnprintf(buffer, sizeof(buffer), + "Bad text property name \"%s\".", params->name); + XtAppWarning(XtDisplayToApplicationContext + (DisplayOfScreen(screen)), buffer); + DestroyTextPropertyList(propl); + if (prev) + prev->next = NULL; + XawFreeParamsStruct(params); + return (NULL); + } + else if (_XawTextSinkGetProperty(propl, ident) != NULL) { + XawFreeParamsStruct(params); + continue; + } + + prop = (XawTextProperty*)XtCalloc(1, sizeof(XawTextProperty)); + prop->identifier = ident; + + if ((argval = XawFindArgVal(params, "font")) != NULL && + argval->value) { + + if ((prop->font = XLoadQueryFont(DisplayOfScreen(screen), + argval->value)) == NULL) { + XmuSnprintf(buffer, sizeof(buffer), + "Cannot load font \"%s\".", argval->value); + XtAppWarning(XtDisplayToApplicationContext + (DisplayOfScreen(screen)), buffer); + DestroyTextPropertyList(propl); + if (prev) + prev->next = NULL; + XawFreeParamsStruct(params); + return (NULL); + } + prop->mask |= XAW_TPROP_FONT; + SetXlfdDefaults(DisplayOfScreen(screen), prop); + } + /* fontset processing here */ + + if ((argval = XawFindArgVal(params, "foreground")) != NULL && + argval->value) { + if (!XAllocNamedColor(DisplayOfScreen(screen), colormap, + argval->value, &color, &exact)) { + XmuSnprintf(buffer, sizeof(buffer), + "Cannot allocate color \"%s\".", argval->value); + XtAppWarning(XtDisplayToApplicationContext + (DisplayOfScreen(screen)), buffer); + DestroyTextPropertyList(propl); + if (prev) + prev->next = NULL; + XawFreeParamsStruct(params); + return (NULL); + } + prop->foreground = color.pixel; + prop->mask |= XAW_TPROP_FOREGROUND; + } + if ((argval = XawFindArgVal(params, "background")) != NULL && + argval->value) { + if (!XAllocNamedColor(DisplayOfScreen(screen), colormap, + argval->value, &color, &exact)) { + XmuSnprintf(buffer, sizeof(buffer), + "Cannot allocate color \"%s\".", argval->value); + XtAppWarning(XtDisplayToApplicationContext + (DisplayOfScreen(screen)), buffer); + DestroyTextPropertyList(propl); + if (prev) + prev->next = NULL; + XawFreeParamsStruct(params); + return (NULL); + } + prop->background = color.pixel; + prop->mask |= XAW_TPROP_BACKGROUND; + } + /* foreground_pixmap and background_pixmap processing here */ + + if (XawFindArgVal(params, "underline")) + prop->mask |= XAW_TPROP_UNDERLINE; + if (XawFindArgVal(params, "overstrike")) + prop->mask |= XAW_TPROP_OVERSTRIKE; + + if (XawFindArgVal(params, "subscript")) + prop->mask |= XAW_TPROP_SUBSCRIPT; + else if (XawFindArgVal(params, "superscript")) + prop->mask |= XAW_TPROP_SUPERSCRIPT; + + /* xlfd */ + if ((argval = XawFindArgVal(params, "foundry")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_FOUNDRY; + prop->foundry = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "family")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_FAMILY; + prop->family = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "weight")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_WEIGHT; + prop->weight = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "slant")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_SLANT; + prop->slant = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "setwidth")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_SETWIDTH; + prop->setwidth = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "addstyle")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_ADDSTYLE; + prop->addstyle = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "pixelsize")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_PIXELSIZE; + prop->pixel_size = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "pointsize")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_POINTSIZE; + prop->point_size = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "resx")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_RESX; + prop->res_x = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "resy")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_RESY; + prop->res_y = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "spacing")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_SPACING; + prop->spacing = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "avgwidth")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_AVGWIDTH; + prop->avgwidth = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "registry")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_REGISTRY; + prop->registry = XrmStringToQuark(argval->value); + } + if ((argval = XawFindArgVal(params, "encoding")) != NULL && + argval->value) { + prop->xlfd_mask |= XAW_TPROP_ENCODING; + prop->encoding = XrmStringToQuark(argval->value); + } + + if (def_prop) + (void)XawTextSinkCombineProperty(NULL, prop, def_prop, False); + (void)_XawTextSinkAddProperty(propl, prop, False); + + XawFreeParamsStruct(params); + } + + prop_lists = (XawTextPropertyList**) + XtRealloc((XtPointer)prop_lists, sizeof(XawTextPropertyList*) * + (num_prop_lists + 1)); + prop_lists[num_prop_lists++] = propl; + qsort((void*)prop_lists, num_prop_lists, sizeof(XawTextPropertyList*), + qcmp_qident); + + XtFree(str); + + return (propl); +} + +/*ARGSUSED*/ +static Boolean +CvtStringToPropertyList(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + XawTextPropertyList *propl = NULL; + String name; + Widget w; + + if (*num_args != 1) { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "wrongParameters", "cvtStringToTextProperties", + "ToolkitError", + "String to textProperties conversion needs widget argument", + NULL, NULL); + return (False); + } + + w = *(Widget*)args[0].addr; + while (w && !XtIsWidget(w)) + w = XtParent(w); + + name = (String)(fromVal[0].addr); + + if (w) { + XawTextPropertyList **ptr = NULL; + if (prop_lists) ptr = (XawTextPropertyList**) + bsearch((void*)(long)XrmStringToQuark(name), + prop_lists, num_prop_lists, + sizeof(XawTextPropertyList*), bcmp_qident); + + if (ptr) { + Screen *screen = w->core.screen; + Colormap colormap = w->core.colormap; + int depth = w->core.depth; + + propl = *ptr; + while (propl) { + if (propl->screen == screen && + propl->colormap == colormap && + propl->depth == depth) + break; + propl = propl->next; + } + } + } + + if (!propl) { + XtDisplayStringConversionWarning(dpy, (String)fromVal->addr, + XawRTextProperties); + toVal->addr = NULL; + toVal->size = sizeof(XawTextPropertyList*); + return (False); + } + + if (toVal->addr != NULL) { + if (toVal->size < sizeof(XawTextPropertyList*)) { + toVal->size = sizeof(XawTextPropertyList*); + return (False); + } + *(XawTextPropertyList**)(toVal->addr) = propl; + } + else { + static XawTextPropertyList *static_val; + + static_val = propl; + toVal->addr = (XPointer)&static_val; + } + toVal->size = sizeof(XawTextProperty*); + + return (True); +} + +/*ARGSUSED*/ +static Boolean +CvtPropertyListToString(Display *dpy, XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + static char *buffer; + Cardinal size; + XawTextPropertyList *propl; + + propl = *(XawTextPropertyList**)fromVal[0].addr; + + buffer = XrmQuarkToString(propl->identifier); + size = strlen(buffer) + 1; + + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = buffer; + toVal->size = size; + + return (True); +} +#endif diff --git a/libXaw/src/TextSrc.c b/libXaw/src/TextSrc.c index bc055aaca..118361ea5 100644 --- a/libXaw/src/TextSrc.c +++ b/libXaw/src/TextSrc.c @@ -1,2008 +1,2008 @@ -/*
-
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-/*
- * Author: Chris Peterson, MIT X Consortium.
- * Much code taken from X11R3 String and Disk Sources.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <ctype.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xutil.h>
-#include <X11/Xmu/Atoms.h>
-#include <X11/Xmu/CharSet.h>
-#include <X11/Xaw/TextSrcP.h>
-#include <X11/Xaw/XawInit.h>
-#include "XawI18n.h"
-#include "Private.h"
-
-#ifndef OLDXAW
-#define UNDO_DEPTH 16384
-
-#define ANCHORS_DIST 4096 /* default distance between anchors */
-
-/*
- * Types
- */
-typedef struct {
- XawTextPosition position;
- char *buffer;
- unsigned length;
- unsigned refcount;
- unsigned long format;
-} XawTextUndoBuffer;
-
-typedef struct _XawTextUndoList XawTextUndoList;
-struct _XawTextUndoList {
- XawTextUndoBuffer *left, *right;
- XawTextUndoList *undo, *redo;
-};
-
-struct _XawTextUndo {
- XawTextUndoBuffer **undo;
- unsigned num_undo;
- XawTextUndoList *list, *pointer, *end_mark, *head;
- unsigned num_list;
- XawTextScanDirection dir;
- XawTextUndoBuffer *l_save, *r_save;
- XawTextUndoList *u_save;
- XawTextUndoBuffer *l_no_change, *r_no_change;
- int merge;
- int erase; /* there are two types of erases */
-};
-#endif /* OLDXAW */
-
-/*
- * Class Methods
- */
-static Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*,
- unsigned long*, int*);
-static XawTextPosition Read(Widget, XawTextPosition, XawTextBlock*, int);
-static int Replace(Widget, XawTextPosition, XawTextPosition, XawTextBlock*);
-static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType,
- XawTextScanDirection, int, Bool);
-static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection,
- XawTextBlock*);
-static void SetSelection(Widget, XawTextPosition, XawTextPosition, Atom);
-static void XawTextSrcClassInitialize(void);
-static void XawTextSrcClassPartInitialize(WidgetClass);
-static void XawTextSrcInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawTextSrcDestroy(Widget);
-static Boolean XawTextSrcSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-/*
- * Prototypes
- */
-static void CvtStringToEditMode(XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr);
-static Boolean CvtEditModeToString(Display*, XrmValuePtr, Cardinal*,
- XrmValuePtr, XrmValuePtr, XtPointer*);
-#ifndef OLDXAW
-static void FreeUndoBuffer(XawTextUndo*);
-static void UndoGC(XawTextUndo*);
-static void TellSourceChanged(TextSrcObject, XawTextPosition, XawTextPosition,
- XawTextBlock*, int);
-Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*);
-Bool _XawTextSrcToggleUndo(TextSrcObject);
-XawTextAnchor *_XawTextSourceFindAnchor(Widget, XawTextPosition);
-
-/*
- * External
- */
-void _XawSourceAddText(Widget, Widget);
-void _XawSourceRemoveText(Widget, Widget, Bool);
-Bool _XawTextSourceNewLineAtEOF(Widget);
-void _XawSourceSetUndoErase(TextSrcObject, int);
-void _XawSourceSetUndoMerge(TextSrcObject, Bool);
-#endif /* OLDXAW */
-
-/*
- * Defined in Text.c
- */
-char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition);
-void _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition,
- XawTextBlock*, int);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(TextSrcRec, textSrc.field)
-static XtResource resources[] = {
- {
- XtNeditType,
- XtCEditType,
- XtREditMode,
- sizeof(XawTextEditType),
- offset(edit_mode),
- XtRString,
- "read"
- },
-#ifndef OLDXAW
- {
- XtNcallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(callback),
- XtRCallback,
- NULL
- },
- {
- XtNsourceChanged,
- XtCChanged,
- XtRBoolean,
- sizeof(Boolean),
- offset(changed),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNenableUndo,
- XtCUndo,
- XtRBoolean,
- sizeof(Boolean),
- offset(enable_undo),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNpropertyCallback,
- XtCCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(property_callback),
- XtRCallback,
- NULL
- },
-#endif /* OLDXAW */
-};
-#undef offset
-
-#define Superclass (&objectClassRec)
-TextSrcClassRec textSrcClassRec = {
- /* object */
- {
- (WidgetClass)Superclass, /* superclass */
- "TextSrc", /* class_name */
- sizeof(TextSrcRec), /* widget_size */
- XawTextSrcClassInitialize, /* class_initialize */
- XawTextSrcClassPartInitialize, /* class_part_initialize */
- False, /* class_inited */
- XawTextSrcInitialize, /* initialize */
- NULL, /* initialize_hook */
- NULL, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- False, /* compress_motion */
- False, /* compress_exposure */
- False, /* compress_enterleave */
- False, /* visible_interest */
- XawTextSrcDestroy, /* destroy */
- NULL, /* resize */
- NULL, /* expose */
- XawTextSrcSetValues, /* set_values */
- NULL, /* set_values_hook */
- NULL, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- NULL, /* query_geometry */
- NULL, /* display_accelerator */
- NULL, /* extension */
- },
- /* text_src */
- {
- Read, /* Read */
- Replace, /* Replace */
- Scan, /* Scan */
- Search, /* Search */
- SetSelection, /* SetSelection */
- ConvertSelection, /* ConvertSelection */
- },
-};
-
-WidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec;
-
-static XrmQuark QRead, QAppend, QEdit;
-#ifndef OLDXAW
-static char *SrcNL = "\n";
-static wchar_t SrcWNL[2];
-#endif
-
-/*
- * Implementation
- */
-static void
-XawTextSrcClassInitialize(void)
-{
- XawInitializeWidgetSet();
-
-#ifndef OLDXAW
- SrcWNL[0] = _Xaw_atowc(XawLF);
- SrcWNL[1] = 0;
-#endif
- QRead = XrmPermStringToQuark(XtEtextRead);
- QAppend = XrmPermStringToQuark(XtEtextAppend);
- QEdit = XrmPermStringToQuark(XtEtextEdit);
- XtAddConverter(XtRString, XtREditMode, CvtStringToEditMode, NULL, 0);
- XtSetTypeConverter(XtREditMode, XtRString, CvtEditModeToString, NULL, 0,
- XtCacheNone, NULL);
-}
-
-static void
-XawTextSrcClassPartInitialize(WidgetClass wc)
-{
- TextSrcObjectClass t_src, superC;
-
- t_src = (TextSrcObjectClass)wc;
- superC = (TextSrcObjectClass)t_src->object_class.superclass;
-
- /*
- * We don't need to check for null super since we'll get to TextSrc
- * eventually
- */
- if (t_src->textSrc_class.Read == XtInheritRead)
- t_src->textSrc_class.Read = superC->textSrc_class.Read;
-
- if (t_src->textSrc_class.Replace == XtInheritReplace)
- t_src->textSrc_class.Replace = superC->textSrc_class.Replace;
-
- if (t_src->textSrc_class.Scan == XtInheritScan)
- t_src->textSrc_class.Scan = superC->textSrc_class.Scan;
-
- if (t_src->textSrc_class.Search == XtInheritSearch)
- t_src->textSrc_class.Search = superC->textSrc_class.Search;
-
- if (t_src->textSrc_class.SetSelection == XtInheritSetSelection)
- t_src->textSrc_class.SetSelection = superC->textSrc_class.SetSelection;
-
- if (t_src->textSrc_class.ConvertSelection == XtInheritConvertSelection)
- t_src->textSrc_class.ConvertSelection =
- superC->textSrc_class.ConvertSelection;
-}
-
-/*ARGSUSED*/
-static void
-XawTextSrcInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
-#ifndef OLDXAW
- TextSrcObject src = (TextSrcObject)cnew;
-
- if (src->textSrc.enable_undo) {
- src->textSrc.undo = (XawTextUndo*)XtCalloc(1, sizeof(XawTextUndo));
- src->textSrc.undo->dir = XawsdLeft;
- }
- else
- src->textSrc.undo = NULL;
- src->textSrc.undo_state = False;
- if (XtIsSubclass(XtParent(cnew), textWidgetClass)) {
- src->textSrc.text = (WidgetList)XtMalloc(sizeof(Widget*));
- src->textSrc.text[0] = XtParent(cnew);
- src->textSrc.num_text = 1;
- }
- else {
- src->textSrc.text = NULL;
- src->textSrc.num_text = 0;
- }
-
- src->textSrc.anchors = NULL;
- src->textSrc.num_anchors = 0;
- (void)XawTextSourceAddAnchor(cnew, 0);
-#endif /* OLDXAW */
-}
-
-static void
-XawTextSrcDestroy(Widget w)
-{
-#ifndef OLDXAW
- TextSrcObject src = (TextSrcObject)w;
-
- if (src->textSrc.enable_undo) {
- FreeUndoBuffer(src->textSrc.undo);
- XtFree((char*)src->textSrc.undo);
- }
- XtFree((char*)src->textSrc.text);
-
- if (src->textSrc.num_anchors) {
- XawTextEntity *entity, *enext;
- int i;
-
- for (i = 0; i < src->textSrc.num_anchors; i++) {
- entity = src->textSrc.anchors[i]->entities;
- while (entity) {
- enext = entity->next;
- XtFree((XtPointer)entity);
- entity = enext;
- }
- XtFree((XtPointer)src->textSrc.anchors[i]);
- }
- XtFree((XtPointer)src->textSrc.anchors);
- }
-#endif /* OLDXAW */
-}
-
-/*ARGSUSED*/
-static Boolean
-XawTextSrcSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
-#ifndef OLDXAW
- TextSrcObject oldtw = (TextSrcObject)current;
- TextSrcObject newtw = (TextSrcObject)cnew;
-
- if (oldtw->textSrc.enable_undo != newtw->textSrc.enable_undo) {
- if (newtw->textSrc.enable_undo) {
- newtw->textSrc.undo = (XawTextUndo*)
- XtCalloc(1, sizeof(XawTextUndo));
- newtw->textSrc.undo->dir = XawsdLeft;
- }
- else {
- FreeUndoBuffer(newtw->textSrc.undo);
- XtFree((char*)newtw->textSrc.undo);
- newtw->textSrc.undo = NULL;
- }
- }
- if (oldtw->textSrc.changed != newtw->textSrc.changed) {
- if (newtw->textSrc.enable_undo) {
- if (newtw->textSrc.undo->list) {
- newtw->textSrc.undo->l_no_change =
- newtw->textSrc.undo->list->left;
- newtw->textSrc.undo->r_no_change =
- newtw->textSrc.undo->list->right;
- }
- else
- newtw->textSrc.undo->l_no_change =
- newtw->textSrc.undo->r_no_change = NULL;
- }
- }
-#endif /* OLDXAW */
- return (False);
-}
-
-/*
- * Function:
- * Read
- *
- * Parameters:
- * w - TextSrc Object
- * pos - position of the text to retreive
- * text - text block that will contain returned text
- * length - maximum number of characters to read
- *
- * Description:
- * This function reads the source.
- *
- * Returns:
- * The character position following the retrieved text.
- */
-/*ARGSUSED*/
-static XawTextPosition
-Read(Widget w, XawTextPosition pos, XawTextBlock *text, int length)
-{
- return ((XawTextPosition)0);
-}
-
-/*
- * Function:
- * Replace
- *
- * Parameters:
- * src - Text Source Object
- * startPos - ends of text that will be removed
- * endPos - ""
- * text - new text to be inserted into buffer at startPos
- *
- * Description:
- * Replaces a block of text with new text.
- */
-/*ARGSUSED*/
-static int
-Replace(Widget w, XawTextPosition startPos, XawTextPosition endPos,
- XawTextBlock *text)
-{
- return (XawEditError);
-}
-
-/*
- * Function:
- * Scan
- *
- * Parameters:
- * w - TextSrc Object
- * position - position to start scanning
- * type - type of thing to scan for
- * dir - direction to scan
- * count - which occurance if this thing to search for
- * include - whether or not to include the character found in
- * the position that is returned
- *
- * Description:
- * Scans the text source for the number and type of item specified.
- */
-/*ARGSUSED*/
-static XawTextPosition
-Scan(Widget w, XawTextPosition position, XawTextScanType type,
- XawTextScanDirection dir, int count, Bool include)
-{
- return ((XawTextPosition)0);
-}
-
-/*
- * Function:
- * Search
- *
- * Parameters:
- * w - TextSource Object
- * position - position to start searching
- * dir - direction to search
- * text - the text block to search for
- *
- * Description:
- * Searchs the text source for the text block passed
- */
-/*ARGSUSED*/
-static XawTextPosition
-Search(Widget w, XawTextPosition position, XawTextScanDirection dir,
- XawTextBlock *text)
-{
- return (XawTextSearchError);
-}
-
-/*ARGSUSED*/
-static Boolean
-ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type,
- XtPointer *value, unsigned long *length, int *format)
-{
- return (False);
-}
-
-/*ARGSUSED*/
-static void
-SetSelection(Widget w, XawTextPosition left, XawTextPosition right,
- Atom selection)
-{
-}
-
-/*ARGSUSED*/
-static void
-CvtStringToEditMode(XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal)
-{
- static XawTextEditType editType;
- XrmQuark q;
- char name[7];
-
- XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
- q = XrmStringToQuark(name);
-
- if (q == QRead)
- editType = XawtextRead;
- else if (q == QAppend)
- editType = XawtextAppend;
- else if (q == QEdit)
- editType = XawtextEdit;
- else {
- toVal->size = 0;
- toVal->addr = NULL;
- XtStringConversionWarning((char *)fromVal->addr, XtREditMode);
- }
- toVal->size = sizeof(XawTextEditType);
- toVal->addr = (XPointer)&editType;
-}
-
-/*ARGSUSED*/
-static Boolean
-CvtEditModeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
- XrmValuePtr fromVal, XrmValuePtr toVal,
- XtPointer *data)
-{
- static String buffer;
- Cardinal size;
-
- switch (*(XawTextEditType *)fromVal->addr) {
- case XawtextRead:
- buffer = XtEtextRead;
- break;
- case XawtextAppend:
- buffer = XtEtextAppend;
- break;
- case XawtextEdit:
- buffer = XtEtextEdit;
- break;
- default:
- XawTypeToStringWarning(dpy, XtREditMode);
- toVal->addr = NULL;
- toVal->size = 0;
- return (False);
- }
-
- size = strlen(buffer) + 1;
- if (toVal->addr != NULL) {
- if (toVal->size < size) {
- toVal->size = size;
- return (False);
- }
- strcpy((char *)toVal->addr, buffer);
- }
- else
- toVal->addr = (XPointer)buffer;
- toVal->size = sizeof(String);
-
- return (True);
-}
-
-#ifndef OLDXAW
-Bool
-_XawTextSourceNewLineAtEOF(Widget w)
-{
- TextSrcObject src = (TextSrcObject)w;
- XawTextBlock text;
-
- text.firstPos = 0;
- if ((text.format = src->textSrc.text_format) == XawFmt8Bit)
- text.ptr = SrcNL;
- else
- text.ptr = (char*)SrcWNL;
- text.length = 1;
-
- return (XawTextSourceSearch(w, XawTextSourceScan(w, 0, XawstAll,
- XawsdRight, 1, True) - 1,
- XawsdRight, &text) != XawTextSearchError);
-}
-
-void
-_XawSourceAddText(Widget source, Widget text)
-{
- TextSrcObject src = (TextSrcObject)source;
- Bool found = False;
- Cardinal i;
-
- for (i = 0; i < src->textSrc.num_text; i++)
- if (src->textSrc.text[i] == text) {
- found = True;
- break;
- }
-
- if (!found) {
- src->textSrc.text = (WidgetList)
- XtRealloc((char*)src->textSrc.text,
- sizeof(Widget) * (src->textSrc.num_text + 1));
- src->textSrc.text[src->textSrc.num_text++] = text;
- }
-}
-
-void
-_XawSourceRemoveText(Widget source, Widget text, Bool destroy)
-{
- TextSrcObject src = (TextSrcObject)source;
- Bool found = False;
- Cardinal i;
-
- if (src == NULL)
- return;
-
- for (i = 0; i < src->textSrc.num_text; i++)
- if (src->textSrc.text[i] == text) {
- found = True;
- break;
- }
-
- if (found) {
- if (--src->textSrc.num_text == 0) {
- if (destroy) {
- XtDestroyWidget(source);
- return;
- }
- else {
- XtFree((char*)src->textSrc.text);
- src->textSrc.text = NULL; /* for realloc "magic" */
- }
- }
- else if (i < src->textSrc.num_text)
- memmove(&src->textSrc.text[i], &src->textSrc.text[i + 1],
- sizeof(Widget) * (src->textSrc.num_text - i));
- }
-}
-#endif /* OLDXAW */
-
-/*
- * Function:
- * XawTextSourceRead
- *
- * Parameters:
- * w - TextSrc Object
- * pos - position of the text to retrieve
- * text - text block that will contain returned text (return)
- * length - maximum number of characters to read
- *
- * Description:
- * This function reads the source.
- *
- * Returns:
- * The number of characters read into the buffer
- */
-XawTextPosition
-XawTextSourceRead(Widget w, XawTextPosition pos, XawTextBlock *text,
- int length)
-{
- TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
-
- return ((*cclass->textSrc_class.Read)(w, pos, text, length));
-}
-
-#ifndef OLDXAW
-static void
-TellSourceChanged(TextSrcObject src, XawTextPosition left,
- XawTextPosition right, XawTextBlock *block, int lines)
-{
- Cardinal i;
-
- for (i = 0; i < src->textSrc.num_text; i++)
- _XawTextSourceChanged(src->textSrc.text[i], left, right, block, lines);
-}
-
-/*
- * This function is required because there is no way to diferentiate
- * if the first erase was generated by a backward-kill-char and the
- * second by a forward-kill-char (or vice-versa) from XawTextSourceReplace.
- * It is only possible to diferentiate after the second character is
- * killed, but then, it is too late.
- */
-void
-_XawSourceSetUndoErase(TextSrcObject src, int value)
-{
- if (src && src->textSrc.enable_undo)
- src->textSrc.undo->erase = value;
-}
-
-/*
- * To diferentiate insert-char's separeted by cursor movements.
- */
-void
-_XawSourceSetUndoMerge(TextSrcObject src, Bool state)
-{
- if (src && src->textSrc.enable_undo)
- src->textSrc.undo->merge += state ? 1 : -1;
-}
-#endif /* OLDXAW */
-
-/*
- * Public Functions
- */
-/*
- * Function:
- * XawTextSourceReplace
- *
- * Parameters:
- * src - Text Source Object
- * startPos - ends of text that will be removed
- * endPos - ""
- * text - new text to be inserted into buffer at startPos
- *
- * Description:
- * Replaces a block of text with new text.
- *
- * Returns:
- * XawEditError or XawEditDone.
- */
-/*ARGSUSED*/
-int
-XawTextSourceReplace(Widget w, XawTextPosition left,
- XawTextPosition right, XawTextBlock *block)
-{
- TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
-#ifndef OLDXAW
- TextSrcObject src = (TextSrcObject)w;
- XawTextUndoBuffer *l_state, *r_state;
- XawTextUndoList *undo;
- Bool enable_undo;
- XawTextPosition start, end;
- int i, error, lines = 0;
-
- if (src->textSrc.edit_mode == XawtextRead)
- return (XawEditError);
-
- enable_undo = src->textSrc.enable_undo && src->textSrc.undo_state == False;
- if (enable_undo) {
- unsigned size, total;
-
- if (src->textSrc.undo->l_save) {
- l_state = src->textSrc.undo->l_save;
- src->textSrc.undo->l_save = NULL;
- }
- else
- l_state = XtNew(XawTextUndoBuffer);
- l_state->refcount = 1;
- l_state->position = left;
- if (left < right) {
- Widget ctx = NULL;
-
- for (i = 0; i < src->textSrc.num_text; i++)
- if (XtIsSubclass(src->textSrc.text[i], textWidgetClass)) {
- ctx = src->textSrc.text[i];
- break;
- }
- l_state->buffer = _XawTextGetText((TextWidget)ctx, left, right);
- l_state->length = right - left;
- }
- else {
- l_state->length = 0;
- l_state->buffer = NULL;
- }
- l_state->format = src->textSrc.text_format;
- if (l_state->length == 1) {
- if (l_state->format == XawFmtWide &&
- *(wchar_t*)l_state->buffer == *SrcWNL) {
- XtFree(l_state->buffer);
- l_state->buffer = (char*)SrcWNL;
- }
- else if (*l_state->buffer == '\n') {
- XtFree(l_state->buffer);
- l_state->buffer = SrcNL;
- }
- }
-
- if (src->textSrc.undo->r_save) {
- r_state = src->textSrc.undo->r_save;
- src->textSrc.undo->r_save = NULL;
- }
- else
- r_state = XtNew(XawTextUndoBuffer);
- r_state->refcount = 1;
- r_state->position = left;
- r_state->format = block->format;
- size = block->format == XawFmtWide ? sizeof(wchar_t) : sizeof(char);
- total = size * block->length;
- r_state->length = block->length;
- r_state->buffer = NULL;
- if (total == size) {
- if (r_state->format == XawFmtWide &&
- *(wchar_t*)block->ptr == *SrcWNL)
- r_state->buffer = (char*)SrcWNL;
- else if (*block->ptr == '\n')
- r_state->buffer = SrcNL;
- }
- if (total && !r_state->buffer) {
- r_state->buffer = XtMalloc(total);
- memcpy(r_state->buffer, block->ptr, total);
- }
-
- if (src->textSrc.undo->u_save) {
- undo = src->textSrc.undo->u_save;
- src->textSrc.undo->u_save = NULL;
- }
- else
- undo = XtNew(XawTextUndoList);
- undo->left = l_state;
- undo->right = r_state;
- undo->undo = src->textSrc.undo->list;
- undo->redo = NULL;
- }
- else {
- undo = NULL;
- l_state = r_state = NULL;
- }
-
-#define LARGE_VALUE 262144 /* 256 K */
- /* optimization, to avoid long delays recalculating the line number
- * when editing huge files
- */
- if (left > LARGE_VALUE) {
- start = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 2, False);
- for (i = 0; i < src->textSrc.num_text; i++) {
- TextWidget tw = (TextWidget)src->textSrc.text[i];
-
- if (left <= tw->text.lt.top &&
- left + block->length - (right - left) > tw->text.lt.top)
- _XawTextBuildLineTable(tw, start, False);
- }
- }
-#undef LARGE_VALUE
-
- start = left;
- end = right;
- while (start < end) {
- start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True);
- if (start <= end) {
- --lines;
- if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) {
- lines += !_XawTextSourceNewLineAtEOF(w);
- break;
- }
- }
- }
-#else
- int error;
-#endif /* OLDXAW */
-
- error = (*cclass->textSrc_class.Replace)(w, left, right, block);
-
-#ifndef OLDXAW
- if (error != XawEditDone) {
- if (enable_undo) {
- if (l_state->buffer) {
- if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL)
- XtFree(l_state->buffer);
- l_state->buffer = NULL;
- }
- src->textSrc.undo->l_save = l_state;
- if (r_state->buffer) {
- if (r_state->buffer != SrcNL && r_state->buffer != (char*)SrcWNL)
- XtFree(r_state->buffer);
- r_state->buffer = NULL;
- }
- src->textSrc.undo->r_save = r_state;
-
- src->textSrc.undo->u_save = undo;
- }
- }
- else if (enable_undo) {
- XawTextUndoList *list = src->textSrc.undo->list;
- XawTextUndoBuffer *unl, *lnl;
- int erase = undo->right->length == 0 && undo->left->length == 1 && list
- && list->right->length == 0;
-
- if (erase) {
- erase = list->left->position - 1 == undo->left->position ? -1 :
- list->left->position == undo->left->position ? 1 : 0;
- if (src->textSrc.undo->erase && erase != src->textSrc.undo->erase)
- erase = 0;
- else
- src->textSrc.undo->erase = erase;
- }
-
- if (erase) {
- unl = l_state;
- lnl = list->left;
- }
- else {
- unl = r_state;
- lnl = list ? list->right : NULL;
- }
-
- /* Try to merge the undo buffers */
- if (src->textSrc.undo->merge > 0 && ((erase ||
- (list && ((list->left->length == 0 && undo->left->length == 0) ||
- (list->left->length == list->right->length &&
- undo->left->length == 1)) &&
- undo->right->length == 1 &&
- list->right->position + list->right->length
- == undo->right->position))
- && src->textSrc.undo->pointer == list
- && unl->format == list->right->format
- && ((unl->format == XawFmt8Bit && unl->buffer[0] != XawLF) ||
- (unl->format == XawFmtWide &&
- *(wchar_t*)(unl->buffer) != _Xaw_atowc(XawLF)))
- && ((lnl->format == XawFmt8Bit && lnl->buffer[0] != XawLF) ||
- (lnl->format == XawFmtWide &&
- *(wchar_t*)(lnl->buffer) != _Xaw_atowc(XawLF))))) {
- unsigned size = lnl->format == XawFmtWide ?
- sizeof(wchar_t) : sizeof(char);
-
- if (!erase) {
- list->right->buffer = XtRealloc(list->right->buffer,
- (list->right->length + 1) * size);
- memcpy(list->right->buffer + list->right->length * size,
- undo->right->buffer, size);
- ++list->right->length;
- XtFree(r_state->buffer);
- }
- else if (erase < 0) {
- --list->left->position;
- --list->right->position;
- }
-
- src->textSrc.undo->l_save = l_state;
- src->textSrc.undo->r_save = r_state;
- src->textSrc.undo->u_save = undo;
-
- if (list->left->length) {
- list->left->buffer = XtRealloc(list->left->buffer,
- (list->left->length + 1) * size);
- if (erase >= 0)
- memcpy(list->left->buffer + list->left->length * size,
- undo->left->buffer, size);
- else {
- /* use memmove, since strings overlap */
- memmove(list->left->buffer + size, list->left->buffer,
- list->left->length * size);
- memcpy(list->left->buffer, undo->left->buffer, size);
- }
- ++list->left->length;
- if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL)
- XtFree(l_state->buffer);
- }
-
- if (src->textSrc.undo->num_list >= UNDO_DEPTH)
- UndoGC(src->textSrc.undo);
- }
- else {
- src->textSrc.undo->undo = (XawTextUndoBuffer**)
- XtRealloc((char*)src->textSrc.undo->undo,
- (2 + src->textSrc.undo->num_undo)
- * sizeof(XawTextUndoBuffer));
- src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = l_state;
- src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = r_state;
-
- if (src->textSrc.undo->list)
- src->textSrc.undo->list->redo = undo;
- else
- src->textSrc.undo->head = undo;
-
- src->textSrc.undo->merge = l_state->length <= 1 &&
- r_state->length <= 1;
-
- src->textSrc.undo->list = src->textSrc.undo->pointer =
- src->textSrc.undo->end_mark = undo;
-
- if (++src->textSrc.undo->num_list >= UNDO_DEPTH)
- UndoGC(src->textSrc.undo);
- }
- src->textSrc.undo->dir = XawsdLeft;
- if (!src->textSrc.changed) {
- src->textSrc.undo->l_no_change = src->textSrc.undo->list->right;
- src->textSrc.undo->r_no_change = src->textSrc.undo->list->left;
- src->textSrc.changed = True;
- }
- }
- else if (!src->textSrc.enable_undo)
- src->textSrc.changed = True;
-
- if (error == XawEditDone) {
- XawTextPropertyInfo info;
- XawTextAnchor *anchor;
-
- /* find anchor and index */
- /* XXX index (i) could be returned by XawTextSourceFindAnchor
- * or similar function, to speed up */
- if ((anchor = XawTextSourceFindAnchor(w, left))) {
- XawTextEntity *eprev, *entity, *enext;
- XawTextPosition offset = 0, diff = block->length - (right - left);
-
- for (i = 0; i < src->textSrc.num_anchors; i++)
- if (src->textSrc.anchors[i] == anchor)
- break;
- if (anchor->cache && anchor->position + anchor->cache->offset +
- anchor->cache->length <= left)
- eprev = entity = anchor->cache;
- else
- eprev = entity = anchor->entities;
- while (entity) {
- offset = anchor->position + entity->offset;
-
- if (offset > left)
- break;
- if (offset + entity->length > left)
- break;
-
- eprev = entity;
- entity = entity->next;
- }
-
- /* try to do the right thing here (and most likely correct), but
- * other code needs to check what was done */
-
- /* adjust entity length */
- if (entity && offset <= left) {
- if (offset + entity->length < right)
- entity->length = left - offset + block->length;
- else
- entity->length += diff;
-
- if (entity->length == 0) {
- enext = entity->next;
- eprev->next = enext;
- anchor->cache = NULL;
- XtFree((XtPointer)entity);
- if (entity == anchor->entities) {
- if ((anchor->entities = enext) == NULL) {
- eprev = NULL;
- anchor = XawTextSourceRemoveAnchor(w, anchor);
- entity = anchor ? anchor->entities : NULL;
- }
- else
- eprev = entity = enext;
- }
- else
- entity = enext;
- }
- else {
- eprev = entity;
- entity = entity->next;
- }
- }
-
- while (anchor) {
- while (entity) {
- offset = anchor->position + entity->offset + entity->length;
-
- if (offset > right) {
- entity->length = XawMin(entity->length, offset - right);
- goto exit_anchor_loop;
- }
-
- enext = entity->next;
- if (eprev)
- eprev->next = enext;
- XtFree((XtPointer)entity);
- anchor->cache = NULL;
- if (entity == anchor->entities) {
- eprev = NULL;
- if ((anchor->entities = enext) == NULL) {
- if (i == 0)
- ++i;
- else if (i < --src->textSrc.num_anchors) {
- memmove(&src->textSrc.anchors[i],
- &src->textSrc.anchors[i + 1],
- (src->textSrc.num_anchors - i) *
- sizeof(XawTextAnchor*));
- XtFree((XtPointer)anchor);
- }
- if (i >= src->textSrc.num_anchors) {
- anchor = NULL;
- entity = NULL;
- break;
- }
- anchor = src->textSrc.anchors[i];
- entity = anchor->entities;
- continue;
- }
- }
- entity = enext;
- }
- if (i + 1 < src->textSrc.num_anchors) {
- anchor = src->textSrc.anchors[++i];
- entity = anchor->entities;
- eprev = NULL;
- }
- else {
- anchor = NULL;
- break;
- }
- eprev = NULL;
- }
-
-exit_anchor_loop:
- if (anchor) {
- XawTextAnchor *aprev;
-
- if (anchor->position >= XawMax(right, left + block->length))
- anchor->position += diff;
- else if (anchor->position > left &&
- (aprev = XawTextSourcePrevAnchor(w, anchor))) {
- XawTextPosition tmp = anchor->position - aprev->position;
-
- if (diff) {
- while (entity) {
- entity->offset += diff;
- entity = entity->next;
- }
- }
- entity = anchor->entities;
- while (entity) {
- entity->offset += tmp;
- entity = entity->next;
- }
- if ((entity = aprev->entities) == NULL)
- aprev->entities = anchor->entities;
- else {
- while (entity->next)
- entity = entity->next;
- entity->next = anchor->entities;
- }
- anchor->entities = NULL;
- (void)XawTextSourceRemoveAnchor(w, anchor);
- --i;
- }
- else if (diff) {
- while (entity) {
- entity->offset += diff;
- entity = entity->next;
- }
- }
- }
-
- if (diff) {
- /* The first anchor is never removed, and should
- * have position 0.
- * i should be -1 if attempted to removed the first
- * anchor, what can be caused when removing a chunk
- * of text of the first entity.
- * */
- if (++i == 0) {
- anchor = src->textSrc.anchors[0];
- eprev = entity = anchor->entities;
- while (entity) {
- enext = entity->next;
- if (entity->offset + entity->length <= -diff)
- XtFree((XtPointer)entity);
- else
- break;
- entity = enext;
- }
- if (eprev != entity) {
- anchor->cache = NULL;
- if ((anchor->entities = entity) != NULL) {
- if ((entity->offset += diff) < 0) {
- entity->length += entity->offset;
- entity->offset = 0;
- }
- }
- }
- ++i;
- }
- for (; i < src->textSrc.num_anchors; i++)
- src->textSrc.anchors[i]->position += diff;
- }
- }
-
- start = left;
- end = start + block->length;
- while (start < end) {
- start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True);
- if (start <= end) {
- ++lines;
- if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) {
- lines -= !_XawTextSourceNewLineAtEOF(w);
- break;
- }
- }
- }
-
- info.left = left;
- info.right = right;
- info.block = block;
- XtCallCallbacks(w, XtNpropertyCallback, &info);
-
- TellSourceChanged(src, left, right, block, lines);
- /* Call callbacks, we have changed the buffer */
- XtCallCallbacks(w, XtNcallback,
- (XtPointer)((long)src->textSrc.changed));
- }
-
-#endif /* OLDXAW */
- return (error);
-}
-
-#ifndef OLDXAW
-Bool
-_XawTextSrcUndo(TextSrcObject src, XawTextPosition *insert_pos)
-{
- static wchar_t wnull = 0;
- XawTextBlock block;
- XawTextUndoList *list, *nlist;
- XawTextUndoBuffer *l_state, *r_state;
- Boolean changed = src->textSrc.changed;
-
- if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo)
- return (False);
-
- list = src->textSrc.undo->pointer;
-
- if (src->textSrc.undo->dir == XawsdLeft) {
- l_state = list->right;
- r_state = list->left;
- }
- else {
- l_state = list->left;
- r_state = list->right;
- }
-
- if (src->textSrc.undo->l_no_change == l_state
- && src->textSrc.undo->r_no_change == r_state)
- src->textSrc.changed = False;
- else
- src->textSrc.changed = True;
-
- block.firstPos = 0;
- block.length = r_state->length;
- block.ptr = r_state->buffer ? r_state->buffer : (char*)&wnull;
- block.format = r_state->format;
-
- src->textSrc.undo_state = True;
- if (XawTextSourceReplace((Widget)src, l_state->position, l_state->position
- + l_state->length, &block) != XawEditDone) {
- src->textSrc.undo_state = False;
- src->textSrc.changed = changed;
- return (False);
- }
- src->textSrc.undo_state = False;
-
- ++l_state->refcount;
- ++r_state->refcount;
- nlist = XtNew(XawTextUndoList);
- nlist->left = l_state;
- nlist->right = r_state;
- nlist->undo = src->textSrc.undo->list;
- nlist->redo = NULL;
-
- if (list == src->textSrc.undo->list)
- src->textSrc.undo->end_mark = nlist;
-
- if (src->textSrc.undo->dir == XawsdLeft) {
- if (list->undo == NULL)
- src->textSrc.undo->dir = XawsdRight;
- else
- list = list->undo;
- }
- else {
- if (list->redo == NULL || list->redo == src->textSrc.undo->end_mark)
- src->textSrc.undo->dir = XawsdLeft;
- else
- list = list->redo;
- }
- *insert_pos = r_state->position + r_state->length;
- src->textSrc.undo->pointer = list;
- src->textSrc.undo->list->redo = nlist;
- src->textSrc.undo->list = nlist;
- src->textSrc.undo->merge = src->textSrc.undo->erase = 0;
-
- if (++src->textSrc.undo->num_list >= UNDO_DEPTH)
- UndoGC(src->textSrc.undo);
-
- return (True);
-}
-
-Bool
-_XawTextSrcToggleUndo(TextSrcObject src)
-{
- if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo)
- return (False);
-
- if (src->textSrc.undo->pointer != src->textSrc.undo->list) {
- if (src->textSrc.undo->dir == XawsdLeft) {
- if (src->textSrc.undo->pointer->redo
- && (src->textSrc.undo->pointer->redo
- != src->textSrc.undo->end_mark)) {
- src->textSrc.undo->pointer = src->textSrc.undo->pointer->redo;
- src->textSrc.undo->dir = XawsdRight;
- }
- }
- else {
- if (src->textSrc.undo->pointer->undo
- && (src->textSrc.undo->pointer != src->textSrc.undo->head)) {
- src->textSrc.undo->pointer = src->textSrc.undo->pointer->undo;
- src->textSrc.undo->dir = XawsdLeft;
- }
- }
- }
-
- return (True);
-}
-
-static void
-FreeUndoBuffer(XawTextUndo *undo)
-{
- unsigned i;
- XawTextUndoList *head, *del;
-
- for (i = 0; i < undo->num_undo; i++) {
- if (undo->undo[i]->buffer && undo->undo[i]->buffer != SrcNL &&
- undo->undo[i]->buffer != (char*)SrcWNL)
- XtFree(undo->undo[i]->buffer);
- XtFree((char*)undo->undo[i]);
- }
- XtFree((char*)undo->undo);
- head = undo->head;
-
- del = head;
- while (head) {
- head = head->redo;
- XtFree((char*)del);
- del = head;
- }
-
- if (undo->l_save) {
- XtFree((char*)undo->l_save);
- undo->l_save = NULL;
- }
- if (undo->r_save) {
- XtFree((char*)undo->r_save);
- undo->r_save = NULL;
- }
- if (undo->u_save) {
- XtFree((char*)undo->u_save);
- undo->u_save = NULL;
- }
-
- undo->list = undo->pointer = undo->head = undo->end_mark = NULL;
- undo->l_no_change = undo->r_no_change = NULL;
- undo->undo = NULL;
- undo->dir = XawsdLeft;
- undo->num_undo = undo->num_list = undo->erase = undo->merge = 0;
-}
-
-static void
-UndoGC(XawTextUndo *undo)
-{
- unsigned i;
- XawTextUndoList *head = undo->head, *redo = head->redo;
-
- if (head == undo->pointer || head == undo->end_mark
- || undo->l_no_change == NULL
- || head->left == undo->l_no_change || head->right == undo->l_no_change)
- return;
-
- undo->head = redo;
- redo->undo = NULL;
-
- --head->left->refcount;
- if (--head->right->refcount == 0) {
- for (i = 0; i < undo->num_undo; i+= 2)
- if (head->left == undo->undo[i] || head->left == undo->undo[i+1]) {
- if (head->left == undo->undo[i+1]) {
- XawTextUndoBuffer *tmp = redo->left;
-
- redo->left = redo->right;
- redo->right = tmp;
- }
- if (head->left->buffer && head->left->buffer != SrcNL &&
- head->left->buffer != (char*)SrcWNL)
- XtFree(head->left->buffer);
- XtFree((char*)head->left);
- if (head->right->buffer && head->right->buffer != SrcNL &&
- head->right->buffer != (char*)SrcWNL)
- XtFree(head->right->buffer);
- XtFree((char*)head->right);
-
- undo->num_undo -= 2;
- memmove(&undo->undo[i], &undo->undo[i + 2],
- (undo->num_undo - i) * sizeof(XawTextUndoBuffer*));
- break;
- }
- }
- XtFree((char*)head);
- --undo->num_list;
-}
-#endif /* OLDXAW */
-
-/*
- * Function:
- * XawTextSourceScan
- *
- * Parameters:
- * w - TextSrc Object
- * position - position to start scanning
- * type - type of thing to scan for
- * dir - direction to scan
- * count - which occurance if this thing to search for
- * include - whether or not to include the character found in
- * the position that is returned.
- *
- * Description:
- * Scans the text source for the number and type of item specified.
- *
- * Returns:
- * The position of the text
- */
-XawTextPosition
-XawTextSourceScan(Widget w, XawTextPosition position,
-#if NeedWidePrototypes
- int type, int dir, int count, int include
-#else
- XawTextScanType type, XawTextScanDirection dir,
- int count, Boolean include
-#endif
-)
-{
- TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
-
- return ((*cclass->textSrc_class.Scan)
- (w, position, type, dir, count, include));
-}
-
-/*
- * Function:
- * XawTextSourceSearch
- *
- * Parameters:
- * w - TextSource Object
- * position - position to start scanning
- * dir - direction to scan
- * text - the text block to search for.
- *
- * Returns:
- * The position of the text we are searching for or XawTextSearchError.
- *
- * Description:
- * Searchs the text source for the text block passed
- */
-XawTextPosition
-XawTextSourceSearch(Widget w, XawTextPosition position,
-#if NeedWidePrototypes
- int dir,
-#else
- XawTextScanDirection dir,
-#endif
- XawTextBlock *text)
-{
- TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
-
- return ((*cclass->textSrc_class.Search)(w, position, dir, text));
-}
-
-/*
- * Function:
- * XawTextSourceConvertSelection
- *
- * Parameters:
- * w - TextSrc object
- * selection - current selection atom
- * target - current target atom
- * type - type to conver the selection to
- * value - return value that has been converted
- * length - ""
- * format - format of the returned value
- *
- * Returns:
- * True if the selection has been converted
- */
-Boolean
-XawTextSourceConvertSelection(Widget w, Atom *selection, Atom *target,
- Atom *type, XtPointer *value,
- unsigned long *length, int *format)
-{
- TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
-
- return((*cclass->textSrc_class.ConvertSelection)
- (w, selection, target, type, value, length, format));
-}
-
-/*
- * Function:
- * XawTextSourceSetSelection
- *
- * Parameters:
- * w - TextSrc object
- * left - bounds of the selection
- * rigth - ""
- * selection - selection atom
- *
- * Description:
- * Allows special setting of the selection.
- */
-void
-XawTextSourceSetSelection(Widget w, XawTextPosition left,
- XawTextPosition right, Atom selection)
-{
- TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
-
- (*cclass->textSrc_class.SetSelection)(w, left, right, selection);
-}
-
-/*
- * External Functions for Multi Text
- */
-/*
- * TextFormat():
- * returns the format of text: FMT8BIT or FMTWIDE
- */
-XrmQuark
-_XawTextFormat(TextWidget tw)
-{
- return (((TextSrcObject)(tw->text.source))->textSrc.text_format);
-}
-
-/* _XawTextWCToMB():
- * Convert the wchar string to external encoding
- * The caller is responsible for freeing both the source and ret string
- *
- * wstr - source wchar string
- * len_in_out - lengh of string.
- * As In, length of source wchar string, measured in wchar
- * As Out, length of returned string
- */
-char *
-_XawTextWCToMB(Display *d, wchar_t *wstr, int *len_in_out)
-{
- XTextProperty textprop;
-
- if (XwcTextListToTextProperty(d, (wchar_t**)&wstr, 1,
- XTextStyle, &textprop) < Success) {
- XtWarningMsg("convertError", "textSource", "XawError",
- "Non-character code(s) in buffer.", NULL, NULL);
- *len_in_out = 0;
- return (NULL);
- }
- *len_in_out = textprop.nitems;
-
- return ((char *)textprop.value);
-}
-
-/* _XawTextMBToWC():
- * Convert the string to internal processing codeset WC.
- * The caller is responsible for freeing both the source and ret string.
- *
- * str - source string
- * len_in_out - lengh of string
- * As In, it is length of source string
- * As Out, it is length of returned string, measured in wchar
- */
-wchar_t *
-_XawTextMBToWC(Display *d, char *str, int *len_in_out)
-{
- XTextProperty textprop;
- char *buf;
- wchar_t **wlist, *wstr;
- int count;
-
- if (*len_in_out == 0)
- return (NULL);
-
- buf = XtMalloc(*len_in_out + 1);
-
- strncpy(buf, str, *len_in_out);
- *(buf + *len_in_out) = '\0';
- if (XmbTextListToTextProperty(d, &buf, 1, XTextStyle, &textprop) != Success) {
- XtWarningMsg("convertError", "textSource", "XawError",
- "No Memory, or Locale not supported.", NULL, NULL);
- XtFree(buf);
- *len_in_out = 0;
- return (NULL);
- }
-
- XtFree(buf);
- if (XwcTextPropertyToTextList(d, &textprop,
- (wchar_t***)&wlist, &count) != Success) {
- XtWarningMsg("convertError", "multiSourceCreate", "XawError",
- "Non-character code(s) in source.", NULL, NULL);
- *len_in_out = 0;
- return (NULL);
- }
- wstr = wlist[0];
- *len_in_out = wcslen(wstr);
- XtFree((XtPointer)wlist);
-
- return (wstr);
-}
-
-#ifndef OLDXAW
-static int
-qcmp_anchors(_Xconst void *left, _Xconst void *right)
-{
- return ((*(XawTextAnchor**)left)->position -
- (*(XawTextAnchor**)right)->position);
-}
-
-XawTextAnchor *
-XawTextSourceAddAnchor(Widget w, XawTextPosition position)
-{
- TextSrcObject src = (TextSrcObject)w;
- XawTextAnchor *anchor, *panchor;
-
- if ((panchor = XawTextSourceFindAnchor(w, position)) != NULL) {
- XawTextEntity *pentity, *entity;
-
- if (position - panchor->position < ANCHORS_DIST)
- return (panchor);
-
- if (panchor->cache && panchor->position + panchor->cache->offset +
- panchor->cache->length < position)
- pentity = entity = panchor->cache;
- else
- pentity = entity = panchor->entities;
-
- while (entity && panchor->position + entity->offset +
- entity->length < position) {
- pentity = entity;
- entity = entity->next;
- }
- if (entity) {
- XawTextPosition diff;
-
- if (panchor->position + entity->offset < position)
- position = panchor->position + entity->offset;
-
- if (position == panchor->position)
- return (panchor);
-
- anchor = XtNew(XawTextAnchor);
- diff = position - panchor->position;
-
- panchor->cache = NULL;
- anchor->entities = entity;
- if (pentity != entity)
- pentity->next = NULL;
- else
- panchor->entities = NULL;
- while (entity) {
- entity->offset -= diff;
- entity = entity->next;
- }
- }
- else {
- anchor = XtNew(XawTextAnchor);
- anchor->entities = NULL;
- }
- }
- else {
- anchor = XtNew(XawTextAnchor);
- anchor->entities = NULL;
- }
-
- anchor->position = position;
- anchor->cache = NULL;
-
- src->textSrc.anchors = (XawTextAnchor**)
- XtRealloc((XtPointer)src->textSrc.anchors, sizeof(XawTextAnchor*) *
- (src->textSrc.num_anchors + 1));
- src->textSrc.anchors[src->textSrc.num_anchors++] = anchor;
- qsort((void*)src->textSrc.anchors, src->textSrc.num_anchors,
- sizeof(XawTextAnchor*), qcmp_anchors);
-
- return (anchor);
-}
-
-XawTextAnchor *
-XawTextSourceFindAnchor(Widget w, XawTextPosition position)
-{
- TextSrcObject src = (TextSrcObject)w;
- int i = 0, left, right, nmemb = src->textSrc.num_anchors;
- XawTextAnchor *anchor, **anchors = src->textSrc.anchors;
-
- left = 0;
- right = nmemb - 1;
- while (left <= right) {
- anchor = anchors[i = (left + right) >> 1];
- if (anchor->position == position)
- return (anchor);
- else if (position < anchor->position)
- right = i - 1;
- else
- left = i + 1;
- }
-
- if (nmemb)
- return (right < 0 ? anchors[0] : anchors[right]);
-
- return (NULL);
-}
-
-Bool
-XawTextSourceAnchorAndEntity(Widget w, XawTextPosition position,
- XawTextAnchor **anchor_return,
- XawTextEntity **entity_return)
-{
- XawTextAnchor *anchor = XawTextSourceFindAnchor(w, position);
- XawTextEntity *pentity, *entity;
- XawTextPosition offset;
- Bool next_anchor = True, retval = False;
-
- if (anchor->cache && anchor->position + anchor->cache->offset +
- anchor->cache->length <= position)
- pentity = entity = anchor->cache;
- else
- pentity = entity = anchor->entities;
- while (entity) {
- offset = anchor->position + entity->offset;
-
- if (offset > position) {
- retval = next_anchor = False;
- break;
- }
- if (offset + entity->length > position) {
- retval = True;
- next_anchor = False;
- break;
- }
- pentity = entity;
- entity = entity->next;
- }
-
- if (next_anchor) {
- *anchor_return = anchor = XawTextSourceNextAnchor(w, anchor);
- *entity_return = anchor ? anchor->entities : NULL;
- }
- else {
- *anchor_return = anchor;
- *entity_return = retval ? entity : pentity;
- }
-
- if (*anchor_return)
- (*anchor_return)->cache = *entity_return;
-
- return (retval);
-}
-
-XawTextAnchor *
-XawTextSourceNextAnchor(Widget w, XawTextAnchor *anchor)
-{
- int i;
- TextSrcObject src = (TextSrcObject)w;
-
- for (i = 0; i < src->textSrc.num_anchors - 1; i++)
- if (src->textSrc.anchors[i] == anchor)
- return (src->textSrc.anchors[i + 1]);
-
- return (NULL);
-}
-
-XawTextAnchor *
-XawTextSourcePrevAnchor(Widget w, XawTextAnchor *anchor)
-{
- int i;
- TextSrcObject src = (TextSrcObject)w;
-
- for (i = src->textSrc.num_anchors - 1; i > 0; i--)
- if (src->textSrc.anchors[i] == anchor)
- return (src->textSrc.anchors[i - 1]);
-
- return (NULL);
-}
-
-XawTextAnchor *
-XawTextSourceRemoveAnchor(Widget w, XawTextAnchor *anchor)
-{
- int i;
- TextSrcObject src = (TextSrcObject)w;
-
- for (i = 0; i < src->textSrc.num_anchors; i++)
- if (src->textSrc.anchors[i] == anchor)
- break;
-
- if (i == 0)
- return (src->textSrc.num_anchors > 1 ? src->textSrc.anchors[1] : NULL);
-
- if (i < src->textSrc.num_anchors) {
- XtFree((XtPointer)anchor);
- if (i < --src->textSrc.num_anchors) {
- memmove(&src->textSrc.anchors[i],
- &src->textSrc.anchors[i + 1],
- (src->textSrc.num_anchors - i) *
- sizeof(XawTextAnchor*));
-
- return (src->textSrc.anchors[i]);
- }
- }
-
- return (NULL);
-}
-
-XawTextEntity *
-XawTextSourceAddEntity(Widget w, int type, int flags, XtPointer data,
- XawTextPosition position, Cardinal length,
- XrmQuark property)
-{
- XawTextAnchor *next, *anchor = _XawTextSourceFindAnchor(w, position);
- XawTextEntity *entity, *eprev;
-
- /* There is no support for zero length entities for now */
- if (length == 0)
- return (NULL);
-
- if (anchor->cache && anchor->position + anchor->cache->offset +
- anchor->cache->length <= position)
- eprev = entity = anchor->cache;
- else
- eprev = entity = anchor->entities;
-
- while (entity && anchor->position + entity->offset + entity->length <=
- position) {
- eprev = entity;
- entity = entity->next;
- }
- if (entity && anchor->position + entity->offset < position + length) {
- fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n");
- return (NULL);
- }
-
- next = XawTextSourceFindAnchor(w, position + length);
- if (next && next != anchor) {
- if ((entity = next->entities) != NULL) {
- if (next->position + entity->offset < position + length) {
- fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n");
- return (NULL);
- }
- }
- if (position + length > next->position) {
- XawTextPosition diff = position + length - next->position;
-
- next->position += diff;
- entity = next->entities;
- while (entity) {
- entity->offset -= diff;
- entity = entity->next;
- }
- entity = anchor->entities;
- while (entity && entity->offset < 0)
- entity = entity->next;
- if (entity && entity->offset < 0) {
- if (eprev)
- eprev->next = next->entities;
- else
- anchor->entities = next->entities;
- if ((next->entities = entity->next) == NULL)
- (void)XawTextSourceRemoveAnchor(w, next);
- entity->next = NULL;
-
- return (XawTextSourceAddEntity(w, type, flags, data, position,
- length, property));
- }
- }
- }
-
- /* Automatically join sequential entities if possible */
- if (eprev &&
- anchor->position + eprev->offset + eprev->length == position &&
- eprev->property == property && eprev->type == type &&
- eprev->flags == flags && eprev->data == data) {
- eprev->length += length;
- return (eprev);
- }
-
- entity = XtNew(XawTextEntity);
- entity->type = type;
- entity->flags = flags;
- entity->data = data;
- entity->offset = position - anchor->position;
- entity->length = length;
- entity->property = property;
-
- if (eprev == NULL) {
- anchor->entities = entity;
- entity->next = NULL;
- anchor->cache = NULL;
- }
- else if (eprev->offset > entity->offset) {
- anchor->cache = NULL;
- anchor->entities = entity;
- entity->next = eprev;
- }
- else {
- anchor->cache = eprev;
- entity->next = eprev->next;
- eprev->next = entity;
- }
-
- return (entity);
-}
-
-void
-XawTextSourceClearEntities(Widget w, XawTextPosition left, XawTextPosition right)
-{
- XawTextAnchor *anchor = XawTextSourceFindAnchor(w, left);
- XawTextEntity *entity, *eprev, *enext;
- XawTextPosition offset;
- int length;
-
- while (anchor && anchor->entities == NULL)
- anchor = XawTextSourceRemoveAnchor(w, anchor);
-
- if (anchor == NULL || left >= right)
- return;
-
- if (anchor->cache && anchor->position + anchor->cache->offset +
- anchor->cache->length < left)
- eprev = entity = anchor->cache;
- else
- eprev = entity = anchor->entities;
-
- /* find first entity before left position */
- while (anchor->position + entity->offset + entity->length < left) {
- eprev = entity;
- if ((entity = entity->next) == NULL) {
- if ((anchor = XawTextSourceNextAnchor(w, anchor)) == NULL)
- return;
- if ((eprev = entity = anchor->entities) == NULL) {
- fprintf(stderr, "Bad anchor found!\n");
- return;
- }
- }
- }
-
- offset = anchor->position + entity->offset;
- if (offset <= left) {
- length = XawMin(entity->length, left - offset);
-
- if (length <= 0) {
- enext = entity->next;
- eprev->next = enext;
- XtFree((XtPointer)entity);
- anchor->cache = NULL;
- if (entity == anchor->entities) {
- eprev = NULL;
- if ((anchor->entities = enext) == NULL) {
- if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL)
- return;
- entity = anchor->entities;
- }
- else
- entity = enext;
- }
- else
- entity = enext;
- }
- else {
- entity->length = length;
- eprev = entity;
- entity = entity->next;
- }
- }
-
- /* clean everything until right position is reached */
- while (anchor) {
- while (entity) {
- offset = anchor->position + entity->offset + entity->length;
-
- if (offset > right) {
- anchor->cache = NULL;
- entity->offset = XawMax(entity->offset, right - anchor->position);
- entity->length = XawMin(entity->length, offset - right);
- return;
- }
-
- enext = entity->next;
- if (eprev)
- eprev->next = enext;
- XtFree((XtPointer)entity);
- if (entity == anchor->entities) {
- eprev = anchor->cache = NULL;
- if ((anchor->entities = enext) == NULL) {
- if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL)
- return;
- entity = anchor->entities;
- continue;
- }
- }
- entity = enext;
- }
- if (anchor)
- anchor->cache = NULL;
- if ((anchor = XawTextSourceNextAnchor(w, anchor)) != NULL)
- entity = anchor->entities;
- eprev = NULL;
- }
-}
-
-/* checks the anchors up to position, and create an appropriate anchor
- * at position, if required.
- */
-XawTextAnchor *
-_XawTextSourceFindAnchor(Widget w, XawTextPosition position)
-{
- XawTextAnchor *anchor;
-
- anchor = XawTextSourceFindAnchor(w, position);
-
- position -= position % ANCHORS_DIST;
-
- if (position - anchor->position >= ANCHORS_DIST)
- return (XawTextSourceAddAnchor(w, position));
-
- return (anchor);
-}
-#endif
+/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Chris Peterson, MIT X Consortium. + * Much code taken from X11R3 String and Disk Sources. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <ctype.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xfuncs.h> +#include <X11/Xutil.h> +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xaw/TextSrcP.h> +#include <X11/Xaw/XawInit.h> +#include "XawI18n.h" +#include "Private.h" + +#ifndef OLDXAW +#define UNDO_DEPTH 16384 + +#define ANCHORS_DIST 4096 /* default distance between anchors */ + +/* + * Types + */ +typedef struct { + XawTextPosition position; + char *buffer; + unsigned length; + unsigned refcount; + unsigned long format; +} XawTextUndoBuffer; + +typedef struct _XawTextUndoList XawTextUndoList; +struct _XawTextUndoList { + XawTextUndoBuffer *left, *right; + XawTextUndoList *undo, *redo; +}; + +struct _XawTextUndo { + XawTextUndoBuffer **undo; + unsigned num_undo; + XawTextUndoList *list, *pointer, *end_mark, *head; + unsigned num_list; + XawTextScanDirection dir; + XawTextUndoBuffer *l_save, *r_save; + XawTextUndoList *u_save; + XawTextUndoBuffer *l_no_change, *r_no_change; + int merge; + int erase; /* there are two types of erases */ +}; +#endif /* OLDXAW */ + +/* + * Class Methods + */ +static Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*, + unsigned long*, int*); +static XawTextPosition Read(Widget, XawTextPosition, XawTextBlock*, int); +static int Replace(Widget, XawTextPosition, XawTextPosition, XawTextBlock*); +static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, + XawTextScanDirection, int, Bool); +static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, + XawTextBlock*); +static void SetSelection(Widget, XawTextPosition, XawTextPosition, Atom); +static void XawTextSrcClassInitialize(void); +static void XawTextSrcClassPartInitialize(WidgetClass); +static void XawTextSrcInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawTextSrcDestroy(Widget); +static Boolean XawTextSrcSetValues(Widget, Widget, Widget, ArgList, Cardinal*); +/* + * Prototypes + */ +static void CvtStringToEditMode(XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr); +static Boolean CvtEditModeToString(Display*, XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr, XtPointer*); +#ifndef OLDXAW +static void FreeUndoBuffer(XawTextUndo*); +static void UndoGC(XawTextUndo*); +static void TellSourceChanged(TextSrcObject, XawTextPosition, XawTextPosition, + XawTextBlock*, int); +Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*); +Bool _XawTextSrcToggleUndo(TextSrcObject); +XawTextAnchor *_XawTextSourceFindAnchor(Widget, XawTextPosition); + +/* + * External + */ +void _XawSourceAddText(Widget, Widget); +void _XawSourceRemoveText(Widget, Widget, Bool); +Bool _XawTextSourceNewLineAtEOF(Widget); +void _XawSourceSetUndoErase(TextSrcObject, int); +void _XawSourceSetUndoMerge(TextSrcObject, Bool); +#endif /* OLDXAW */ + +/* + * Defined in Text.c + */ +char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); +void _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition, + XawTextBlock*, int); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(TextSrcRec, textSrc.field) +static XtResource resources[] = { + { + XtNeditType, + XtCEditType, + XtREditMode, + sizeof(XawTextEditType), + offset(edit_mode), + XtRString, + "read" + }, +#ifndef OLDXAW + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(callback), + XtRCallback, + NULL + }, + { + XtNsourceChanged, + XtCChanged, + XtRBoolean, + sizeof(Boolean), + offset(changed), + XtRImmediate, + (XtPointer)False + }, + { + XtNenableUndo, + XtCUndo, + XtRBoolean, + sizeof(Boolean), + offset(enable_undo), + XtRImmediate, + (XtPointer)False + }, + { + XtNpropertyCallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(property_callback), + XtRCallback, + NULL + }, +#endif /* OLDXAW */ +}; +#undef offset + +#define Superclass (&objectClassRec) +TextSrcClassRec textSrcClassRec = { + /* object */ + { + (WidgetClass)Superclass, /* superclass */ + "TextSrc", /* class_name */ + sizeof(TextSrcRec), /* widget_size */ + XawTextSrcClassInitialize, /* class_initialize */ + XawTextSrcClassPartInitialize, /* class_part_initialize */ + False, /* class_inited */ + XawTextSrcInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + False, /* compress_exposure */ + False, /* compress_enterleave */ + False, /* visible_interest */ + XawTextSrcDestroy, /* destroy */ + NULL, /* resize */ + NULL, /* expose */ + XawTextSrcSetValues, /* set_values */ + NULL, /* set_values_hook */ + NULL, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + NULL, /* query_geometry */ + NULL, /* display_accelerator */ + NULL, /* extension */ + }, + /* text_src */ + { + Read, /* Read */ + Replace, /* Replace */ + Scan, /* Scan */ + Search, /* Search */ + SetSelection, /* SetSelection */ + ConvertSelection, /* ConvertSelection */ + }, +}; + +WidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec; + +static XrmQuark QRead, QAppend, QEdit; +#ifndef OLDXAW +static char *SrcNL = "\n"; +static wchar_t SrcWNL[2]; +#endif + +/* + * Implementation + */ +static void +XawTextSrcClassInitialize(void) +{ + XawInitializeWidgetSet(); + +#ifndef OLDXAW + SrcWNL[0] = _Xaw_atowc(XawLF); + SrcWNL[1] = 0; +#endif + QRead = XrmPermStringToQuark(XtEtextRead); + QAppend = XrmPermStringToQuark(XtEtextAppend); + QEdit = XrmPermStringToQuark(XtEtextEdit); + XtAddConverter(XtRString, XtREditMode, CvtStringToEditMode, NULL, 0); + XtSetTypeConverter(XtREditMode, XtRString, CvtEditModeToString, NULL, 0, + XtCacheNone, NULL); +} + +static void +XawTextSrcClassPartInitialize(WidgetClass wc) +{ + TextSrcObjectClass t_src, superC; + + t_src = (TextSrcObjectClass)wc; + superC = (TextSrcObjectClass)t_src->object_class.superclass; + + /* + * We don't need to check for null super since we'll get to TextSrc + * eventually + */ + if (t_src->textSrc_class.Read == XtInheritRead) + t_src->textSrc_class.Read = superC->textSrc_class.Read; + + if (t_src->textSrc_class.Replace == XtInheritReplace) + t_src->textSrc_class.Replace = superC->textSrc_class.Replace; + + if (t_src->textSrc_class.Scan == XtInheritScan) + t_src->textSrc_class.Scan = superC->textSrc_class.Scan; + + if (t_src->textSrc_class.Search == XtInheritSearch) + t_src->textSrc_class.Search = superC->textSrc_class.Search; + + if (t_src->textSrc_class.SetSelection == XtInheritSetSelection) + t_src->textSrc_class.SetSelection = superC->textSrc_class.SetSelection; + + if (t_src->textSrc_class.ConvertSelection == XtInheritConvertSelection) + t_src->textSrc_class.ConvertSelection = + superC->textSrc_class.ConvertSelection; +} + +/*ARGSUSED*/ +static void +XawTextSrcInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ +#ifndef OLDXAW + TextSrcObject src = (TextSrcObject)cnew; + + if (src->textSrc.enable_undo) { + src->textSrc.undo = (XawTextUndo*)XtCalloc(1, sizeof(XawTextUndo)); + src->textSrc.undo->dir = XawsdLeft; + } + else + src->textSrc.undo = NULL; + src->textSrc.undo_state = False; + if (XtIsSubclass(XtParent(cnew), textWidgetClass)) { + src->textSrc.text = (WidgetList)XtMalloc(sizeof(Widget*)); + src->textSrc.text[0] = XtParent(cnew); + src->textSrc.num_text = 1; + } + else { + src->textSrc.text = NULL; + src->textSrc.num_text = 0; + } + + src->textSrc.anchors = NULL; + src->textSrc.num_anchors = 0; + (void)XawTextSourceAddAnchor(cnew, 0); +#endif /* OLDXAW */ +} + +static void +XawTextSrcDestroy(Widget w) +{ +#ifndef OLDXAW + TextSrcObject src = (TextSrcObject)w; + + if (src->textSrc.enable_undo) { + FreeUndoBuffer(src->textSrc.undo); + XtFree((char*)src->textSrc.undo); + } + XtFree((char*)src->textSrc.text); + + if (src->textSrc.num_anchors) { + XawTextEntity *entity, *enext; + int i; + + for (i = 0; i < src->textSrc.num_anchors; i++) { + entity = src->textSrc.anchors[i]->entities; + while (entity) { + enext = entity->next; + XtFree((XtPointer)entity); + entity = enext; + } + XtFree((XtPointer)src->textSrc.anchors[i]); + } + XtFree((XtPointer)src->textSrc.anchors); + } +#endif /* OLDXAW */ +} + +/*ARGSUSED*/ +static Boolean +XawTextSrcSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ +#ifndef OLDXAW + TextSrcObject oldtw = (TextSrcObject)current; + TextSrcObject newtw = (TextSrcObject)cnew; + + if (oldtw->textSrc.enable_undo != newtw->textSrc.enable_undo) { + if (newtw->textSrc.enable_undo) { + newtw->textSrc.undo = (XawTextUndo*) + XtCalloc(1, sizeof(XawTextUndo)); + newtw->textSrc.undo->dir = XawsdLeft; + } + else { + FreeUndoBuffer(newtw->textSrc.undo); + XtFree((char*)newtw->textSrc.undo); + newtw->textSrc.undo = NULL; + } + } + if (oldtw->textSrc.changed != newtw->textSrc.changed) { + if (newtw->textSrc.enable_undo) { + if (newtw->textSrc.undo->list) { + newtw->textSrc.undo->l_no_change = + newtw->textSrc.undo->list->left; + newtw->textSrc.undo->r_no_change = + newtw->textSrc.undo->list->right; + } + else + newtw->textSrc.undo->l_no_change = + newtw->textSrc.undo->r_no_change = NULL; + } + } +#endif /* OLDXAW */ + return (False); +} + +/* + * Function: + * Read + * + * Parameters: + * w - TextSrc Object + * pos - position of the text to retreive + * text - text block that will contain returned text + * length - maximum number of characters to read + * + * Description: + * This function reads the source. + * + * Returns: + * The character position following the retrieved text. + */ +/*ARGSUSED*/ +static XawTextPosition +Read(Widget w, XawTextPosition pos, XawTextBlock *text, int length) +{ + return ((XawTextPosition)0); +} + +/* + * Function: + * Replace + * + * Parameters: + * src - Text Source Object + * startPos - ends of text that will be removed + * endPos - "" + * text - new text to be inserted into buffer at startPos + * + * Description: + * Replaces a block of text with new text. + */ +/*ARGSUSED*/ +static int +Replace(Widget w, XawTextPosition startPos, XawTextPosition endPos, + XawTextBlock *text) +{ + return (XawEditError); +} + +/* + * Function: + * Scan + * + * Parameters: + * w - TextSrc Object + * position - position to start scanning + * type - type of thing to scan for + * dir - direction to scan + * count - which occurance if this thing to search for + * include - whether or not to include the character found in + * the position that is returned + * + * Description: + * Scans the text source for the number and type of item specified. + */ +/*ARGSUSED*/ +static XawTextPosition +Scan(Widget w, XawTextPosition position, XawTextScanType type, + XawTextScanDirection dir, int count, Bool include) +{ + return ((XawTextPosition)0); +} + +/* + * Function: + * Search + * + * Parameters: + * w - TextSource Object + * position - position to start searching + * dir - direction to search + * text - the text block to search for + * + * Description: + * Searchs the text source for the text block passed + */ +/*ARGSUSED*/ +static XawTextPosition +Search(Widget w, XawTextPosition position, XawTextScanDirection dir, + XawTextBlock *text) +{ + return (XawTextSearchError); +} + +/*ARGSUSED*/ +static Boolean +ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type, + XtPointer *value, unsigned long *length, int *format) +{ + return (False); +} + +/*ARGSUSED*/ +static void +SetSelection(Widget w, XawTextPosition left, XawTextPosition right, + Atom selection) +{ +} + +/*ARGSUSED*/ +static void +CvtStringToEditMode(XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal) +{ + static XawTextEditType editType; + XrmQuark q; + char name[7]; + + XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); + q = XrmStringToQuark(name); + + if (q == QRead) + editType = XawtextRead; + else if (q == QAppend) + editType = XawtextAppend; + else if (q == QEdit) + editType = XawtextEdit; + else { + toVal->size = 0; + toVal->addr = NULL; + XtStringConversionWarning((char *)fromVal->addr, XtREditMode); + } + toVal->size = sizeof(XawTextEditType); + toVal->addr = (XPointer)&editType; +} + +/*ARGSUSED*/ +static Boolean +CvtEditModeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal, + XtPointer *data) +{ + static String buffer; + Cardinal size; + + switch (*(XawTextEditType *)fromVal->addr) { + case XawtextRead: + buffer = XtEtextRead; + break; + case XawtextAppend: + buffer = XtEtextAppend; + break; + case XawtextEdit: + buffer = XtEtextEdit; + break; + default: + XawTypeToStringWarning(dpy, XtREditMode); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + + size = strlen(buffer) + 1; + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +#ifndef OLDXAW +Bool +_XawTextSourceNewLineAtEOF(Widget w) +{ + TextSrcObject src = (TextSrcObject)w; + XawTextBlock text; + + text.firstPos = 0; + if ((text.format = src->textSrc.text_format) == XawFmt8Bit) + text.ptr = SrcNL; + else + text.ptr = (char*)SrcWNL; + text.length = 1; + + return (XawTextSourceSearch(w, XawTextSourceScan(w, 0, XawstAll, + XawsdRight, 1, True) - 1, + XawsdRight, &text) != XawTextSearchError); +} + +void +_XawSourceAddText(Widget source, Widget text) +{ + TextSrcObject src = (TextSrcObject)source; + Bool found = False; + Cardinal i; + + for (i = 0; i < src->textSrc.num_text; i++) + if (src->textSrc.text[i] == text) { + found = True; + break; + } + + if (!found) { + src->textSrc.text = (WidgetList) + XtRealloc((char*)src->textSrc.text, + sizeof(Widget) * (src->textSrc.num_text + 1)); + src->textSrc.text[src->textSrc.num_text++] = text; + } +} + +void +_XawSourceRemoveText(Widget source, Widget text, Bool destroy) +{ + TextSrcObject src = (TextSrcObject)source; + Bool found = False; + Cardinal i; + + if (src == NULL) + return; + + for (i = 0; i < src->textSrc.num_text; i++) + if (src->textSrc.text[i] == text) { + found = True; + break; + } + + if (found) { + if (--src->textSrc.num_text == 0) { + if (destroy) { + XtDestroyWidget(source); + return; + } + else { + XtFree((char*)src->textSrc.text); + src->textSrc.text = NULL; /* for realloc "magic" */ + } + } + else if (i < src->textSrc.num_text) + memmove(&src->textSrc.text[i], &src->textSrc.text[i + 1], + sizeof(Widget) * (src->textSrc.num_text - i)); + } +} +#endif /* OLDXAW */ + +/* + * Function: + * XawTextSourceRead + * + * Parameters: + * w - TextSrc Object + * pos - position of the text to retrieve + * text - text block that will contain returned text (return) + * length - maximum number of characters to read + * + * Description: + * This function reads the source. + * + * Returns: + * The number of characters read into the buffer + */ +XawTextPosition +XawTextSourceRead(Widget w, XawTextPosition pos, XawTextBlock *text, + int length) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + return ((*cclass->textSrc_class.Read)(w, pos, text, length)); +} + +#ifndef OLDXAW +static void +TellSourceChanged(TextSrcObject src, XawTextPosition left, + XawTextPosition right, XawTextBlock *block, int lines) +{ + Cardinal i; + + for (i = 0; i < src->textSrc.num_text; i++) + _XawTextSourceChanged(src->textSrc.text[i], left, right, block, lines); +} + +/* + * This function is required because there is no way to diferentiate + * if the first erase was generated by a backward-kill-char and the + * second by a forward-kill-char (or vice-versa) from XawTextSourceReplace. + * It is only possible to diferentiate after the second character is + * killed, but then, it is too late. + */ +void +_XawSourceSetUndoErase(TextSrcObject src, int value) +{ + if (src && src->textSrc.enable_undo) + src->textSrc.undo->erase = value; +} + +/* + * To diferentiate insert-char's separeted by cursor movements. + */ +void +_XawSourceSetUndoMerge(TextSrcObject src, Bool state) +{ + if (src && src->textSrc.enable_undo) + src->textSrc.undo->merge += state ? 1 : -1; +} +#endif /* OLDXAW */ + +/* + * Public Functions + */ +/* + * Function: + * XawTextSourceReplace + * + * Parameters: + * src - Text Source Object + * startPos - ends of text that will be removed + * endPos - "" + * text - new text to be inserted into buffer at startPos + * + * Description: + * Replaces a block of text with new text. + * + * Returns: + * XawEditError or XawEditDone. + */ +/*ARGSUSED*/ +int +XawTextSourceReplace(Widget w, XawTextPosition left, + XawTextPosition right, XawTextBlock *block) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; +#ifndef OLDXAW + TextSrcObject src = (TextSrcObject)w; + XawTextUndoBuffer *l_state, *r_state; + XawTextUndoList *undo; + Bool enable_undo; + XawTextPosition start, end; + int i, error, lines = 0; + + if (src->textSrc.edit_mode == XawtextRead) + return (XawEditError); + + enable_undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; + if (enable_undo) { + unsigned size, total; + + if (src->textSrc.undo->l_save) { + l_state = src->textSrc.undo->l_save; + src->textSrc.undo->l_save = NULL; + } + else + l_state = XtNew(XawTextUndoBuffer); + l_state->refcount = 1; + l_state->position = left; + if (left < right) { + Widget ctx = NULL; + + for (i = 0; i < src->textSrc.num_text; i++) + if (XtIsSubclass(src->textSrc.text[i], textWidgetClass)) { + ctx = src->textSrc.text[i]; + break; + } + l_state->buffer = _XawTextGetText((TextWidget)ctx, left, right); + l_state->length = right - left; + } + else { + l_state->length = 0; + l_state->buffer = NULL; + } + l_state->format = src->textSrc.text_format; + if (l_state->length == 1) { + if (l_state->format == XawFmtWide && + *(wchar_t*)l_state->buffer == *SrcWNL) { + XtFree(l_state->buffer); + l_state->buffer = (char*)SrcWNL; + } + else if (*l_state->buffer == '\n') { + XtFree(l_state->buffer); + l_state->buffer = SrcNL; + } + } + + if (src->textSrc.undo->r_save) { + r_state = src->textSrc.undo->r_save; + src->textSrc.undo->r_save = NULL; + } + else + r_state = XtNew(XawTextUndoBuffer); + r_state->refcount = 1; + r_state->position = left; + r_state->format = block->format; + size = block->format == XawFmtWide ? sizeof(wchar_t) : sizeof(char); + total = size * block->length; + r_state->length = block->length; + r_state->buffer = NULL; + if (total == size) { + if (r_state->format == XawFmtWide && + *(wchar_t*)block->ptr == *SrcWNL) + r_state->buffer = (char*)SrcWNL; + else if (*block->ptr == '\n') + r_state->buffer = SrcNL; + } + if (total && !r_state->buffer) { + r_state->buffer = XtMalloc(total); + memcpy(r_state->buffer, block->ptr, total); + } + + if (src->textSrc.undo->u_save) { + undo = src->textSrc.undo->u_save; + src->textSrc.undo->u_save = NULL; + } + else + undo = XtNew(XawTextUndoList); + undo->left = l_state; + undo->right = r_state; + undo->undo = src->textSrc.undo->list; + undo->redo = NULL; + } + else { + undo = NULL; + l_state = r_state = NULL; + } + +#define LARGE_VALUE 262144 /* 256 K */ + /* optimization, to avoid long delays recalculating the line number + * when editing huge files + */ + if (left > LARGE_VALUE) { + start = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 2, False); + for (i = 0; i < src->textSrc.num_text; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + + if (left <= tw->text.lt.top && + left + block->length - (right - left) > tw->text.lt.top) + _XawTextBuildLineTable(tw, start, False); + } + } +#undef LARGE_VALUE + + start = left; + end = right; + while (start < end) { + start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True); + if (start <= end) { + --lines; + if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) { + lines += !_XawTextSourceNewLineAtEOF(w); + break; + } + } + } +#else + int error; +#endif /* OLDXAW */ + + error = (*cclass->textSrc_class.Replace)(w, left, right, block); + +#ifndef OLDXAW + if (error != XawEditDone) { + if (enable_undo) { + if (l_state->buffer) { + if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL) + XtFree(l_state->buffer); + l_state->buffer = NULL; + } + src->textSrc.undo->l_save = l_state; + if (r_state->buffer) { + if (r_state->buffer != SrcNL && r_state->buffer != (char*)SrcWNL) + XtFree(r_state->buffer); + r_state->buffer = NULL; + } + src->textSrc.undo->r_save = r_state; + + src->textSrc.undo->u_save = undo; + } + } + else if (enable_undo) { + XawTextUndoList *list = src->textSrc.undo->list; + XawTextUndoBuffer *unl, *lnl; + int erase = undo->right->length == 0 && undo->left->length == 1 && list + && list->right->length == 0; + + if (erase) { + erase = list->left->position - 1 == undo->left->position ? -1 : + list->left->position == undo->left->position ? 1 : 0; + if (src->textSrc.undo->erase && erase != src->textSrc.undo->erase) + erase = 0; + else + src->textSrc.undo->erase = erase; + } + + if (erase) { + unl = l_state; + lnl = list->left; + } + else { + unl = r_state; + lnl = list ? list->right : NULL; + } + + /* Try to merge the undo buffers */ + if (src->textSrc.undo->merge > 0 && ((erase || + (list && ((list->left->length == 0 && undo->left->length == 0) || + (list->left->length == list->right->length && + undo->left->length == 1)) && + undo->right->length == 1 && + list->right->position + list->right->length + == undo->right->position)) + && src->textSrc.undo->pointer == list + && unl->format == list->right->format + && ((unl->format == XawFmt8Bit && unl->buffer[0] != XawLF) || + (unl->format == XawFmtWide && + *(wchar_t*)(unl->buffer) != _Xaw_atowc(XawLF))) + && ((lnl->format == XawFmt8Bit && lnl->buffer[0] != XawLF) || + (lnl->format == XawFmtWide && + *(wchar_t*)(lnl->buffer) != _Xaw_atowc(XawLF))))) { + unsigned size = lnl->format == XawFmtWide ? + sizeof(wchar_t) : sizeof(char); + + if (!erase) { + list->right->buffer = XtRealloc(list->right->buffer, + (list->right->length + 1) * size); + memcpy(list->right->buffer + list->right->length * size, + undo->right->buffer, size); + ++list->right->length; + XtFree(r_state->buffer); + } + else if (erase < 0) { + --list->left->position; + --list->right->position; + } + + src->textSrc.undo->l_save = l_state; + src->textSrc.undo->r_save = r_state; + src->textSrc.undo->u_save = undo; + + if (list->left->length) { + list->left->buffer = XtRealloc(list->left->buffer, + (list->left->length + 1) * size); + if (erase >= 0) + memcpy(list->left->buffer + list->left->length * size, + undo->left->buffer, size); + else { + /* use memmove, since strings overlap */ + memmove(list->left->buffer + size, list->left->buffer, + list->left->length * size); + memcpy(list->left->buffer, undo->left->buffer, size); + } + ++list->left->length; + if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL) + XtFree(l_state->buffer); + } + + if (src->textSrc.undo->num_list >= UNDO_DEPTH) + UndoGC(src->textSrc.undo); + } + else { + src->textSrc.undo->undo = (XawTextUndoBuffer**) + XtRealloc((char*)src->textSrc.undo->undo, + (2 + src->textSrc.undo->num_undo) + * sizeof(XawTextUndoBuffer)); + src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = l_state; + src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = r_state; + + if (src->textSrc.undo->list) + src->textSrc.undo->list->redo = undo; + else + src->textSrc.undo->head = undo; + + src->textSrc.undo->merge = l_state->length <= 1 && + r_state->length <= 1; + + src->textSrc.undo->list = src->textSrc.undo->pointer = + src->textSrc.undo->end_mark = undo; + + if (++src->textSrc.undo->num_list >= UNDO_DEPTH) + UndoGC(src->textSrc.undo); + } + src->textSrc.undo->dir = XawsdLeft; + if (!src->textSrc.changed) { + src->textSrc.undo->l_no_change = src->textSrc.undo->list->right; + src->textSrc.undo->r_no_change = src->textSrc.undo->list->left; + src->textSrc.changed = True; + } + } + else if (!src->textSrc.enable_undo) + src->textSrc.changed = True; + + if (error == XawEditDone) { + XawTextPropertyInfo info; + XawTextAnchor *anchor; + + /* find anchor and index */ + /* XXX index (i) could be returned by XawTextSourceFindAnchor + * or similar function, to speed up */ + if ((anchor = XawTextSourceFindAnchor(w, left))) { + XawTextEntity *eprev, *entity, *enext; + XawTextPosition offset = 0, diff = block->length - (right - left); + + for (i = 0; i < src->textSrc.num_anchors; i++) + if (src->textSrc.anchors[i] == anchor) + break; + if (anchor->cache && anchor->position + anchor->cache->offset + + anchor->cache->length <= left) + eprev = entity = anchor->cache; + else + eprev = entity = anchor->entities; + while (entity) { + offset = anchor->position + entity->offset; + + if (offset > left) + break; + if (offset + entity->length > left) + break; + + eprev = entity; + entity = entity->next; + } + + /* try to do the right thing here (and most likely correct), but + * other code needs to check what was done */ + + /* adjust entity length */ + if (entity && offset <= left) { + if (offset + entity->length < right) + entity->length = left - offset + block->length; + else + entity->length += diff; + + if (entity->length == 0) { + enext = entity->next; + eprev->next = enext; + anchor->cache = NULL; + XtFree((XtPointer)entity); + if (entity == anchor->entities) { + if ((anchor->entities = enext) == NULL) { + eprev = NULL; + anchor = XawTextSourceRemoveAnchor(w, anchor); + entity = anchor ? anchor->entities : NULL; + } + else + eprev = entity = enext; + } + else + entity = enext; + } + else { + eprev = entity; + entity = entity->next; + } + } + + while (anchor) { + while (entity) { + offset = anchor->position + entity->offset + entity->length; + + if (offset > right) { + entity->length = XawMin(entity->length, offset - right); + goto exit_anchor_loop; + } + + enext = entity->next; + if (eprev) + eprev->next = enext; + XtFree((XtPointer)entity); + anchor->cache = NULL; + if (entity == anchor->entities) { + eprev = NULL; + if ((anchor->entities = enext) == NULL) { + if (i == 0) + ++i; + else if (i < --src->textSrc.num_anchors) { + memmove(&src->textSrc.anchors[i], + &src->textSrc.anchors[i + 1], + (src->textSrc.num_anchors - i) * + sizeof(XawTextAnchor*)); + XtFree((XtPointer)anchor); + } + if (i >= src->textSrc.num_anchors) { + anchor = NULL; + entity = NULL; + break; + } + anchor = src->textSrc.anchors[i]; + entity = anchor->entities; + continue; + } + } + entity = enext; + } + if (i + 1 < src->textSrc.num_anchors) { + anchor = src->textSrc.anchors[++i]; + entity = anchor->entities; + eprev = NULL; + } + else { + anchor = NULL; + break; + } + eprev = NULL; + } + +exit_anchor_loop: + if (anchor) { + XawTextAnchor *aprev; + + if (anchor->position >= XawMax(right, left + block->length)) + anchor->position += diff; + else if (anchor->position > left && + (aprev = XawTextSourcePrevAnchor(w, anchor))) { + XawTextPosition tmp = anchor->position - aprev->position; + + if (diff) { + while (entity) { + entity->offset += diff; + entity = entity->next; + } + } + entity = anchor->entities; + while (entity) { + entity->offset += tmp; + entity = entity->next; + } + if ((entity = aprev->entities) == NULL) + aprev->entities = anchor->entities; + else { + while (entity->next) + entity = entity->next; + entity->next = anchor->entities; + } + anchor->entities = NULL; + (void)XawTextSourceRemoveAnchor(w, anchor); + --i; + } + else if (diff) { + while (entity) { + entity->offset += diff; + entity = entity->next; + } + } + } + + if (diff) { + /* The first anchor is never removed, and should + * have position 0. + * i should be -1 if attempted to removed the first + * anchor, what can be caused when removing a chunk + * of text of the first entity. + * */ + if (++i == 0) { + anchor = src->textSrc.anchors[0]; + eprev = entity = anchor->entities; + while (entity) { + enext = entity->next; + if (entity->offset + entity->length <= -diff) + XtFree((XtPointer)entity); + else + break; + entity = enext; + } + if (eprev != entity) { + anchor->cache = NULL; + if ((anchor->entities = entity) != NULL) { + if ((entity->offset += diff) < 0) { + entity->length += entity->offset; + entity->offset = 0; + } + } + } + ++i; + } + for (; i < src->textSrc.num_anchors; i++) + src->textSrc.anchors[i]->position += diff; + } + } + + start = left; + end = start + block->length; + while (start < end) { + start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True); + if (start <= end) { + ++lines; + if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) { + lines -= !_XawTextSourceNewLineAtEOF(w); + break; + } + } + } + + info.left = left; + info.right = right; + info.block = block; + XtCallCallbacks(w, XtNpropertyCallback, &info); + + TellSourceChanged(src, left, right, block, lines); + /* Call callbacks, we have changed the buffer */ + XtCallCallbacks(w, XtNcallback, + (XtPointer)((long)src->textSrc.changed)); + } + +#endif /* OLDXAW */ + return (error); +} + +#ifndef OLDXAW +Bool +_XawTextSrcUndo(TextSrcObject src, XawTextPosition *insert_pos) +{ + static wchar_t wnull = 0; + XawTextBlock block; + XawTextUndoList *list, *nlist; + XawTextUndoBuffer *l_state, *r_state; + Boolean changed = src->textSrc.changed; + + if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo) + return (False); + + list = src->textSrc.undo->pointer; + + if (src->textSrc.undo->dir == XawsdLeft) { + l_state = list->right; + r_state = list->left; + } + else { + l_state = list->left; + r_state = list->right; + } + + if (src->textSrc.undo->l_no_change == l_state + && src->textSrc.undo->r_no_change == r_state) + src->textSrc.changed = False; + else + src->textSrc.changed = True; + + block.firstPos = 0; + block.length = r_state->length; + block.ptr = r_state->buffer ? r_state->buffer : (char*)&wnull; + block.format = r_state->format; + + src->textSrc.undo_state = True; + if (XawTextSourceReplace((Widget)src, l_state->position, l_state->position + + l_state->length, &block) != XawEditDone) { + src->textSrc.undo_state = False; + src->textSrc.changed = changed; + return (False); + } + src->textSrc.undo_state = False; + + ++l_state->refcount; + ++r_state->refcount; + nlist = XtNew(XawTextUndoList); + nlist->left = l_state; + nlist->right = r_state; + nlist->undo = src->textSrc.undo->list; + nlist->redo = NULL; + + if (list == src->textSrc.undo->list) + src->textSrc.undo->end_mark = nlist; + + if (src->textSrc.undo->dir == XawsdLeft) { + if (list->undo == NULL) + src->textSrc.undo->dir = XawsdRight; + else + list = list->undo; + } + else { + if (list->redo == NULL || list->redo == src->textSrc.undo->end_mark) + src->textSrc.undo->dir = XawsdLeft; + else + list = list->redo; + } + *insert_pos = r_state->position + r_state->length; + src->textSrc.undo->pointer = list; + src->textSrc.undo->list->redo = nlist; + src->textSrc.undo->list = nlist; + src->textSrc.undo->merge = src->textSrc.undo->erase = 0; + + if (++src->textSrc.undo->num_list >= UNDO_DEPTH) + UndoGC(src->textSrc.undo); + + return (True); +} + +Bool +_XawTextSrcToggleUndo(TextSrcObject src) +{ + if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo) + return (False); + + if (src->textSrc.undo->pointer != src->textSrc.undo->list) { + if (src->textSrc.undo->dir == XawsdLeft) { + if (src->textSrc.undo->pointer->redo + && (src->textSrc.undo->pointer->redo + != src->textSrc.undo->end_mark)) { + src->textSrc.undo->pointer = src->textSrc.undo->pointer->redo; + src->textSrc.undo->dir = XawsdRight; + } + } + else { + if (src->textSrc.undo->pointer->undo + && (src->textSrc.undo->pointer != src->textSrc.undo->head)) { + src->textSrc.undo->pointer = src->textSrc.undo->pointer->undo; + src->textSrc.undo->dir = XawsdLeft; + } + } + } + + return (True); +} + +static void +FreeUndoBuffer(XawTextUndo *undo) +{ + unsigned i; + XawTextUndoList *head, *del; + + for (i = 0; i < undo->num_undo; i++) { + if (undo->undo[i]->buffer && undo->undo[i]->buffer != SrcNL && + undo->undo[i]->buffer != (char*)SrcWNL) + XtFree(undo->undo[i]->buffer); + XtFree((char*)undo->undo[i]); + } + XtFree((char*)undo->undo); + head = undo->head; + + del = head; + while (head) { + head = head->redo; + XtFree((char*)del); + del = head; + } + + if (undo->l_save) { + XtFree((char*)undo->l_save); + undo->l_save = NULL; + } + if (undo->r_save) { + XtFree((char*)undo->r_save); + undo->r_save = NULL; + } + if (undo->u_save) { + XtFree((char*)undo->u_save); + undo->u_save = NULL; + } + + undo->list = undo->pointer = undo->head = undo->end_mark = NULL; + undo->l_no_change = undo->r_no_change = NULL; + undo->undo = NULL; + undo->dir = XawsdLeft; + undo->num_undo = undo->num_list = undo->erase = undo->merge = 0; +} + +static void +UndoGC(XawTextUndo *undo) +{ + unsigned i; + XawTextUndoList *head = undo->head, *redo = head->redo; + + if (head == undo->pointer || head == undo->end_mark + || undo->l_no_change == NULL + || head->left == undo->l_no_change || head->right == undo->l_no_change) + return; + + undo->head = redo; + redo->undo = NULL; + + --head->left->refcount; + if (--head->right->refcount == 0) { + for (i = 0; i < undo->num_undo; i+= 2) + if (head->left == undo->undo[i] || head->left == undo->undo[i+1]) { + if (head->left == undo->undo[i+1]) { + XawTextUndoBuffer *tmp = redo->left; + + redo->left = redo->right; + redo->right = tmp; + } + if (head->left->buffer && head->left->buffer != SrcNL && + head->left->buffer != (char*)SrcWNL) + XtFree(head->left->buffer); + XtFree((char*)head->left); + if (head->right->buffer && head->right->buffer != SrcNL && + head->right->buffer != (char*)SrcWNL) + XtFree(head->right->buffer); + XtFree((char*)head->right); + + undo->num_undo -= 2; + memmove(&undo->undo[i], &undo->undo[i + 2], + (undo->num_undo - i) * sizeof(XawTextUndoBuffer*)); + break; + } + } + XtFree((char*)head); + --undo->num_list; +} +#endif /* OLDXAW */ + +/* + * Function: + * XawTextSourceScan + * + * Parameters: + * w - TextSrc Object + * position - position to start scanning + * type - type of thing to scan for + * dir - direction to scan + * count - which occurance if this thing to search for + * include - whether or not to include the character found in + * the position that is returned. + * + * Description: + * Scans the text source for the number and type of item specified. + * + * Returns: + * The position of the text + */ +XawTextPosition +XawTextSourceScan(Widget w, XawTextPosition position, +#if NeedWidePrototypes + int type, int dir, int count, int include +#else + XawTextScanType type, XawTextScanDirection dir, + int count, Boolean include +#endif +) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + return ((*cclass->textSrc_class.Scan) + (w, position, type, dir, count, include)); +} + +/* + * Function: + * XawTextSourceSearch + * + * Parameters: + * w - TextSource Object + * position - position to start scanning + * dir - direction to scan + * text - the text block to search for. + * + * Returns: + * The position of the text we are searching for or XawTextSearchError. + * + * Description: + * Searchs the text source for the text block passed + */ +XawTextPosition +XawTextSourceSearch(Widget w, XawTextPosition position, +#if NeedWidePrototypes + int dir, +#else + XawTextScanDirection dir, +#endif + XawTextBlock *text) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + return ((*cclass->textSrc_class.Search)(w, position, dir, text)); +} + +/* + * Function: + * XawTextSourceConvertSelection + * + * Parameters: + * w - TextSrc object + * selection - current selection atom + * target - current target atom + * type - type to conver the selection to + * value - return value that has been converted + * length - "" + * format - format of the returned value + * + * Returns: + * True if the selection has been converted + */ +Boolean +XawTextSourceConvertSelection(Widget w, Atom *selection, Atom *target, + Atom *type, XtPointer *value, + unsigned long *length, int *format) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + return((*cclass->textSrc_class.ConvertSelection) + (w, selection, target, type, value, length, format)); +} + +/* + * Function: + * XawTextSourceSetSelection + * + * Parameters: + * w - TextSrc object + * left - bounds of the selection + * rigth - "" + * selection - selection atom + * + * Description: + * Allows special setting of the selection. + */ +void +XawTextSourceSetSelection(Widget w, XawTextPosition left, + XawTextPosition right, Atom selection) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + (*cclass->textSrc_class.SetSelection)(w, left, right, selection); +} + +/* + * External Functions for Multi Text + */ +/* + * TextFormat(): + * returns the format of text: FMT8BIT or FMTWIDE + */ +XrmQuark +_XawTextFormat(TextWidget tw) +{ + return (((TextSrcObject)(tw->text.source))->textSrc.text_format); +} + +/* _XawTextWCToMB(): + * Convert the wchar string to external encoding + * The caller is responsible for freeing both the source and ret string + * + * wstr - source wchar string + * len_in_out - lengh of string. + * As In, length of source wchar string, measured in wchar + * As Out, length of returned string + */ +char * +_XawTextWCToMB(Display *d, wchar_t *wstr, int *len_in_out) +{ + XTextProperty textprop; + + if (XwcTextListToTextProperty(d, (wchar_t**)&wstr, 1, + XTextStyle, &textprop) < Success) { + XtWarningMsg("convertError", "textSource", "XawError", + "Non-character code(s) in buffer.", NULL, NULL); + *len_in_out = 0; + return (NULL); + } + *len_in_out = textprop.nitems; + + return ((char *)textprop.value); +} + +/* _XawTextMBToWC(): + * Convert the string to internal processing codeset WC. + * The caller is responsible for freeing both the source and ret string. + * + * str - source string + * len_in_out - lengh of string + * As In, it is length of source string + * As Out, it is length of returned string, measured in wchar + */ +wchar_t * +_XawTextMBToWC(Display *d, char *str, int *len_in_out) +{ + XTextProperty textprop; + char *buf; + wchar_t **wlist, *wstr; + int count; + + if (*len_in_out == 0) + return (NULL); + + buf = XtMalloc(*len_in_out + 1); + + strncpy(buf, str, *len_in_out); + *(buf + *len_in_out) = '\0'; + if (XmbTextListToTextProperty(d, &buf, 1, XTextStyle, &textprop) != Success) { + XtWarningMsg("convertError", "textSource", "XawError", + "No Memory, or Locale not supported.", NULL, NULL); + XtFree(buf); + *len_in_out = 0; + return (NULL); + } + + XtFree(buf); + if (XwcTextPropertyToTextList(d, &textprop, + (wchar_t***)&wlist, &count) != Success) { + XtWarningMsg("convertError", "multiSourceCreate", "XawError", + "Non-character code(s) in source.", NULL, NULL); + *len_in_out = 0; + return (NULL); + } + wstr = wlist[0]; + *len_in_out = wcslen(wstr); + XtFree((XtPointer)wlist); + + return (wstr); +} + +#ifndef OLDXAW +static int +qcmp_anchors(_Xconst void *left, _Xconst void *right) +{ + return ((*(XawTextAnchor**)left)->position - + (*(XawTextAnchor**)right)->position); +} + +XawTextAnchor * +XawTextSourceAddAnchor(Widget w, XawTextPosition position) +{ + TextSrcObject src = (TextSrcObject)w; + XawTextAnchor *anchor, *panchor; + + if ((panchor = XawTextSourceFindAnchor(w, position)) != NULL) { + XawTextEntity *pentity, *entity; + + if (position - panchor->position < ANCHORS_DIST) + return (panchor); + + if (panchor->cache && panchor->position + panchor->cache->offset + + panchor->cache->length < position) + pentity = entity = panchor->cache; + else + pentity = entity = panchor->entities; + + while (entity && panchor->position + entity->offset + + entity->length < position) { + pentity = entity; + entity = entity->next; + } + if (entity) { + XawTextPosition diff; + + if (panchor->position + entity->offset < position) + position = panchor->position + entity->offset; + + if (position == panchor->position) + return (panchor); + + anchor = XtNew(XawTextAnchor); + diff = position - panchor->position; + + panchor->cache = NULL; + anchor->entities = entity; + if (pentity != entity) + pentity->next = NULL; + else + panchor->entities = NULL; + while (entity) { + entity->offset -= diff; + entity = entity->next; + } + } + else { + anchor = XtNew(XawTextAnchor); + anchor->entities = NULL; + } + } + else { + anchor = XtNew(XawTextAnchor); + anchor->entities = NULL; + } + + anchor->position = position; + anchor->cache = NULL; + + src->textSrc.anchors = (XawTextAnchor**) + XtRealloc((XtPointer)src->textSrc.anchors, sizeof(XawTextAnchor*) * + (src->textSrc.num_anchors + 1)); + src->textSrc.anchors[src->textSrc.num_anchors++] = anchor; + qsort((void*)src->textSrc.anchors, src->textSrc.num_anchors, + sizeof(XawTextAnchor*), qcmp_anchors); + + return (anchor); +} + +XawTextAnchor * +XawTextSourceFindAnchor(Widget w, XawTextPosition position) +{ + TextSrcObject src = (TextSrcObject)w; + int i = 0, left, right, nmemb = src->textSrc.num_anchors; + XawTextAnchor *anchor, **anchors = src->textSrc.anchors; + + left = 0; + right = nmemb - 1; + while (left <= right) { + anchor = anchors[i = (left + right) >> 1]; + if (anchor->position == position) + return (anchor); + else if (position < anchor->position) + right = i - 1; + else + left = i + 1; + } + + if (nmemb) + return (right < 0 ? anchors[0] : anchors[right]); + + return (NULL); +} + +Bool +XawTextSourceAnchorAndEntity(Widget w, XawTextPosition position, + XawTextAnchor **anchor_return, + XawTextEntity **entity_return) +{ + XawTextAnchor *anchor = XawTextSourceFindAnchor(w, position); + XawTextEntity *pentity, *entity; + XawTextPosition offset; + Bool next_anchor = True, retval = False; + + if (anchor->cache && anchor->position + anchor->cache->offset + + anchor->cache->length <= position) + pentity = entity = anchor->cache; + else + pentity = entity = anchor->entities; + while (entity) { + offset = anchor->position + entity->offset; + + if (offset > position) { + retval = next_anchor = False; + break; + } + if (offset + entity->length > position) { + retval = True; + next_anchor = False; + break; + } + pentity = entity; + entity = entity->next; + } + + if (next_anchor) { + *anchor_return = anchor = XawTextSourceNextAnchor(w, anchor); + *entity_return = anchor ? anchor->entities : NULL; + } + else { + *anchor_return = anchor; + *entity_return = retval ? entity : pentity; + } + + if (*anchor_return) + (*anchor_return)->cache = *entity_return; + + return (retval); +} + +XawTextAnchor * +XawTextSourceNextAnchor(Widget w, XawTextAnchor *anchor) +{ + int i; + TextSrcObject src = (TextSrcObject)w; + + for (i = 0; i < src->textSrc.num_anchors - 1; i++) + if (src->textSrc.anchors[i] == anchor) + return (src->textSrc.anchors[i + 1]); + + return (NULL); +} + +XawTextAnchor * +XawTextSourcePrevAnchor(Widget w, XawTextAnchor *anchor) +{ + int i; + TextSrcObject src = (TextSrcObject)w; + + for (i = src->textSrc.num_anchors - 1; i > 0; i--) + if (src->textSrc.anchors[i] == anchor) + return (src->textSrc.anchors[i - 1]); + + return (NULL); +} + +XawTextAnchor * +XawTextSourceRemoveAnchor(Widget w, XawTextAnchor *anchor) +{ + int i; + TextSrcObject src = (TextSrcObject)w; + + for (i = 0; i < src->textSrc.num_anchors; i++) + if (src->textSrc.anchors[i] == anchor) + break; + + if (i == 0) + return (src->textSrc.num_anchors > 1 ? src->textSrc.anchors[1] : NULL); + + if (i < src->textSrc.num_anchors) { + XtFree((XtPointer)anchor); + if (i < --src->textSrc.num_anchors) { + memmove(&src->textSrc.anchors[i], + &src->textSrc.anchors[i + 1], + (src->textSrc.num_anchors - i) * + sizeof(XawTextAnchor*)); + + return (src->textSrc.anchors[i]); + } + } + + return (NULL); +} + +XawTextEntity * +XawTextSourceAddEntity(Widget w, int type, int flags, XtPointer data, + XawTextPosition position, Cardinal length, + XrmQuark property) +{ + XawTextAnchor *next, *anchor = _XawTextSourceFindAnchor(w, position); + XawTextEntity *entity, *eprev; + + /* There is no support for zero length entities for now */ + if (length == 0) + return (NULL); + + if (anchor->cache && anchor->position + anchor->cache->offset + + anchor->cache->length <= position) + eprev = entity = anchor->cache; + else + eprev = entity = anchor->entities; + + while (entity && anchor->position + entity->offset + entity->length <= + position) { + eprev = entity; + entity = entity->next; + } + if (entity && anchor->position + entity->offset < position + length) { + fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n"); + return (NULL); + } + + next = XawTextSourceFindAnchor(w, position + length); + if (next && next != anchor) { + if ((entity = next->entities) != NULL) { + if (next->position + entity->offset < position + length) { + fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n"); + return (NULL); + } + } + if (position + length > next->position) { + XawTextPosition diff = position + length - next->position; + + next->position += diff; + entity = next->entities; + while (entity) { + entity->offset -= diff; + entity = entity->next; + } + entity = anchor->entities; + while (entity && entity->offset < 0) + entity = entity->next; + if (entity && entity->offset < 0) { + if (eprev) + eprev->next = next->entities; + else + anchor->entities = next->entities; + if ((next->entities = entity->next) == NULL) + (void)XawTextSourceRemoveAnchor(w, next); + entity->next = NULL; + + return (XawTextSourceAddEntity(w, type, flags, data, position, + length, property)); + } + } + } + + /* Automatically join sequential entities if possible */ + if (eprev && + anchor->position + eprev->offset + eprev->length == position && + eprev->property == property && eprev->type == type && + eprev->flags == flags && eprev->data == data) { + eprev->length += length; + return (eprev); + } + + entity = XtNew(XawTextEntity); + entity->type = type; + entity->flags = flags; + entity->data = data; + entity->offset = position - anchor->position; + entity->length = length; + entity->property = property; + + if (eprev == NULL) { + anchor->entities = entity; + entity->next = NULL; + anchor->cache = NULL; + } + else if (eprev->offset > entity->offset) { + anchor->cache = NULL; + anchor->entities = entity; + entity->next = eprev; + } + else { + anchor->cache = eprev; + entity->next = eprev->next; + eprev->next = entity; + } + + return (entity); +} + +void +XawTextSourceClearEntities(Widget w, XawTextPosition left, XawTextPosition right) +{ + XawTextAnchor *anchor = XawTextSourceFindAnchor(w, left); + XawTextEntity *entity, *eprev, *enext; + XawTextPosition offset; + int length; + + while (anchor && anchor->entities == NULL) + anchor = XawTextSourceRemoveAnchor(w, anchor); + + if (anchor == NULL || left >= right) + return; + + if (anchor->cache && anchor->position + anchor->cache->offset + + anchor->cache->length < left) + eprev = entity = anchor->cache; + else + eprev = entity = anchor->entities; + + /* find first entity before left position */ + while (anchor->position + entity->offset + entity->length < left) { + eprev = entity; + if ((entity = entity->next) == NULL) { + if ((anchor = XawTextSourceNextAnchor(w, anchor)) == NULL) + return; + if ((eprev = entity = anchor->entities) == NULL) { + fprintf(stderr, "Bad anchor found!\n"); + return; + } + } + } + + offset = anchor->position + entity->offset; + if (offset <= left) { + length = XawMin(entity->length, left - offset); + + if (length <= 0) { + enext = entity->next; + eprev->next = enext; + XtFree((XtPointer)entity); + anchor->cache = NULL; + if (entity == anchor->entities) { + eprev = NULL; + if ((anchor->entities = enext) == NULL) { + if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL) + return; + entity = anchor->entities; + } + else + entity = enext; + } + else + entity = enext; + } + else { + entity->length = length; + eprev = entity; + entity = entity->next; + } + } + + /* clean everything until right position is reached */ + while (anchor) { + while (entity) { + offset = anchor->position + entity->offset + entity->length; + + if (offset > right) { + anchor->cache = NULL; + entity->offset = XawMax(entity->offset, right - anchor->position); + entity->length = XawMin(entity->length, offset - right); + return; + } + + enext = entity->next; + if (eprev) + eprev->next = enext; + XtFree((XtPointer)entity); + if (entity == anchor->entities) { + eprev = anchor->cache = NULL; + if ((anchor->entities = enext) == NULL) { + if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL) + return; + entity = anchor->entities; + continue; + } + } + entity = enext; + } + if (anchor) + anchor->cache = NULL; + if ((anchor = XawTextSourceNextAnchor(w, anchor)) != NULL) + entity = anchor->entities; + eprev = NULL; + } +} + +/* checks the anchors up to position, and create an appropriate anchor + * at position, if required. + */ +XawTextAnchor * +_XawTextSourceFindAnchor(Widget w, XawTextPosition position) +{ + XawTextAnchor *anchor; + + anchor = XawTextSourceFindAnchor(w, position); + + position -= position % ANCHORS_DIST; + + if (position - anchor->position >= ANCHORS_DIST) + return (XawTextSourceAddAnchor(w, position)); + + return (anchor); +} +#endif diff --git a/libXaw/src/TextTr.c b/libXaw/src/TextTr.c index 5c524196a..f354683e2 100644 --- a/libXaw/src/TextTr.c +++ b/libXaw/src/TextTr.c @@ -1,158 +1,158 @@ -/*
-
-Copyright 1991, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-/* INTERNATIONALIZATION:
-
-The OMRON R5 contrib added the following action to the old TextTr:
-
- Ctrl<Key>backslash: reconnect-im()
-
-This is needed when the im is killed or otherwise becomes unreachable.
-This keystroke is evil (inconvenient, hard-to-remember, not obvious)
-so I am adding one more translation:
-
- <Key>Kanji: reconnect-im()
-
-The Japanese user typically hits their Kanji key when they want to do
-input. This merely makes sure the input is connected.
-*/
-
-#include <X11/Xaw/Text.h>
-
-char _XawDefaultTextTranslations[] =
-"c<Key>A:" "beginning-of-line()\n"
-"c<Key>B:" "backward-character()\n"
-"c<Key>C:" "insert-selection(CUT_BUFFER0)\n"
-"c<Key>D:" "delete-next-character()\n"
-"c<Key>E:" "end-of-line()\n"
-"c<Key>F:" "forward-character()\n"
-#ifndef OLDXAW
-"c<Key>G:" "keyboard-reset()\n"
-#else
-"c<Key>G:" "multiply(Reset)\n"
-#endif
-"c<Key>H:" "delete-previous-character()\n"
-"c<Key>J:" "newline-and-indent()\n"
-"c<Key>K:" "kill-to-end-of-line()\n"
-"c<Key>L:" "redraw-display()\n"
-"c<Key>M:" "newline()\n"
-"c<Key>N:" "next-line()\n"
-"c<Key>O:" "newline-and-backup()\n"
-"c<Key>P:" "previous-line()\n"
-"c<Key>R:" "search(backward)\n"
-"c<Key>S:" "search(forward)\n"
-"c<Key>T:" "transpose-characters()\n"
-#ifndef OLDXAW
-"c<Key>U:" "multiply(Start)\n"
-#else
-"c<Key>U:" "multiply(4)\n"
-#endif
-"c<Key>V:" "next-page()\n"
-"c<Key>W:" "kill-selection()\n"
-"c<Key>Y:" "insert-selection(SECONDARY)\n"
-"c<Key>Z:" "scroll-one-line-up()\n"
-"m<Key>B:" "backward-word()\n"
-"m<Key>C:" "capitalize-word()\n"
-"m<Key>F:" "forward-word()\n"
-"m<Key>I:" "insert-file()\n"
-"m<Key>K:" "kill-to-end-of-paragraph()\n"
-"m<Key>L:" "downcase-word()\n"
-"m<Key>Q:" "form-paragraph()\n"
-"m<Key>U:" "upcase-word()\n"
-"m<Key>V:" "previous-page()\n"
-#ifndef OLDXAW
-"m<Key>Y:" "kill-ring-yank()\n"
-#endif
-"m<Key>Z:" "scroll-one-line-down()\n"
-"~s m<Key>d:" "kill-word(alnum)\n"
-"s m<Key>d:" "delete-next-word(alnum)\n"
-"~s m<Key>h:" "backward-kill-word(alnum)\n"
-"s m<Key>h:" "delete-previous-word(alnum)\n"
-":m<Key>\\<:" "beginning-of-file()\n"
-":m<Key>\\>:" "end-of-file()\n"
-":m<Key>]:" "forward-paragraph()\n"
-":m<Key>[:" "backward-paragraph()\n"
-"~s m<Key>Delete:" "backward-kill-word(alnum)\n"
-"s m<Key>Delete:" "delete-previous-word(alnum)\n"
-"~s m<Key>BackSpace:" "backward-kill-word(alnum)\n"
-"s m<Key>BackSpace:" "delete-previous-word(alnum)\n"
-"c<Key>Left:" "backward-word(alnum)\n"
-"c<Key>Right:" "forward-word(alnum)\n"
-"c<Key>Up:" "backward-paragraph()\n"
-"c<Key>Down:" "forward-paragraph()\n"
-"<Key>Home:" "beginning-of-file()\n"
-":<Key>KP_Home:" "beginning-of-file()\n"
-"<Key>End:" "end-of-file()\n"
-":<Key>KP_End:" "end-of-file()\n"
-"<Key>Next:" "next-page()\n"
-":<Key>KP_Next:" "next-page()\n"
-"<Key>Prior:" "previous-page()\n"
-":<Key>KP_Prior:" "previous-page()\n"
-"<Key>Right:" "forward-character()\n"
-":<Key>KP_Right:" "forward-character()\n"
-"<Key>Left:" "backward-character()\n"
-":<Key>KP_Left:" "backward-character()\n"
-"<Key>Down:" "next-line()\n"
-":<Key>KP_Down:" "next-line()\n"
-"<Key>Up:" "previous-line()\n"
-":<Key>KP_Up:" "previous-line()\n"
-"<Key>Delete:" "delete()\n"
-":<Key>KP_Delete:" "delete()\n"
-"<Key>BackSpace:" "delete-previous-character()\n"
-"<Key>Linefeed:" "newline-and-indent()\n"
-"<Key>Return:" "newline()\n"
-":<Key>KP_Enter:" "newline()\n"
-"c<Key>backslash:" "reconnect-im()\n"
-"<Key>Kanji:" "reconnect-im()\n"
-#ifndef OLDXAW
-":<Key>0:" "numeric(0)\n"
-":<Key>1:" "numeric(1)\n"
-":<Key>2:" "numeric(2)\n"
-":<Key>3:" "numeric(3)\n"
-":<Key>4:" "numeric(4)\n"
-":<Key>5:" "numeric(5)\n"
-":<Key>6:" "numeric(6)\n"
-":<Key>7:" "numeric(7)\n"
-":<Key>8:" "numeric(8)\n"
-":<Key>9:" "numeric(9)\n"
-":<Key>-:" "numeric(-)\n"
-":c<Key>_:" "undo()\n"
-#endif
-"s <Key>Insert:" "insert-selection(PRIMARY, CUT_BUFFER0)\n"
-"<Ctrl>Q,<Key>:" "insert-char()\n"
-"<Key>:" "insert-char()\n"
-"<Enter>:" "enter-window()\n"
-"<Leave>:" "leave-window()\n"
-"<FocusIn>:" "focus-in()\n"
-"<FocusOut>:" "focus-out()\n"
-"<Btn1Down>:" "select-start()\n"
-"<Btn1Motion>:" "extend-adjust()\n"
-"<Btn1Up>:" "extend-end(PRIMARY, CUT_BUFFER0)\n"
-"<Btn2Down>:" "insert-selection(PRIMARY, CUT_BUFFER0)\n"
-"<Btn3Down>:" "extend-start()\n"
-"<Btn3Motion>:" "extend-adjust()\n"
-"<Btn3Up>:" "extend-end(PRIMARY, CUT_BUFFER0)\n"
-;
+/* + +Copyright 1991, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* INTERNATIONALIZATION: + +The OMRON R5 contrib added the following action to the old TextTr: + + Ctrl<Key>backslash: reconnect-im() + +This is needed when the im is killed or otherwise becomes unreachable. +This keystroke is evil (inconvenient, hard-to-remember, not obvious) +so I am adding one more translation: + + <Key>Kanji: reconnect-im() + +The Japanese user typically hits their Kanji key when they want to do +input. This merely makes sure the input is connected. +*/ + +#include <X11/Xaw/Text.h> + +char _XawDefaultTextTranslations[] = +"c<Key>A:" "beginning-of-line()\n" +"c<Key>B:" "backward-character()\n" +"c<Key>C:" "insert-selection(CUT_BUFFER0)\n" +"c<Key>D:" "delete-next-character()\n" +"c<Key>E:" "end-of-line()\n" +"c<Key>F:" "forward-character()\n" +#ifndef OLDXAW +"c<Key>G:" "keyboard-reset()\n" +#else +"c<Key>G:" "multiply(Reset)\n" +#endif +"c<Key>H:" "delete-previous-character()\n" +"c<Key>J:" "newline-and-indent()\n" +"c<Key>K:" "kill-to-end-of-line()\n" +"c<Key>L:" "redraw-display()\n" +"c<Key>M:" "newline()\n" +"c<Key>N:" "next-line()\n" +"c<Key>O:" "newline-and-backup()\n" +"c<Key>P:" "previous-line()\n" +"c<Key>R:" "search(backward)\n" +"c<Key>S:" "search(forward)\n" +"c<Key>T:" "transpose-characters()\n" +#ifndef OLDXAW +"c<Key>U:" "multiply(Start)\n" +#else +"c<Key>U:" "multiply(4)\n" +#endif +"c<Key>V:" "next-page()\n" +"c<Key>W:" "kill-selection()\n" +"c<Key>Y:" "insert-selection(SECONDARY)\n" +"c<Key>Z:" "scroll-one-line-up()\n" +"m<Key>B:" "backward-word()\n" +"m<Key>C:" "capitalize-word()\n" +"m<Key>F:" "forward-word()\n" +"m<Key>I:" "insert-file()\n" +"m<Key>K:" "kill-to-end-of-paragraph()\n" +"m<Key>L:" "downcase-word()\n" +"m<Key>Q:" "form-paragraph()\n" +"m<Key>U:" "upcase-word()\n" +"m<Key>V:" "previous-page()\n" +#ifndef OLDXAW +"m<Key>Y:" "kill-ring-yank()\n" +#endif +"m<Key>Z:" "scroll-one-line-down()\n" +"~s m<Key>d:" "kill-word(alnum)\n" +"s m<Key>d:" "delete-next-word(alnum)\n" +"~s m<Key>h:" "backward-kill-word(alnum)\n" +"s m<Key>h:" "delete-previous-word(alnum)\n" +":m<Key>\\<:" "beginning-of-file()\n" +":m<Key>\\>:" "end-of-file()\n" +":m<Key>]:" "forward-paragraph()\n" +":m<Key>[:" "backward-paragraph()\n" +"~s m<Key>Delete:" "backward-kill-word(alnum)\n" +"s m<Key>Delete:" "delete-previous-word(alnum)\n" +"~s m<Key>BackSpace:" "backward-kill-word(alnum)\n" +"s m<Key>BackSpace:" "delete-previous-word(alnum)\n" +"c<Key>Left:" "backward-word(alnum)\n" +"c<Key>Right:" "forward-word(alnum)\n" +"c<Key>Up:" "backward-paragraph()\n" +"c<Key>Down:" "forward-paragraph()\n" +"<Key>Home:" "beginning-of-file()\n" +":<Key>KP_Home:" "beginning-of-file()\n" +"<Key>End:" "end-of-file()\n" +":<Key>KP_End:" "end-of-file()\n" +"<Key>Next:" "next-page()\n" +":<Key>KP_Next:" "next-page()\n" +"<Key>Prior:" "previous-page()\n" +":<Key>KP_Prior:" "previous-page()\n" +"<Key>Right:" "forward-character()\n" +":<Key>KP_Right:" "forward-character()\n" +"<Key>Left:" "backward-character()\n" +":<Key>KP_Left:" "backward-character()\n" +"<Key>Down:" "next-line()\n" +":<Key>KP_Down:" "next-line()\n" +"<Key>Up:" "previous-line()\n" +":<Key>KP_Up:" "previous-line()\n" +"<Key>Delete:" "delete()\n" +":<Key>KP_Delete:" "delete()\n" +"<Key>BackSpace:" "delete-previous-character()\n" +"<Key>Linefeed:" "newline-and-indent()\n" +"<Key>Return:" "newline()\n" +":<Key>KP_Enter:" "newline()\n" +"c<Key>backslash:" "reconnect-im()\n" +"<Key>Kanji:" "reconnect-im()\n" +#ifndef OLDXAW +":<Key>0:" "numeric(0)\n" +":<Key>1:" "numeric(1)\n" +":<Key>2:" "numeric(2)\n" +":<Key>3:" "numeric(3)\n" +":<Key>4:" "numeric(4)\n" +":<Key>5:" "numeric(5)\n" +":<Key>6:" "numeric(6)\n" +":<Key>7:" "numeric(7)\n" +":<Key>8:" "numeric(8)\n" +":<Key>9:" "numeric(9)\n" +":<Key>-:" "numeric(-)\n" +":c<Key>_:" "undo()\n" +#endif +"s <Key>Insert:" "insert-selection(PRIMARY, CUT_BUFFER0)\n" +"<Ctrl>Q,<Key>:" "insert-char()\n" +"<Key>:" "insert-char()\n" +"<Enter>:" "enter-window()\n" +"<Leave>:" "leave-window()\n" +"<FocusIn>:" "focus-in()\n" +"<FocusOut>:" "focus-out()\n" +"<Btn1Down>:" "select-start()\n" +"<Btn1Motion>:" "extend-adjust()\n" +"<Btn1Up>:" "extend-end(PRIMARY, CUT_BUFFER0)\n" +"<Btn2Down>:" "insert-selection(PRIMARY, CUT_BUFFER0)\n" +"<Btn3Down>:" "extend-start()\n" +"<Btn3Motion>:" "extend-adjust()\n" +"<Btn3Up>:" "extend-end(PRIMARY, CUT_BUFFER0)\n" +; diff --git a/libXaw/src/Tip.c b/libXaw/src/Tip.c index bca994ca5..9f8b32ad3 100644 --- a/libXaw/src/Tip.c +++ b/libXaw/src/Tip.c @@ -1,637 +1,637 @@ -/*
- * Copyright (c) 1999 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the XFree86 Project shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from the
- * XFree86 Project.
- *
- * Author: Paulo César Pereira de Andrade
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xos.h>
-#include <X11/Xaw/TipP.h>
-#include <X11/Xaw/XawInit.h>
-#include <X11/Xmu/Converters.h>
-#include "Private.h"
-
-#define TIP_EVENT_MASK (ButtonPressMask | \
- ButtonReleaseMask | \
- PointerMotionMask | \
- ButtonMotionMask | \
- KeyPressMask | \
- KeyReleaseMask | \
- EnterWindowMask | \
- LeaveWindowMask)
-
-/*
- * Types
- */
-typedef struct _XawTipInfo {
- Screen *screen;
- TipWidget tip;
- Widget widget;
- Bool mapped;
- struct _XawTipInfo *next;
-} XawTipInfo;
-
-/*
- * Class Methods
- */
-static void XawTipClassInitialize(void);
-static void XawTipInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawTipDestroy(Widget);
-static void XawTipExpose(Widget, XEvent*, Region);
-static void XawTipRealize(Widget, Mask*, XSetWindowAttributes*);
-static Boolean XawTipSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void TipEventHandler(Widget, XtPointer, XEvent*, Boolean*);
-static void TipShellEventHandler(Widget, XtPointer, XEvent*, Boolean*);
-static XawTipInfo *CreateTipInfo(Widget);
-static XawTipInfo *FindTipInfo(Widget);
-static void ResetTip(XawTipInfo*, Bool);
-static void TipTimeoutCallback(XtPointer, XtIntervalId*);
-static void TipLayout(XawTipInfo*);
-static void TipPosition(XawTipInfo*);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(TipRec, tip.field)
-static XtResource resources[] = {
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(foreground),
- XtRString,
- XtDefaultForeground,
- },
- {
- XtNfont,
- XtCFont,
- XtRFontStruct,
- sizeof(XFontStruct*),
- offset(font),
- XtRString,
- XtDefaultFont
- },
- {
- XtNfontSet,
- XtCFontSet,
- XtRFontSet,
- sizeof(XFontSet),
- offset(fontset),
- XtRString,
- XtDefaultFontSet
- },
- {
- XtNtopMargin,
- XtCVerticalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(top_margin),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNbottomMargin,
- XtCVerticalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(bottom_margin),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNleftMargin,
- XtCHorizontalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(left_margin),
- XtRImmediate,
- (XtPointer)6
- },
- {
- XtNrightMargin,
- XtCHorizontalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(right_margin),
- XtRImmediate,
- (XtPointer)6
- },
- {
- XtNbackingStore,
- XtCBackingStore,
- XtRBackingStore,
- sizeof(int),
- offset(backing_store),
- XtRImmediate,
- (XtPointer)(Always + WhenMapped + NotUseful)
- },
- {
- XtNtimeout,
- XtCTimeout,
- XtRInt,
- sizeof(int),
- offset(timeout),
- XtRImmediate,
- (XtPointer)500
- },
- {
- XawNdisplayList,
- XawCDisplayList,
- XawRDisplayList,
- sizeof(XawDisplayList*),
- offset(display_list),
- XtRImmediate,
- NULL
- },
-};
-#undef offset
-
-TipClassRec tipClassRec = {
- /* core */
- {
- (WidgetClass)&widgetClassRec, /* superclass */
- "Tip", /* class_name */
- sizeof(TipRec), /* widget_size */
- XawTipClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawTipInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawTipRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawTipDestroy, /* destroy */
- NULL, /* resize */
- XawTipExpose, /* expose */
- XawTipSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* tip */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass tipWidgetClass = (WidgetClass)&tipClassRec;
-
-static XawTipInfo *first_tip;
-
-/*
- * Implementation
- */
-static void
-XawTipClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
- NULL, 0);
- XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-/*ARGSUSED*/
-static void
-XawTipInitialize(Widget req, Widget w, ArgList args, Cardinal *num_args)
-{
- TipWidget tip = (TipWidget)w;
- XGCValues values;
-
- if (!tip->tip.font) XtError("Aborting: no font found\n");
- if (tip->tip.international && !tip->tip.fontset)
- XtError("Aborting: no fontset found\n");
-
- tip->tip.timer = 0;
-
- values.foreground = tip->tip.foreground;
- values.background = tip->core.background_pixel;
- values.font = tip->tip.font->fid;
- values.graphics_exposures = False;
-
- tip->tip.gc = XtAllocateGC(w, 0, GCForeground | GCBackground | GCFont |
- GCGraphicsExposures, &values, GCFont, 0);
-}
-
-static void
-XawTipDestroy(Widget w)
-{
- XawTipInfo *info = FindTipInfo(w);
- TipWidget tip = (TipWidget)w;
-
- if (tip->tip.timer)
- XtRemoveTimeOut(tip->tip.timer);
-
- XtReleaseGC(w, tip->tip.gc);
-
- XtRemoveEventHandler(XtParent(w), KeyPressMask, False, TipShellEventHandler,
- (XtPointer)NULL);
- if (info == first_tip)
- first_tip = first_tip->next;
- else {
- XawTipInfo *p = first_tip;
-
- while (p && p->next != info)
- p = p->next;
- if (p)
- p->next = info->next;
- }
- XtFree((char*)info);
-}
-
-static void
-XawTipRealize(Widget w, Mask *mask, XSetWindowAttributes *attr)
-{
- TipWidget tip = (TipWidget)w;
-
- if (tip->tip.backing_store == Always ||
- tip->tip.backing_store == NotUseful ||
- tip->tip.backing_store == WhenMapped) {
- *mask |= CWBackingStore;
- attr->backing_store = tip->tip.backing_store;
- }
- else
- *mask &= ~CWBackingStore;
- *mask |= CWOverrideRedirect;
- attr->override_redirect = True;
-
- XtWindow(w) = XCreateWindow(DisplayOfScreen(XtScreen(w)),
- RootWindowOfScreen(XtScreen(w)),
- XtX(w), XtY(w),
- XtWidth(w) ? XtWidth(w) : 1,
- XtHeight(w) ? XtHeight(w) : 1,
- XtBorderWidth(w),
- DefaultDepthOfScreen(XtScreen(w)),
- InputOutput,
- (Visual *)CopyFromParent,
- *mask, attr);
-}
-
-static void
-XawTipExpose(Widget w, XEvent *event, Region region)
-{
- TipWidget tip = (TipWidget)w;
- GC gc = tip->tip.gc;
- char *nl, *label = tip->tip.label;
- Position y = tip->tip.top_margin + tip->tip.font->max_bounds.ascent;
- int len;
-
- if (tip->tip.display_list)
- XawRunDisplayList(w, tip->tip.display_list, event, region);
-
- if (tip->tip.international == True) {
- Position ksy = tip->tip.top_margin;
- XFontSetExtents *ext = XExtentsOfFontSet(tip->tip.fontset);
-
- ksy += XawAbs(ext->max_ink_extent.y);
-
- while ((nl = index(label, '\n')) != NULL) {
- XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset,
- gc, tip->tip.left_margin, ksy, label,
- (int)(nl - label));
- ksy += ext->max_ink_extent.height;
- label = nl + 1;
- }
- len = strlen(label);
- if (len)
- XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset, gc,
- tip->tip.left_margin, ksy, label, len);
- }
- else {
- while ((nl = index(label, '\n')) != NULL) {
- if (tip->tip.encoding)
- XDrawString16(XtDisplay(w), XtWindow(w), gc,
- tip->tip.left_margin, y,
- (XChar2b*)label, (int)(nl - label) >> 1);
- else
- XDrawString(XtDisplay(w), XtWindow(w), gc,
- tip->tip.left_margin, y, label, (int)(nl - label));
- y += tip->tip.font->max_bounds.ascent +
- tip->tip.font->max_bounds.descent;
- label = nl + 1;
- }
- len = strlen(label);
- if (len) {
- if (tip->tip.encoding)
- XDrawString16(XtDisplay(w), XtWindow(w), gc,
- tip->tip.left_margin, y, (XChar2b*)label, len >> 1);
- else
- XDrawString(XtDisplay(w), XtWindow(w), gc,
- tip->tip.left_margin, y, label, len);
- }
- }
-}
-
-/*ARGSUSED*/
-static Boolean
-XawTipSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- TipWidget curtip = (TipWidget)current;
- TipWidget newtip = (TipWidget)cnew;
- Boolean redisplay = False;
-
- if (curtip->tip.font->fid != newtip->tip.font->fid ||
- curtip->tip.foreground != newtip->tip.foreground) {
- XGCValues values;
-
- values.foreground = newtip->tip.foreground;
- values.background = newtip->core.background_pixel;
- values.font = newtip->tip.font->fid;
- values.graphics_exposures = False;
- XtReleaseGC(cnew, curtip->tip.gc);
- newtip->tip.gc = XtAllocateGC(cnew, 0, GCForeground | GCBackground |
- GCFont | GCGraphicsExposures, &values,
- GCFont, 0);
- redisplay = True;
- }
- if (curtip->tip.display_list != newtip->tip.display_list)
- redisplay = True;
-
- return (redisplay);
-}
-
-static void
-TipLayout(XawTipInfo *info)
-{
- XFontStruct *fs = info->tip->tip.font;
- int width = 0, height;
- char *nl, *label = info->tip->tip.label;
-
- if (info->tip->tip.international == True) {
- XFontSet fset = info->tip->tip.fontset;
- XFontSetExtents *ext = XExtentsOfFontSet(fset);
-
- height = ext->max_ink_extent.height;
- if ((nl = index(label, '\n')) != NULL) {
- /*CONSTCOND*/
- while (True) {
- int w = XmbTextEscapement(fset, label, (int)(nl - label));
-
- if (w > width)
- width = w;
- if (*nl == '\0')
- break;
- label = nl + 1;
- if (*label)
- height += ext->max_ink_extent.height;
- if ((nl = index(label, '\n')) == NULL)
- nl = index(label, '\0');
- }
- }
- else
- width = XmbTextEscapement(fset, label, strlen(label));
- }
- else {
- height = fs->max_bounds.ascent + fs->max_bounds.descent;
- if ((nl = index(label, '\n')) != NULL) {
- /*CONSTCOND*/
- while (True) {
- int w = info->tip->tip.encoding ?
- XTextWidth16(fs, (XChar2b*)label, (int)(nl - label) >> 1) :
- XTextWidth(fs, label, (int)(nl - label));
- if (w > width)
- width = w;
- if (*nl == '\0')
- break;
- label = nl + 1;
- if (*label)
- height += fs->max_bounds.ascent + fs->max_bounds.descent;
- if ((nl = index(label, '\n')) == NULL)
- nl = index(label, '\0');
- }
- }
- else
- width = info->tip->tip.encoding ?
- XTextWidth16(fs, (XChar2b*)label, strlen(label) >> 1) :
- XTextWidth(fs, label, strlen(label));
- }
- XtWidth(info->tip) = width + info->tip->tip.left_margin +
- info->tip->tip.right_margin;
- XtHeight(info->tip) = height + info->tip->tip.top_margin +
- info->tip->tip.bottom_margin;
-}
-
-#define DEFAULT_TIP_Y_OFFSET 12
-static void
-TipPosition(XawTipInfo *info)
-{
- Window r, c;
- int rx, ry, wx, wy;
- unsigned mask;
- Position x, y;
-
- XQueryPointer(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip),
- &r, &c, &rx, &ry, &wx, &wy, &mask);
- x = rx - (XtWidth(info->tip) >> 1);
- y = ry + DEFAULT_TIP_Y_OFFSET;
-
- if (x >= 0) {
- int scr_width = WidthOfScreen(XtScreen(info->tip));
-
- if (x + XtWidth(info->tip) + XtBorderWidth(info->tip) > scr_width)
- x = scr_width - XtWidth(info->tip) - XtBorderWidth(info->tip);
- }
- if (x < 0)
- x = 0;
- if (y >= 0) {
- int scr_height = HeightOfScreen(XtScreen(info->tip));
-
- if (y + XtHeight(info->tip) + XtBorderWidth(info->tip) > scr_height)
- y -= XtHeight(info->tip) + XtBorderWidth(info->tip) +
- (DEFAULT_TIP_Y_OFFSET << 1);
- }
- if (y < 0)
- y = 0;
-
- XMoveResizeWindow(XtDisplay(info->tip), XtWindow(info->tip),
- (int)(XtX(info->tip) = x), (int)(XtY(info->tip) = y),
- (unsigned)XtWidth(info->tip), (unsigned)XtHeight(info->tip));
-}
-
-static XawTipInfo *
-CreateTipInfo(Widget w)
-{
- XawTipInfo *info = XtNew(XawTipInfo);
- Widget shell = w;
-
- info->screen = XtScreen(w);
-
- while (XtParent(shell))
- shell = XtParent(shell);
-
- info->tip = (TipWidget)XtCreateWidget("tip", tipWidgetClass, shell, NULL, 0);
- XtRealizeWidget((Widget)info->tip);
- info->widget = NULL;
- info->mapped = False;
- info->next = NULL;
- XtAddEventHandler(shell, KeyPressMask, False, TipShellEventHandler,
- (XtPointer)NULL);
-
- return (info);
-}
-
-static XawTipInfo *
-FindTipInfo(Widget w)
-{
- XawTipInfo *ptip, *tip = first_tip;
- Screen *screen = XtScreenOfObject(w);
-
- if (tip == NULL)
- return (first_tip = tip = CreateTipInfo(w));
-
- for (ptip = tip; tip; ptip = tip, tip = tip->next)
- if (tip->screen == screen)
- return (tip);
-
- return (ptip->next = CreateTipInfo(w));
-}
-
-static void
-ResetTip(XawTipInfo *info, Bool add_timeout)
-{
- if (info->tip->tip.timer) {
- XtRemoveTimeOut(info->tip->tip.timer);
- info->tip->tip.timer = 0;
- }
- if (info->mapped) {
- XtRemoveGrab(XtParent((Widget)info->tip));
- XUnmapWindow(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip));
- info->mapped = False;
- }
- if (add_timeout) {
- info->tip->tip.timer =
- XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)info->tip),
- info->tip->tip.timeout, TipTimeoutCallback,
- (XtPointer)info);
- }
-}
-
-static void
-TipTimeoutCallback(XtPointer closure, XtIntervalId *id)
-{
- XawTipInfo *info = (XawTipInfo*)closure;
- Arg args[3];
-
- info->tip->tip.label = NULL;
- info->tip->tip.international = False;
- info->tip->tip.encoding = 0;
- info->tip->tip.timer = 0;
- XtSetArg(args[0], XtNtip, &info->tip->tip.label);
- XtSetArg(args[1], XtNinternational, &info->tip->tip.international);
- XtSetArg(args[2], XtNencoding, &info->tip->tip.encoding);
- XtGetValues(info->widget, args, 3);
-
- if (info->tip->tip.label) {
- TipLayout(info);
- TipPosition(info);
- XMapRaised(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip));
- XtAddGrab(XtParent((Widget)info->tip), True, True);
- info->mapped = True;
- }
-}
-
-/*ARGSUSED*/
-static void
-TipShellEventHandler(Widget w, XtPointer client_data, XEvent *event,
- Boolean *continue_to_dispatch)
-{
- ResetTip(FindTipInfo(w), False);
-}
-
-/*ARGSUSED*/
-static void
-TipEventHandler(Widget w, XtPointer client_data, XEvent *event,
- Boolean *continue_to_dispatch)
-{
- XawTipInfo *info = FindTipInfo(w);
- Boolean add_timeout;
-
- if (info->widget != w) {
- ResetTip(info, False);
- info->widget = w;
- }
-
- switch (event->type) {
- case EnterNotify:
- add_timeout = True;
- break;
- case MotionNotify:
- /* If any button is pressed, timer is 0 */
- if (info->mapped)
- return;
- add_timeout = info->tip->tip.timer != 0;
- break;
- default:
- add_timeout = False;
- break;
- }
- ResetTip(info, add_timeout);
-}
-
-/*
- * Public routines
- */
-void
-XawTipEnable(Widget w)
-{
- XtAddEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler,
- (XtPointer)NULL);
-}
-
-void
-XawTipDisable(Widget w)
-{
- XawTipInfo *info = FindTipInfo(w);
-
- XtRemoveEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler,
- (XtPointer)NULL);
- if (info->widget == w)
- ResetTip(info, False);
-}
+/* + * Copyright (c) 1999 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + * + * Author: Paulo César Pereira de Andrade + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xaw/TipP.h> +#include <X11/Xaw/XawInit.h> +#include <X11/Xmu/Converters.h> +#include "Private.h" + +#define TIP_EVENT_MASK (ButtonPressMask | \ + ButtonReleaseMask | \ + PointerMotionMask | \ + ButtonMotionMask | \ + KeyPressMask | \ + KeyReleaseMask | \ + EnterWindowMask | \ + LeaveWindowMask) + +/* + * Types + */ +typedef struct _XawTipInfo { + Screen *screen; + TipWidget tip; + Widget widget; + Bool mapped; + struct _XawTipInfo *next; +} XawTipInfo; + +/* + * Class Methods + */ +static void XawTipClassInitialize(void); +static void XawTipInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawTipDestroy(Widget); +static void XawTipExpose(Widget, XEvent*, Region); +static void XawTipRealize(Widget, Mask*, XSetWindowAttributes*); +static Boolean XawTipSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +static void TipEventHandler(Widget, XtPointer, XEvent*, Boolean*); +static void TipShellEventHandler(Widget, XtPointer, XEvent*, Boolean*); +static XawTipInfo *CreateTipInfo(Widget); +static XawTipInfo *FindTipInfo(Widget); +static void ResetTip(XawTipInfo*, Bool); +static void TipTimeoutCallback(XtPointer, XtIntervalId*); +static void TipLayout(XawTipInfo*); +static void TipPosition(XawTipInfo*); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(TipRec, tip.field) +static XtResource resources[] = { + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(foreground), + XtRString, + XtDefaultForeground, + }, + { + XtNfont, + XtCFont, + XtRFontStruct, + sizeof(XFontStruct*), + offset(font), + XtRString, + XtDefaultFont + }, + { + XtNfontSet, + XtCFontSet, + XtRFontSet, + sizeof(XFontSet), + offset(fontset), + XtRString, + XtDefaultFontSet + }, + { + XtNtopMargin, + XtCVerticalMargins, + XtRDimension, + sizeof(Dimension), + offset(top_margin), + XtRImmediate, + (XtPointer)2 + }, + { + XtNbottomMargin, + XtCVerticalMargins, + XtRDimension, + sizeof(Dimension), + offset(bottom_margin), + XtRImmediate, + (XtPointer)2 + }, + { + XtNleftMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(left_margin), + XtRImmediate, + (XtPointer)6 + }, + { + XtNrightMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(right_margin), + XtRImmediate, + (XtPointer)6 + }, + { + XtNbackingStore, + XtCBackingStore, + XtRBackingStore, + sizeof(int), + offset(backing_store), + XtRImmediate, + (XtPointer)(Always + WhenMapped + NotUseful) + }, + { + XtNtimeout, + XtCTimeout, + XtRInt, + sizeof(int), + offset(timeout), + XtRImmediate, + (XtPointer)500 + }, + { + XawNdisplayList, + XawCDisplayList, + XawRDisplayList, + sizeof(XawDisplayList*), + offset(display_list), + XtRImmediate, + NULL + }, +}; +#undef offset + +TipClassRec tipClassRec = { + /* core */ + { + (WidgetClass)&widgetClassRec, /* superclass */ + "Tip", /* class_name */ + sizeof(TipRec), /* widget_size */ + XawTipClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawTipInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawTipRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawTipDestroy, /* destroy */ + NULL, /* resize */ + XawTipExpose, /* expose */ + XawTipSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* tip */ + { + NULL, /* extension */ + }, +}; + +WidgetClass tipWidgetClass = (WidgetClass)&tipClassRec; + +static XawTipInfo *first_tip; + +/* + * Implementation + */ +static void +XawTipClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore, + NULL, 0); + XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString, + NULL, 0, XtCacheNone, NULL); +} + +/*ARGSUSED*/ +static void +XawTipInitialize(Widget req, Widget w, ArgList args, Cardinal *num_args) +{ + TipWidget tip = (TipWidget)w; + XGCValues values; + + if (!tip->tip.font) XtError("Aborting: no font found\n"); + if (tip->tip.international && !tip->tip.fontset) + XtError("Aborting: no fontset found\n"); + + tip->tip.timer = 0; + + values.foreground = tip->tip.foreground; + values.background = tip->core.background_pixel; + values.font = tip->tip.font->fid; + values.graphics_exposures = False; + + tip->tip.gc = XtAllocateGC(w, 0, GCForeground | GCBackground | GCFont | + GCGraphicsExposures, &values, GCFont, 0); +} + +static void +XawTipDestroy(Widget w) +{ + XawTipInfo *info = FindTipInfo(w); + TipWidget tip = (TipWidget)w; + + if (tip->tip.timer) + XtRemoveTimeOut(tip->tip.timer); + + XtReleaseGC(w, tip->tip.gc); + + XtRemoveEventHandler(XtParent(w), KeyPressMask, False, TipShellEventHandler, + (XtPointer)NULL); + if (info == first_tip) + first_tip = first_tip->next; + else { + XawTipInfo *p = first_tip; + + while (p && p->next != info) + p = p->next; + if (p) + p->next = info->next; + } + XtFree((char*)info); +} + +static void +XawTipRealize(Widget w, Mask *mask, XSetWindowAttributes *attr) +{ + TipWidget tip = (TipWidget)w; + + if (tip->tip.backing_store == Always || + tip->tip.backing_store == NotUseful || + tip->tip.backing_store == WhenMapped) { + *mask |= CWBackingStore; + attr->backing_store = tip->tip.backing_store; + } + else + *mask &= ~CWBackingStore; + *mask |= CWOverrideRedirect; + attr->override_redirect = True; + + XtWindow(w) = XCreateWindow(DisplayOfScreen(XtScreen(w)), + RootWindowOfScreen(XtScreen(w)), + XtX(w), XtY(w), + XtWidth(w) ? XtWidth(w) : 1, + XtHeight(w) ? XtHeight(w) : 1, + XtBorderWidth(w), + DefaultDepthOfScreen(XtScreen(w)), + InputOutput, + (Visual *)CopyFromParent, + *mask, attr); +} + +static void +XawTipExpose(Widget w, XEvent *event, Region region) +{ + TipWidget tip = (TipWidget)w; + GC gc = tip->tip.gc; + char *nl, *label = tip->tip.label; + Position y = tip->tip.top_margin + tip->tip.font->max_bounds.ascent; + int len; + + if (tip->tip.display_list) + XawRunDisplayList(w, tip->tip.display_list, event, region); + + if (tip->tip.international == True) { + Position ksy = tip->tip.top_margin; + XFontSetExtents *ext = XExtentsOfFontSet(tip->tip.fontset); + + ksy += XawAbs(ext->max_ink_extent.y); + + while ((nl = index(label, '\n')) != NULL) { + XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset, + gc, tip->tip.left_margin, ksy, label, + (int)(nl - label)); + ksy += ext->max_ink_extent.height; + label = nl + 1; + } + len = strlen(label); + if (len) + XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset, gc, + tip->tip.left_margin, ksy, label, len); + } + else { + while ((nl = index(label, '\n')) != NULL) { + if (tip->tip.encoding) + XDrawString16(XtDisplay(w), XtWindow(w), gc, + tip->tip.left_margin, y, + (XChar2b*)label, (int)(nl - label) >> 1); + else + XDrawString(XtDisplay(w), XtWindow(w), gc, + tip->tip.left_margin, y, label, (int)(nl - label)); + y += tip->tip.font->max_bounds.ascent + + tip->tip.font->max_bounds.descent; + label = nl + 1; + } + len = strlen(label); + if (len) { + if (tip->tip.encoding) + XDrawString16(XtDisplay(w), XtWindow(w), gc, + tip->tip.left_margin, y, (XChar2b*)label, len >> 1); + else + XDrawString(XtDisplay(w), XtWindow(w), gc, + tip->tip.left_margin, y, label, len); + } + } +} + +/*ARGSUSED*/ +static Boolean +XawTipSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + TipWidget curtip = (TipWidget)current; + TipWidget newtip = (TipWidget)cnew; + Boolean redisplay = False; + + if (curtip->tip.font->fid != newtip->tip.font->fid || + curtip->tip.foreground != newtip->tip.foreground) { + XGCValues values; + + values.foreground = newtip->tip.foreground; + values.background = newtip->core.background_pixel; + values.font = newtip->tip.font->fid; + values.graphics_exposures = False; + XtReleaseGC(cnew, curtip->tip.gc); + newtip->tip.gc = XtAllocateGC(cnew, 0, GCForeground | GCBackground | + GCFont | GCGraphicsExposures, &values, + GCFont, 0); + redisplay = True; + } + if (curtip->tip.display_list != newtip->tip.display_list) + redisplay = True; + + return (redisplay); +} + +static void +TipLayout(XawTipInfo *info) +{ + XFontStruct *fs = info->tip->tip.font; + int width = 0, height; + char *nl, *label = info->tip->tip.label; + + if (info->tip->tip.international == True) { + XFontSet fset = info->tip->tip.fontset; + XFontSetExtents *ext = XExtentsOfFontSet(fset); + + height = ext->max_ink_extent.height; + if ((nl = index(label, '\n')) != NULL) { + /*CONSTCOND*/ + while (True) { + int w = XmbTextEscapement(fset, label, (int)(nl - label)); + + if (w > width) + width = w; + if (*nl == '\0') + break; + label = nl + 1; + if (*label) + height += ext->max_ink_extent.height; + if ((nl = index(label, '\n')) == NULL) + nl = index(label, '\0'); + } + } + else + width = XmbTextEscapement(fset, label, strlen(label)); + } + else { + height = fs->max_bounds.ascent + fs->max_bounds.descent; + if ((nl = index(label, '\n')) != NULL) { + /*CONSTCOND*/ + while (True) { + int w = info->tip->tip.encoding ? + XTextWidth16(fs, (XChar2b*)label, (int)(nl - label) >> 1) : + XTextWidth(fs, label, (int)(nl - label)); + if (w > width) + width = w; + if (*nl == '\0') + break; + label = nl + 1; + if (*label) + height += fs->max_bounds.ascent + fs->max_bounds.descent; + if ((nl = index(label, '\n')) == NULL) + nl = index(label, '\0'); + } + } + else + width = info->tip->tip.encoding ? + XTextWidth16(fs, (XChar2b*)label, strlen(label) >> 1) : + XTextWidth(fs, label, strlen(label)); + } + XtWidth(info->tip) = width + info->tip->tip.left_margin + + info->tip->tip.right_margin; + XtHeight(info->tip) = height + info->tip->tip.top_margin + + info->tip->tip.bottom_margin; +} + +#define DEFAULT_TIP_Y_OFFSET 12 +static void +TipPosition(XawTipInfo *info) +{ + Window r, c; + int rx, ry, wx, wy; + unsigned mask; + Position x, y; + + XQueryPointer(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip), + &r, &c, &rx, &ry, &wx, &wy, &mask); + x = rx - (XtWidth(info->tip) >> 1); + y = ry + DEFAULT_TIP_Y_OFFSET; + + if (x >= 0) { + int scr_width = WidthOfScreen(XtScreen(info->tip)); + + if (x + XtWidth(info->tip) + XtBorderWidth(info->tip) > scr_width) + x = scr_width - XtWidth(info->tip) - XtBorderWidth(info->tip); + } + if (x < 0) + x = 0; + if (y >= 0) { + int scr_height = HeightOfScreen(XtScreen(info->tip)); + + if (y + XtHeight(info->tip) + XtBorderWidth(info->tip) > scr_height) + y -= XtHeight(info->tip) + XtBorderWidth(info->tip) + + (DEFAULT_TIP_Y_OFFSET << 1); + } + if (y < 0) + y = 0; + + XMoveResizeWindow(XtDisplay(info->tip), XtWindow(info->tip), + (int)(XtX(info->tip) = x), (int)(XtY(info->tip) = y), + (unsigned)XtWidth(info->tip), (unsigned)XtHeight(info->tip)); +} + +static XawTipInfo * +CreateTipInfo(Widget w) +{ + XawTipInfo *info = XtNew(XawTipInfo); + Widget shell = w; + + info->screen = XtScreen(w); + + while (XtParent(shell)) + shell = XtParent(shell); + + info->tip = (TipWidget)XtCreateWidget("tip", tipWidgetClass, shell, NULL, 0); + XtRealizeWidget((Widget)info->tip); + info->widget = NULL; + info->mapped = False; + info->next = NULL; + XtAddEventHandler(shell, KeyPressMask, False, TipShellEventHandler, + (XtPointer)NULL); + + return (info); +} + +static XawTipInfo * +FindTipInfo(Widget w) +{ + XawTipInfo *ptip, *tip = first_tip; + Screen *screen = XtScreenOfObject(w); + + if (tip == NULL) + return (first_tip = tip = CreateTipInfo(w)); + + for (ptip = tip; tip; ptip = tip, tip = tip->next) + if (tip->screen == screen) + return (tip); + + return (ptip->next = CreateTipInfo(w)); +} + +static void +ResetTip(XawTipInfo *info, Bool add_timeout) +{ + if (info->tip->tip.timer) { + XtRemoveTimeOut(info->tip->tip.timer); + info->tip->tip.timer = 0; + } + if (info->mapped) { + XtRemoveGrab(XtParent((Widget)info->tip)); + XUnmapWindow(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip)); + info->mapped = False; + } + if (add_timeout) { + info->tip->tip.timer = + XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)info->tip), + info->tip->tip.timeout, TipTimeoutCallback, + (XtPointer)info); + } +} + +static void +TipTimeoutCallback(XtPointer closure, XtIntervalId *id) +{ + XawTipInfo *info = (XawTipInfo*)closure; + Arg args[3]; + + info->tip->tip.label = NULL; + info->tip->tip.international = False; + info->tip->tip.encoding = 0; + info->tip->tip.timer = 0; + XtSetArg(args[0], XtNtip, &info->tip->tip.label); + XtSetArg(args[1], XtNinternational, &info->tip->tip.international); + XtSetArg(args[2], XtNencoding, &info->tip->tip.encoding); + XtGetValues(info->widget, args, 3); + + if (info->tip->tip.label) { + TipLayout(info); + TipPosition(info); + XMapRaised(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip)); + XtAddGrab(XtParent((Widget)info->tip), True, True); + info->mapped = True; + } +} + +/*ARGSUSED*/ +static void +TipShellEventHandler(Widget w, XtPointer client_data, XEvent *event, + Boolean *continue_to_dispatch) +{ + ResetTip(FindTipInfo(w), False); +} + +/*ARGSUSED*/ +static void +TipEventHandler(Widget w, XtPointer client_data, XEvent *event, + Boolean *continue_to_dispatch) +{ + XawTipInfo *info = FindTipInfo(w); + Boolean add_timeout; + + if (info->widget != w) { + ResetTip(info, False); + info->widget = w; + } + + switch (event->type) { + case EnterNotify: + add_timeout = True; + break; + case MotionNotify: + /* If any button is pressed, timer is 0 */ + if (info->mapped) + return; + add_timeout = info->tip->tip.timer != 0; + break; + default: + add_timeout = False; + break; + } + ResetTip(info, add_timeout); +} + +/* + * Public routines + */ +void +XawTipEnable(Widget w) +{ + XtAddEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler, + (XtPointer)NULL); +} + +void +XawTipDisable(Widget w) +{ + XawTipInfo *info = FindTipInfo(w); + + XtRemoveEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler, + (XtPointer)NULL); + if (info->widget == w) + ResetTip(info, False); +} diff --git a/libXaw/src/Toggle.c b/libXaw/src/Toggle.c index cd288c5a2..1b9afadf9 100644 --- a/libXaw/src/Toggle.c +++ b/libXaw/src/Toggle.c @@ -1,629 +1,629 @@ -/*
-
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-/*
- * Author: Chris D. Peterson
- * MIT X Consortium
- * kit@expo.lcs.mit.edu
- *
- * Date: January 12, 1989
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/Converters.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xmu/SysUtil.h>
-#include <X11/Xaw/ToggleP.h>
-#include <X11/Xaw/XawInit.h>
-
-/*
- * Class Methods
- */
-static void XawToggleClassInitialize(void);
-static void XawToggleInitialize(Widget, Widget, ArgList, Cardinal*);
-static Boolean XawToggleSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void AddToRadioGroup(RadioGroup*, Widget);
-static void CreateRadioGroup(Widget, Widget);
-static RadioGroup *GetRadioGroup(Widget);
-static void RemoveFromRadioGroup(Widget);
-static void TurnOffRadioSiblings(Widget);
-static void XawToggleDestroy(Widget, XtPointer, XtPointer);
-
-/*
- * Actions
- */
-static void Notify(Widget, XEvent*, String*, Cardinal*);
-static void Toggle(Widget, XEvent*, String*, Cardinal*);
-static void ToggleSet(Widget, XEvent*, String*, Cardinal*);
-
-/*
- * Initialization
- */
-/*
- * The order of toggle and notify are important, as the state has
- * to be set when we call the notify proc
- */
-static char defaultTranslations[] =
-"<Enter>:" "highlight(Always)\n"
-"<Leave>:" "unhighlight()\n"
-"<Btn1Down>,<Btn1Up>:" "toggle() notify()\n"
-;
-
-#define offset(field) XtOffsetOf(ToggleRec, field)
-static XtResource resources[] = {
- {
- XtNstate,
- XtCState,
- XtRBoolean,
- sizeof(Boolean),
- offset(command.set),
- XtRString,
- "off"
- },
- {
- XtNradioGroup,
- XtCWidget,
- XtRWidget,
- sizeof(Widget),
- offset(toggle.widget),
- XtRWidget,
- NULL
- },
- {
- XtNradioData,
- XtCRadioData,
- XtRPointer,
- sizeof(XtPointer),
- offset(toggle.radio_data),
- XtRPointer,
- NULL
- },
-};
-#undef offset
-
-static XtActionsRec actionsList[] = {
- {"toggle", Toggle},
- {"notify", Notify},
- {"set", ToggleSet},
-};
-
-#define Superclass ((CommandWidgetClass)&commandClassRec)
-ToggleClassRec toggleClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "Toggle", /* class_name */
- sizeof(ToggleRec), /* size */
- XawToggleClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawToggleInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- actionsList, /* actions */
- XtNumber(actionsList), /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* resource_count */
- NULLQUARK, /* xrm_class */
- False, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- XtInheritResize, /* resize */
- XtInheritExpose, /* expose */
- XawToggleSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- defaultTranslations, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* simple */
- {
- XtInheritChangeSensitive, /* change_sensitive */
- },
- /* label */
- {
- NULL, /* extension */
- },
- /* command */
- {
- NULL, /* extension */
- },
- /* toggle */
- {
- NULL, /* Set */
- NULL, /* Unset */
- NULL, /* extension */
- }
-};
-
-WidgetClass toggleWidgetClass = (WidgetClass)&toggleClassRec;
-
-/*
- * Impelementation
- */
-static void
-XawToggleClassInitialize(void)
-{
- XtActionList actions;
- Cardinal num_actions;
- Cardinal i;
- ToggleWidgetClass cclass = (ToggleWidgetClass)toggleWidgetClass;
- static XtConvertArgRec parentCvtArgs[] = {
- {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent),
- sizeof(Widget)}
- };
-
- XawInitializeWidgetSet();
- XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget,
- parentCvtArgs, XtNumber(parentCvtArgs),
- XtCacheNone, NULL);
- XtSetTypeConverter(XtRWidget, XtRString, XmuCvtWidgetToString,
- NULL, 0, XtCacheNone, NULL);
-
- /*
- * Find the set and unset actions in the command widget's action table
- */
- XtGetActionList(commandWidgetClass, &actions, &num_actions);
-
- for (i = 0 ; i < num_actions ; i++) {
- if (streq(actions[i].string, "set"))
- cclass->toggle_class.Set = actions[i].proc;
- if (streq(actions[i].string, "unset"))
- cclass->toggle_class.Unset = actions[i].proc;
-
- if (cclass->toggle_class.Set != NULL &&
- cclass->toggle_class.Unset != NULL) {
- XtFree((char *)actions);
- return;
- }
- }
-
- /* We should never get here */
- XtError("Aborting, due to errors resolving bindings in the Toggle widget.");
-}
-
-/*ARGSUSED*/
-static void
-XawToggleInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- ToggleWidget tw = (ToggleWidget)cnew;
- ToggleWidget tw_req = (ToggleWidget)request;
-
- tw->toggle.radio_group = NULL;
-
- if (tw->toggle.radio_data == NULL)
- tw->toggle.radio_data = (XtPointer)cnew->core.name;
-
- if (tw->toggle.widget != NULL) {
- if (GetRadioGroup(tw->toggle.widget) == NULL)
- CreateRadioGroup(cnew, tw->toggle.widget);
- else
- AddToRadioGroup(GetRadioGroup(tw->toggle.widget), cnew);
- }
- XtAddCallback(cnew, XtNdestroyCallback, XawToggleDestroy, NULL);
-
- /*
- * Command widget assumes that the widget is unset, so we only
- * have to handle the case where it needs to be set
- *
- * If this widget is in a radio group then it may cause another
- * widget to be unset, thus calling the notify proceedure
- *
- * I want to set the toggle if the user set the state to "On" in
- * the resource group, reguardless of what my ancestors did
- */
- if (tw_req->command.set)
- ToggleSet(cnew, NULL, NULL, NULL);
-}
-
-/*ARGSUSED*/
-static void
-ToggleSet(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class;
-
- TurnOffRadioSiblings(w);
- cclass->toggle_class.Set(w, event, NULL, NULL);
-}
-
-static void
-Toggle(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- ToggleWidget tw = (ToggleWidget)w;
- ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class;
-
- if (tw->command.set)
- cclass->toggle_class.Unset(w, event, NULL, NULL);
- else
- ToggleSet(w, event, params, num_params);
-}
-
-/*ARGSUSED*/
-static void
-Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- ToggleWidget tw = (ToggleWidget)w;
- long antilint = tw->command.set;
-
- XtCallCallbacks(w, XtNcallback, (XtPointer)antilint);
-}
-
-/*ARGSUSED*/
-static Boolean
-XawToggleSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- ToggleWidget oldtw = (ToggleWidget)current;
- ToggleWidget tw = (ToggleWidget)cnew;
- ToggleWidget rtw = (ToggleWidget)request;
-
- if (oldtw->toggle.widget != tw->toggle.widget)
- XawToggleChangeRadioGroup(cnew, tw->toggle.widget);
-
- if (!tw->core.sensitive && oldtw->core.sensitive && rtw->command.set)
- tw->command.set = True;
-
- if (oldtw->command.set != tw->command.set) {
- tw->command.set = oldtw->command.set;
- Toggle(cnew, NULL, NULL, NULL);
- }
-
- return (False);
-}
-
-/*
- * Function:
- * XawToggleDestroy
- *
- * Parameters:
- * w - toggle widget that is being destroyed
- * temp1 - not used
- * temp2 - ""
- *
- * Description:
- * Destroy Callback for toggle widget.
- */
-/*ARGSUSED*/
-static void
-XawToggleDestroy(Widget w, XtPointer temp1, XtPointer temp2)
-{
- RemoveFromRadioGroup(w);
-}
-
-/*
- * Function:
- * GetRadioGroup
- *
- * Parameters:
- * w - toggle widget who's radio group we are getting
- *
- * Description:
- * Gets the radio group associated with a give toggle widget.
- *
- * Returns:
- * The radio group associated with this toggle group
- */
-static RadioGroup *
-GetRadioGroup(Widget w)
-{
- ToggleWidget tw = (ToggleWidget)w;
-
- if (tw == NULL)
- return (NULL);
-
- return (tw->toggle.radio_group);
-}
-
-/*
- * Function:
- * CreateRadioGroup
- *
- * Parameters:
- * w1 - toggle widgets to add to the radio group
- * w2 - ""
- *
- * Description:
- * Creates a radio group. give two widgets.
- *
- * Note:
- * A pointer to the group is added to each widget's radio_group field.
- */
-static void
-CreateRadioGroup(Widget w1, Widget w2)
-{
- ToggleWidget tw1 = (ToggleWidget)w1;
- ToggleWidget tw2 = (ToggleWidget) w2;
-
- if (tw1->toggle.radio_group != NULL || tw2->toggle.radio_group != NULL)
- XtAppWarning(XtWidgetToApplicationContext(w1),
- "Toggle Widget Error - Attempting to create a "
- "new toggle group, when one already exists.");
-
- AddToRadioGroup(NULL, w1);
- AddToRadioGroup(GetRadioGroup(w1), w2);
-}
-
-/*
- * Function:
- * AddToRadioGroup
- *
- * Parameters:
- * group - element of the radio group the we are adding to
- * w - new toggle widget to add to the group
- *
- * Description:
- * Adds a toggle to the radio group.
- */
-static void
-AddToRadioGroup(RadioGroup *group, Widget w)
-{
- ToggleWidget tw = (ToggleWidget)w;
- RadioGroup *local;
-
- local = (RadioGroup *)XtMalloc(sizeof(RadioGroup));
- local->widget = w;
- tw->toggle.radio_group = local;
-
- if (group == NULL) { /* Creating new group */
- group = local;
- group->next = NULL;
- group->prev = NULL;
- return;
- }
- local->prev = group; /* Adding to previous group */
- if ((local->next = group->next) != NULL)
- local->next->prev = local;
- group->next = local;
-}
-
-/*
- * Function:
- * TurnOffRadioSiblings
- *
- * Parameters:
- * widget - toggle widget
- *
- * Description:
- * Deactivates all radio siblings.
- */
-static void
-TurnOffRadioSiblings(Widget w)
-{
- RadioGroup *group;
- ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class;
-
- if ((group = GetRadioGroup(w)) == NULL) /* Punt if there is no group */
- return;
-
- /* Go to the top of the group */
- for (; group->prev != NULL ; group = group->prev)
- ;
-
- while (group != NULL) {
- ToggleWidget local_tog = (ToggleWidget)group->widget;
-
- if (local_tog->command.set) {
- cclass->toggle_class.Unset(group->widget, NULL, NULL, NULL);
- Notify(group->widget, NULL, NULL, NULL);
- }
- group = group->next;
- }
-}
-
-/*
- * Function:
- * RemoveFromRadioGroup
- *
- * Parameters:
- * w - toggle widget to remove
- *
- * Description:
- * Removes a toggle from a RadioGroup.
- */
-static void
-RemoveFromRadioGroup(Widget w)
-{
- RadioGroup *group = GetRadioGroup(w);
- if (group != NULL) {
- if (group->prev != NULL)
- (group->prev)->next = group->next;
- if (group->next != NULL)
- (group->next)->prev = group->prev;
- XtFree((char *)group);
- }
-}
-
-/*
- * Function:
- * XawToggleChangeRadioGroup
- *
- * Parameters:
- * w - toggle widget to change groups
- * radio_group - any widget in the new group
- *
- * Description:
- * Allows a toggle widget to change radio groups.
- */
-void
-XawToggleChangeRadioGroup(Widget w, Widget radio_group)
-{
- ToggleWidget tw = (ToggleWidget)w;
- RadioGroup *group;
-
- RemoveFromRadioGroup(w);
-
- /*
- * If the toggle that we are about to add is set then we will
- * unset all toggles in the new radio group
- */
-
- if (tw->command.set && radio_group != NULL)
- XawToggleUnsetCurrent(radio_group);
-
- if (radio_group != NULL) {
- if ((group = GetRadioGroup(radio_group)) == NULL)
- CreateRadioGroup(w, radio_group);
- else
- AddToRadioGroup(group, w);
- }
-}
-
-/*
- * Function:
- * XawToggleGetCurrent
- *
- * Parameters:
- * w - any toggle widget in the toggle group
- *
- * Description:
- * Returns the RadioData associated with the toggle
- * widget that is currently active in a toggle group.
- *
- * Returns:
- * The XtNradioData associated with the toggle widget
- */
-XtPointer
-XawToggleGetCurrent(Widget w)
-{
- RadioGroup *group;
-
- if ((group = GetRadioGroup(w)) == NULL)
- return (NULL);
-
- for (; group->prev != NULL ; group = group->prev)
- ;
-
- while (group != NULL) {
- ToggleWidget local_tog = (ToggleWidget)group->widget;
-
- if (local_tog->command.set)
- return (local_tog->toggle.radio_data);
- group = group->next;
- }
-
- return (NULL);
-}
-
-/*
- * Function:
- * XawToggleSetCurrent
- *
- * Parameters:
- * radio_group - any toggle widget in the toggle group
- * radio_data - radio data of the toggle widget to set
- *
- * Description:
- * Sets the Toggle widget associated with the radio_data specified.
- */
-void
-XawToggleSetCurrent(Widget radio_group, XtPointer radio_data)
-{
- RadioGroup *group;
- ToggleWidget local_tog;
-
- /* Special case of no radio group */
-
- if ((group = GetRadioGroup(radio_group)) == NULL) {
- local_tog = (ToggleWidget)radio_group;
-
- if (local_tog->toggle.radio_data == radio_data &&
- !local_tog->command.set) {
- ToggleSet(radio_group, NULL, NULL, NULL);
- Notify(radio_group, NULL, NULL, NULL);
- }
- return;
- }
-
- /*
- * find top of radio_roup
- */
- for (; group->prev != NULL ; group = group->prev)
- ;
-
- /*
- * search for matching radio data
- */
- while (group != NULL) {
- local_tog = (ToggleWidget)group->widget;
-
- if (local_tog->toggle.radio_data == radio_data) {
- if (!local_tog->command.set) { /* if not already set */
- ToggleSet(group->widget, NULL, NULL, NULL);
- Notify(group->widget, NULL, NULL, NULL);
- }
- return; /* found it, done */
- }
- group = group->next;
- }
-}
-
-/*
- * Function:
- * XawToggleUnsetCurrent
- *
- * Parameters:
- * radio_group - any toggle widget in the toggle group
- *
- * Description:
- * Unsets all Toggles in the radio_group specified.
- */
-void
-XawToggleUnsetCurrent(Widget radio_group)
-{
- ToggleWidgetClass cclass;
- ToggleWidget local_tog = (ToggleWidget)radio_group;
-
- /* Special Case no radio group */
-
- if (local_tog->command.set) {
- cclass = (ToggleWidgetClass)local_tog->core.widget_class;
- cclass->toggle_class.Unset(radio_group, NULL, NULL, NULL);
- Notify(radio_group, NULL, NULL, NULL);
- }
- if (GetRadioGroup(radio_group) == NULL)
- return;
-
- TurnOffRadioSiblings(radio_group);
-}
+/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + * + * Date: January 12, 1989 + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/ToggleP.h> +#include <X11/Xaw/XawInit.h> + +/* + * Class Methods + */ +static void XawToggleClassInitialize(void); +static void XawToggleInitialize(Widget, Widget, ArgList, Cardinal*); +static Boolean XawToggleSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +static void AddToRadioGroup(RadioGroup*, Widget); +static void CreateRadioGroup(Widget, Widget); +static RadioGroup *GetRadioGroup(Widget); +static void RemoveFromRadioGroup(Widget); +static void TurnOffRadioSiblings(Widget); +static void XawToggleDestroy(Widget, XtPointer, XtPointer); + +/* + * Actions + */ +static void Notify(Widget, XEvent*, String*, Cardinal*); +static void Toggle(Widget, XEvent*, String*, Cardinal*); +static void ToggleSet(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +/* + * The order of toggle and notify are important, as the state has + * to be set when we call the notify proc + */ +static char defaultTranslations[] = +"<Enter>:" "highlight(Always)\n" +"<Leave>:" "unhighlight()\n" +"<Btn1Down>,<Btn1Up>:" "toggle() notify()\n" +; + +#define offset(field) XtOffsetOf(ToggleRec, field) +static XtResource resources[] = { + { + XtNstate, + XtCState, + XtRBoolean, + sizeof(Boolean), + offset(command.set), + XtRString, + "off" + }, + { + XtNradioGroup, + XtCWidget, + XtRWidget, + sizeof(Widget), + offset(toggle.widget), + XtRWidget, + NULL + }, + { + XtNradioData, + XtCRadioData, + XtRPointer, + sizeof(XtPointer), + offset(toggle.radio_data), + XtRPointer, + NULL + }, +}; +#undef offset + +static XtActionsRec actionsList[] = { + {"toggle", Toggle}, + {"notify", Notify}, + {"set", ToggleSet}, +}; + +#define Superclass ((CommandWidgetClass)&commandClassRec) +ToggleClassRec toggleClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Toggle", /* class_name */ + sizeof(ToggleRec), /* size */ + XawToggleClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawToggleInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + actionsList, /* actions */ + XtNumber(actionsList), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* resource_count */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + XawToggleSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* label */ + { + NULL, /* extension */ + }, + /* command */ + { + NULL, /* extension */ + }, + /* toggle */ + { + NULL, /* Set */ + NULL, /* Unset */ + NULL, /* extension */ + } +}; + +WidgetClass toggleWidgetClass = (WidgetClass)&toggleClassRec; + +/* + * Impelementation + */ +static void +XawToggleClassInitialize(void) +{ + XtActionList actions; + Cardinal num_actions; + Cardinal i; + ToggleWidgetClass cclass = (ToggleWidgetClass)toggleWidgetClass; + static XtConvertArgRec parentCvtArgs[] = { + {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent), + sizeof(Widget)} + }; + + XawInitializeWidgetSet(); + XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget, + parentCvtArgs, XtNumber(parentCvtArgs), + XtCacheNone, NULL); + XtSetTypeConverter(XtRWidget, XtRString, XmuCvtWidgetToString, + NULL, 0, XtCacheNone, NULL); + + /* + * Find the set and unset actions in the command widget's action table + */ + XtGetActionList(commandWidgetClass, &actions, &num_actions); + + for (i = 0 ; i < num_actions ; i++) { + if (streq(actions[i].string, "set")) + cclass->toggle_class.Set = actions[i].proc; + if (streq(actions[i].string, "unset")) + cclass->toggle_class.Unset = actions[i].proc; + + if (cclass->toggle_class.Set != NULL && + cclass->toggle_class.Unset != NULL) { + XtFree((char *)actions); + return; + } + } + + /* We should never get here */ + XtError("Aborting, due to errors resolving bindings in the Toggle widget."); +} + +/*ARGSUSED*/ +static void +XawToggleInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ToggleWidget tw = (ToggleWidget)cnew; + ToggleWidget tw_req = (ToggleWidget)request; + + tw->toggle.radio_group = NULL; + + if (tw->toggle.radio_data == NULL) + tw->toggle.radio_data = (XtPointer)cnew->core.name; + + if (tw->toggle.widget != NULL) { + if (GetRadioGroup(tw->toggle.widget) == NULL) + CreateRadioGroup(cnew, tw->toggle.widget); + else + AddToRadioGroup(GetRadioGroup(tw->toggle.widget), cnew); + } + XtAddCallback(cnew, XtNdestroyCallback, XawToggleDestroy, NULL); + + /* + * Command widget assumes that the widget is unset, so we only + * have to handle the case where it needs to be set + * + * If this widget is in a radio group then it may cause another + * widget to be unset, thus calling the notify proceedure + * + * I want to set the toggle if the user set the state to "On" in + * the resource group, reguardless of what my ancestors did + */ + if (tw_req->command.set) + ToggleSet(cnew, NULL, NULL, NULL); +} + +/*ARGSUSED*/ +static void +ToggleSet(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class; + + TurnOffRadioSiblings(w); + cclass->toggle_class.Set(w, event, NULL, NULL); +} + +static void +Toggle(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + ToggleWidget tw = (ToggleWidget)w; + ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class; + + if (tw->command.set) + cclass->toggle_class.Unset(w, event, NULL, NULL); + else + ToggleSet(w, event, params, num_params); +} + +/*ARGSUSED*/ +static void +Notify(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + ToggleWidget tw = (ToggleWidget)w; + long antilint = tw->command.set; + + XtCallCallbacks(w, XtNcallback, (XtPointer)antilint); +} + +/*ARGSUSED*/ +static Boolean +XawToggleSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ToggleWidget oldtw = (ToggleWidget)current; + ToggleWidget tw = (ToggleWidget)cnew; + ToggleWidget rtw = (ToggleWidget)request; + + if (oldtw->toggle.widget != tw->toggle.widget) + XawToggleChangeRadioGroup(cnew, tw->toggle.widget); + + if (!tw->core.sensitive && oldtw->core.sensitive && rtw->command.set) + tw->command.set = True; + + if (oldtw->command.set != tw->command.set) { + tw->command.set = oldtw->command.set; + Toggle(cnew, NULL, NULL, NULL); + } + + return (False); +} + +/* + * Function: + * XawToggleDestroy + * + * Parameters: + * w - toggle widget that is being destroyed + * temp1 - not used + * temp2 - "" + * + * Description: + * Destroy Callback for toggle widget. + */ +/*ARGSUSED*/ +static void +XawToggleDestroy(Widget w, XtPointer temp1, XtPointer temp2) +{ + RemoveFromRadioGroup(w); +} + +/* + * Function: + * GetRadioGroup + * + * Parameters: + * w - toggle widget who's radio group we are getting + * + * Description: + * Gets the radio group associated with a give toggle widget. + * + * Returns: + * The radio group associated with this toggle group + */ +static RadioGroup * +GetRadioGroup(Widget w) +{ + ToggleWidget tw = (ToggleWidget)w; + + if (tw == NULL) + return (NULL); + + return (tw->toggle.radio_group); +} + +/* + * Function: + * CreateRadioGroup + * + * Parameters: + * w1 - toggle widgets to add to the radio group + * w2 - "" + * + * Description: + * Creates a radio group. give two widgets. + * + * Note: + * A pointer to the group is added to each widget's radio_group field. + */ +static void +CreateRadioGroup(Widget w1, Widget w2) +{ + ToggleWidget tw1 = (ToggleWidget)w1; + ToggleWidget tw2 = (ToggleWidget) w2; + + if (tw1->toggle.radio_group != NULL || tw2->toggle.radio_group != NULL) + XtAppWarning(XtWidgetToApplicationContext(w1), + "Toggle Widget Error - Attempting to create a " + "new toggle group, when one already exists."); + + AddToRadioGroup(NULL, w1); + AddToRadioGroup(GetRadioGroup(w1), w2); +} + +/* + * Function: + * AddToRadioGroup + * + * Parameters: + * group - element of the radio group the we are adding to + * w - new toggle widget to add to the group + * + * Description: + * Adds a toggle to the radio group. + */ +static void +AddToRadioGroup(RadioGroup *group, Widget w) +{ + ToggleWidget tw = (ToggleWidget)w; + RadioGroup *local; + + local = (RadioGroup *)XtMalloc(sizeof(RadioGroup)); + local->widget = w; + tw->toggle.radio_group = local; + + if (group == NULL) { /* Creating new group */ + group = local; + group->next = NULL; + group->prev = NULL; + return; + } + local->prev = group; /* Adding to previous group */ + if ((local->next = group->next) != NULL) + local->next->prev = local; + group->next = local; +} + +/* + * Function: + * TurnOffRadioSiblings + * + * Parameters: + * widget - toggle widget + * + * Description: + * Deactivates all radio siblings. + */ +static void +TurnOffRadioSiblings(Widget w) +{ + RadioGroup *group; + ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class; + + if ((group = GetRadioGroup(w)) == NULL) /* Punt if there is no group */ + return; + + /* Go to the top of the group */ + for (; group->prev != NULL ; group = group->prev) + ; + + while (group != NULL) { + ToggleWidget local_tog = (ToggleWidget)group->widget; + + if (local_tog->command.set) { + cclass->toggle_class.Unset(group->widget, NULL, NULL, NULL); + Notify(group->widget, NULL, NULL, NULL); + } + group = group->next; + } +} + +/* + * Function: + * RemoveFromRadioGroup + * + * Parameters: + * w - toggle widget to remove + * + * Description: + * Removes a toggle from a RadioGroup. + */ +static void +RemoveFromRadioGroup(Widget w) +{ + RadioGroup *group = GetRadioGroup(w); + if (group != NULL) { + if (group->prev != NULL) + (group->prev)->next = group->next; + if (group->next != NULL) + (group->next)->prev = group->prev; + XtFree((char *)group); + } +} + +/* + * Function: + * XawToggleChangeRadioGroup + * + * Parameters: + * w - toggle widget to change groups + * radio_group - any widget in the new group + * + * Description: + * Allows a toggle widget to change radio groups. + */ +void +XawToggleChangeRadioGroup(Widget w, Widget radio_group) +{ + ToggleWidget tw = (ToggleWidget)w; + RadioGroup *group; + + RemoveFromRadioGroup(w); + + /* + * If the toggle that we are about to add is set then we will + * unset all toggles in the new radio group + */ + + if (tw->command.set && radio_group != NULL) + XawToggleUnsetCurrent(radio_group); + + if (radio_group != NULL) { + if ((group = GetRadioGroup(radio_group)) == NULL) + CreateRadioGroup(w, radio_group); + else + AddToRadioGroup(group, w); + } +} + +/* + * Function: + * XawToggleGetCurrent + * + * Parameters: + * w - any toggle widget in the toggle group + * + * Description: + * Returns the RadioData associated with the toggle + * widget that is currently active in a toggle group. + * + * Returns: + * The XtNradioData associated with the toggle widget + */ +XtPointer +XawToggleGetCurrent(Widget w) +{ + RadioGroup *group; + + if ((group = GetRadioGroup(w)) == NULL) + return (NULL); + + for (; group->prev != NULL ; group = group->prev) + ; + + while (group != NULL) { + ToggleWidget local_tog = (ToggleWidget)group->widget; + + if (local_tog->command.set) + return (local_tog->toggle.radio_data); + group = group->next; + } + + return (NULL); +} + +/* + * Function: + * XawToggleSetCurrent + * + * Parameters: + * radio_group - any toggle widget in the toggle group + * radio_data - radio data of the toggle widget to set + * + * Description: + * Sets the Toggle widget associated with the radio_data specified. + */ +void +XawToggleSetCurrent(Widget radio_group, XtPointer radio_data) +{ + RadioGroup *group; + ToggleWidget local_tog; + + /* Special case of no radio group */ + + if ((group = GetRadioGroup(radio_group)) == NULL) { + local_tog = (ToggleWidget)radio_group; + + if (local_tog->toggle.radio_data == radio_data && + !local_tog->command.set) { + ToggleSet(radio_group, NULL, NULL, NULL); + Notify(radio_group, NULL, NULL, NULL); + } + return; + } + + /* + * find top of radio_roup + */ + for (; group->prev != NULL ; group = group->prev) + ; + + /* + * search for matching radio data + */ + while (group != NULL) { + local_tog = (ToggleWidget)group->widget; + + if (local_tog->toggle.radio_data == radio_data) { + if (!local_tog->command.set) { /* if not already set */ + ToggleSet(group->widget, NULL, NULL, NULL); + Notify(group->widget, NULL, NULL, NULL); + } + return; /* found it, done */ + } + group = group->next; + } +} + +/* + * Function: + * XawToggleUnsetCurrent + * + * Parameters: + * radio_group - any toggle widget in the toggle group + * + * Description: + * Unsets all Toggles in the radio_group specified. + */ +void +XawToggleUnsetCurrent(Widget radio_group) +{ + ToggleWidgetClass cclass; + ToggleWidget local_tog = (ToggleWidget)radio_group; + + /* Special Case no radio group */ + + if (local_tog->command.set) { + cclass = (ToggleWidgetClass)local_tog->core.widget_class; + cclass->toggle_class.Unset(radio_group, NULL, NULL, NULL); + Notify(radio_group, NULL, NULL, NULL); + } + if (GetRadioGroup(radio_group) == NULL) + return; + + TurnOffRadioSiblings(radio_group); +} diff --git a/libXaw/src/Tree.c b/libXaw/src/Tree.c index c5e9a00f6..9dd9b7f53 100644 --- a/libXaw/src/Tree.c +++ b/libXaw/src/Tree.c @@ -1,1014 +1,1014 @@ -/*
-
-Copyright 1990, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
- * Copyright 1989 Prentice Hall
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright notice appear in all copies and that both the copyright notice
- * and this permission notice appear in supporting documentation.
- *
- * Prentice Hall and the authors disclaim all warranties with regard
- * to this software, including all implied warranties of merchantability and
- * fitness. In no event shall Prentice Hall or the authors be liable
- * for any special, indirect or cosequential damages or any damages whatsoever
- * resulting from loss of use, data or profits, whether in an action of
- * contract, negligence or other tortious action, arising out of or in
- * connection with the use or performance of this software.
- *
- * Authors: Jim Fulton, MIT X Consortium,
- * based on a version by Douglas Young, Prentice Hall
- *
- * This widget is based on the Tree widget described on pages 397-419 of
- * Douglas Young's book "The X Window System, Programming and Applications
- * with Xt OSF/Motif Edition." The layout code has been rewritten to use
- * additional blank space to make the structure of the graph easier to see
- * as well as to support vertical trees.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/XawInit.h>
-#include <X11/Xaw/Cardinals.h>
-#include <X11/Xaw/TreeP.h>
-#include "Private.h"
-
-#define IsHorizontal(tw) ((tw)->tree.gravity == WestGravity || \
- (tw)->tree.gravity == EastGravity)
-
-/*
- * Class Methods
- */
-static void XawTreeChangeManaged(Widget);
-static void XawTreeClassInitialize(void);
-static void XawTreeConstraintDestroy(Widget);
-static void XawTreeConstraintInitialize(Widget, Widget, ArgList, Cardinal*);
-static Boolean XawTreeConstraintSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static void XawTreeDestroy(Widget);
-static XtGeometryResult XawTreeGeometryManager(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawTreeInitialize(Widget, Widget, ArgList, Cardinal*);
-static XtGeometryResult XawTreeQueryGeometry(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawTreeRedisplay(Widget, XEvent*, Region);
-static Boolean XawTreeSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void arrange_subtree(TreeWidget, Widget, int, int, int);
-static void check_gravity(TreeWidget, XtGravity);
-static void compute_bounding_box_subtree(TreeWidget, Widget, int);
-static void delete_node(Widget, Widget);
-static GC get_tree_gc(TreeWidget);
-static void initialize_dimensions(Dimension**, int*, int);
-static void insert_node(Widget, Widget);
-static void layout_tree(TreeWidget, Bool);
-static void set_positions(TreeWidget, Widget, int);
-static void set_tree_size(TreeWidget, Bool, unsigned int, unsigned int);
-
-/*
- * Initialization
- */
-
-/*
- * resources of the tree itself
- */
-static XtResource resources[] = {
- { XtNautoReconfigure, XtCAutoReconfigure, XtRBoolean, sizeof (Boolean),
- XtOffsetOf(TreeRec, tree.auto_reconfigure), XtRImmediate,
- (XtPointer) FALSE },
- { XtNhSpace, XtCHSpace, XtRDimension, sizeof (Dimension),
- XtOffsetOf(TreeRec, tree.hpad), XtRImmediate, (XtPointer) 0 },
- { XtNvSpace, XtCVSpace, XtRDimension, sizeof (Dimension),
- XtOffsetOf(TreeRec, tree.vpad), XtRImmediate, (XtPointer) 0 },
- { XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
- XtOffsetOf(TreeRec, tree.foreground), XtRString,
- XtDefaultForeground},
- { XtNlineWidth, XtCLineWidth, XtRDimension, sizeof (Dimension),
- XtOffsetOf(TreeRec, tree.line_width), XtRImmediate, (XtPointer) 0 },
- { XtNgravity, XtCGravity, XtRGravity, sizeof (XtGravity),
- XtOffsetOf(TreeRec, tree.gravity), XtRImmediate,
- (XtPointer) WestGravity },
-#ifndef OLDXAW
- { XawNdisplayList, XawCDisplayList, XawRDisplayList, sizeof(XawDisplayList*),
- XtOffsetOf(TreeRec, tree.display_list), XtRImmediate,
- NULL },
-#endif
-};
-
-
-/*
- * resources that are attached to all children of the tree
- */
-static XtResource treeConstraintResources[] = {
- { XtNtreeParent, XtCTreeParent, XtRWidget, sizeof (Widget),
- XtOffsetOf(TreeConstraintsRec, tree.parent), XtRImmediate, NULL },
- { XtNtreeGC, XtCTreeGC, XtRGC, sizeof(GC),
- XtOffsetOf(TreeConstraintsRec, tree.gc), XtRImmediate, NULL },
-};
-
-
-TreeClassRec treeClassRec = {
- {
- /* core_class fields */
- (WidgetClass) &constraintClassRec, /* superclass */
- "Tree", /* class_name */
- sizeof(TreeRec), /* widget_size */
- XawTreeClassInitialize, /* class_init */
- NULL, /* class_part_init */
- FALSE, /* class_inited */
- XawTreeInitialize, /* initialize */
- NULL, /* initialize_hook */
- XtInheritRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- TRUE, /* compress_motion */
- TRUE, /* compress_exposure */
- TRUE, /* compress_enterleave*/
- TRUE, /* visible_interest */
- XawTreeDestroy, /* destroy */
- NULL, /* resize */
- XawTreeRedisplay, /* expose */
- XawTreeSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XawTreeQueryGeometry, /* query_geometry */
- NULL, /* display_accelerator*/
- NULL, /* extension */
- },
- {
- /* composite_class fields */
- XawTreeGeometryManager, /* geometry_manager */
- XawTreeChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- {
- /* constraint_class fields */
- treeConstraintResources, /* subresources */
- XtNumber(treeConstraintResources), /* subresource_count */
- sizeof(TreeConstraintsRec), /* constraint_size */
- XawTreeConstraintInitialize, /* initialize */
- XawTreeConstraintDestroy, /* destroy */
- XawTreeConstraintSetValues, /* set_values */
- NULL, /* extension */
- },
- {
- /* Tree class fields */
- NULL, /* ignore */
- }
-};
-
-WidgetClass treeWidgetClass = (WidgetClass) &treeClassRec;
-
-
-/*****************************************************************************
- * *
- * tree utility routines *
- * *
- *****************************************************************************/
-
-static void
-initialize_dimensions(Dimension **listp, int *sizep, int n)
-{
- int i;
- Dimension *l;
-
- if (!*listp) {
- *listp = (Dimension *) XtCalloc ((unsigned int) n,
- (unsigned int) sizeof(Dimension));
- *sizep = ((*listp) ? n : 0);
- return;
- }
- if (n > *sizep) {
- *listp = (Dimension *) XtRealloc((char *) *listp,
- (unsigned int) (n*sizeof(Dimension)));
- if (!*listp) {
- *sizep = 0;
- return;
- }
- for (i = *sizep, l = (*listp) + i; i < n; i++, l++) *l = 0;
- *sizep = n;
- }
- return;
-}
-
-static GC
-get_tree_gc(TreeWidget w)
-{
- XtGCMask valuemask = GCBackground | GCForeground;
- XGCValues values;
-
- values.background = w->core.background_pixel;
- values.foreground = w->tree.foreground;
- if (w->tree.line_width != 0) {
- valuemask |= GCLineWidth;
- values.line_width = w->tree.line_width;
- }
-
- return XtGetGC ((Widget) w, valuemask, &values);
-}
-
-static void
-insert_node(Widget parent, Widget node)
-{
- TreeConstraints pc;
- TreeConstraints nc = TREE_CONSTRAINT(node);
- int nindex;
-
- nc->tree.parent = parent;
-
- if (parent == NULL) return;
-
- /*
- * If there isn't more room in the children array,
- * allocate additional space.
- */
- pc = TREE_CONSTRAINT(parent);
- nindex = pc->tree.n_children;
-
- if (pc->tree.n_children == pc->tree.max_children) {
- pc->tree.max_children += (pc->tree.max_children / 2) + 2;
- pc->tree.children = (WidgetList) XtRealloc ((char *)pc->tree.children,
- (unsigned int)
- ((pc->tree.max_children) *
- sizeof(Widget)));
- }
-
- /*
- * Add the sub_node in the next available slot and
- * increment the counter.
- */
- pc->tree.children[nindex] = node;
- pc->tree.n_children++;
-}
-
-static void
-delete_node(Widget parent, Widget node)
-{
- TreeConstraints pc;
- int pos, i;
-
- /*
- * Make sure the parent exists.
- */
- if (!parent) return;
-
- pc = TREE_CONSTRAINT(parent);
-
- /*
- * Find the sub_node on its parent's list.
- */
- for (pos = 0; pos < pc->tree.n_children; pos++)
- if (pc->tree.children[pos] == node) break;
-
- if (pos == pc->tree.n_children) return;
-
- /*
- * Decrement the number of children
- */
- pc->tree.n_children--;
-
- /*
- * Fill in the gap left by the sub_node.
- * Zero the last slot for good luck.
- */
- for (i = pos; i < pc->tree.n_children; i++)
- pc->tree.children[i] = pc->tree.children[i+1];
-
- pc->tree.children[pc->tree.n_children] = NULL;
-}
-
-static void
-check_gravity(TreeWidget tw, XtGravity grav)
-{
- switch (tw->tree.gravity) {
- case WestGravity: case NorthGravity: case EastGravity: case SouthGravity:
- break;
- default:
- tw->tree.gravity = grav;
- break;
- }
-}
-
-
-/*****************************************************************************
- * *
- * tree class methods *
- * *
- *****************************************************************************/
-
-static void
-XawTreeClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity, NULL, 0);
- XtSetTypeConverter(XtRGravity, XtRString, XmuCvtGravityToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-
-/*ARGSUSED*/
-static void
-XawTreeInitialize(Widget grequest, Widget gnew,
- ArgList args, Cardinal *num_args)
-{
- TreeWidget request = (TreeWidget) grequest, cnew = (TreeWidget) gnew;
- Arg arglist[2];
-
- /*
- * Make sure the widget's width and height are
- * greater than zero.
- */
- if (request->core.width <= 0) cnew->core.width = 5;
- if (request->core.height <= 0) cnew->core.height = 5;
-
- /*
- * Set the padding according to the orientation
- */
- if (request->tree.hpad == 0 && request->tree.vpad == 0) {
- if (IsHorizontal (request)) {
- cnew->tree.hpad = TREE_HORIZONTAL_DEFAULT_SPACING;
- cnew->tree.vpad = TREE_VERTICAL_DEFAULT_SPACING;
- } else {
- cnew->tree.hpad = TREE_VERTICAL_DEFAULT_SPACING;
- cnew->tree.vpad = TREE_HORIZONTAL_DEFAULT_SPACING;
- }
- }
-
- /*
- * Create a graphics context for the connecting lines.
- */
- cnew->tree.gc = get_tree_gc (cnew);
-
- /*
- * Create the hidden root widget.
- */
- cnew->tree.tree_root = (Widget) NULL;
- XtSetArg(arglist[0], XtNwidth, 1);
- XtSetArg(arglist[1], XtNheight, 1);
- cnew->tree.tree_root = XtCreateWidget ("root", widgetClass, gnew,
- arglist,TWO);
-
- /*
- * Allocate the array used to hold the widest values per depth
- */
- cnew->tree.largest = NULL;
- cnew->tree.n_largest = 0;
- initialize_dimensions (&cnew->tree.largest, &cnew->tree.n_largest,
- TREE_INITIAL_DEPTH);
-
- /*
- * make sure that our gravity is one of the acceptable values
- */
- check_gravity (cnew, WestGravity);
-}
-
-
-/* ARGSUSED */
-static void
-XawTreeConstraintInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- TreeConstraints tc = TREE_CONSTRAINT(cnew);
- TreeWidget tw = (TreeWidget) cnew->core.parent;
-
- /*
- * Initialize the widget to have no sub-nodes.
- */
- tc->tree.n_children = 0;
- tc->tree.max_children = 0;
- tc->tree.children = (Widget *) NULL;
- tc->tree.x = tc->tree.y = 0;
- tc->tree.bbsubwidth = 0;
- tc->tree.bbsubheight = 0;
-
-
- /*
- * If this widget has a super-node, add it to that
- * widget' sub-nodes list. Otherwise make it a sub-node of
- * the tree_root widget.
- */
- if (tc->tree.parent)
- insert_node (tc->tree.parent, cnew);
- else if (tw->tree.tree_root)
- insert_node (tw->tree.tree_root, cnew);
-}
-
-
-/* ARGSUSED */
-static Boolean
-XawTreeSetValues(Widget gcurrent, Widget grequest, Widget gnew,
- ArgList args, Cardinal *num_args)
-{
- TreeWidget current = (TreeWidget) gcurrent, cnew = (TreeWidget) gnew;
- Boolean redraw = FALSE;
-
- /*
- * If the foreground color has changed, redo the GC's
- * and indicate a redraw.
- */
- if (cnew->tree.foreground != current->tree.foreground ||
- cnew->core.background_pixel != current->core.background_pixel ||
- cnew->tree.line_width != current->tree.line_width) {
- XtReleaseGC (gnew, cnew->tree.gc);
- cnew->tree.gc = get_tree_gc (cnew);
- redraw = TRUE;
- }
-
- /*
- * If the minimum spacing has changed, recalculate the
- * tree layout. layout_tree() does a redraw, so we don't
- * need SetValues to do another one.
- */
- if (cnew->tree.gravity != current->tree.gravity) {
- check_gravity (cnew, current->tree.gravity);
- }
-
- if (IsHorizontal(cnew) != IsHorizontal(current)) {
- if (cnew->tree.vpad == current->tree.vpad &&
- cnew->tree.hpad == current->tree.hpad) {
- cnew->tree.vpad = current->tree.hpad;
- cnew->tree.hpad = current->tree.vpad;
- }
- }
-
- if (cnew->tree.vpad != current->tree.vpad ||
- cnew->tree.hpad != current->tree.hpad ||
- cnew->tree.gravity != current->tree.gravity) {
- layout_tree (cnew, TRUE);
- redraw = FALSE;
- }
- return redraw;
-}
-
-
-/* ARGSUSED */
-static Boolean
-XawTreeConstraintSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- TreeConstraints newc = TREE_CONSTRAINT(cnew);
- TreeConstraints curc = TREE_CONSTRAINT(current);
- TreeWidget tw = (TreeWidget) cnew->core.parent;
-
- /*
- * If the parent field has changed, remove the widget
- * from the old widget's children list and add it to the
- * new one.
- */
- if (curc->tree.parent != newc->tree.parent){
- if (curc->tree.parent)
- delete_node (curc->tree.parent, cnew);
- if (newc->tree.parent)
- insert_node(newc->tree.parent, cnew);
-
- /*
- * If the Tree widget has been realized,
- * compute new layout.
- */
- if (XtIsRealized((Widget)tw))
- layout_tree (tw, FALSE);
- }
- return False;
-}
-
-
-static void
-XawTreeConstraintDestroy(Widget w)
-{
- TreeConstraints tc = TREE_CONSTRAINT(w);
- TreeWidget tw = (TreeWidget) XtParent(w);
- int i;
-
- /*
- * Remove the widget from its parent's sub-nodes list and
- * make all this widget's sub-nodes sub-nodes of the parent.
- */
-
- if (tw->tree.tree_root == w) {
- if (tc->tree.n_children > 0)
- tw->tree.tree_root = tc->tree.children[0];
- else
- tw->tree.tree_root = NULL;
- }
-
- delete_node (tc->tree.parent, (Widget) w);
- for (i = 0; i< tc->tree.n_children; i++)
- insert_node (tc->tree.parent, tc->tree.children[i]);
-
- layout_tree ((TreeWidget) (w->core.parent), FALSE);
-}
-
-/* ARGSUSED */
-static XtGeometryResult
-XawTreeGeometryManager(Widget w, XtWidgetGeometry *request,
- XtWidgetGeometry *reply)
-{
-
- TreeWidget tw = (TreeWidget) w->core.parent;
-
- /*
- * No position changes allowed!.
- */
- if ((request->request_mode & CWX && request->x!=w->core.x)
- ||(request->request_mode & CWY && request->y!=w->core.y))
- return (XtGeometryNo);
-
- /*
- * Allow all resize requests.
- */
-
- if (request->request_mode & CWWidth)
- w->core.width = request->width;
- if (request->request_mode & CWHeight)
- w->core.height = request->height;
- if (request->request_mode & CWBorderWidth)
- w->core.border_width = request->border_width;
-
- if (tw->tree.auto_reconfigure) layout_tree (tw, FALSE);
- return (XtGeometryYes);
-}
-
-static void
-XawTreeChangeManaged(Widget gw)
-{
- layout_tree ((TreeWidget) gw, FALSE);
-}
-
-
-static void
-XawTreeDestroy(Widget gw)
-{
- TreeWidget w = (TreeWidget) gw;
-
- XtReleaseGC (gw, w->tree.gc);
- if (w->tree.largest) XtFree ((char *) w->tree.largest);
-}
-
-
-/* ARGSUSED */
-static void
-XawTreeRedisplay(Widget gw, XEvent *event, Region region)
-{
- TreeWidget tw = (TreeWidget) gw;
-
-#ifndef OLDXAW
- if (tw->tree.display_list)
- XawRunDisplayList(gw, tw->tree.display_list, event, region);
-#endif
-
- /*
- * If the Tree widget is visible, visit each managed child.
- */
- if (tw->core.visible) {
- Cardinal i;
- int j;
- Display *dpy = XtDisplay (tw);
- Window w = XtWindow (tw);
-
- for (i = 0; i < tw->composite.num_children; i++) {
- Widget child = tw->composite.children[i];
- TreeConstraints tc = TREE_CONSTRAINT(child);
-
- /*
- * Don't draw lines from the fake tree_root.
- */
- if (child != tw->tree.tree_root && tc->tree.n_children) {
- int srcx = child->core.x + child->core.border_width;
- int srcy = child->core.y + child->core.border_width;
-
- switch (tw->tree.gravity) {
- case WestGravity:
- srcx += child->core.width + child->core.border_width;
- /* fall through */
- case EastGravity:
- srcy += child->core.height / 2;
- break;
-
- case NorthGravity:
- srcy += child->core.height + child->core.border_width;
- /* fall through */
- case SouthGravity:
- srcx += child->core.width / 2;
- break;
- }
-
- for (j = 0; j < tc->tree.n_children; j++) {
- Widget k = tc->tree.children[j];
- GC gc = (tc->tree.gc ? tc->tree.gc : tw->tree.gc);
-
- switch (tw->tree.gravity) {
- case WestGravity:
- /*
- * right center to left center
- */
- XDrawLine (dpy, w, gc, srcx, srcy,
- (int) k->core.x,
- (k->core.y + ((int) k->core.border_width) +
- ((int) k->core.height) / 2));
- break;
-
- case NorthGravity:
- /*
- * bottom center to top center
- */
- XDrawLine (dpy, w, gc, srcx, srcy,
- (k->core.x + ((int) k->core.border_width) +
- ((int) k->core.width) / 2),
- (int) k->core.y);
- break;
-
- case EastGravity:
- /*
- * left center to right center
- */
- XDrawLine (dpy, w, gc, srcx, srcy,
- (k->core.x +
- (((int) k->core.border_width) << 1) +
- (int) k->core.width),
- (k->core.y + ((int) k->core.border_width) +
- ((int) k->core.height) / 2));
- break;
-
- case SouthGravity:
- /*
- * top center to bottom center
- */
- XDrawLine (dpy, w, gc, srcx, srcy,
- (k->core.x + ((int) k->core.border_width) +
- ((int) k->core.width) / 2),
- (k->core.y +
- (((int) k->core.border_width) << 1) +
- (int) k->core.height));
- break;
- }
- }
- }
- }
- }
-}
-
-static XtGeometryResult
-XawTreeQueryGeometry(Widget w, XtWidgetGeometry *intended,
- XtWidgetGeometry *preferred)
-{
- TreeWidget tw = (TreeWidget) w;
-
- preferred->request_mode = (CWWidth | CWHeight);
- preferred->width = tw->tree.maxwidth;
- preferred->height = tw->tree.maxheight;
-
- if (((intended->request_mode & (CWWidth | CWHeight)) ==
- (CWWidth | CWHeight)) &&
- intended->width == preferred->width &&
- intended->height == preferred->height)
- return XtGeometryYes;
- else if (preferred->width == w->core.width &&
- preferred->height == w->core.height)
- return XtGeometryNo;
- else
- return XtGeometryAlmost;
-}
-
-
-/*****************************************************************************
- * *
- * tree layout algorithm *
- * *
- * Each node in the tree is "shrink-wrapped" with a minimal bounding *
- * rectangle, laid next to its siblings (with a small about of padding in *
- * between) and then wrapped with their parent. Parents are centered about *
- * their children (or vice versa if the parent is larger than the children). *
- * *
- *****************************************************************************/
-
-static void
-compute_bounding_box_subtree(TreeWidget tree, Widget w, int depth)
-{
- TreeConstraints tc = TREE_CONSTRAINT(w); /* info attached to all kids */
- int i;
- Bool horiz = IsHorizontal (tree);
- Dimension newwidth, newheight;
- Dimension bw2 = w->core.border_width * 2;
-
- /*
- * Set the max-size per level.
- */
- if (depth >= tree->tree.n_largest) {
- initialize_dimensions (&tree->tree.largest,
- &tree->tree.n_largest, depth + 1);
- }
- newwidth = ((horiz ? w->core.width : w->core.height) + bw2);
- if (tree->tree.largest[depth] < newwidth)
- tree->tree.largest[depth] = newwidth;
-
-
- /*
- * initialize
- */
- tc->tree.bbwidth = w->core.width + bw2;
- tc->tree.bbheight = w->core.height + bw2;
-
- if (tc->tree.n_children == 0) return;
-
- /*
- * Figure the size of the opposite dimension (vertical if tree is
- * horizontal, else vice versa). The other dimension will be set
- * in the second pass once we know the maximum dimensions.
- */
- newwidth = 0;
- newheight = 0;
- for (i = 0; i < tc->tree.n_children; i++) {
- Widget child = tc->tree.children[i];
- TreeConstraints cc = TREE_CONSTRAINT(child);
-
- compute_bounding_box_subtree (tree, child, depth + 1);
-
- if (horiz) {
- if (newwidth < cc->tree.bbwidth) newwidth = cc->tree.bbwidth;
- newheight += tree->tree.vpad + cc->tree.bbheight;
- } else {
- if (newheight < cc->tree.bbheight) newheight = cc->tree.bbheight;
- newwidth += tree->tree.hpad + cc->tree.bbwidth;
- }
- }
-
-
- tc->tree.bbsubwidth = newwidth;
- tc->tree.bbsubheight = newheight;
-
- /*
- * Now fit parent onto side (or top) of bounding box and correct for
- * extra padding. Be careful of unsigned arithmetic.
- */
- if (horiz) {
- tc->tree.bbwidth += tree->tree.hpad + newwidth;
- newheight -= tree->tree.vpad;
- if (newheight > tc->tree.bbheight) tc->tree.bbheight = newheight;
- } else {
- tc->tree.bbheight += tree->tree.vpad + newheight;
- newwidth -= tree->tree.hpad;
- if (newwidth > tc->tree.bbwidth) tc->tree.bbwidth = newwidth;
- }
-}
-
-
-static void
-set_positions(TreeWidget tw, Widget w, int level)
-{
- int i;
-
- if (w) {
- TreeConstraints tc = TREE_CONSTRAINT(w);
-
- if (level > 0) {
- /*
- * mirror if necessary
- */
- switch (tw->tree.gravity) {
- case EastGravity:
- tc->tree.x = (((Position) tw->tree.maxwidth) -
- ((Position) w->core.width) - tc->tree.x);
- break;
-
- case SouthGravity:
- tc->tree.y = (((Position) tw->tree.maxheight) -
- ((Position) w->core.height) - tc->tree.y);
- break;
- }
-
- /*
- * Move the widget into position.
- */
- XtMoveWidget (w, tc->tree.x, tc->tree.y);
- }
-
- /*
- * Set the positions of all children.
- */
- for (i = 0; i < tc->tree.n_children; i++)
- set_positions (tw, tc->tree.children[i], level + 1);
- }
-}
-
-
-static void
-arrange_subtree(TreeWidget tree, Widget w, int depth, int x, int y)
-{
- TreeConstraints tc = TREE_CONSTRAINT(w); /* info attached to all kids */
- TreeConstraints firstcc, lastcc;
- int i;
- int newx, newy;
- Bool horiz = IsHorizontal (tree);
- Widget child = NULL;
- Dimension tmp;
- Dimension bw2 = w->core.border_width * 2;
- Bool relayout = True;
-
-
- /*
- * If no children, then just lay out where requested.
- */
- tc->tree.x = x;
- tc->tree.y = y;
-
- if (horiz) {
- int myh = (w->core.height + bw2);
-
- if (myh > (int)tc->tree.bbsubheight) {
- y += (myh - (int)tc->tree.bbsubheight) / 2;
- relayout = False;
- }
- } else {
- int myw = (w->core.width + bw2);
-
- if (myw > (int)tc->tree.bbsubwidth) {
- x += (myw - (int)tc->tree.bbsubwidth) / 2;
- relayout = False;
- }
- }
-
- if ((tmp = ((Dimension) x) + tc->tree.bbwidth) > tree->tree.maxwidth)
- tree->tree.maxwidth = tmp;
- if ((tmp = ((Dimension) y) + tc->tree.bbheight) > tree->tree.maxheight)
- tree->tree.maxheight = tmp;
-
- if (tc->tree.n_children == 0) return;
-
-
- /*
- * Have children, so walk down tree laying out children, then laying
- * out parents.
- */
- if (horiz) {
- newx = x + tree->tree.largest[depth];
- if (depth > 0) newx += tree->tree.hpad;
- newy = y;
- } else {
- newx = x;
- newy = y + tree->tree.largest[depth];
- if (depth > 0) newy += tree->tree.vpad;
- }
-
- for (i = 0; i < tc->tree.n_children; i++) {
- TreeConstraints cc;
-
- child = tc->tree.children[i]; /* last value is used outside loop */
- cc = TREE_CONSTRAINT(child);
-
- arrange_subtree (tree, child, depth + 1, newx, newy);
- if (horiz) {
- newy += tree->tree.vpad + cc->tree.bbheight;
- } else {
- newx += tree->tree.hpad + cc->tree.bbwidth;
- }
- }
-
- /*
- * now layout parent between first and last children
- */
- if (relayout) {
- Position adjusted;
- firstcc = TREE_CONSTRAINT (tc->tree.children[0]);
- lastcc = TREE_CONSTRAINT (child);
-
- /* Adjustments are disallowed if they result in a position above
- * or to the left of the originally requested position, because
- * this could collide with the position of the previous sibling.
- */
- if (horiz) {
- tc->tree.x = x;
- adjusted = firstcc->tree.y +
- ((lastcc->tree.y + (Position) child->core.height +
- (Position) child->core.border_width * 2 -
- firstcc->tree.y - (Position) w->core.height -
- (Position) w->core.border_width * 2 + 1) / 2);
- if (adjusted > tc->tree.y) tc->tree.y = adjusted;
- } else {
- adjusted = firstcc->tree.x +
- ((lastcc->tree.x + (Position) child->core.width +
- (Position) child->core.border_width * 2 -
- firstcc->tree.x - (Position) w->core.width -
- (Position) w->core.border_width * 2 + 1) / 2);
- if (adjusted > tc->tree.x) tc->tree.x = adjusted;
- tc->tree.y = y;
- }
- }
-}
-
-static void
-set_tree_size(TreeWidget tw, Bool insetvalues,
- unsigned int width, unsigned int height)
-{
- if (insetvalues) {
- tw->core.width = width;
- tw->core.height = height;
- } else {
- Dimension replyWidth = 0, replyHeight = 0;
- XtGeometryResult result = XtMakeResizeRequest ((Widget) tw,
- width, height,
- &replyWidth,
- &replyHeight);
- /*
- * Accept any compromise.
- */
- if (result == XtGeometryAlmost)
- XtMakeResizeRequest ((Widget) tw, replyWidth, replyHeight,
- (Dimension *) NULL, (Dimension *) NULL);
- }
- return;
-}
-
-static void
-layout_tree(TreeWidget tw, Bool insetvalues)
-{
- int i;
- Dimension *dp;
-
- /*
- * Do a depth-first search computing the width and height of the bounding
- * box for the tree at that position (and below). Then, walk again using
- * this information to layout the children at each level.
- */
-
- if (tw->tree.tree_root == NULL)
- return;
-
- tw->tree.maxwidth = tw->tree.maxheight = 0;
- for (i = 0, dp = tw->tree.largest; i < tw->tree.n_largest; i++, dp++)
- *dp = 0;
- initialize_dimensions (&tw->tree.largest, &tw->tree.n_largest,
- tw->tree.n_largest);
- compute_bounding_box_subtree (tw, tw->tree.tree_root, 0);
-
- /*
- * Second pass to do final layout. Each child's bounding box is stacked
- * on top of (if horizontal, else next to) on top of its siblings. The
- * parent is centered between the first and last children.
- */
- arrange_subtree (tw, tw->tree.tree_root, 0, 0, 0);
-
- /*
- * Move each widget into place.
- */
- set_tree_size (tw, insetvalues, tw->tree.maxwidth, tw->tree.maxheight);
- set_positions (tw, tw->tree.tree_root, 0);
-
- /*
- * And redisplay.
- */
- if (XtIsRealized ((Widget) tw)) {
- XClearArea (XtDisplay(tw), XtWindow((Widget)tw), 0, 0, 0, 0, True);
- }
-}
-
-
-
-/*****************************************************************************
- * *
- * Public Routines *
- * *
- *****************************************************************************/
-
-void
-XawTreeForceLayout(Widget tree)
-{
- layout_tree ((TreeWidget) tree, FALSE);
-}
-
+/* + +Copyright 1990, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + * Copyright 1989 Prentice Hall + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation. + * + * Prentice Hall and the authors disclaim all warranties with regard + * to this software, including all implied warranties of merchantability and + * fitness. In no event shall Prentice Hall or the authors be liable + * for any special, indirect or cosequential damages or any damages whatsoever + * resulting from loss of use, data or profits, whether in an action of + * contract, negligence or other tortious action, arising out of or in + * connection with the use or performance of this software. + * + * Authors: Jim Fulton, MIT X Consortium, + * based on a version by Douglas Young, Prentice Hall + * + * This widget is based on the Tree widget described on pages 397-419 of + * Douglas Young's book "The X Window System, Programming and Applications + * with Xt OSF/Motif Edition." The layout code has been rewritten to use + * additional blank space to make the structure of the graph easier to see + * as well as to support vertical trees. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/XawInit.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/TreeP.h> +#include "Private.h" + +#define IsHorizontal(tw) ((tw)->tree.gravity == WestGravity || \ + (tw)->tree.gravity == EastGravity) + +/* + * Class Methods + */ +static void XawTreeChangeManaged(Widget); +static void XawTreeClassInitialize(void); +static void XawTreeConstraintDestroy(Widget); +static void XawTreeConstraintInitialize(Widget, Widget, ArgList, Cardinal*); +static Boolean XawTreeConstraintSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static void XawTreeDestroy(Widget); +static XtGeometryResult XawTreeGeometryManager(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawTreeInitialize(Widget, Widget, ArgList, Cardinal*); +static XtGeometryResult XawTreeQueryGeometry(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawTreeRedisplay(Widget, XEvent*, Region); +static Boolean XawTreeSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +static void arrange_subtree(TreeWidget, Widget, int, int, int); +static void check_gravity(TreeWidget, XtGravity); +static void compute_bounding_box_subtree(TreeWidget, Widget, int); +static void delete_node(Widget, Widget); +static GC get_tree_gc(TreeWidget); +static void initialize_dimensions(Dimension**, int*, int); +static void insert_node(Widget, Widget); +static void layout_tree(TreeWidget, Bool); +static void set_positions(TreeWidget, Widget, int); +static void set_tree_size(TreeWidget, Bool, unsigned int, unsigned int); + +/* + * Initialization + */ + +/* + * resources of the tree itself + */ +static XtResource resources[] = { + { XtNautoReconfigure, XtCAutoReconfigure, XtRBoolean, sizeof (Boolean), + XtOffsetOf(TreeRec, tree.auto_reconfigure), XtRImmediate, + (XtPointer) FALSE }, + { XtNhSpace, XtCHSpace, XtRDimension, sizeof (Dimension), + XtOffsetOf(TreeRec, tree.hpad), XtRImmediate, (XtPointer) 0 }, + { XtNvSpace, XtCVSpace, XtRDimension, sizeof (Dimension), + XtOffsetOf(TreeRec, tree.vpad), XtRImmediate, (XtPointer) 0 }, + { XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), + XtOffsetOf(TreeRec, tree.foreground), XtRString, + XtDefaultForeground}, + { XtNlineWidth, XtCLineWidth, XtRDimension, sizeof (Dimension), + XtOffsetOf(TreeRec, tree.line_width), XtRImmediate, (XtPointer) 0 }, + { XtNgravity, XtCGravity, XtRGravity, sizeof (XtGravity), + XtOffsetOf(TreeRec, tree.gravity), XtRImmediate, + (XtPointer) WestGravity }, +#ifndef OLDXAW + { XawNdisplayList, XawCDisplayList, XawRDisplayList, sizeof(XawDisplayList*), + XtOffsetOf(TreeRec, tree.display_list), XtRImmediate, + NULL }, +#endif +}; + + +/* + * resources that are attached to all children of the tree + */ +static XtResource treeConstraintResources[] = { + { XtNtreeParent, XtCTreeParent, XtRWidget, sizeof (Widget), + XtOffsetOf(TreeConstraintsRec, tree.parent), XtRImmediate, NULL }, + { XtNtreeGC, XtCTreeGC, XtRGC, sizeof(GC), + XtOffsetOf(TreeConstraintsRec, tree.gc), XtRImmediate, NULL }, +}; + + +TreeClassRec treeClassRec = { + { + /* core_class fields */ + (WidgetClass) &constraintClassRec, /* superclass */ + "Tree", /* class_name */ + sizeof(TreeRec), /* widget_size */ + XawTreeClassInitialize, /* class_init */ + NULL, /* class_part_init */ + FALSE, /* class_inited */ + XawTreeInitialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + TRUE, /* compress_motion */ + TRUE, /* compress_exposure */ + TRUE, /* compress_enterleave*/ + TRUE, /* visible_interest */ + XawTreeDestroy, /* destroy */ + NULL, /* resize */ + XawTreeRedisplay, /* expose */ + XawTreeSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XawTreeQueryGeometry, /* query_geometry */ + NULL, /* display_accelerator*/ + NULL, /* extension */ + }, + { + /* composite_class fields */ + XawTreeGeometryManager, /* geometry_manager */ + XawTreeChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + { + /* constraint_class fields */ + treeConstraintResources, /* subresources */ + XtNumber(treeConstraintResources), /* subresource_count */ + sizeof(TreeConstraintsRec), /* constraint_size */ + XawTreeConstraintInitialize, /* initialize */ + XawTreeConstraintDestroy, /* destroy */ + XawTreeConstraintSetValues, /* set_values */ + NULL, /* extension */ + }, + { + /* Tree class fields */ + NULL, /* ignore */ + } +}; + +WidgetClass treeWidgetClass = (WidgetClass) &treeClassRec; + + +/***************************************************************************** + * * + * tree utility routines * + * * + *****************************************************************************/ + +static void +initialize_dimensions(Dimension **listp, int *sizep, int n) +{ + int i; + Dimension *l; + + if (!*listp) { + *listp = (Dimension *) XtCalloc ((unsigned int) n, + (unsigned int) sizeof(Dimension)); + *sizep = ((*listp) ? n : 0); + return; + } + if (n > *sizep) { + *listp = (Dimension *) XtRealloc((char *) *listp, + (unsigned int) (n*sizeof(Dimension))); + if (!*listp) { + *sizep = 0; + return; + } + for (i = *sizep, l = (*listp) + i; i < n; i++, l++) *l = 0; + *sizep = n; + } + return; +} + +static GC +get_tree_gc(TreeWidget w) +{ + XtGCMask valuemask = GCBackground | GCForeground; + XGCValues values; + + values.background = w->core.background_pixel; + values.foreground = w->tree.foreground; + if (w->tree.line_width != 0) { + valuemask |= GCLineWidth; + values.line_width = w->tree.line_width; + } + + return XtGetGC ((Widget) w, valuemask, &values); +} + +static void +insert_node(Widget parent, Widget node) +{ + TreeConstraints pc; + TreeConstraints nc = TREE_CONSTRAINT(node); + int nindex; + + nc->tree.parent = parent; + + if (parent == NULL) return; + + /* + * If there isn't more room in the children array, + * allocate additional space. + */ + pc = TREE_CONSTRAINT(parent); + nindex = pc->tree.n_children; + + if (pc->tree.n_children == pc->tree.max_children) { + pc->tree.max_children += (pc->tree.max_children / 2) + 2; + pc->tree.children = (WidgetList) XtRealloc ((char *)pc->tree.children, + (unsigned int) + ((pc->tree.max_children) * + sizeof(Widget))); + } + + /* + * Add the sub_node in the next available slot and + * increment the counter. + */ + pc->tree.children[nindex] = node; + pc->tree.n_children++; +} + +static void +delete_node(Widget parent, Widget node) +{ + TreeConstraints pc; + int pos, i; + + /* + * Make sure the parent exists. + */ + if (!parent) return; + + pc = TREE_CONSTRAINT(parent); + + /* + * Find the sub_node on its parent's list. + */ + for (pos = 0; pos < pc->tree.n_children; pos++) + if (pc->tree.children[pos] == node) break; + + if (pos == pc->tree.n_children) return; + + /* + * Decrement the number of children + */ + pc->tree.n_children--; + + /* + * Fill in the gap left by the sub_node. + * Zero the last slot for good luck. + */ + for (i = pos; i < pc->tree.n_children; i++) + pc->tree.children[i] = pc->tree.children[i+1]; + + pc->tree.children[pc->tree.n_children] = NULL; +} + +static void +check_gravity(TreeWidget tw, XtGravity grav) +{ + switch (tw->tree.gravity) { + case WestGravity: case NorthGravity: case EastGravity: case SouthGravity: + break; + default: + tw->tree.gravity = grav; + break; + } +} + + +/***************************************************************************** + * * + * tree class methods * + * * + *****************************************************************************/ + +static void +XawTreeClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity, NULL, 0); + XtSetTypeConverter(XtRGravity, XtRString, XmuCvtGravityToString, + NULL, 0, XtCacheNone, NULL); +} + + +/*ARGSUSED*/ +static void +XawTreeInitialize(Widget grequest, Widget gnew, + ArgList args, Cardinal *num_args) +{ + TreeWidget request = (TreeWidget) grequest, cnew = (TreeWidget) gnew; + Arg arglist[2]; + + /* + * Make sure the widget's width and height are + * greater than zero. + */ + if (request->core.width <= 0) cnew->core.width = 5; + if (request->core.height <= 0) cnew->core.height = 5; + + /* + * Set the padding according to the orientation + */ + if (request->tree.hpad == 0 && request->tree.vpad == 0) { + if (IsHorizontal (request)) { + cnew->tree.hpad = TREE_HORIZONTAL_DEFAULT_SPACING; + cnew->tree.vpad = TREE_VERTICAL_DEFAULT_SPACING; + } else { + cnew->tree.hpad = TREE_VERTICAL_DEFAULT_SPACING; + cnew->tree.vpad = TREE_HORIZONTAL_DEFAULT_SPACING; + } + } + + /* + * Create a graphics context for the connecting lines. + */ + cnew->tree.gc = get_tree_gc (cnew); + + /* + * Create the hidden root widget. + */ + cnew->tree.tree_root = (Widget) NULL; + XtSetArg(arglist[0], XtNwidth, 1); + XtSetArg(arglist[1], XtNheight, 1); + cnew->tree.tree_root = XtCreateWidget ("root", widgetClass, gnew, + arglist,TWO); + + /* + * Allocate the array used to hold the widest values per depth + */ + cnew->tree.largest = NULL; + cnew->tree.n_largest = 0; + initialize_dimensions (&cnew->tree.largest, &cnew->tree.n_largest, + TREE_INITIAL_DEPTH); + + /* + * make sure that our gravity is one of the acceptable values + */ + check_gravity (cnew, WestGravity); +} + + +/* ARGSUSED */ +static void +XawTreeConstraintInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + TreeConstraints tc = TREE_CONSTRAINT(cnew); + TreeWidget tw = (TreeWidget) cnew->core.parent; + + /* + * Initialize the widget to have no sub-nodes. + */ + tc->tree.n_children = 0; + tc->tree.max_children = 0; + tc->tree.children = (Widget *) NULL; + tc->tree.x = tc->tree.y = 0; + tc->tree.bbsubwidth = 0; + tc->tree.bbsubheight = 0; + + + /* + * If this widget has a super-node, add it to that + * widget' sub-nodes list. Otherwise make it a sub-node of + * the tree_root widget. + */ + if (tc->tree.parent) + insert_node (tc->tree.parent, cnew); + else if (tw->tree.tree_root) + insert_node (tw->tree.tree_root, cnew); +} + + +/* ARGSUSED */ +static Boolean +XawTreeSetValues(Widget gcurrent, Widget grequest, Widget gnew, + ArgList args, Cardinal *num_args) +{ + TreeWidget current = (TreeWidget) gcurrent, cnew = (TreeWidget) gnew; + Boolean redraw = FALSE; + + /* + * If the foreground color has changed, redo the GC's + * and indicate a redraw. + */ + if (cnew->tree.foreground != current->tree.foreground || + cnew->core.background_pixel != current->core.background_pixel || + cnew->tree.line_width != current->tree.line_width) { + XtReleaseGC (gnew, cnew->tree.gc); + cnew->tree.gc = get_tree_gc (cnew); + redraw = TRUE; + } + + /* + * If the minimum spacing has changed, recalculate the + * tree layout. layout_tree() does a redraw, so we don't + * need SetValues to do another one. + */ + if (cnew->tree.gravity != current->tree.gravity) { + check_gravity (cnew, current->tree.gravity); + } + + if (IsHorizontal(cnew) != IsHorizontal(current)) { + if (cnew->tree.vpad == current->tree.vpad && + cnew->tree.hpad == current->tree.hpad) { + cnew->tree.vpad = current->tree.hpad; + cnew->tree.hpad = current->tree.vpad; + } + } + + if (cnew->tree.vpad != current->tree.vpad || + cnew->tree.hpad != current->tree.hpad || + cnew->tree.gravity != current->tree.gravity) { + layout_tree (cnew, TRUE); + redraw = FALSE; + } + return redraw; +} + + +/* ARGSUSED */ +static Boolean +XawTreeConstraintSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + TreeConstraints newc = TREE_CONSTRAINT(cnew); + TreeConstraints curc = TREE_CONSTRAINT(current); + TreeWidget tw = (TreeWidget) cnew->core.parent; + + /* + * If the parent field has changed, remove the widget + * from the old widget's children list and add it to the + * new one. + */ + if (curc->tree.parent != newc->tree.parent){ + if (curc->tree.parent) + delete_node (curc->tree.parent, cnew); + if (newc->tree.parent) + insert_node(newc->tree.parent, cnew); + + /* + * If the Tree widget has been realized, + * compute new layout. + */ + if (XtIsRealized((Widget)tw)) + layout_tree (tw, FALSE); + } + return False; +} + + +static void +XawTreeConstraintDestroy(Widget w) +{ + TreeConstraints tc = TREE_CONSTRAINT(w); + TreeWidget tw = (TreeWidget) XtParent(w); + int i; + + /* + * Remove the widget from its parent's sub-nodes list and + * make all this widget's sub-nodes sub-nodes of the parent. + */ + + if (tw->tree.tree_root == w) { + if (tc->tree.n_children > 0) + tw->tree.tree_root = tc->tree.children[0]; + else + tw->tree.tree_root = NULL; + } + + delete_node (tc->tree.parent, (Widget) w); + for (i = 0; i< tc->tree.n_children; i++) + insert_node (tc->tree.parent, tc->tree.children[i]); + + layout_tree ((TreeWidget) (w->core.parent), FALSE); +} + +/* ARGSUSED */ +static XtGeometryResult +XawTreeGeometryManager(Widget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + + TreeWidget tw = (TreeWidget) w->core.parent; + + /* + * No position changes allowed!. + */ + if ((request->request_mode & CWX && request->x!=w->core.x) + ||(request->request_mode & CWY && request->y!=w->core.y)) + return (XtGeometryNo); + + /* + * Allow all resize requests. + */ + + if (request->request_mode & CWWidth) + w->core.width = request->width; + if (request->request_mode & CWHeight) + w->core.height = request->height; + if (request->request_mode & CWBorderWidth) + w->core.border_width = request->border_width; + + if (tw->tree.auto_reconfigure) layout_tree (tw, FALSE); + return (XtGeometryYes); +} + +static void +XawTreeChangeManaged(Widget gw) +{ + layout_tree ((TreeWidget) gw, FALSE); +} + + +static void +XawTreeDestroy(Widget gw) +{ + TreeWidget w = (TreeWidget) gw; + + XtReleaseGC (gw, w->tree.gc); + if (w->tree.largest) XtFree ((char *) w->tree.largest); +} + + +/* ARGSUSED */ +static void +XawTreeRedisplay(Widget gw, XEvent *event, Region region) +{ + TreeWidget tw = (TreeWidget) gw; + +#ifndef OLDXAW + if (tw->tree.display_list) + XawRunDisplayList(gw, tw->tree.display_list, event, region); +#endif + + /* + * If the Tree widget is visible, visit each managed child. + */ + if (tw->core.visible) { + Cardinal i; + int j; + Display *dpy = XtDisplay (tw); + Window w = XtWindow (tw); + + for (i = 0; i < tw->composite.num_children; i++) { + Widget child = tw->composite.children[i]; + TreeConstraints tc = TREE_CONSTRAINT(child); + + /* + * Don't draw lines from the fake tree_root. + */ + if (child != tw->tree.tree_root && tc->tree.n_children) { + int srcx = child->core.x + child->core.border_width; + int srcy = child->core.y + child->core.border_width; + + switch (tw->tree.gravity) { + case WestGravity: + srcx += child->core.width + child->core.border_width; + /* fall through */ + case EastGravity: + srcy += child->core.height / 2; + break; + + case NorthGravity: + srcy += child->core.height + child->core.border_width; + /* fall through */ + case SouthGravity: + srcx += child->core.width / 2; + break; + } + + for (j = 0; j < tc->tree.n_children; j++) { + Widget k = tc->tree.children[j]; + GC gc = (tc->tree.gc ? tc->tree.gc : tw->tree.gc); + + switch (tw->tree.gravity) { + case WestGravity: + /* + * right center to left center + */ + XDrawLine (dpy, w, gc, srcx, srcy, + (int) k->core.x, + (k->core.y + ((int) k->core.border_width) + + ((int) k->core.height) / 2)); + break; + + case NorthGravity: + /* + * bottom center to top center + */ + XDrawLine (dpy, w, gc, srcx, srcy, + (k->core.x + ((int) k->core.border_width) + + ((int) k->core.width) / 2), + (int) k->core.y); + break; + + case EastGravity: + /* + * left center to right center + */ + XDrawLine (dpy, w, gc, srcx, srcy, + (k->core.x + + (((int) k->core.border_width) << 1) + + (int) k->core.width), + (k->core.y + ((int) k->core.border_width) + + ((int) k->core.height) / 2)); + break; + + case SouthGravity: + /* + * top center to bottom center + */ + XDrawLine (dpy, w, gc, srcx, srcy, + (k->core.x + ((int) k->core.border_width) + + ((int) k->core.width) / 2), + (k->core.y + + (((int) k->core.border_width) << 1) + + (int) k->core.height)); + break; + } + } + } + } + } +} + +static XtGeometryResult +XawTreeQueryGeometry(Widget w, XtWidgetGeometry *intended, + XtWidgetGeometry *preferred) +{ + TreeWidget tw = (TreeWidget) w; + + preferred->request_mode = (CWWidth | CWHeight); + preferred->width = tw->tree.maxwidth; + preferred->height = tw->tree.maxheight; + + if (((intended->request_mode & (CWWidth | CWHeight)) == + (CWWidth | CWHeight)) && + intended->width == preferred->width && + intended->height == preferred->height) + return XtGeometryYes; + else if (preferred->width == w->core.width && + preferred->height == w->core.height) + return XtGeometryNo; + else + return XtGeometryAlmost; +} + + +/***************************************************************************** + * * + * tree layout algorithm * + * * + * Each node in the tree is "shrink-wrapped" with a minimal bounding * + * rectangle, laid next to its siblings (with a small about of padding in * + * between) and then wrapped with their parent. Parents are centered about * + * their children (or vice versa if the parent is larger than the children). * + * * + *****************************************************************************/ + +static void +compute_bounding_box_subtree(TreeWidget tree, Widget w, int depth) +{ + TreeConstraints tc = TREE_CONSTRAINT(w); /* info attached to all kids */ + int i; + Bool horiz = IsHorizontal (tree); + Dimension newwidth, newheight; + Dimension bw2 = w->core.border_width * 2; + + /* + * Set the max-size per level. + */ + if (depth >= tree->tree.n_largest) { + initialize_dimensions (&tree->tree.largest, + &tree->tree.n_largest, depth + 1); + } + newwidth = ((horiz ? w->core.width : w->core.height) + bw2); + if (tree->tree.largest[depth] < newwidth) + tree->tree.largest[depth] = newwidth; + + + /* + * initialize + */ + tc->tree.bbwidth = w->core.width + bw2; + tc->tree.bbheight = w->core.height + bw2; + + if (tc->tree.n_children == 0) return; + + /* + * Figure the size of the opposite dimension (vertical if tree is + * horizontal, else vice versa). The other dimension will be set + * in the second pass once we know the maximum dimensions. + */ + newwidth = 0; + newheight = 0; + for (i = 0; i < tc->tree.n_children; i++) { + Widget child = tc->tree.children[i]; + TreeConstraints cc = TREE_CONSTRAINT(child); + + compute_bounding_box_subtree (tree, child, depth + 1); + + if (horiz) { + if (newwidth < cc->tree.bbwidth) newwidth = cc->tree.bbwidth; + newheight += tree->tree.vpad + cc->tree.bbheight; + } else { + if (newheight < cc->tree.bbheight) newheight = cc->tree.bbheight; + newwidth += tree->tree.hpad + cc->tree.bbwidth; + } + } + + + tc->tree.bbsubwidth = newwidth; + tc->tree.bbsubheight = newheight; + + /* + * Now fit parent onto side (or top) of bounding box and correct for + * extra padding. Be careful of unsigned arithmetic. + */ + if (horiz) { + tc->tree.bbwidth += tree->tree.hpad + newwidth; + newheight -= tree->tree.vpad; + if (newheight > tc->tree.bbheight) tc->tree.bbheight = newheight; + } else { + tc->tree.bbheight += tree->tree.vpad + newheight; + newwidth -= tree->tree.hpad; + if (newwidth > tc->tree.bbwidth) tc->tree.bbwidth = newwidth; + } +} + + +static void +set_positions(TreeWidget tw, Widget w, int level) +{ + int i; + + if (w) { + TreeConstraints tc = TREE_CONSTRAINT(w); + + if (level > 0) { + /* + * mirror if necessary + */ + switch (tw->tree.gravity) { + case EastGravity: + tc->tree.x = (((Position) tw->tree.maxwidth) - + ((Position) w->core.width) - tc->tree.x); + break; + + case SouthGravity: + tc->tree.y = (((Position) tw->tree.maxheight) - + ((Position) w->core.height) - tc->tree.y); + break; + } + + /* + * Move the widget into position. + */ + XtMoveWidget (w, tc->tree.x, tc->tree.y); + } + + /* + * Set the positions of all children. + */ + for (i = 0; i < tc->tree.n_children; i++) + set_positions (tw, tc->tree.children[i], level + 1); + } +} + + +static void +arrange_subtree(TreeWidget tree, Widget w, int depth, int x, int y) +{ + TreeConstraints tc = TREE_CONSTRAINT(w); /* info attached to all kids */ + TreeConstraints firstcc, lastcc; + int i; + int newx, newy; + Bool horiz = IsHorizontal (tree); + Widget child = NULL; + Dimension tmp; + Dimension bw2 = w->core.border_width * 2; + Bool relayout = True; + + + /* + * If no children, then just lay out where requested. + */ + tc->tree.x = x; + tc->tree.y = y; + + if (horiz) { + int myh = (w->core.height + bw2); + + if (myh > (int)tc->tree.bbsubheight) { + y += (myh - (int)tc->tree.bbsubheight) / 2; + relayout = False; + } + } else { + int myw = (w->core.width + bw2); + + if (myw > (int)tc->tree.bbsubwidth) { + x += (myw - (int)tc->tree.bbsubwidth) / 2; + relayout = False; + } + } + + if ((tmp = ((Dimension) x) + tc->tree.bbwidth) > tree->tree.maxwidth) + tree->tree.maxwidth = tmp; + if ((tmp = ((Dimension) y) + tc->tree.bbheight) > tree->tree.maxheight) + tree->tree.maxheight = tmp; + + if (tc->tree.n_children == 0) return; + + + /* + * Have children, so walk down tree laying out children, then laying + * out parents. + */ + if (horiz) { + newx = x + tree->tree.largest[depth]; + if (depth > 0) newx += tree->tree.hpad; + newy = y; + } else { + newx = x; + newy = y + tree->tree.largest[depth]; + if (depth > 0) newy += tree->tree.vpad; + } + + for (i = 0; i < tc->tree.n_children; i++) { + TreeConstraints cc; + + child = tc->tree.children[i]; /* last value is used outside loop */ + cc = TREE_CONSTRAINT(child); + + arrange_subtree (tree, child, depth + 1, newx, newy); + if (horiz) { + newy += tree->tree.vpad + cc->tree.bbheight; + } else { + newx += tree->tree.hpad + cc->tree.bbwidth; + } + } + + /* + * now layout parent between first and last children + */ + if (relayout) { + Position adjusted; + firstcc = TREE_CONSTRAINT (tc->tree.children[0]); + lastcc = TREE_CONSTRAINT (child); + + /* Adjustments are disallowed if they result in a position above + * or to the left of the originally requested position, because + * this could collide with the position of the previous sibling. + */ + if (horiz) { + tc->tree.x = x; + adjusted = firstcc->tree.y + + ((lastcc->tree.y + (Position) child->core.height + + (Position) child->core.border_width * 2 - + firstcc->tree.y - (Position) w->core.height - + (Position) w->core.border_width * 2 + 1) / 2); + if (adjusted > tc->tree.y) tc->tree.y = adjusted; + } else { + adjusted = firstcc->tree.x + + ((lastcc->tree.x + (Position) child->core.width + + (Position) child->core.border_width * 2 - + firstcc->tree.x - (Position) w->core.width - + (Position) w->core.border_width * 2 + 1) / 2); + if (adjusted > tc->tree.x) tc->tree.x = adjusted; + tc->tree.y = y; + } + } +} + +static void +set_tree_size(TreeWidget tw, Bool insetvalues, + unsigned int width, unsigned int height) +{ + if (insetvalues) { + tw->core.width = width; + tw->core.height = height; + } else { + Dimension replyWidth = 0, replyHeight = 0; + XtGeometryResult result = XtMakeResizeRequest ((Widget) tw, + width, height, + &replyWidth, + &replyHeight); + /* + * Accept any compromise. + */ + if (result == XtGeometryAlmost) + XtMakeResizeRequest ((Widget) tw, replyWidth, replyHeight, + (Dimension *) NULL, (Dimension *) NULL); + } + return; +} + +static void +layout_tree(TreeWidget tw, Bool insetvalues) +{ + int i; + Dimension *dp; + + /* + * Do a depth-first search computing the width and height of the bounding + * box for the tree at that position (and below). Then, walk again using + * this information to layout the children at each level. + */ + + if (tw->tree.tree_root == NULL) + return; + + tw->tree.maxwidth = tw->tree.maxheight = 0; + for (i = 0, dp = tw->tree.largest; i < tw->tree.n_largest; i++, dp++) + *dp = 0; + initialize_dimensions (&tw->tree.largest, &tw->tree.n_largest, + tw->tree.n_largest); + compute_bounding_box_subtree (tw, tw->tree.tree_root, 0); + + /* + * Second pass to do final layout. Each child's bounding box is stacked + * on top of (if horizontal, else next to) on top of its siblings. The + * parent is centered between the first and last children. + */ + arrange_subtree (tw, tw->tree.tree_root, 0, 0, 0); + + /* + * Move each widget into place. + */ + set_tree_size (tw, insetvalues, tw->tree.maxwidth, tw->tree.maxheight); + set_positions (tw, tw->tree.tree_root, 0); + + /* + * And redisplay. + */ + if (XtIsRealized ((Widget) tw)) { + XClearArea (XtDisplay(tw), XtWindow((Widget)tw), 0, 0, 0, 0, True); + } +} + + + +/***************************************************************************** + * * + * Public Routines * + * * + *****************************************************************************/ + +void +XawTreeForceLayout(Widget tree) +{ + layout_tree ((TreeWidget) tree, FALSE); +} + diff --git a/libXaw/src/Vendor.c b/libXaw/src/Vendor.c index 88398906f..c73d17fe7 100644 --- a/libXaw/src/Vendor.c +++ b/libXaw/src/Vendor.c @@ -1,524 +1,524 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
- * This is a copy of Xt/Vendor.c with an additional ClassInitialize
- * procedure to register Xmu resource type converters, and all the
- * monkey business associated with input methods...
- *
- */
-
-/* Make sure all wm properties can make it out of the resource manager */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/ShellP.h>
-#include <X11/VendorP.h>
-#include <X11/Xmu/Converters.h>
-#include <X11/Xmu/Atoms.h>
-#include <X11/Xmu/Editres.h>
-#include <X11/Xmu/ExtAgent.h>
-
-/* The following two headers are for the input method. */
-
-#include <X11/Xaw/VendorEP.h>
-#include <X11/Xaw/XawImP.h>
-
-/*
- * Class Methods
- */
-static void XawVendorShellChangeManaged(Widget);
-static Boolean XawCvtCompoundTextToString(Display*, XrmValuePtr, Cardinal*,
- XrmValue*, XrmValue*, XtPointer*);
-static void XawVendorShellClassInitialize(void);
-static XtGeometryResult XawVendorShellGeometryManager(Widget,
- XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawVendorShellExtClassInitialize(void);
-static void XawVendorShellExtDestroy(Widget);
-static void XawVendorShellExtInitialize(Widget, Widget, ArgList, Cardinal*);
-void XawVendorShellExtResize(Widget);
-static Boolean XawVendorShellExtSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-static void XawVendorShellClassPartInit(WidgetClass);
-static void XawVendorShellInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawVendorShellRealize(Widget, Mask*, XSetWindowAttributes*);
-static Boolean XawVendorShellSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * External
- */
-void XawVendorStructureNotifyHandler(Widget, XtPointer, XEvent*, Boolean*);
-
-static XtResource resources[] = {
- {XtNinput, XtCInput, XtRBool, sizeof(Bool),
- XtOffsetOf(VendorShellRec, wm.wm_hints.input),
- XtRImmediate, (XtPointer)True}
-};
-
-/***************************************************************************
- *
- * Vendor shell class record
- *
- ***************************************************************************/
-
-#if defined(__UNIXOS2__) || defined(__CYGWIN__) || defined(__MINGW32__)
-/* to fix the EditRes problem because of wrong linker semantics */
-extern WidgetClass vendorShellWidgetClass; /* from Xt/Vendor.c */
-extern VendorShellClassRec _XawVendorShellClassRec;
-extern void _XawFixupVendorShell();
-
-#if defined(__UNIXOS2__)
-unsigned long _DLL_InitTerm(unsigned long mod,unsigned long flag)
-{
- switch (flag) {
- case 0: /*called on init*/
- _CRT_init();
- vendorShellWidgetClass = (WidgetClass)(&_XawVendorShellClassRec);
- _XawFixupVendorShell();
- return 1;
- case 1: /*called on exit*/
- return 1;
- default:
- return 0;
- }
-}
-#endif
-
-#if defined(__CYGWIN__) || defined(__MINGW32__) && !defined(_MSC_VER)
-int __stdcall
-DllMain(unsigned long mod_handle, unsigned long flag, void *routine)
-{
- switch (flag)
- {
- case 1: /* DLL_PROCESS_ATTACH - process attach */
- vendorShellWidgetClass = (WidgetClass)(&_XawVendorShellClassRec);
- _XawFixupVendorShell();
- break;
- case 0: /* DLL_PROCESS_DETACH - process detach */
- break;
- }
- return 1;
-}
-#endif
-
-#define vendorShellClassRec _XawVendorShellClassRec
-
-#endif
-
-static CompositeClassExtensionRec vendorCompositeExt = {
- /* next_extension */ NULL,
- /* record_type */ NULLQUARK,
- /* version */ XtCompositeExtensionVersion,
- /* record_size */ sizeof (CompositeClassExtensionRec),
- /* accepts_objects */ TRUE,
- /* allows_change_managed_set */ FALSE
-};
-
-#define SuperClass (&wmShellClassRec)
-externaldef(vendorshellclassrec) VendorShellClassRec vendorShellClassRec = {
- {
- /* superclass */ (WidgetClass)SuperClass,
- /* class_name */ "VendorShell",
- /* size */ sizeof(VendorShellRec),
- /* class_initialize */ XawVendorShellClassInitialize,
- /* class_part_init */ XawVendorShellClassPartInit,
- /* Class init'ed ? */ FALSE,
- /* initialize */ XawVendorShellInitialize,
- /* initialize_hook */ NULL,
- /* realize */ XawVendorShellRealize,
- /* actions */ NULL,
- /* num_actions */ 0,
- /* resources */ resources,
- /* resource_count */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ FALSE,
- /* compress_exposure */ TRUE,
- /* compress_enterleave*/ FALSE,
- /* visible_interest */ FALSE,
- /* destroy */ NULL,
- /* resize */ XawVendorShellExtResize,
- /* expose */ NULL,
- /* set_values */ XawVendorShellSetValues,
- /* set_values_hook */ NULL,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ NULL,
- /* accept_focus */ NULL,
- /* intrinsics version */ XtVersion,
- /* callback offsets */ NULL,
- /* tm_table */ NULL,
- /* query_geometry */ NULL,
- /* display_accelerator*/ NULL,
- /* extension */ NULL
- },{
- /* geometry_manager */ XawVendorShellGeometryManager,
- /* change_managed */ XawVendorShellChangeManaged,
- /* insert_child */ XtInheritInsertChild,
- /* delete_child */ XtInheritDeleteChild,
- /* extension */ (XtPointer) &vendorCompositeExt
- },{
- /* extension */ NULL
- },{
- /* extension */ NULL
- },{
- /* extension */ NULL
- }
-};
-
-#ifndef __UNIXOS2__
-externaldef(vendorshellwidgetclass) WidgetClass vendorShellWidgetClass =
- (WidgetClass) (&vendorShellClassRec);
-#endif
-
-/***************************************************************************
- *
- * The following section is for the Vendor shell Extension class record
- *
- ***************************************************************************/
-
-static XtResource ext_resources[] = {
- {XtNinputMethod, XtCInputMethod, XtRString, sizeof(String),
- XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.input_method),
- XtRString, (XtPointer)NULL},
- {XtNpreeditType, XtCPreeditType, XtRString, sizeof(String),
- XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.preedit_type),
- XtRString, (XtPointer)"OverTheSpot,OffTheSpot,Root"},
- {XtNopenIm, XtCOpenIm, XtRBoolean, sizeof(Boolean),
- XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.open_im),
- XtRImmediate, (XtPointer)TRUE},
- {XtNsharedIc, XtCSharedIc, XtRBoolean, sizeof(Boolean),
- XtOffsetOf(XawVendorShellExtRec, vendor_ext.ic.shared_ic),
- XtRImmediate, (XtPointer)FALSE}
-};
-
-externaldef(vendorshellextclassrec) XawVendorShellExtClassRec
- xawvendorShellExtClassRec = {
- {
- /* superclass */ (WidgetClass)&objectClassRec,
- /* class_name */ "VendorShellExt",
- /* size */ sizeof(XawVendorShellExtRec),
- /* class_initialize */ XawVendorShellExtClassInitialize,
- /* class_part_initialize*/ NULL,
- /* Class init'ed ? */ FALSE,
- /* initialize */ XawVendorShellExtInitialize,
- /* initialize_hook */ NULL,
- /* pad */ NULL,
- /* pad */ NULL,
- /* pad */ 0,
- /* resources */ ext_resources,
- /* resource_count */ XtNumber(ext_resources),
- /* xrm_class */ NULLQUARK,
- /* pad */ FALSE,
- /* pad */ FALSE,
- /* pad */ FALSE,
- /* pad */ FALSE,
- /* destroy */ XawVendorShellExtDestroy,
- /* pad */ NULL,
- /* pad */ NULL,
- /* set_values */ XawVendorShellExtSetValues,
- /* set_values_hook */ NULL,
- /* pad */ NULL,
- /* get_values_hook */ NULL,
- /* pad */ NULL,
- /* version */ XtVersion,
- /* callback_offsets */ NULL,
- /* pad */ NULL,
- /* pad */ NULL,
- /* pad */ NULL,
- /* extension */ NULL
- },{
- /* extension */ NULL
- }
-};
-
-externaldef(xawvendorshellwidgetclass) WidgetClass
- xawvendorShellExtWidgetClass = (WidgetClass) (&xawvendorShellExtClassRec);
-
-
-/*ARGSUSED*/
-static Boolean
-XawCvtCompoundTextToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
- XrmValue *fromVal, XrmValue *toVal,
- XtPointer *cvt_data)
-{
- XTextProperty prop;
- char **list;
- int count;
- static char *mbs = NULL;
- int len;
-
- prop.value = (unsigned char *)fromVal->addr;
- prop.encoding = XA_COMPOUND_TEXT(dpy);
- prop.format = 8;
- prop.nitems = fromVal->size;
-
- if(XmbTextPropertyToTextList(dpy, &prop, &list, &count) < Success) {
- XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
- "converter", "XmbTextPropertyToTextList", "XawError",
- "conversion from CT to MB failed.", NULL, NULL);
- return False;
- }
- len = strlen(*list);
- toVal->size = len;
- mbs = XtRealloc(mbs, len + 1); /* keep buffer because no one call free :( */
- strcpy(mbs, *list);
- XFreeStringList(list);
- toVal->addr = (XtPointer)mbs;
- return True;
-}
-
-static void
-XawVendorShellClassInitialize(void)
-{
- static XtConvertArgRec screenConvertArg[] = {
- {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen),
- sizeof(Screen *)}
- };
-
- XtAddConverter(XtRString, XtRCursor, XmuCvtStringToCursor,
- screenConvertArg, XtNumber(screenConvertArg));
-
- XtAddConverter(XtRString, XtRBitmap, XmuCvtStringToBitmap,
- screenConvertArg, XtNumber(screenConvertArg));
-
- XtSetTypeConverter("CompoundText", XtRString, XawCvtCompoundTextToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-static void
-XawVendorShellClassPartInit(WidgetClass cclass)
-{
- CompositeClassExtension ext;
- VendorShellWidgetClass vsclass = (VendorShellWidgetClass)cclass;
-
- if ((ext = (CompositeClassExtension)
- XtGetClassExtension (cclass,
- XtOffsetOf(CompositeClassRec,
- composite_class.extension),
- NULLQUARK, 1L, (Cardinal) 0)) == NULL) {
- ext = (CompositeClassExtension) XtNew (CompositeClassExtensionRec);
- if (ext != NULL) {
- ext->next_extension = vsclass->composite_class.extension;
- ext->record_type = NULLQUARK;
- ext->version = XtCompositeExtensionVersion;
- ext->record_size = sizeof (CompositeClassExtensionRec);
- ext->accepts_objects = TRUE;
- ext->allows_change_managed_set = FALSE;
- vsclass->composite_class.extension = (XtPointer) ext;
- }
- }
-}
-
-#if defined(__osf__) || defined(__UNIXOS2__) || defined(__CYGWIN__) || defined(__MINGW32__)
-/* stupid OSF/1 shared libraries have the wrong semantics */
-/* symbols do not get resolved external to the shared library */
-void _XawFixupVendorShell()
-{
- transientShellWidgetClass->core_class.superclass =
- (WidgetClass) &vendorShellClassRec;
- topLevelShellWidgetClass->core_class.superclass =
- (WidgetClass) &vendorShellClassRec;
-}
-#endif
-
-/* ARGSUSED */
-static void
-XawVendorShellInitialize(Widget req, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- XtAddEventHandler(cnew, (EventMask) 0, TRUE, _XEditResCheckMessages, NULL);
- XtAddEventHandler(cnew, (EventMask) 0, TRUE, XmuRegisterExternalAgent, NULL);
- XtCreateWidget("shellext", xawvendorShellExtWidgetClass,
- cnew, args, *num_args);
-}
-
-/* ARGSUSED */
-static Boolean
-XawVendorShellSetValues(Widget old, Widget ref, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- return FALSE;
-}
-
-static void
-XawVendorShellRealize(Widget wid, Mask *vmask, XSetWindowAttributes *attr)
-{
- WidgetClass super = wmShellWidgetClass;
-
- /* Make my superclass do all the dirty work */
-
- (*super->core_class.realize) (wid, vmask, attr);
- _XawImRealize(wid);
-}
-
-
-static void
-XawVendorShellExtClassInitialize(void)
-{
-}
-
-/* ARGSUSED */
-static void
-XawVendorShellExtInitialize(Widget req, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- _XawImInitialize(cnew->core.parent, cnew);
-}
-
-/* ARGSUSED */
-static void
-XawVendorShellExtDestroy(Widget w)
-{
- _XawImDestroy( w->core.parent, w );
-}
-
-/* ARGSUSED */
-static Boolean
-XawVendorShellExtSetValues(Widget old, Widget ref, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- return FALSE;
-}
-
-void
-XawVendorShellExtResize(Widget w)
-{
- ShellWidget sw = (ShellWidget) w;
- Widget childwid;
- Cardinal i;
- int core_height;
-
- _XawImResizeVendorShell( w );
- core_height = _XawImGetShellHeight( w );
- for( i = 0; i < sw->composite.num_children; i++ ) {
- if( XtIsManaged( sw->composite.children[ i ] ) ) {
- childwid = sw->composite.children[ i ];
- XtResizeWidget( childwid, sw->core.width, core_height,
- childwid->core.border_width );
- }
- }
-}
-
-/*ARGSUSED*/
-void
-XawVendorStructureNotifyHandler(Widget w, XtPointer closure, XEvent *event,
- Boolean *continue_to_dispatch)
-{
- XawVendorShellExtResize(w);
-}
-
-/*ARGSUSED*/
-static XtGeometryResult
-XawVendorShellGeometryManager(Widget wid, XtWidgetGeometry *request,
- XtWidgetGeometry *reply)
-{
- ShellWidget shell = (ShellWidget)(wid->core.parent);
- XtWidgetGeometry my_request;
-
- if(shell->shell.allow_shell_resize == FALSE && XtIsRealized(wid))
- return(XtGeometryNo);
-
- if (request->request_mode & (CWX | CWY))
- return(XtGeometryNo);
-
- /* %%% worry about XtCWQueryOnly */
- my_request.request_mode = 0;
- if (request->request_mode & CWWidth) {
- my_request.width = request->width;
- my_request.request_mode |= CWWidth;
- }
- if (request->request_mode & CWHeight) {
- my_request.height = request->height
- + _XawImGetImAreaHeight( wid );
- my_request.request_mode |= CWHeight;
- }
- if (request->request_mode & CWBorderWidth) {
- my_request.border_width = request->border_width;
- my_request.request_mode |= CWBorderWidth;
- }
- if (XtMakeGeometryRequest((Widget)shell, &my_request, NULL)
- == XtGeometryYes) {
- /* assert: if (request->request_mode & CWWidth) then
- * shell->core.width == request->width
- * assert: if (request->request_mode & CWHeight) then
- * shell->core.height == request->height
- *
- * so, whatever the WM sized us to (if the Shell requested
- * only one of the two) is now the correct child size
- */
-
- wid->core.width = shell->core.width;
- wid->core.height = shell->core.height;
- if (request->request_mode & CWBorderWidth) {
- wid->core.x = wid->core.y = -request->border_width;
- }
- _XawImCallVendorShellExtResize(wid);
- return XtGeometryYes;
- } else return XtGeometryNo;
-}
-
-static void
-XawVendorShellChangeManaged(Widget wid)
-{
- ShellWidget w = (ShellWidget) wid;
- Widget* childP;
- int i;
-
- (*SuperClass->composite_class.change_managed)(wid);
- for (i = w->composite.num_children, childP = w->composite.children;
- i; i--, childP++) {
- if (XtIsManaged(*childP)) {
- XtSetKeyboardFocus(wid, *childP);
- break;
- }
- }
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * This is a copy of Xt/Vendor.c with an additional ClassInitialize + * procedure to register Xmu resource type converters, and all the + * monkey business associated with input methods... + * + */ + +/* Make sure all wm properties can make it out of the resource manager */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/ShellP.h> +#include <X11/VendorP.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/Editres.h> +#include <X11/Xmu/ExtAgent.h> + +/* The following two headers are for the input method. */ + +#include <X11/Xaw/VendorEP.h> +#include <X11/Xaw/XawImP.h> + +/* + * Class Methods + */ +static void XawVendorShellChangeManaged(Widget); +static Boolean XawCvtCompoundTextToString(Display*, XrmValuePtr, Cardinal*, + XrmValue*, XrmValue*, XtPointer*); +static void XawVendorShellClassInitialize(void); +static XtGeometryResult XawVendorShellGeometryManager(Widget, + XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawVendorShellExtClassInitialize(void); +static void XawVendorShellExtDestroy(Widget); +static void XawVendorShellExtInitialize(Widget, Widget, ArgList, Cardinal*); +void XawVendorShellExtResize(Widget); +static Boolean XawVendorShellExtSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); +static void XawVendorShellClassPartInit(WidgetClass); +static void XawVendorShellInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawVendorShellRealize(Widget, Mask*, XSetWindowAttributes*); +static Boolean XawVendorShellSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * External + */ +void XawVendorStructureNotifyHandler(Widget, XtPointer, XEvent*, Boolean*); + +static XtResource resources[] = { + {XtNinput, XtCInput, XtRBool, sizeof(Bool), + XtOffsetOf(VendorShellRec, wm.wm_hints.input), + XtRImmediate, (XtPointer)True} +}; + +/*************************************************************************** + * + * Vendor shell class record + * + ***************************************************************************/ + +#if defined(__UNIXOS2__) || defined(__CYGWIN__) || defined(__MINGW32__) +/* to fix the EditRes problem because of wrong linker semantics */ +extern WidgetClass vendorShellWidgetClass; /* from Xt/Vendor.c */ +extern VendorShellClassRec _XawVendorShellClassRec; +extern void _XawFixupVendorShell(); + +#if defined(__UNIXOS2__) +unsigned long _DLL_InitTerm(unsigned long mod,unsigned long flag) +{ + switch (flag) { + case 0: /*called on init*/ + _CRT_init(); + vendorShellWidgetClass = (WidgetClass)(&_XawVendorShellClassRec); + _XawFixupVendorShell(); + return 1; + case 1: /*called on exit*/ + return 1; + default: + return 0; + } +} +#endif + +#if defined(__CYGWIN__) || defined(__MINGW32__) && !defined(_MSC_VER) +int __stdcall +DllMain(unsigned long mod_handle, unsigned long flag, void *routine) +{ + switch (flag) + { + case 1: /* DLL_PROCESS_ATTACH - process attach */ + vendorShellWidgetClass = (WidgetClass)(&_XawVendorShellClassRec); + _XawFixupVendorShell(); + break; + case 0: /* DLL_PROCESS_DETACH - process detach */ + break; + } + return 1; +} +#endif + +#define vendorShellClassRec _XawVendorShellClassRec + +#endif + +static CompositeClassExtensionRec vendorCompositeExt = { + /* next_extension */ NULL, + /* record_type */ NULLQUARK, + /* version */ XtCompositeExtensionVersion, + /* record_size */ sizeof (CompositeClassExtensionRec), + /* accepts_objects */ TRUE, + /* allows_change_managed_set */ FALSE +}; + +#define SuperClass (&wmShellClassRec) +externaldef(vendorshellclassrec) VendorShellClassRec vendorShellClassRec = { + { + /* superclass */ (WidgetClass)SuperClass, + /* class_name */ "VendorShell", + /* size */ sizeof(VendorShellRec), + /* class_initialize */ XawVendorShellClassInitialize, + /* class_part_init */ XawVendorShellClassPartInit, + /* Class init'ed ? */ FALSE, + /* initialize */ XawVendorShellInitialize, + /* initialize_hook */ NULL, + /* realize */ XawVendorShellRealize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ FALSE, + /* compress_exposure */ TRUE, + /* compress_enterleave*/ FALSE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ XawVendorShellExtResize, + /* expose */ NULL, + /* set_values */ XawVendorShellSetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* intrinsics version */ XtVersion, + /* callback offsets */ NULL, + /* tm_table */ NULL, + /* query_geometry */ NULL, + /* display_accelerator*/ NULL, + /* extension */ NULL + },{ + /* geometry_manager */ XawVendorShellGeometryManager, + /* change_managed */ XawVendorShellChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ (XtPointer) &vendorCompositeExt + },{ + /* extension */ NULL + },{ + /* extension */ NULL + },{ + /* extension */ NULL + } +}; + +#ifndef __UNIXOS2__ +externaldef(vendorshellwidgetclass) WidgetClass vendorShellWidgetClass = + (WidgetClass) (&vendorShellClassRec); +#endif + +/*************************************************************************** + * + * The following section is for the Vendor shell Extension class record + * + ***************************************************************************/ + +static XtResource ext_resources[] = { + {XtNinputMethod, XtCInputMethod, XtRString, sizeof(String), + XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.input_method), + XtRString, (XtPointer)NULL}, + {XtNpreeditType, XtCPreeditType, XtRString, sizeof(String), + XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.preedit_type), + XtRString, (XtPointer)"OverTheSpot,OffTheSpot,Root"}, + {XtNopenIm, XtCOpenIm, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.open_im), + XtRImmediate, (XtPointer)TRUE}, + {XtNsharedIc, XtCSharedIc, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XawVendorShellExtRec, vendor_ext.ic.shared_ic), + XtRImmediate, (XtPointer)FALSE} +}; + +externaldef(vendorshellextclassrec) XawVendorShellExtClassRec + xawvendorShellExtClassRec = { + { + /* superclass */ (WidgetClass)&objectClassRec, + /* class_name */ "VendorShellExt", + /* size */ sizeof(XawVendorShellExtRec), + /* class_initialize */ XawVendorShellExtClassInitialize, + /* class_part_initialize*/ NULL, + /* Class init'ed ? */ FALSE, + /* initialize */ XawVendorShellExtInitialize, + /* initialize_hook */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* pad */ 0, + /* resources */ ext_resources, + /* resource_count */ XtNumber(ext_resources), + /* xrm_class */ NULLQUARK, + /* pad */ FALSE, + /* pad */ FALSE, + /* pad */ FALSE, + /* pad */ FALSE, + /* destroy */ XawVendorShellExtDestroy, + /* pad */ NULL, + /* pad */ NULL, + /* set_values */ XawVendorShellExtSetValues, + /* set_values_hook */ NULL, + /* pad */ NULL, + /* get_values_hook */ NULL, + /* pad */ NULL, + /* version */ XtVersion, + /* callback_offsets */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* extension */ NULL + },{ + /* extension */ NULL + } +}; + +externaldef(xawvendorshellwidgetclass) WidgetClass + xawvendorShellExtWidgetClass = (WidgetClass) (&xawvendorShellExtClassRec); + + +/*ARGSUSED*/ +static Boolean +XawCvtCompoundTextToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *cvt_data) +{ + XTextProperty prop; + char **list; + int count; + static char *mbs = NULL; + int len; + + prop.value = (unsigned char *)fromVal->addr; + prop.encoding = XA_COMPOUND_TEXT(dpy); + prop.format = 8; + prop.nitems = fromVal->size; + + if(XmbTextPropertyToTextList(dpy, &prop, &list, &count) < Success) { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "converter", "XmbTextPropertyToTextList", "XawError", + "conversion from CT to MB failed.", NULL, NULL); + return False; + } + len = strlen(*list); + toVal->size = len; + mbs = XtRealloc(mbs, len + 1); /* keep buffer because no one call free :( */ + strcpy(mbs, *list); + XFreeStringList(list); + toVal->addr = (XtPointer)mbs; + return True; +} + +static void +XawVendorShellClassInitialize(void) +{ + static XtConvertArgRec screenConvertArg[] = { + {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)} + }; + + XtAddConverter(XtRString, XtRCursor, XmuCvtStringToCursor, + screenConvertArg, XtNumber(screenConvertArg)); + + XtAddConverter(XtRString, XtRBitmap, XmuCvtStringToBitmap, + screenConvertArg, XtNumber(screenConvertArg)); + + XtSetTypeConverter("CompoundText", XtRString, XawCvtCompoundTextToString, + NULL, 0, XtCacheNone, NULL); +} + +static void +XawVendorShellClassPartInit(WidgetClass cclass) +{ + CompositeClassExtension ext; + VendorShellWidgetClass vsclass = (VendorShellWidgetClass)cclass; + + if ((ext = (CompositeClassExtension) + XtGetClassExtension (cclass, + XtOffsetOf(CompositeClassRec, + composite_class.extension), + NULLQUARK, 1L, (Cardinal) 0)) == NULL) { + ext = (CompositeClassExtension) XtNew (CompositeClassExtensionRec); + if (ext != NULL) { + ext->next_extension = vsclass->composite_class.extension; + ext->record_type = NULLQUARK; + ext->version = XtCompositeExtensionVersion; + ext->record_size = sizeof (CompositeClassExtensionRec); + ext->accepts_objects = TRUE; + ext->allows_change_managed_set = FALSE; + vsclass->composite_class.extension = (XtPointer) ext; + } + } +} + +#if defined(__osf__) || defined(__UNIXOS2__) || defined(__CYGWIN__) || defined(__MINGW32__) +/* stupid OSF/1 shared libraries have the wrong semantics */ +/* symbols do not get resolved external to the shared library */ +void _XawFixupVendorShell() +{ + transientShellWidgetClass->core_class.superclass = + (WidgetClass) &vendorShellClassRec; + topLevelShellWidgetClass->core_class.superclass = + (WidgetClass) &vendorShellClassRec; +} +#endif + +/* ARGSUSED */ +static void +XawVendorShellInitialize(Widget req, Widget cnew, + ArgList args, Cardinal *num_args) +{ + XtAddEventHandler(cnew, (EventMask) 0, TRUE, _XEditResCheckMessages, NULL); + XtAddEventHandler(cnew, (EventMask) 0, TRUE, XmuRegisterExternalAgent, NULL); + XtCreateWidget("shellext", xawvendorShellExtWidgetClass, + cnew, args, *num_args); +} + +/* ARGSUSED */ +static Boolean +XawVendorShellSetValues(Widget old, Widget ref, Widget cnew, + ArgList args, Cardinal *num_args) +{ + return FALSE; +} + +static void +XawVendorShellRealize(Widget wid, Mask *vmask, XSetWindowAttributes *attr) +{ + WidgetClass super = wmShellWidgetClass; + + /* Make my superclass do all the dirty work */ + + (*super->core_class.realize) (wid, vmask, attr); + _XawImRealize(wid); +} + + +static void +XawVendorShellExtClassInitialize(void) +{ +} + +/* ARGSUSED */ +static void +XawVendorShellExtInitialize(Widget req, Widget cnew, + ArgList args, Cardinal *num_args) +{ + _XawImInitialize(cnew->core.parent, cnew); +} + +/* ARGSUSED */ +static void +XawVendorShellExtDestroy(Widget w) +{ + _XawImDestroy( w->core.parent, w ); +} + +/* ARGSUSED */ +static Boolean +XawVendorShellExtSetValues(Widget old, Widget ref, Widget cnew, + ArgList args, Cardinal *num_args) +{ + return FALSE; +} + +void +XawVendorShellExtResize(Widget w) +{ + ShellWidget sw = (ShellWidget) w; + Widget childwid; + Cardinal i; + int core_height; + + _XawImResizeVendorShell( w ); + core_height = _XawImGetShellHeight( w ); + for( i = 0; i < sw->composite.num_children; i++ ) { + if( XtIsManaged( sw->composite.children[ i ] ) ) { + childwid = sw->composite.children[ i ]; + XtResizeWidget( childwid, sw->core.width, core_height, + childwid->core.border_width ); + } + } +} + +/*ARGSUSED*/ +void +XawVendorStructureNotifyHandler(Widget w, XtPointer closure, XEvent *event, + Boolean *continue_to_dispatch) +{ + XawVendorShellExtResize(w); +} + +/*ARGSUSED*/ +static XtGeometryResult +XawVendorShellGeometryManager(Widget wid, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + ShellWidget shell = (ShellWidget)(wid->core.parent); + XtWidgetGeometry my_request; + + if(shell->shell.allow_shell_resize == FALSE && XtIsRealized(wid)) + return(XtGeometryNo); + + if (request->request_mode & (CWX | CWY)) + return(XtGeometryNo); + + /* %%% worry about XtCWQueryOnly */ + my_request.request_mode = 0; + if (request->request_mode & CWWidth) { + my_request.width = request->width; + my_request.request_mode |= CWWidth; + } + if (request->request_mode & CWHeight) { + my_request.height = request->height + + _XawImGetImAreaHeight( wid ); + my_request.request_mode |= CWHeight; + } + if (request->request_mode & CWBorderWidth) { + my_request.border_width = request->border_width; + my_request.request_mode |= CWBorderWidth; + } + if (XtMakeGeometryRequest((Widget)shell, &my_request, NULL) + == XtGeometryYes) { + /* assert: if (request->request_mode & CWWidth) then + * shell->core.width == request->width + * assert: if (request->request_mode & CWHeight) then + * shell->core.height == request->height + * + * so, whatever the WM sized us to (if the Shell requested + * only one of the two) is now the correct child size + */ + + wid->core.width = shell->core.width; + wid->core.height = shell->core.height; + if (request->request_mode & CWBorderWidth) { + wid->core.x = wid->core.y = -request->border_width; + } + _XawImCallVendorShellExtResize(wid); + return XtGeometryYes; + } else return XtGeometryNo; +} + +static void +XawVendorShellChangeManaged(Widget wid) +{ + ShellWidget w = (ShellWidget) wid; + Widget* childP; + int i; + + (*SuperClass->composite_class.change_managed)(wid); + for (i = w->composite.num_children, childP = w->composite.children; + i; i--, childP++) { + if (XtIsManaged(*childP)) { + XtSetKeyboardFocus(wid, *childP); + break; + } + } +} diff --git a/libXaw/src/Viewport.c b/libXaw/src/Viewport.c index ac2857257..68bd1682b 100644 --- a/libXaw/src/Viewport.c +++ b/libXaw/src/Viewport.c @@ -1,1099 +1,1099 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-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 and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xmu/Misc.h>
-#include <X11/Xaw/Scrollbar.h>
-#include <X11/Xaw/ViewportP.h>
-#include <X11/Xaw/XawInit.h>
-#include "Private.h"
-
-/*
- * Class Methods
- */
-static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool);
-static void XawViewportChangeManaged(Widget);
-static void XawViewportInitialize(Widget, Widget, ArgList, Cardinal*);
-static void
-XawViewportConstraintInitialize(Widget, Widget, ArgList, Cardinal*);
-static XtGeometryResult XawViewportGeometryManager(Widget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static XtGeometryResult XawViewportQueryGeometry(Widget,
- XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void XawViewportRealize(Widget, XtValueMask*, XSetWindowAttributes*);
-static void XawViewportResize(Widget);
-static Boolean XawViewportSetValues(Widget, Widget, Widget,
- ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void ComputeLayout(Widget, Bool, Bool);
-static void ComputeWithForceBars(Widget, Bool, XtWidgetGeometry*,
- int*, int*);
-static Widget CreateScrollbar(ViewportWidget, Bool);
-static XtGeometryResult GeometryRequestPlusScrollbar(ViewportWidget, Bool,
- XtWidgetGeometry*,
- XtWidgetGeometry*);
-static Bool GetGeometry(Widget, unsigned int, unsigned int);
-static void MoveChild(ViewportWidget, int, int);
-static XtGeometryResult QueryGeometry(ViewportWidget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void RedrawThumbs(ViewportWidget);
-static void ScrollUpDownProc(Widget, XtPointer, XtPointer);
-static void SendReport(ViewportWidget, unsigned int);
-static void SetBar(Widget, int, unsigned int, unsigned int);
-static XtGeometryResult TestSmaller(ViewportWidget, XtWidgetGeometry*,
- XtWidgetGeometry*);
-static void ThumbProc(Widget, XtPointer, XtPointer);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(ViewportRec, viewport.field)
-static XtResource resources[] = {
- {
- XtNforceBars,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(forcebars),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNallowHoriz,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(allowhoriz),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNallowVert,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(allowvert),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNuseBottom,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(usebottom),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNuseRight,
- XtCBoolean,
- XtRBoolean,
- sizeof(Boolean),
- offset(useright),
- XtRImmediate,
- (XtPointer)False
- },
- {
- XtNreportCallback,
- XtCReportCallback,
- XtRCallback,
- sizeof(XtPointer),
- offset(report_callbacks),
- XtRImmediate,
- NULL
- },
-};
-#undef offset
-
-#define Superclass (&formClassRec)
-ViewportClassRec viewportClassRec = {
- /* core */
- {
- (WidgetClass)Superclass, /* superclass */
- "Viewport", /* class_name */
- sizeof(ViewportRec), /* widget_size */
- XawInitializeWidgetSet, /* class_initialize */
- NULL, /* class_part_init */
- False, /* class_inited */
- XawViewportInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawViewportRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- NULL, /* destroy */
- XawViewportResize, /* resize */
- XtInheritExpose, /* expose */
- XawViewportSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XawViewportQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* composite */
- {
- XawViewportGeometryManager, /* geometry_manager */
- XawViewportChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
- /* constraint */
- {
- NULL, /* subresourses */
- 0, /* subresource_count */
- sizeof(ViewportConstraintsRec), /* constraint_size */
- XawViewportConstraintInitialize, /* initialize */
- NULL, /* destroy */
- NULL, /* set_values */
- NULL, /* extension */
- },
- /* form */
- {
- Layout, /* layout */
- },
- /* viewport */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec;
-
-/*
- * Implementation
- */
-static Widget
-CreateScrollbar(ViewportWidget w, Bool horizontal)
-{
- static Arg barArgs[] = {
- {XtNorientation, 0},
- {XtNlength, 0},
- {XtNleft, 0},
- {XtNright, 0},
- {XtNtop, 0},
- {XtNbottom, 0},
- {XtNmappedWhenManaged, False},
- };
- Widget clip = w->viewport.clip;
- ViewportConstraints constraints =
- (ViewportConstraints)clip->core.constraints;
- Widget bar;
-
- XtSetArg(barArgs[0], XtNorientation,
- horizontal ? XtorientHorizontal : XtorientVertical);
- XtSetArg(barArgs[1], XtNlength,
- horizontal ? XtWidth(clip) : XtHeight(clip));
- XtSetArg(barArgs[2], XtNleft,
- !horizontal && w->viewport.useright ? XtChainRight : XtChainLeft);
- XtSetArg(barArgs[3], XtNright,
- !horizontal && !w->viewport.useright ? XtChainLeft : XtChainRight);
- XtSetArg(barArgs[4], XtNtop,
- horizontal && w->viewport.usebottom ? XtChainBottom: XtChainTop);
- XtSetArg(barArgs[5], XtNbottom,
- horizontal && !w->viewport.usebottom ? XtChainTop: XtChainBottom);
-
- bar = XtCreateWidget(horizontal ? "horizontal" : "vertical",
- scrollbarWidgetClass, (Widget)w,
- barArgs, XtNumber(barArgs));
- XtAddCallback(bar, XtNscrollProc, ScrollUpDownProc, (XtPointer)w);
- XtAddCallback(bar, XtNjumpProc, ThumbProc, (XtPointer)w);
-
- if (horizontal) {
- w->viewport.horiz_bar = bar;
- constraints->form.vert_base = bar;
- }
- else {
- w->viewport.vert_bar = bar;
- constraints->form.horiz_base = bar;
- }
-
- XtManageChild(bar);
-
- return (bar);
-}
-
-/*ARGSUSED*/
-static void
-XawViewportInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- ViewportWidget w = (ViewportWidget)cnew;
- static Arg clip_args[8];
- Cardinal arg_cnt;
- Widget h_bar, v_bar;
- Dimension clip_height, clip_width;
-
- w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels */
-
- /*
- * Initialize all widget pointers to NULL
- */
- w->viewport.child = NULL;
- w->viewport.horiz_bar = w->viewport.vert_bar = NULL;
-
- /*
- * Create Clip Widget
- */
- arg_cnt = 0;
- XtSetArg(clip_args[arg_cnt], XtNbackgroundPixmap, None); arg_cnt++;
- XtSetArg(clip_args[arg_cnt], XtNborderWidth, 0); arg_cnt++;
- XtSetArg(clip_args[arg_cnt], XtNleft, XtChainLeft); arg_cnt++;
- XtSetArg(clip_args[arg_cnt], XtNright, XtChainRight); arg_cnt++;
- XtSetArg(clip_args[arg_cnt], XtNtop, XtChainTop); arg_cnt++;
- XtSetArg(clip_args[arg_cnt], XtNbottom, XtChainBottom); arg_cnt++;
- XtSetArg(clip_args[arg_cnt], XtNwidth, XtWidth(w)); arg_cnt++;
- XtSetArg(clip_args[arg_cnt], XtNheight, XtHeight(w)); arg_cnt++;
-
- w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, cnew,
- clip_args, arg_cnt);
-
- if (!w->viewport.forcebars)
- return; /* If we are not forcing the bars then we are done */
-
- if (w->viewport.allowhoriz)
- (void)CreateScrollbar(w, True);
- if (w->viewport.allowvert)
- (void)CreateScrollbar(w, False);
-
- h_bar = w->viewport.horiz_bar;
- v_bar = w->viewport.vert_bar;
-
- /*
- * Set the clip widget to the correct height
- */
- clip_width = XtWidth(w);
- clip_height = XtHeight(w);
-
- if (h_bar != NULL && XtWidth(w) > XtWidth(h_bar) + XtBorderWidth(h_bar))
- clip_width -= XtWidth(h_bar) + XtBorderWidth(h_bar);
-
- if (v_bar != NULL && XtHeight(w) > XtHeight(v_bar) + XtBorderWidth(v_bar))
- clip_height -= XtHeight(v_bar) + XtBorderWidth(v_bar);
-
- arg_cnt = 0;
- XtSetArg(clip_args[arg_cnt], XtNwidth, clip_width); arg_cnt++;
- XtSetArg(clip_args[arg_cnt], XtNheight, clip_height); arg_cnt++;
- XtSetValues(w->viewport.clip, clip_args, arg_cnt);
-}
-
-/*ARGSUSED*/
-static void
-XawViewportConstraintInitialize(Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- ((ViewportConstraints)cnew->core.constraints)->viewport.reparented = False;
-}
-
-static void
-XawViewportRealize(Widget widget, XtValueMask *value_mask,
- XSetWindowAttributes *attributes)
-{
- ViewportWidget w = (ViewportWidget)widget;
- Widget child = w->viewport.child;
- Widget clip = w->viewport.clip;
-
- *value_mask |= CWBitGravity;
- attributes->bit_gravity = NorthWestGravity;
- (*Superclass->core_class.realize)(widget, value_mask, attributes);
-
- (*w->core.widget_class->core_class.resize)(widget); /* turn on bars */
-
- if (child != NULL) {
- XtMoveWidget(child, 0, 0);
- XtRealizeWidget(clip);
- XtRealizeWidget(child);
- XReparentWindow(XtDisplay(w), XtWindow(child), XtWindow(clip), 0, 0);
- XtMapWidget(child);
- }
-}
-
-/*ARGSUSED*/
-static Boolean
-XawViewportSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- ViewportWidget w = (ViewportWidget)cnew;
- ViewportWidget cw = (ViewportWidget)current;
-
- if (w->viewport.forcebars != cw->viewport.forcebars
- || w->viewport.allowvert != cw->viewport.allowvert
- || w->viewport.allowhoriz != cw->viewport.allowhoriz
- || w->viewport.useright != cw->viewport.useright
- || w->viewport.usebottom != cw->viewport.usebottom)
- (*w->core.widget_class->core_class.resize)(cnew); /* Recompute layout */
-
- return (False);
-}
-
-static void
-XawViewportChangeManaged(Widget widget)
-{
- ViewportWidget w = (ViewportWidget)widget;
- int num_children = w->composite.num_children;
- Widget child, *childP;
- int i;
-
- child = NULL;
- for (childP = w->composite.children,
- i = 0; i < num_children;
- childP++, i++) {
- if (XtIsManaged(*childP)
- && *childP != w->viewport.clip
- && *childP != w->viewport.horiz_bar
- && *childP != w->viewport.vert_bar) {
- child = *childP;
- break;
- }
- }
-
- if (child != w->viewport.child) {
- w->viewport.child = child;
- if (child != NULL) {
- XtResizeWidget(child, XtWidth(child), XtHeight(child), 0);
- if (XtIsRealized(widget)) {
- ViewportConstraints constraints =
- (ViewportConstraints)child->core.constraints;
- if (!XtIsRealized(child)) {
- Window window = XtWindow(w);
-
- XtMoveWidget(child, 0, 0);
- w->core.window = XtWindow(w->viewport.clip);
- XtRealizeWidget(child);
- w->core.window = window;
- constraints->viewport.reparented = True;
- }
- else if (!constraints->viewport.reparented) {
- XReparentWindow(XtDisplay(w), XtWindow(child),
- XtWindow(w->viewport.clip), 0, 0);
- constraints->viewport.reparented = True;
- if (child->core.mapped_when_managed)
- XtMapWidget(child);
- }
- }
- GetGeometry(widget, XtWidth(child), XtHeight(child));
- (*((ViewportWidgetClass)w->core.widget_class)->form_class.layout)
- ((FormWidget)w, XtWidth(w), XtHeight(w), True /* True? */);
- }
- }
-
-#ifdef notdef
- (*Superclass->composite_class.change_managed)(widget);
-#endif
-}
-
-static void
-SetBar(Widget w, int top, unsigned int length, unsigned int total)
-{
- XawScrollbarSetThumb(w, (float)top / (float)total,
- (float)length / (float)total);
-}
-
-static void
-RedrawThumbs(ViewportWidget w)
-{
- Widget child = w->viewport.child;
- Widget clip = w->viewport.clip;
-
- if (w->viewport.horiz_bar != NULL)
- SetBar(w->viewport.horiz_bar, -(int)XtX(child),
- XtWidth(clip), XtWidth(child));
-
- if (w->viewport.vert_bar != NULL)
- SetBar(w->viewport.vert_bar, -(int)XtY(child),
- XtHeight(clip), XtHeight(child));
-}
-
-static void
-SendReport(ViewportWidget w, unsigned int changed)
-{
- XawPannerReport rep;
-
- if (w->viewport.report_callbacks) {
- Widget child = w->viewport.child;
- Widget clip = w->viewport.clip;
-
- rep.changed = changed;
- rep.slider_x = -XtX(child); /* child is canvas */
- rep.slider_y = -XtY(child); /* clip is slider */
- rep.slider_width = XtWidth(clip);
- rep.slider_height = XtHeight(clip);
- rep.canvas_width = XtWidth(child);
- rep.canvas_height = XtHeight(child);
- XtCallCallbackList((Widget)w, w->viewport.report_callbacks,
- (XtPointer)&rep);
- }
-}
-
-static void
-MoveChild(ViewportWidget w, int x, int y)
-{
- Widget child = w->viewport.child;
- Widget clip = w->viewport.clip;
-
- /* make sure we never move past right/bottom borders */
- if (-x + (int)XtWidth(clip) > XtWidth(child))
- x = -(int)(XtWidth(child) - XtWidth(clip));
-
- if (-y + (int)XtHeight(clip) > XtHeight(child))
- y = -(int)(XtHeight(child) - XtHeight(clip));
-
- /* make sure we never move past left/top borders */
- if (x >= 0)
- x = 0;
- if (y >= 0)
- y = 0;
-
- XtMoveWidget(child, x, y);
- SendReport(w, (XawPRSliderX | XawPRSliderY));
-
- RedrawThumbs(w);
-}
-
-static void
-ComputeLayout(Widget widget, Bool query, Bool destroy_scrollbars)
-{
- ViewportWidget w = (ViewportWidget)widget;
- Widget child = w->viewport.child;
- Widget clip = w->viewport.clip;
- ViewportConstraints constraints =
- (ViewportConstraints)clip->core.constraints;
- Bool needshoriz, needsvert;
- int clip_width, clip_height;
- XtWidgetGeometry intended;
-
- if (child == NULL)
- return;
-
- clip_width = XtWidth(w);
- clip_height = XtHeight(w);
- intended.request_mode = CWBorderWidth;
- intended.border_width = 0;
-
- if (w->viewport.forcebars) {
- needsvert = w->viewport.allowvert;
- needshoriz = w->viewport.allowhoriz;
- ComputeWithForceBars(widget, query, &intended,
- &clip_width, &clip_height);
- }
- else {
- Dimension prev_width, prev_height;
- XtGeometryMask prev_mode;
- XtWidgetGeometry preferred;
-
- needshoriz = needsvert = False;
-
- /*
- * intended.{width,height} caches the eventual child dimensions,
- * but we don't set the mode bits until after we decide that the
- * child's preferences are not acceptable
- */
- if (!w->viewport.allowhoriz)
- intended.request_mode |= CWWidth;
-
- if (XtWidth(child) < clip_width)
- intended.width = clip_width;
- else
- intended.width = XtWidth(child);
-
- if (XtHeight(child) < clip_height)
- intended.height = clip_height;
- else
- intended.height = XtHeight(child);
-
- if (!w->viewport.allowvert)
- intended.request_mode |= CWHeight;
-
- if (!query) {
- preferred.width = XtWidth(child);
- preferred.height = XtHeight(child);
- }
- do { /* while intended != prev */
- if (query) {
- (void)XtQueryGeometry(child, &intended, &preferred);
- if (!(preferred.request_mode & CWWidth))
- preferred.width = intended.width;
- if (!(preferred.request_mode & CWHeight))
- preferred.height = intended.height;
- }
- prev_width = intended.width;
- prev_height = intended.height;
- prev_mode = intended.request_mode;
- /*
- * note that having once decided to turn on either bar
- * we'll not change our mind until we're next resized,
- * thus avoiding potential oscillations
- */
-#define CheckHoriz() \
- if (w->viewport.allowhoriz && \
- preferred.width > clip_width) { \
- if (!needshoriz) { \
- Widget bar; \
- \
- needshoriz = True; \
- if ((bar = w->viewport.horiz_bar) == NULL) \
- bar = CreateScrollbar(w, True); \
- clip_height -= XtHeight(bar) + XtBorderWidth(bar); \
- if (clip_height < 1) \
- clip_height = 1; \
- } \
- intended.width = preferred.width; \
- }
-
- CheckHoriz();
- if (w->viewport.allowvert && preferred.height > clip_height) {
- if (!needsvert) {
- Widget bar;
- needsvert = True;
- if ((bar = w->viewport.vert_bar) == NULL)
- bar = CreateScrollbar(w, False);
- clip_width -= XtWidth(bar) + XtBorderWidth(bar);
- if (clip_width < 1)
- clip_width = 1;
- CheckHoriz();
- }
- intended.height = preferred.height;
- }
- if (!w->viewport.allowhoriz || preferred.width < clip_width) {
- intended.width = clip_width;
- intended.request_mode |= CWWidth;
- }
- if (!w->viewport.allowvert || preferred.height < clip_height) {
- intended.height = clip_height;
- intended.request_mode |= CWHeight;
- }
- } while (intended.request_mode != prev_mode
- || (intended.request_mode & CWWidth
- && intended.width != prev_width)
- || (intended.request_mode & CWHeight
- && intended.height != prev_height));
- }
-
- if (XtIsRealized(clip))
- XRaiseWindow(XtDisplay(clip), XtWindow(clip));
-
- XtMoveWidget(clip,
- needsvert ? w->viewport.useright ? 0 :
- XtWidth(w->viewport.vert_bar)
- + XtBorderWidth(w->viewport.vert_bar) : 0,
- needshoriz ? w->viewport.usebottom ? 0 :
- XtHeight(w->viewport.horiz_bar)
- + XtBorderWidth(w->viewport.horiz_bar) : 0);
- XtResizeWidget(clip, clip_width, clip_height, 0);
-
- if (w->viewport.horiz_bar != NULL) {
- Widget bar = w->viewport.horiz_bar;
-
- if (!needshoriz) {
- constraints->form.vert_base = NULL;
- if (destroy_scrollbars) {
- XtDestroyWidget(bar);
- w->viewport.horiz_bar = NULL;
- }
- }
- else {
- int bw = XtBorderWidth(bar);
-
- XtResizeWidget(bar, clip_width, XtHeight(bar), bw);
- XtMoveWidget(bar,
- needsvert && !w->viewport.useright
- ? XtWidth(w->viewport.vert_bar) : -bw,
- w->viewport.usebottom
- ? XtHeight(w) - XtHeight(bar) - bw : -bw);
- XtSetMappedWhenManaged(bar, True);
- }
- }
-
- if (w->viewport.vert_bar != NULL) {
- Widget bar = w->viewport.vert_bar;
-
- if (!needsvert) {
- constraints->form.horiz_base = NULL;
- if (destroy_scrollbars) {
- XtDestroyWidget(bar);
- w->viewport.vert_bar = NULL;
- }
- }
- else {
- int bw = bar->core.border_width;
-
- XtResizeWidget(bar, XtWidth(bar), clip_height, bw);
- XtMoveWidget(bar,
- w->viewport.useright
- ? XtWidth(w) - XtWidth(bar) - bw : -bw,
- needshoriz && !w->viewport.usebottom
- ? XtHeight(w->viewport.horiz_bar) : -bw);
- XtSetMappedWhenManaged(bar, True);
- }
- }
-
- if (child != NULL) {
- XtResizeWidget(child, intended.width, intended.height, 0);
- MoveChild(w, needshoriz ? XtX(child) : 0, needsvert ? XtY(child) : 0);
- }
-
- SendReport (w, XawPRAll);
-}
-
-/*
- * Function:
- * ComputeWithForceBars
- *
- * Parameters:
- * widget - viewport widget
- * query - whether or not to query the child
- * intended - cache of the childs height is stored here
- * (used and returned)
- * clip_width - size of clip window (used and returned)
- * clip_height - ""
- *
- * Description:
- * Computes the layout give forcebars is set.
- */
-static void
-ComputeWithForceBars(Widget widget, Bool query, XtWidgetGeometry *intended,
- int *clip_width, int *clip_height)
-{
- ViewportWidget w = (ViewportWidget)widget;
- Widget child = w->viewport.child;
- XtWidgetGeometry preferred;
-
- /*
- * If forcebars then needs = allows = has
- * Thus if needsvert is set it MUST have a scrollbar
- */
- if (w->viewport.allowvert) {
- if (w->viewport.vert_bar == NULL)
- w->viewport.vert_bar = CreateScrollbar(w, False);
-
- *clip_width -= XtWidth(w->viewport.vert_bar) +
- XtBorderWidth(w->viewport.vert_bar);
- }
-
- if (w->viewport.allowhoriz) {
- if (w->viewport.horiz_bar == NULL)
- w->viewport.horiz_bar = CreateScrollbar(w, True);
-
- *clip_height -= XtHeight(w->viewport.horiz_bar) +
- XtBorderWidth(w->viewport.horiz_bar);
- }
-
- AssignMax(*clip_width, 1);
- AssignMax(*clip_height, 1);
-
- if (!w->viewport.allowvert) {
- intended->height = *clip_height;
- intended->request_mode = CWHeight;
- }
- if (!w->viewport.allowhoriz) {
- intended->width = *clip_width;
- intended->request_mode = CWWidth;
- }
-
- if (query) {
- if (w->viewport.allowvert || w->viewport.allowhoriz) {
- XtQueryGeometry(child, intended, &preferred);
-
- if (!(intended->request_mode & CWWidth)) {
- if (preferred.request_mode & CWWidth)
- intended->width = preferred.width;
- else
- intended->width = XtWidth(child);
- }
-
- if (!(intended->request_mode & CWHeight)) {
- if (preferred.request_mode & CWHeight)
- intended->height = preferred.height;
- else
- intended->height = XtHeight(child);
- }
- }
- }
- else {
- if (w->viewport.allowvert)
- intended->height = XtHeight(child);
- if (w->viewport.allowhoriz)
- intended->width = XtWidth(child);
- }
-
- if (*clip_width > (int)intended->width)
- intended->width = *clip_width;
- if (*clip_height > (int)intended->height)
- intended->height = *clip_height;
-}
-
-static void
-XawViewportResize(Widget widget)
-{
- ComputeLayout(widget, True, True);
-}
-
-/*ARGSUSED*/
-static Boolean
-Layout(FormWidget w, unsigned int width, unsigned int height, Bool force)
-{
- ComputeLayout((Widget)w, True, True);
- w->form.preferred_width = XtWidth(w);
- w->form.preferred_height = XtHeight(w);
-
- return (False);
-}
-
-static void
-ScrollUpDownProc(Widget widget, XtPointer closure, XtPointer call_data)
-{
- ViewportWidget w = (ViewportWidget)closure;
- Widget child = w->viewport.child;
- int pix = (long)call_data;
- int x, y;
-
- if (child == NULL)
- return;
-
- x = XtX(child) - (widget == w->viewport.horiz_bar ? pix : 0);
- y = XtY(child) - (widget == w->viewport.vert_bar ? pix : 0);
- MoveChild(w, x, y);
-}
-
-/*ARGSUSED*/
-static void
-ThumbProc(Widget widget, XtPointer closure, XtPointer call_data)
-{
- ViewportWidget w = (ViewportWidget)closure;
- Widget child = w->viewport.child;
- float percent = *(float *)call_data;
- int x, y;
-
- if (child == NULL)
- return;
-
- if (widget == w->viewport.horiz_bar)
- x = -percent * XtWidth(child);
- else
- x = XtX(child);
-
- if (widget == w->viewport.vert_bar)
- y = -percent * XtHeight(child);
- else
- y = XtY(child);
-
- MoveChild(w, x, y);
-}
-
-static XtGeometryResult
-TestSmaller(ViewportWidget w, XtWidgetGeometry *request,
- XtWidgetGeometry *reply_return)
-{
- if (request->width < XtWidth(w) || request->height < XtHeight(w))
- return (XtMakeGeometryRequest((Widget)w, request, reply_return));
-
- return (XtGeometryYes);
-}
-
-static XtGeometryResult
-GeometryRequestPlusScrollbar(ViewportWidget w, Bool horizontal,
- XtWidgetGeometry *request,
- XtWidgetGeometry *reply_return)
-{
- Widget sb;
- XtWidgetGeometry plusScrollbars;
-
- plusScrollbars = *request;
- if ((sb = w->viewport.horiz_bar) == NULL)
- sb = CreateScrollbar(w, horizontal);
- request->width += XtWidth(sb);
- request->height += XtHeight(sb);
- XtDestroyWidget(sb);
- return (XtMakeGeometryRequest((Widget)w, &plusScrollbars, reply_return));
-}
-
-#define WidthChange() (request->width != XtWidth(w))
-#define HeightChange() (request->height != XtHeight(w))
-static XtGeometryResult
-QueryGeometry(ViewportWidget w, XtWidgetGeometry *request,
- XtWidgetGeometry *reply_return)
-{
- if (w->viewport.allowhoriz && w->viewport.allowvert)
- return (TestSmaller(w, request, reply_return));
-
- else if (w->viewport.allowhoriz && !w->viewport.allowvert) {
- if (WidthChange() && !HeightChange())
- return (TestSmaller(w, request, reply_return));
- else if (!WidthChange() && HeightChange())
- return (XtMakeGeometryRequest((Widget)w, request, reply_return));
- else if (WidthChange() && HeightChange())
- return (GeometryRequestPlusScrollbar(w, True, request, reply_return));
- else /* !WidthChange() && !HeightChange() */
- return (XtGeometryYes);
- }
- else if (!w->viewport.allowhoriz && w->viewport.allowvert) {
- if (!WidthChange() && HeightChange())
- return (TestSmaller(w, request, reply_return));
- else if (WidthChange() && !HeightChange())
- return (XtMakeGeometryRequest((Widget)w, request, reply_return));
- else if (WidthChange() && HeightChange())
- return (GeometryRequestPlusScrollbar(w, False, request, reply_return));
- else /* !WidthChange() && !HeightChange() */
- return (XtGeometryYes);
- }
- else /* (!w->viewport.allowhoriz && !w->viewport.allowvert) */
- return (XtMakeGeometryRequest((Widget)w, request, reply_return));
-}
-#undef WidthChange
-#undef HeightChange
-
-static XtGeometryResult
-XawViewportGeometryManager(Widget child, XtWidgetGeometry *request,
- XtWidgetGeometry *reply)
-{
- ViewportWidget w = (ViewportWidget)child->core.parent;
- Bool rWidth = (request->request_mode & CWWidth) != 0;
- Bool rHeight = (request->request_mode & CWHeight) != 0;
- XtWidgetGeometry allowed;
- XtGeometryResult result;
- Bool reconfigured;
- Bool child_changed_size;
- unsigned int height_remaining;
-
- if (request->request_mode & XtCWQueryOnly)
- return (QueryGeometry(w, request, reply));
-
- if (child != w->viewport.child
- || request->request_mode & ~(CWWidth | CWHeight | CWBorderWidth)
- || ((request->request_mode & CWBorderWidth)
- && request->border_width > 0))
- return (XtGeometryNo);
-
- allowed = *request;
-
- reconfigured = GetGeometry((Widget)w,
- rWidth ? request->width : XtWidth(w),
- rHeight ? request->height : XtHeight(w));
-
- child_changed_size = (rWidth && XtWidth(child) != request->width) ||
- (rHeight && XtHeight(child) != request->height);
-
- height_remaining = XtHeight(w);
- if (rWidth && XtWidth(w) != request->width) {
- if (w->viewport.allowhoriz && request->width > XtWidth(w)) {
- /* horizontal scrollbar will be needed so possibly reduce height */
- Widget bar;
-
- if ((bar = w->viewport.horiz_bar) == NULL)
- bar = CreateScrollbar(w, True);
- height_remaining -= XtHeight(bar) + XtBorderWidth(bar);
- reconfigured = True;
- }
- else
- allowed.width = XtWidth(w);
- }
- if (rHeight && height_remaining != request->height) {
- if (w->viewport.allowvert && request->height > height_remaining) {
- /* vertical scrollbar will be needed, so possibly reduce width */
- if (!w->viewport.allowhoriz || request->width < XtWidth(w)) {
- Widget bar;
-
- if ((bar = w->viewport.vert_bar) == NULL)
- bar = CreateScrollbar(w, False);
- if (!rWidth) {
- allowed.width = XtWidth(w);
- allowed.request_mode |= CWWidth;
- }
- if (allowed.width > XtWidth(bar) + XtBorderWidth(bar))
- allowed.width -= XtWidth(bar) + XtBorderWidth(bar);
- else
- allowed.width = 1;
- reconfigured = True;
- }
- }
- else
- allowed.height = height_remaining;
- }
-
- if (allowed.width != request->width || allowed.height != request->height) {
- *reply = allowed;
- result = XtGeometryAlmost;
- }
- else {
- if (rWidth)
- XtWidth(child) = request->width;
- if (rHeight)
- XtHeight(child) = request->height;
- result = XtGeometryYes;
- }
-
- if (reconfigured || child_changed_size)
- ComputeLayout((Widget)w, False, result == XtGeometryYes);
-
- return (result);
-}
-
-static Bool
-GetGeometry(Widget w, unsigned int width, unsigned int height)
-{
- XtWidgetGeometry geometry, return_geom;
- XtGeometryResult result;
-
- if (width == XtWidth(w) && height == XtHeight(w))
- return (False);
-
- geometry.request_mode = CWWidth | CWHeight;
- geometry.width = width;
- geometry.height = height;
-
- if (XtIsRealized(w)) {
- if (((ViewportWidget)w)->viewport.allowhoriz && width > XtWidth(w))
- geometry.width = XtWidth(w);
- if (((ViewportWidget)w)->viewport.allowvert && height > XtHeight(w))
- geometry.height = XtHeight(w);
- }
- else {
- /* This is the Realize call; we'll inherit a w&h iff none currently */
- if (XtWidth(w) != 0) {
- if (XtHeight(w) != 0)
- return (False);
- geometry.width = XtWidth(w);
- }
- if (XtHeight(w) != 0)
- geometry.height = XtHeight(w);
- }
-
- result = XtMakeGeometryRequest(w, &geometry, &return_geom);
- if (result == XtGeometryAlmost)
- result = XtMakeGeometryRequest(w, &return_geom, NULL);
-
- return (result == XtGeometryYes);
-}
-
-static XtGeometryResult
-XawViewportQueryGeometry(Widget w, XtWidgetGeometry *constraints,
- XtWidgetGeometry *reply)
-{
- if (((ViewportWidget)w)->viewport.child != NULL)
- return (XtQueryGeometry(((ViewportWidget)w)->viewport.child,
- constraints, reply));
-
- return (XtGeometryYes);
-}
-
-void
-XawViewportSetLocation
-(
- Widget gw,
-#if NeedWidePrototypes
- double xoff, double yoff
-#else
- float xoff, float yoff
-#endif
- )
-{
- ViewportWidget w = (ViewportWidget)gw;
- Widget child = w->viewport.child;
- int x, y;
-
- if (xoff > 1.0) /* scroll to right */
- x = XtWidth(child);
- else if (xoff < 0.0) /* if the offset is < 0.0 nothing */
- x = XtX(child);
- else
- x = (float)XtWidth(child) * xoff;
-
- if (yoff > 1.0)
- y = XtHeight(child);
- else if (yoff < 0.0)
- y = XtY(child);
- else
- y = (float)XtHeight(child) * yoff;
-
- MoveChild (w, -x, -y);
-}
-
-void
-XawViewportSetCoordinates(Widget gw,
-#if NeedWidePrototypes
- int x, int y
-#else
- Position x, Position y
-#endif
-)
-{
- ViewportWidget w = (ViewportWidget)gw;
- Widget child = w->viewport.child;
-
- if (x > XtWidth(child))
- x = XtWidth(child);
- else if (x < 0)
- x = XtX(child);
-
- if (y > XtHeight(child))
- y = XtHeight(child);
- else if (y < 0)
- y = XtY(child);
-
- MoveChild (w, -x, -y);
-}
+/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw/Scrollbar.h> +#include <X11/Xaw/ViewportP.h> +#include <X11/Xaw/XawInit.h> +#include "Private.h" + +/* + * Class Methods + */ +static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool); +static void XawViewportChangeManaged(Widget); +static void XawViewportInitialize(Widget, Widget, ArgList, Cardinal*); +static void +XawViewportConstraintInitialize(Widget, Widget, ArgList, Cardinal*); +static XtGeometryResult XawViewportGeometryManager(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static XtGeometryResult XawViewportQueryGeometry(Widget, + XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawViewportRealize(Widget, XtValueMask*, XSetWindowAttributes*); +static void XawViewportResize(Widget); +static Boolean XawViewportSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void ComputeLayout(Widget, Bool, Bool); +static void ComputeWithForceBars(Widget, Bool, XtWidgetGeometry*, + int*, int*); +static Widget CreateScrollbar(ViewportWidget, Bool); +static XtGeometryResult GeometryRequestPlusScrollbar(ViewportWidget, Bool, + XtWidgetGeometry*, + XtWidgetGeometry*); +static Bool GetGeometry(Widget, unsigned int, unsigned int); +static void MoveChild(ViewportWidget, int, int); +static XtGeometryResult QueryGeometry(ViewportWidget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void RedrawThumbs(ViewportWidget); +static void ScrollUpDownProc(Widget, XtPointer, XtPointer); +static void SendReport(ViewportWidget, unsigned int); +static void SetBar(Widget, int, unsigned int, unsigned int); +static XtGeometryResult TestSmaller(ViewportWidget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void ThumbProc(Widget, XtPointer, XtPointer); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(ViewportRec, viewport.field) +static XtResource resources[] = { + { + XtNforceBars, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(forcebars), + XtRImmediate, + (XtPointer)False + }, + { + XtNallowHoriz, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(allowhoriz), + XtRImmediate, + (XtPointer)False + }, + { + XtNallowVert, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(allowvert), + XtRImmediate, + (XtPointer)False + }, + { + XtNuseBottom, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(usebottom), + XtRImmediate, + (XtPointer)False + }, + { + XtNuseRight, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(useright), + XtRImmediate, + (XtPointer)False + }, + { + XtNreportCallback, + XtCReportCallback, + XtRCallback, + sizeof(XtPointer), + offset(report_callbacks), + XtRImmediate, + NULL + }, +}; +#undef offset + +#define Superclass (&formClassRec) +ViewportClassRec viewportClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Viewport", /* class_name */ + sizeof(ViewportRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + XawViewportInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawViewportRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XawViewportResize, /* resize */ + XtInheritExpose, /* expose */ + XawViewportSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XawViewportQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* composite */ + { + XawViewportGeometryManager, /* geometry_manager */ + XawViewportChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + /* constraint */ + { + NULL, /* subresourses */ + 0, /* subresource_count */ + sizeof(ViewportConstraintsRec), /* constraint_size */ + XawViewportConstraintInitialize, /* initialize */ + NULL, /* destroy */ + NULL, /* set_values */ + NULL, /* extension */ + }, + /* form */ + { + Layout, /* layout */ + }, + /* viewport */ + { + NULL, /* extension */ + }, +}; + +WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec; + +/* + * Implementation + */ +static Widget +CreateScrollbar(ViewportWidget w, Bool horizontal) +{ + static Arg barArgs[] = { + {XtNorientation, 0}, + {XtNlength, 0}, + {XtNleft, 0}, + {XtNright, 0}, + {XtNtop, 0}, + {XtNbottom, 0}, + {XtNmappedWhenManaged, False}, + }; + Widget clip = w->viewport.clip; + ViewportConstraints constraints = + (ViewportConstraints)clip->core.constraints; + Widget bar; + + XtSetArg(barArgs[0], XtNorientation, + horizontal ? XtorientHorizontal : XtorientVertical); + XtSetArg(barArgs[1], XtNlength, + horizontal ? XtWidth(clip) : XtHeight(clip)); + XtSetArg(barArgs[2], XtNleft, + !horizontal && w->viewport.useright ? XtChainRight : XtChainLeft); + XtSetArg(barArgs[3], XtNright, + !horizontal && !w->viewport.useright ? XtChainLeft : XtChainRight); + XtSetArg(barArgs[4], XtNtop, + horizontal && w->viewport.usebottom ? XtChainBottom: XtChainTop); + XtSetArg(barArgs[5], XtNbottom, + horizontal && !w->viewport.usebottom ? XtChainTop: XtChainBottom); + + bar = XtCreateWidget(horizontal ? "horizontal" : "vertical", + scrollbarWidgetClass, (Widget)w, + barArgs, XtNumber(barArgs)); + XtAddCallback(bar, XtNscrollProc, ScrollUpDownProc, (XtPointer)w); + XtAddCallback(bar, XtNjumpProc, ThumbProc, (XtPointer)w); + + if (horizontal) { + w->viewport.horiz_bar = bar; + constraints->form.vert_base = bar; + } + else { + w->viewport.vert_bar = bar; + constraints->form.horiz_base = bar; + } + + XtManageChild(bar); + + return (bar); +} + +/*ARGSUSED*/ +static void +XawViewportInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ViewportWidget w = (ViewportWidget)cnew; + static Arg clip_args[8]; + Cardinal arg_cnt; + Widget h_bar, v_bar; + Dimension clip_height, clip_width; + + w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels */ + + /* + * Initialize all widget pointers to NULL + */ + w->viewport.child = NULL; + w->viewport.horiz_bar = w->viewport.vert_bar = NULL; + + /* + * Create Clip Widget + */ + arg_cnt = 0; + XtSetArg(clip_args[arg_cnt], XtNbackgroundPixmap, None); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNborderWidth, 0); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNright, XtChainRight); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNtop, XtChainTop); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNbottom, XtChainBottom); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNwidth, XtWidth(w)); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNheight, XtHeight(w)); arg_cnt++; + + w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, cnew, + clip_args, arg_cnt); + + if (!w->viewport.forcebars) + return; /* If we are not forcing the bars then we are done */ + + if (w->viewport.allowhoriz) + (void)CreateScrollbar(w, True); + if (w->viewport.allowvert) + (void)CreateScrollbar(w, False); + + h_bar = w->viewport.horiz_bar; + v_bar = w->viewport.vert_bar; + + /* + * Set the clip widget to the correct height + */ + clip_width = XtWidth(w); + clip_height = XtHeight(w); + + if (h_bar != NULL && XtWidth(w) > XtWidth(h_bar) + XtBorderWidth(h_bar)) + clip_width -= XtWidth(h_bar) + XtBorderWidth(h_bar); + + if (v_bar != NULL && XtHeight(w) > XtHeight(v_bar) + XtBorderWidth(v_bar)) + clip_height -= XtHeight(v_bar) + XtBorderWidth(v_bar); + + arg_cnt = 0; + XtSetArg(clip_args[arg_cnt], XtNwidth, clip_width); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNheight, clip_height); arg_cnt++; + XtSetValues(w->viewport.clip, clip_args, arg_cnt); +} + +/*ARGSUSED*/ +static void +XawViewportConstraintInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ((ViewportConstraints)cnew->core.constraints)->viewport.reparented = False; +} + +static void +XawViewportRealize(Widget widget, XtValueMask *value_mask, + XSetWindowAttributes *attributes) +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + *value_mask |= CWBitGravity; + attributes->bit_gravity = NorthWestGravity; + (*Superclass->core_class.realize)(widget, value_mask, attributes); + + (*w->core.widget_class->core_class.resize)(widget); /* turn on bars */ + + if (child != NULL) { + XtMoveWidget(child, 0, 0); + XtRealizeWidget(clip); + XtRealizeWidget(child); + XReparentWindow(XtDisplay(w), XtWindow(child), XtWindow(clip), 0, 0); + XtMapWidget(child); + } +} + +/*ARGSUSED*/ +static Boolean +XawViewportSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ViewportWidget w = (ViewportWidget)cnew; + ViewportWidget cw = (ViewportWidget)current; + + if (w->viewport.forcebars != cw->viewport.forcebars + || w->viewport.allowvert != cw->viewport.allowvert + || w->viewport.allowhoriz != cw->viewport.allowhoriz + || w->viewport.useright != cw->viewport.useright + || w->viewport.usebottom != cw->viewport.usebottom) + (*w->core.widget_class->core_class.resize)(cnew); /* Recompute layout */ + + return (False); +} + +static void +XawViewportChangeManaged(Widget widget) +{ + ViewportWidget w = (ViewportWidget)widget; + int num_children = w->composite.num_children; + Widget child, *childP; + int i; + + child = NULL; + for (childP = w->composite.children, + i = 0; i < num_children; + childP++, i++) { + if (XtIsManaged(*childP) + && *childP != w->viewport.clip + && *childP != w->viewport.horiz_bar + && *childP != w->viewport.vert_bar) { + child = *childP; + break; + } + } + + if (child != w->viewport.child) { + w->viewport.child = child; + if (child != NULL) { + XtResizeWidget(child, XtWidth(child), XtHeight(child), 0); + if (XtIsRealized(widget)) { + ViewportConstraints constraints = + (ViewportConstraints)child->core.constraints; + if (!XtIsRealized(child)) { + Window window = XtWindow(w); + + XtMoveWidget(child, 0, 0); + w->core.window = XtWindow(w->viewport.clip); + XtRealizeWidget(child); + w->core.window = window; + constraints->viewport.reparented = True; + } + else if (!constraints->viewport.reparented) { + XReparentWindow(XtDisplay(w), XtWindow(child), + XtWindow(w->viewport.clip), 0, 0); + constraints->viewport.reparented = True; + if (child->core.mapped_when_managed) + XtMapWidget(child); + } + } + GetGeometry(widget, XtWidth(child), XtHeight(child)); + (*((ViewportWidgetClass)w->core.widget_class)->form_class.layout) + ((FormWidget)w, XtWidth(w), XtHeight(w), True /* True? */); + } + } + +#ifdef notdef + (*Superclass->composite_class.change_managed)(widget); +#endif +} + +static void +SetBar(Widget w, int top, unsigned int length, unsigned int total) +{ + XawScrollbarSetThumb(w, (float)top / (float)total, + (float)length / (float)total); +} + +static void +RedrawThumbs(ViewportWidget w) +{ + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + if (w->viewport.horiz_bar != NULL) + SetBar(w->viewport.horiz_bar, -(int)XtX(child), + XtWidth(clip), XtWidth(child)); + + if (w->viewport.vert_bar != NULL) + SetBar(w->viewport.vert_bar, -(int)XtY(child), + XtHeight(clip), XtHeight(child)); +} + +static void +SendReport(ViewportWidget w, unsigned int changed) +{ + XawPannerReport rep; + + if (w->viewport.report_callbacks) { + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + rep.changed = changed; + rep.slider_x = -XtX(child); /* child is canvas */ + rep.slider_y = -XtY(child); /* clip is slider */ + rep.slider_width = XtWidth(clip); + rep.slider_height = XtHeight(clip); + rep.canvas_width = XtWidth(child); + rep.canvas_height = XtHeight(child); + XtCallCallbackList((Widget)w, w->viewport.report_callbacks, + (XtPointer)&rep); + } +} + +static void +MoveChild(ViewportWidget w, int x, int y) +{ + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + /* make sure we never move past right/bottom borders */ + if (-x + (int)XtWidth(clip) > XtWidth(child)) + x = -(int)(XtWidth(child) - XtWidth(clip)); + + if (-y + (int)XtHeight(clip) > XtHeight(child)) + y = -(int)(XtHeight(child) - XtHeight(clip)); + + /* make sure we never move past left/top borders */ + if (x >= 0) + x = 0; + if (y >= 0) + y = 0; + + XtMoveWidget(child, x, y); + SendReport(w, (XawPRSliderX | XawPRSliderY)); + + RedrawThumbs(w); +} + +static void +ComputeLayout(Widget widget, Bool query, Bool destroy_scrollbars) +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + ViewportConstraints constraints = + (ViewportConstraints)clip->core.constraints; + Bool needshoriz, needsvert; + int clip_width, clip_height; + XtWidgetGeometry intended; + + if (child == NULL) + return; + + clip_width = XtWidth(w); + clip_height = XtHeight(w); + intended.request_mode = CWBorderWidth; + intended.border_width = 0; + + if (w->viewport.forcebars) { + needsvert = w->viewport.allowvert; + needshoriz = w->viewport.allowhoriz; + ComputeWithForceBars(widget, query, &intended, + &clip_width, &clip_height); + } + else { + Dimension prev_width, prev_height; + XtGeometryMask prev_mode; + XtWidgetGeometry preferred; + + needshoriz = needsvert = False; + + /* + * intended.{width,height} caches the eventual child dimensions, + * but we don't set the mode bits until after we decide that the + * child's preferences are not acceptable + */ + if (!w->viewport.allowhoriz) + intended.request_mode |= CWWidth; + + if (XtWidth(child) < clip_width) + intended.width = clip_width; + else + intended.width = XtWidth(child); + + if (XtHeight(child) < clip_height) + intended.height = clip_height; + else + intended.height = XtHeight(child); + + if (!w->viewport.allowvert) + intended.request_mode |= CWHeight; + + if (!query) { + preferred.width = XtWidth(child); + preferred.height = XtHeight(child); + } + do { /* while intended != prev */ + if (query) { + (void)XtQueryGeometry(child, &intended, &preferred); + if (!(preferred.request_mode & CWWidth)) + preferred.width = intended.width; + if (!(preferred.request_mode & CWHeight)) + preferred.height = intended.height; + } + prev_width = intended.width; + prev_height = intended.height; + prev_mode = intended.request_mode; + /* + * note that having once decided to turn on either bar + * we'll not change our mind until we're next resized, + * thus avoiding potential oscillations + */ +#define CheckHoriz() \ + if (w->viewport.allowhoriz && \ + preferred.width > clip_width) { \ + if (!needshoriz) { \ + Widget bar; \ + \ + needshoriz = True; \ + if ((bar = w->viewport.horiz_bar) == NULL) \ + bar = CreateScrollbar(w, True); \ + clip_height -= XtHeight(bar) + XtBorderWidth(bar); \ + if (clip_height < 1) \ + clip_height = 1; \ + } \ + intended.width = preferred.width; \ + } + + CheckHoriz(); + if (w->viewport.allowvert && preferred.height > clip_height) { + if (!needsvert) { + Widget bar; + needsvert = True; + if ((bar = w->viewport.vert_bar) == NULL) + bar = CreateScrollbar(w, False); + clip_width -= XtWidth(bar) + XtBorderWidth(bar); + if (clip_width < 1) + clip_width = 1; + CheckHoriz(); + } + intended.height = preferred.height; + } + if (!w->viewport.allowhoriz || preferred.width < clip_width) { + intended.width = clip_width; + intended.request_mode |= CWWidth; + } + if (!w->viewport.allowvert || preferred.height < clip_height) { + intended.height = clip_height; + intended.request_mode |= CWHeight; + } + } while (intended.request_mode != prev_mode + || (intended.request_mode & CWWidth + && intended.width != prev_width) + || (intended.request_mode & CWHeight + && intended.height != prev_height)); + } + + if (XtIsRealized(clip)) + XRaiseWindow(XtDisplay(clip), XtWindow(clip)); + + XtMoveWidget(clip, + needsvert ? w->viewport.useright ? 0 : + XtWidth(w->viewport.vert_bar) + + XtBorderWidth(w->viewport.vert_bar) : 0, + needshoriz ? w->viewport.usebottom ? 0 : + XtHeight(w->viewport.horiz_bar) + + XtBorderWidth(w->viewport.horiz_bar) : 0); + XtResizeWidget(clip, clip_width, clip_height, 0); + + if (w->viewport.horiz_bar != NULL) { + Widget bar = w->viewport.horiz_bar; + + if (!needshoriz) { + constraints->form.vert_base = NULL; + if (destroy_scrollbars) { + XtDestroyWidget(bar); + w->viewport.horiz_bar = NULL; + } + } + else { + int bw = XtBorderWidth(bar); + + XtResizeWidget(bar, clip_width, XtHeight(bar), bw); + XtMoveWidget(bar, + needsvert && !w->viewport.useright + ? XtWidth(w->viewport.vert_bar) : -bw, + w->viewport.usebottom + ? XtHeight(w) - XtHeight(bar) - bw : -bw); + XtSetMappedWhenManaged(bar, True); + } + } + + if (w->viewport.vert_bar != NULL) { + Widget bar = w->viewport.vert_bar; + + if (!needsvert) { + constraints->form.horiz_base = NULL; + if (destroy_scrollbars) { + XtDestroyWidget(bar); + w->viewport.vert_bar = NULL; + } + } + else { + int bw = bar->core.border_width; + + XtResizeWidget(bar, XtWidth(bar), clip_height, bw); + XtMoveWidget(bar, + w->viewport.useright + ? XtWidth(w) - XtWidth(bar) - bw : -bw, + needshoriz && !w->viewport.usebottom + ? XtHeight(w->viewport.horiz_bar) : -bw); + XtSetMappedWhenManaged(bar, True); + } + } + + if (child != NULL) { + XtResizeWidget(child, intended.width, intended.height, 0); + MoveChild(w, needshoriz ? XtX(child) : 0, needsvert ? XtY(child) : 0); + } + + SendReport (w, XawPRAll); +} + +/* + * Function: + * ComputeWithForceBars + * + * Parameters: + * widget - viewport widget + * query - whether or not to query the child + * intended - cache of the childs height is stored here + * (used and returned) + * clip_width - size of clip window (used and returned) + * clip_height - "" + * + * Description: + * Computes the layout give forcebars is set. + */ +static void +ComputeWithForceBars(Widget widget, Bool query, XtWidgetGeometry *intended, + int *clip_width, int *clip_height) +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + XtWidgetGeometry preferred; + + /* + * If forcebars then needs = allows = has + * Thus if needsvert is set it MUST have a scrollbar + */ + if (w->viewport.allowvert) { + if (w->viewport.vert_bar == NULL) + w->viewport.vert_bar = CreateScrollbar(w, False); + + *clip_width -= XtWidth(w->viewport.vert_bar) + + XtBorderWidth(w->viewport.vert_bar); + } + + if (w->viewport.allowhoriz) { + if (w->viewport.horiz_bar == NULL) + w->viewport.horiz_bar = CreateScrollbar(w, True); + + *clip_height -= XtHeight(w->viewport.horiz_bar) + + XtBorderWidth(w->viewport.horiz_bar); + } + + AssignMax(*clip_width, 1); + AssignMax(*clip_height, 1); + + if (!w->viewport.allowvert) { + intended->height = *clip_height; + intended->request_mode = CWHeight; + } + if (!w->viewport.allowhoriz) { + intended->width = *clip_width; + intended->request_mode = CWWidth; + } + + if (query) { + if (w->viewport.allowvert || w->viewport.allowhoriz) { + XtQueryGeometry(child, intended, &preferred); + + if (!(intended->request_mode & CWWidth)) { + if (preferred.request_mode & CWWidth) + intended->width = preferred.width; + else + intended->width = XtWidth(child); + } + + if (!(intended->request_mode & CWHeight)) { + if (preferred.request_mode & CWHeight) + intended->height = preferred.height; + else + intended->height = XtHeight(child); + } + } + } + else { + if (w->viewport.allowvert) + intended->height = XtHeight(child); + if (w->viewport.allowhoriz) + intended->width = XtWidth(child); + } + + if (*clip_width > (int)intended->width) + intended->width = *clip_width; + if (*clip_height > (int)intended->height) + intended->height = *clip_height; +} + +static void +XawViewportResize(Widget widget) +{ + ComputeLayout(widget, True, True); +} + +/*ARGSUSED*/ +static Boolean +Layout(FormWidget w, unsigned int width, unsigned int height, Bool force) +{ + ComputeLayout((Widget)w, True, True); + w->form.preferred_width = XtWidth(w); + w->form.preferred_height = XtHeight(w); + + return (False); +} + +static void +ScrollUpDownProc(Widget widget, XtPointer closure, XtPointer call_data) +{ + ViewportWidget w = (ViewportWidget)closure; + Widget child = w->viewport.child; + int pix = (long)call_data; + int x, y; + + if (child == NULL) + return; + + x = XtX(child) - (widget == w->viewport.horiz_bar ? pix : 0); + y = XtY(child) - (widget == w->viewport.vert_bar ? pix : 0); + MoveChild(w, x, y); +} + +/*ARGSUSED*/ +static void +ThumbProc(Widget widget, XtPointer closure, XtPointer call_data) +{ + ViewportWidget w = (ViewportWidget)closure; + Widget child = w->viewport.child; + float percent = *(float *)call_data; + int x, y; + + if (child == NULL) + return; + + if (widget == w->viewport.horiz_bar) + x = -percent * XtWidth(child); + else + x = XtX(child); + + if (widget == w->viewport.vert_bar) + y = -percent * XtHeight(child); + else + y = XtY(child); + + MoveChild(w, x, y); +} + +static XtGeometryResult +TestSmaller(ViewportWidget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply_return) +{ + if (request->width < XtWidth(w) || request->height < XtHeight(w)) + return (XtMakeGeometryRequest((Widget)w, request, reply_return)); + + return (XtGeometryYes); +} + +static XtGeometryResult +GeometryRequestPlusScrollbar(ViewportWidget w, Bool horizontal, + XtWidgetGeometry *request, + XtWidgetGeometry *reply_return) +{ + Widget sb; + XtWidgetGeometry plusScrollbars; + + plusScrollbars = *request; + if ((sb = w->viewport.horiz_bar) == NULL) + sb = CreateScrollbar(w, horizontal); + request->width += XtWidth(sb); + request->height += XtHeight(sb); + XtDestroyWidget(sb); + return (XtMakeGeometryRequest((Widget)w, &plusScrollbars, reply_return)); +} + +#define WidthChange() (request->width != XtWidth(w)) +#define HeightChange() (request->height != XtHeight(w)) +static XtGeometryResult +QueryGeometry(ViewportWidget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply_return) +{ + if (w->viewport.allowhoriz && w->viewport.allowvert) + return (TestSmaller(w, request, reply_return)); + + else if (w->viewport.allowhoriz && !w->viewport.allowvert) { + if (WidthChange() && !HeightChange()) + return (TestSmaller(w, request, reply_return)); + else if (!WidthChange() && HeightChange()) + return (XtMakeGeometryRequest((Widget)w, request, reply_return)); + else if (WidthChange() && HeightChange()) + return (GeometryRequestPlusScrollbar(w, True, request, reply_return)); + else /* !WidthChange() && !HeightChange() */ + return (XtGeometryYes); + } + else if (!w->viewport.allowhoriz && w->viewport.allowvert) { + if (!WidthChange() && HeightChange()) + return (TestSmaller(w, request, reply_return)); + else if (WidthChange() && !HeightChange()) + return (XtMakeGeometryRequest((Widget)w, request, reply_return)); + else if (WidthChange() && HeightChange()) + return (GeometryRequestPlusScrollbar(w, False, request, reply_return)); + else /* !WidthChange() && !HeightChange() */ + return (XtGeometryYes); + } + else /* (!w->viewport.allowhoriz && !w->viewport.allowvert) */ + return (XtMakeGeometryRequest((Widget)w, request, reply_return)); +} +#undef WidthChange +#undef HeightChange + +static XtGeometryResult +XawViewportGeometryManager(Widget child, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + ViewportWidget w = (ViewportWidget)child->core.parent; + Bool rWidth = (request->request_mode & CWWidth) != 0; + Bool rHeight = (request->request_mode & CWHeight) != 0; + XtWidgetGeometry allowed; + XtGeometryResult result; + Bool reconfigured; + Bool child_changed_size; + unsigned int height_remaining; + + if (request->request_mode & XtCWQueryOnly) + return (QueryGeometry(w, request, reply)); + + if (child != w->viewport.child + || request->request_mode & ~(CWWidth | CWHeight | CWBorderWidth) + || ((request->request_mode & CWBorderWidth) + && request->border_width > 0)) + return (XtGeometryNo); + + allowed = *request; + + reconfigured = GetGeometry((Widget)w, + rWidth ? request->width : XtWidth(w), + rHeight ? request->height : XtHeight(w)); + + child_changed_size = (rWidth && XtWidth(child) != request->width) || + (rHeight && XtHeight(child) != request->height); + + height_remaining = XtHeight(w); + if (rWidth && XtWidth(w) != request->width) { + if (w->viewport.allowhoriz && request->width > XtWidth(w)) { + /* horizontal scrollbar will be needed so possibly reduce height */ + Widget bar; + + if ((bar = w->viewport.horiz_bar) == NULL) + bar = CreateScrollbar(w, True); + height_remaining -= XtHeight(bar) + XtBorderWidth(bar); + reconfigured = True; + } + else + allowed.width = XtWidth(w); + } + if (rHeight && height_remaining != request->height) { + if (w->viewport.allowvert && request->height > height_remaining) { + /* vertical scrollbar will be needed, so possibly reduce width */ + if (!w->viewport.allowhoriz || request->width < XtWidth(w)) { + Widget bar; + + if ((bar = w->viewport.vert_bar) == NULL) + bar = CreateScrollbar(w, False); + if (!rWidth) { + allowed.width = XtWidth(w); + allowed.request_mode |= CWWidth; + } + if (allowed.width > XtWidth(bar) + XtBorderWidth(bar)) + allowed.width -= XtWidth(bar) + XtBorderWidth(bar); + else + allowed.width = 1; + reconfigured = True; + } + } + else + allowed.height = height_remaining; + } + + if (allowed.width != request->width || allowed.height != request->height) { + *reply = allowed; + result = XtGeometryAlmost; + } + else { + if (rWidth) + XtWidth(child) = request->width; + if (rHeight) + XtHeight(child) = request->height; + result = XtGeometryYes; + } + + if (reconfigured || child_changed_size) + ComputeLayout((Widget)w, False, result == XtGeometryYes); + + return (result); +} + +static Bool +GetGeometry(Widget w, unsigned int width, unsigned int height) +{ + XtWidgetGeometry geometry, return_geom; + XtGeometryResult result; + + if (width == XtWidth(w) && height == XtHeight(w)) + return (False); + + geometry.request_mode = CWWidth | CWHeight; + geometry.width = width; + geometry.height = height; + + if (XtIsRealized(w)) { + if (((ViewportWidget)w)->viewport.allowhoriz && width > XtWidth(w)) + geometry.width = XtWidth(w); + if (((ViewportWidget)w)->viewport.allowvert && height > XtHeight(w)) + geometry.height = XtHeight(w); + } + else { + /* This is the Realize call; we'll inherit a w&h iff none currently */ + if (XtWidth(w) != 0) { + if (XtHeight(w) != 0) + return (False); + geometry.width = XtWidth(w); + } + if (XtHeight(w) != 0) + geometry.height = XtHeight(w); + } + + result = XtMakeGeometryRequest(w, &geometry, &return_geom); + if (result == XtGeometryAlmost) + result = XtMakeGeometryRequest(w, &return_geom, NULL); + + return (result == XtGeometryYes); +} + +static XtGeometryResult +XawViewportQueryGeometry(Widget w, XtWidgetGeometry *constraints, + XtWidgetGeometry *reply) +{ + if (((ViewportWidget)w)->viewport.child != NULL) + return (XtQueryGeometry(((ViewportWidget)w)->viewport.child, + constraints, reply)); + + return (XtGeometryYes); +} + +void +XawViewportSetLocation +( + Widget gw, +#if NeedWidePrototypes + double xoff, double yoff +#else + float xoff, float yoff +#endif + ) +{ + ViewportWidget w = (ViewportWidget)gw; + Widget child = w->viewport.child; + int x, y; + + if (xoff > 1.0) /* scroll to right */ + x = XtWidth(child); + else if (xoff < 0.0) /* if the offset is < 0.0 nothing */ + x = XtX(child); + else + x = (float)XtWidth(child) * xoff; + + if (yoff > 1.0) + y = XtHeight(child); + else if (yoff < 0.0) + y = XtY(child); + else + y = (float)XtHeight(child) * yoff; + + MoveChild (w, -x, -y); +} + +void +XawViewportSetCoordinates(Widget gw, +#if NeedWidePrototypes + int x, int y +#else + Position x, Position y +#endif +) +{ + ViewportWidget w = (ViewportWidget)gw; + Widget child = w->viewport.child; + + if (x > XtWidth(child)) + x = XtWidth(child); + else if (x < 0) + x = XtX(child); + + if (y > XtHeight(child)) + y = XtHeight(child); + else if (y < 0) + y = XtY(child); + + MoveChild (w, -x, -y); +} diff --git a/libXaw/src/XawI18n.c b/libXaw/src/XawI18n.c index 38483f40e..9a49521a9 100644 --- a/libXaw/src/XawI18n.c +++ b/libXaw/src/XawI18n.c @@ -1,105 +1,105 @@ -/* Copyright 1991 NCR Corporation - Dayton, Ohio, USA */
-
-/*
- * Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation,
- * and Nippon Telegraph and Telephone Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the names of OMRON, NTT Software, and NTT
- * not be used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. OMRON, NTT Software,
- * and NTT make no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * OMRON, NTT SOFTWARE, AND NTT, DISCLAIM ALL WARRANTIES WITH REGARD
- * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL OMRON, NTT SOFTWARE, OR NTT BE
- * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Li Yuhong OMRON Corporation
- */
-
-/*
-
-Copyright 1991, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include "XawI18n.h"
-
-wchar_t
-#if NeedWidePrototypes
-_Xaw_atowc(int c)
-#else
-_Xaw_atowc(unsigned char c)
-#endif
-{
- wchar_t wc;
- char str[2];
-
- str[0] = c;
- str[1] = '\0';
-
- mbtowc(&wc, str, 1);
-
- return (wc);
-}
-
-#ifdef NCR
-int
-_Xaw_iswspace(wchar_t w)
-{
- int ret = 0;
- wchar_t s = _Xaw_atowc(' ');
-
- if (s == w)
- ret = 1;
-
- return (ret);
-}
-#endif
-
-int
-_Xaw_iswalnum(wchar_t ch)
-{
-#ifdef HAVE_ISWALNUM
- return iswalnum(ch);
-#else
- unsigned char mb[MB_LEN_MAX];
-
- wctomb((char*)mb, ch);
-
- return (isalnum(*mb));
-#endif
-}
+/* Copyright 1991 NCR Corporation - Dayton, Ohio, USA */ + +/* + * Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation, + * and Nippon Telegraph and Telephone Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of OMRON, NTT Software, and NTT + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. OMRON, NTT Software, + * and NTT make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OMRON, NTT SOFTWARE, AND NTT, DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL OMRON, NTT SOFTWARE, OR NTT BE + * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Li Yuhong OMRON Corporation + */ + +/* + +Copyright 1991, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include "XawI18n.h" + +wchar_t +#if NeedWidePrototypes +_Xaw_atowc(int c) +#else +_Xaw_atowc(unsigned char c) +#endif +{ + wchar_t wc; + char str[2]; + + str[0] = c; + str[1] = '\0'; + + mbtowc(&wc, str, 1); + + return (wc); +} + +#ifdef NCR +int +_Xaw_iswspace(wchar_t w) +{ + int ret = 0; + wchar_t s = _Xaw_atowc(' '); + + if (s == w) + ret = 1; + + return (ret); +} +#endif + +int +_Xaw_iswalnum(wchar_t ch) +{ +#ifdef HAVE_ISWALNUM + return iswalnum(ch); +#else + unsigned char mb[MB_LEN_MAX]; + + wctomb((char*)mb, ch); + + return (isalnum(*mb)); +#endif +} diff --git a/libXaw/src/XawI18n.h b/libXaw/src/XawI18n.h index 6a9064a3a..d50171cfb 100644 --- a/libXaw/src/XawI18n.h +++ b/libXaw/src/XawI18n.h @@ -1,118 +1,118 @@ -/************************************************************
-
-Copyright 1993, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-********************************************************/
-
-#ifdef HAVE_WCTYPE_H
-#include <wctype.h>
-#ifdef HAVE_WIDEC_H
-#include <widec.h>
-#define wcslen(c) wslen(c)
-#define wcscpy(d, s) wscpy(d, s)
-#define wcsncpy(d, s, l) wsncpy(d, s, l)
-#endif
-#endif
-
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-
-#if defined(AIXV3) || defined(__SCO__)
-#include <ctype.h>
-#endif
-
-#ifdef NCR
-#define iswspace(c) _Xaw_iswspace(c)
-int _Xaw_iswspace
-(
- wchar_t c
- );
-#endif
-
-#ifdef sony
-#ifndef SVR4
-#include <jctype.h>
-#define iswspace(c) jisspace(c)
-#endif
-#endif
-
-#ifdef QNX4
-#define toascii( c ) ((unsigned)(c) & 0x007f)
-#endif
-
-#include <stdlib.h>
-
-#ifdef USE_XWCHAR_STRING
-int _Xwcslen
-(
- wchar_t *wstr
- );
-
-#define wcslen(c) _Xwcslen(c)
-
-wchar_t *_Xwcscpy
-(
- wchar_t *wstr1,
- wchar_t *wstr2
- );
-
-#define wcscpy(d,s) _Xwcscpy(d,s)
-
-wchar_t *_Xwcsncpy
-(
- wchar_t *wstr1,
- wchar_t *wstr2,
- int len
- );
-
-#define wcsncpy(d, s, l) _Xwcsncpy(d, s, l)
-
-#ifdef USE_XMBTOWC
-#define mbtowc(wc, s, l) _Xmbtowc(wc, s, l)
-#endif
-#endif
-
-wchar_t _Xaw_atowc
-(
-#if NeedWidePrototypes
- int c
-#else
- unsigned char c
-#endif
- );
-
-#ifndef HAS_ISW_FUNCS
-#include <ctype.h>
-#ifndef iswspace
-#define iswspace(c) (isascii(c) && isspace(toascii(c)))
-#endif
-#endif
-
-#if !defined(iswalnum) && !defined(HAVE_ISWALNUM)
-#define iswalnum(c) _Xaw_iswalnum(c)
-#endif
-int _Xaw_iswalnum
-(
- wchar_t c
- );
+/************************************************************ + +Copyright 1993, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +#ifdef HAVE_WCTYPE_H +#include <wctype.h> +#ifdef HAVE_WIDEC_H +#include <widec.h> +#define wcslen(c) wslen(c) +#define wcscpy(d, s) wscpy(d, s) +#define wcsncpy(d, s, l) wsncpy(d, s, l) +#endif +#endif + +#ifdef HAVE_WCHAR_H +#include <wchar.h> +#endif + +#if defined(AIXV3) || defined(__SCO__) +#include <ctype.h> +#endif + +#ifdef NCR +#define iswspace(c) _Xaw_iswspace(c) +int _Xaw_iswspace +( + wchar_t c + ); +#endif + +#ifdef sony +#ifndef SVR4 +#include <jctype.h> +#define iswspace(c) jisspace(c) +#endif +#endif + +#ifdef QNX4 +#define toascii( c ) ((unsigned)(c) & 0x007f) +#endif + +#include <stdlib.h> + +#ifdef USE_XWCHAR_STRING +int _Xwcslen +( + wchar_t *wstr + ); + +#define wcslen(c) _Xwcslen(c) + +wchar_t *_Xwcscpy +( + wchar_t *wstr1, + wchar_t *wstr2 + ); + +#define wcscpy(d,s) _Xwcscpy(d,s) + +wchar_t *_Xwcsncpy +( + wchar_t *wstr1, + wchar_t *wstr2, + int len + ); + +#define wcsncpy(d, s, l) _Xwcsncpy(d, s, l) + +#ifdef USE_XMBTOWC +#define mbtowc(wc, s, l) _Xmbtowc(wc, s, l) +#endif +#endif + +wchar_t _Xaw_atowc +( +#if NeedWidePrototypes + int c +#else + unsigned char c +#endif + ); + +#ifndef HAS_ISW_FUNCS +#include <ctype.h> +#ifndef iswspace +#define iswspace(c) (isascii(c) && isspace(toascii(c))) +#endif +#endif + +#if !defined(iswalnum) && !defined(HAVE_ISWALNUM) +#define iswalnum(c) _Xaw_iswalnum(c) +#endif +int _Xaw_iswalnum +( + wchar_t c + ); diff --git a/libXaw/src/XawIm.c b/libXaw/src/XawIm.c index 11391b57a..3b7032b74 100644 --- a/libXaw/src/XawIm.c +++ b/libXaw/src/XawIm.c @@ -1,1609 +1,1609 @@ -/*
- * Copyright 1991 by OMRON Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of OMRON not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. OMRON makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- * OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- * Author: Seiji Kuwari OMRON Corporation
- * kuwa@omron.co.jp
- * kuwa%omron.co.jp@uunet.uu.net
- */
-
-
-/*
-
-Copyright 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xos.h>
-#include <X11/Xfuncs.h>
-#include <X11/ShellP.h>
-#include <X11/Xaw/TextP.h>
-#include <X11/Xaw/MultiSrc.h>
-#include <X11/Xaw/MultiSinkP.h>
-#include <X11/Xaw/XawImP.h>
-#include <X11/Xaw/VendorEP.h>
-#include "XawI18n.h"
-#include <ctype.h>
-
-#include <stdarg.h>
-
-#define maxAscentOfFontSet(fontset) \
- ( - (XExtentsOfFontSet((fontset)))->max_logical_extent.y)
-
-#define maxHeightOfFontSet(fontset) \
- ((XExtentsOfFontSet((fontset)))->max_logical_extent.height)
-
-#define maxDescentOfFontSet(fontset) \
- (maxHeightOfFontSet(fontset) - maxAscentOfFontSet(fontset))
-
-#define Offset(field) (XtOffsetOf(XawIcTablePart, field))
-
-/*****************************************************
- *
- * Forward reference prototypes
- *
- *****************************************************/
-
-/*
- * Prototypes
- */
-static void AllCreateIC(XawVendorShellExtPart*);
-static void CloseIM(XawVendorShellExtPart*);
-static void CompileResourceList(XtResourceList, unsigned int);
-static void ConfigureCB(Widget, XtPointer, XEvent*, Boolean*);
-static void CreateIC(Widget, XawVendorShellExtPart*);
-static XawIcTableList CreateIcTable(Widget, XawVendorShellExtPart*);
-static XawIcTableList CurrentSharedIcTable(XawVendorShellExtPart*);
-static void Destroy(Widget, XawVendorShellExtPart*);
-static void DestroyAllIM(XawVendorShellExtPart*);
-static void DestroyIC(Widget, XawVendorShellExtPart*);
-static void FreeAllDataOfVendorShell(XawVendorShellExtPart*,
- VendorShellWidget);
-static XawVendorShellExtPart *GetExtPart(VendorShellWidget);
-static XawIcTableList GetIcTable(Widget, XawVendorShellExtPart*);
-static XawIcTableList GetIcTableShared(Widget, XawVendorShellExtPart*);
-static XIMStyle GetInputStyleOfIC(XawVendorShellExtPart*);
-static Bool Initialize(VendorShellWidget, XawVendorShellExtPart*);
-static Bool IsCreatedIC(Widget, XawVendorShellExtPart*);
-static Bool IsRegistered(Widget, XawVendorShellExtPart*);
-static Bool IsSharedIC(XawVendorShellExtPart*);
-static Bool NoRegistered(XawVendorShellExtPart*);
-static void OpenIM(XawVendorShellExtPart*);
-static void Reconnect(XawVendorShellExtPart*);
-static void Register(Widget, XawVendorShellExtPart*);
-static Bool RegisterToVendorShell(Widget, XawVendorShellExtPart*);
-static void ResizeVendorShell(VendorShellWidget, XawVendorShellExtPart*);
-static Bool ResizeVendorShell_Core(VendorShellWidget, XawVendorShellExtPart*,
- XawIcTableList);
-static VendorShellWidget SearchVendorShell(Widget);
-static Widget SetErrCnxt(Widget, XIM);
-static XawVendorShellExtPart *SetExtPart(VendorShellWidget,
- XawVendorShellExtWidget);
-static void SetFocus(Widget, XawVendorShellExtPart*);
-static void SetFocusValues(Widget, ArgList, Cardinal, Bool);
-static void SetICFocus(Widget, XawVendorShellExtPart*);
-static void SetICValues(Widget, XawVendorShellExtPart*, Bool);
-static void SetICValuesShared(Widget, XawVendorShellExtPart*, XawIcTableList,
- Bool);
-static void SetValues(Widget, XawVendorShellExtPart*, ArgList, Cardinal);
-static unsigned int SetVendorShellHeight(XawVendorShellExtPart*,
- unsigned int);
-static void SharedICChangeFocusWindow(Widget, XawVendorShellExtPart*,
- XawIcTableList);
-static void SizeNegotiation(XawIcTableList, unsigned int, unsigned int);
-static void Unregister(Widget, XawVendorShellExtPart*);
-static void UnregisterFromVendorShell(Widget, XawVendorShellExtPart*);
-static void UnsetFocus(Widget);
-static void UnsetICFocus(Widget, XawVendorShellExtPart*);
-static void VendorShellDestroyed(Widget, XtPointer, XtPointer);
-
-/*
- * From Vendor.c
- */
-void XawVendorShellExtResize(Widget);
-void XawVendorStructureNotifyHandler(Widget, XtPointer, XEvent*, Boolean*);
-
-
-/*
- * From Xt/Resources.c
- */
-void _XtCopyFromArg(XtArgVal src, char*, unsigned int);
-
-static XtResource resources[] =
-{
- {
- XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet),
- Offset (font_set), XtRString, XtDefaultFontSet
- },
- {
- XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
- Offset (foreground), XtRString, (XtPointer)"XtDefaultForeground"
- },
- {
- XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
- Offset (background), XtRString, (XtPointer)"XtDefaultBackground"
- },
- {
- XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
- Offset (bg_pixmap), XtRImmediate, (XtPointer) XtUnspecifiedPixmap
- },
- {
- XtNinsertPosition, XtCTextPosition, XtRInt, sizeof (XawTextPosition),
- Offset (cursor_position), XtRImmediate, (XtPointer) 0
- }
-};
-#undef Offset
-
-
-static VendorShellWidget SearchVendorShell(Widget w)
-{
- while(w && !XtIsShell(w)) w = XtParent(w);
- if (w && XtIsVendorShell(w)) return((VendorShellWidget)w);
- return(NULL);
-}
-
-static XContext extContext = (XContext)NULL;
-
-static XawVendorShellExtPart *
-SetExtPart(VendorShellWidget w, XawVendorShellExtWidget vew)
-{
- contextDataRec *contextData;
-
- if (extContext == (XContext)NULL) extContext = XUniqueContext();
-
- contextData = XtNew(contextDataRec);
- contextData->parent = (Widget)w;
- contextData->ve = (Widget)vew;
- if (XSaveContext(XtDisplay(w), (Window)w, extContext, (char *)contextData)) {
- return(NULL);
- }
- return(&(vew->vendor_ext));
-}
-
-static XawVendorShellExtPart *
-GetExtPart(VendorShellWidget w)
-{
- contextDataRec *contextData;
- XawVendorShellExtWidget vew;
-
- if (XFindContext(XtDisplay(w), (Window)w, extContext,
- (XPointer*)&contextData)) {
- return(NULL);
- }
- vew = (XawVendorShellExtWidget)contextData->ve;
- return(&(vew->vendor_ext));
-}
-
-static Bool
-IsSharedIC(XawVendorShellExtPart * ve)
-{
- return( ve->ic.shared_ic );
-}
-
-static XawIcTableList
-GetIcTableShared(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
-
- for (p = ve->ic.ic_table; p; p = p->next) {
- if (p->widget == w) {
- if (IsSharedIC(ve)) {
- return(ve->ic.shared_ic_table);
- } else {
- return(p);
- }
- }
- }
- return(NULL);
-}
-
-static XawIcTableList
-GetIcTable(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
-
- for (p = ve->ic.ic_table; p; p = p->next) {
- if (p->widget == w) {
- return(p);
- }
- }
- return(NULL);
-}
-
-static XIMStyle
-GetInputStyleOfIC(XawVendorShellExtPart *ve)
-{
-
- if (!ve) return((XIMStyle)0);
- return(ve->ic.input_style);
-}
-
-/*ARGSUSED*/
-static void
-ConfigureCB(Widget w, XtPointer closure, XEvent *event, Boolean *unused)
-{
- XawIcTableList p;
- XawVendorShellExtPart *ve;
- VendorShellWidget vw;
- XVaNestedList pe_attr;
- XRectangle pe_area;
- XawTextMargin *margin;
-
- if (event->type != ConfigureNotify) return;
-
- if ((vw = SearchVendorShell(w)) == NULL) return;
-
- if ((ve = GetExtPart(vw)) != NULL) {
- if (IsSharedIC(ve)) return;
- if ((ve->im.xim == NULL) ||
- ((p = GetIcTableShared(w, ve)) == NULL) ||
- (p->xic == NULL) || !(p->input_style & XIMPreeditPosition)) return;
- pe_area.x = 0;
- pe_area.y = 0;
- pe_area.width = w->core.width;
- pe_area.height = w->core.height;
- margin = &(((TextWidget)w)->text.margin);
- pe_area.x += margin->left;
- pe_area.y += margin->top;
- pe_area.width -= (margin->left + margin->right - 1);
- pe_area.height -= (margin->top + margin->bottom - 1);
-
- pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL);
- XSetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL);
- XtFree(pe_attr);
- }
-}
-
-static XContext errContext = (XContext)NULL;
-
-static Widget SetErrCnxt(Widget w, XIM xim)
-{
- contextErrDataRec *contextErrData;
-
- if (errContext == (XContext)NULL) errContext = XUniqueContext();
-
- contextErrData = XtNew(contextErrDataRec);
- contextErrData->widget = w;
- contextErrData->xim = xim;
- if (XSaveContext(XtDisplay(w), (Window)xim, errContext,
- (char *)contextErrData)) {
- return(NULL);
- }
- return(contextErrData->widget);
-}
-
-#if 0
-static Widget
-GetErrCnxt(XIM error_im)
-{
- contextErrDataRec *contextErrData;
-
- if (XFindContext(XDisplayOfIM(error_im), (Window)error_im, errContext,
- (XPointer*)&contextErrData)) {
- return(NULL);
- }
- return(contextErrData->widget);
-}
-#endif
-
-static void
-CloseIM(XawVendorShellExtPart *ve)
-{
- if (ve->im.xim)
- XCloseIM(ve->im.xim);
-}
-
-static unsigned int
-SetVendorShellHeight(XawVendorShellExtPart* ve, unsigned int height)
-{
- Arg args[2];
- Cardinal i = 0;
-
- if (ve->im.area_height < height || height == 0) {
- XtSetArg(args[i], XtNheight,
- (ve->parent->core.height + height - ve->im.area_height));
- ve->im.area_height = height;
- XtSetValues(ve->parent, args, 1);
- }
- return(ve->im.area_height);
-}
-
-static void
-DestroyAllIM(XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
- contextErrDataRec *contextErrData;
-
- /*
- * Destory all ICs
- */
- if (IsSharedIC(ve)) {
- if ((p = ve->ic.shared_ic_table) && p->xic) {
- DestroyIC(p->widget, ve);
- p->xic = NULL;
- p->ic_focused = FALSE;
- }
- } else {
- for (p = ve->ic.ic_table; p; p = p->next) {
- if (p->xic == NULL) continue;
- DestroyIC(p->widget, ve);
- p->xic = NULL;
- p->ic_focused = FALSE;
- }
- }
- if (!ve->im.xim) return;
- /*
- * Close Input Method
- */
- if (!XFindContext(XDisplayOfIM(ve->im.xim), (Window)ve->im.xim, errContext,
- (XPointer*)&contextErrData)) {
- if (contextErrData) XtFree((char *)contextErrData);
- }
- XDeleteContext(XDisplayOfIM(ve->im.xim), (Window)ve->im.xim, errContext);
- CloseIM(ve);
- ve->im.xim = NULL;
-
- /*
- * resize vendor shell to core size
- */
- (void) SetVendorShellHeight(ve, 0);
- /*
- XawVendorShellExtResize(vw);
- */
- return;
-}
-
-static void
-FreeAllDataOfVendorShell(XawVendorShellExtPart *ve, VendorShellWidget vw)
-{
- XawIcTableList p, next;
- contextErrDataRec *contextErrData;
-
- if (!XFindContext(XtDisplay(vw), (Window)vw, extContext,
- (XPointer*)&contextErrData)) {
- if (contextErrData) XtFree((char *)contextErrData);
- }
- XDeleteContext(XtDisplay(vw), (Window)vw, extContext);
- if (ve->ic.shared_ic_table)
- XtFree((char *)ve->ic.shared_ic_table);
- if (ve->im.resources) XtFree((char *)ve->im.resources);
- for (p = ve->ic.ic_table; p; p = next) {
- next = p->next;
- XtFree((char *)p);
- }
-}
-
-static void
-VendorShellDestroyed(Widget w, XtPointer cl_data, XtPointer ca_data)
-{
- XawVendorShellExtPart *ve;
-
- if ( ( ve = GetExtPart( (VendorShellWidget) w ) ) == NULL ) return;
- DestroyAllIM( ve );
- FreeAllDataOfVendorShell( ve, (VendorShellWidget) w );
- return;
-}
-
-#if 0
-static int
-IOErrorHandler(XIM error_im)
-{
- VendorShellWidget vw;
- XawVendorShellExtPart * ve;
-
- if ((vw = (VendorShellWidget)GetErrCnxt(error_im)) == NULL
- || (ve = GetExtPart(vw)) == NULL) return(0);
-
- DestroyAllIM(ve);
- return(0);
-}
-#endif
-
-/*
- * Attempt to open an input method
- */
-
-static void
-OpenIM(XawVendorShellExtPart *ve)
-{
- int i;
- char *p, *s, *ns, *end, *pbuf, buf[32];
- XIM xim = NULL;
- XIMStyles *xim_styles;
- XIMStyle input_style = 0;
- Boolean found;
-
- if (ve->im.open_im == False) return;
- ve->im.xim = NULL;
- if (ve->im.input_method == NULL) {
- if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
- xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL);
- } else {
- /* no fragment can be longer than the whole string */
- Cardinal len = strlen (ve->im.input_method) + 5;
-
- if (len < sizeof buf) pbuf = buf;
- else pbuf = XtMalloc (len);
-
- if (pbuf == NULL) return;
-
- for(ns=s=ve->im.input_method; ns && *s;) {
- /* skip any leading blanks */
- while (*s && isspace(*s)) s++;
- if (!*s) break;
- if ((ns = end = strchr(s, ',')) == NULL)
- end = s + strlen(s);
- /* If there is a spurious comma end can be the same as s */
- if (end > s) {
- /* strip any trailing blanks */
- while (isspace(*(end - 1))) end--;
-
- strcpy (pbuf, "@im=");
- strncat (pbuf, s, end - s);
- pbuf[end - s + 4] = '\0';
- }
-
- if ((p = XSetLocaleModifiers(pbuf)) != NULL && *p
- && (xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL)) != NULL)
- break;
-
- s = ns + 1;
- }
-
- if (pbuf != buf) XtFree (pbuf);
- }
- if (xim == NULL) {
- if ((p = XSetLocaleModifiers("")) != NULL) {
- xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL);
- }
- }
- if (xim == NULL) {
- XtAppWarning(XtWidgetToApplicationContext(ve->parent),
- "Input Method Open Failed");
- return;
- }
- if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL)
- || !xim_styles) {
- XtAppWarning(XtWidgetToApplicationContext(ve->parent),
- "input method doesn't support any style");
- XCloseIM(xim);
- return;
- }
- found = False;
- for(ns = s = ve->im.preedit_type; s && !found;) {
- while (*s && isspace(*s)) s++;
- if (!*s) break;
- if ((ns = end = strchr(s, ',')) == NULL)
- end = s + strlen(s);
- else
- ns++;
- if (end > s)
- while (isspace(*(end - 1))) end--;
-
- if (!strncmp(s, "OverTheSpot", end - s)) {
- input_style = (XIMPreeditPosition | XIMStatusArea);
- } else if (!strncmp(s, "OffTheSpot", end - s)) {
- input_style = (XIMPreeditArea | XIMStatusArea);
- } else if (!strncmp(s, "Root", end - s)) {
- input_style = (XIMPreeditNothing | XIMStatusNothing);
- }
- for (i = 0; (unsigned short)i < xim_styles->count_styles; i++)
- if (input_style == xim_styles->supported_styles[i]) {
- ve->ic.input_style = input_style;
- SetErrCnxt(ve->parent, xim);
- ve->im.xim = xim;
- found = True;
- break;
- }
-
- s = ns;
- }
- XFree(xim_styles);
-
- if (!found) {
- XCloseIM(xim);
- XtAppWarning(XtWidgetToApplicationContext(ve->parent),
- "input method doesn't support my input style");
- }
-}
-
-static Bool
-ResizeVendorShell_Core(VendorShellWidget vw, XawVendorShellExtPart *ve,
- XawIcTableList p)
-{
- XVaNestedList pe_attr, st_attr;
- XRectangle pe_area, st_area;
- XRectangle *get_pe_area = NULL, *get_st_area = NULL;
-
- st_area.width = 0;
- if (p->input_style & XIMStatusArea) {
- st_attr = XVaCreateNestedList(0, XNArea, &get_st_area, NULL);
- XGetICValues(p->xic, XNStatusAttributes, st_attr, NULL);
- XFree(st_attr);
- if (p->xic == NULL) {
- return(FALSE);
- }
- st_area.x = 0;
- st_area.y = vw->core.height - ve->im.area_height;
- st_area.width = get_st_area->width;
- st_area.height = get_st_area->height;
- XFree(get_st_area);
- st_attr = XVaCreateNestedList(0, XNArea, &st_area, NULL);
- XSetICValues(p->xic, XNStatusAttributes, st_attr, NULL);
- XFree(st_attr);
- if (p->xic == NULL) {
- return(FALSE);
- }
- }
- if (p->input_style & XIMPreeditArea) {
- pe_attr = XVaCreateNestedList(0, XNArea, &get_pe_area, NULL);
- XGetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL);
- XFree(pe_attr);
- if (p->xic == NULL) {
- return(FALSE);
- }
- pe_area.x = st_area.width;
- pe_area.y = vw->core.height - ve->im.area_height;
- pe_area.width = vw->core.width;
- pe_area.height = get_pe_area->height;
- if (p->input_style & XIMStatusArea) {
- pe_area.width -= st_area.width;
- }
- XFree(get_pe_area);
- pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL);
- XSetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL);
- XFree(pe_attr);
- }
- return(TRUE);
-}
-
-static void
-ResizeVendorShell(VendorShellWidget vw, XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
-
- if (IsSharedIC(ve)) {
- p = ve->ic.shared_ic_table;
- if (p->xic == NULL) return;
- ResizeVendorShell_Core(vw, ve, p);
- return;
- }
- for (p = ve->ic.ic_table; p; p = p->next) {
- if (p->xic == NULL) continue;
- if (ResizeVendorShell_Core(vw, ve, p) == FALSE) return;
- }
-}
-
-static XawIcTableList
-CreateIcTable(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList table;
-
- table = (XawIcTableList) XtMalloc(sizeof(XawIcTablePart));
- if (table == NULL) return(NULL);
- table->widget = w;
- table->xic = NULL;
- table->flg = table->prev_flg = 0;
- table->font_set = NULL;
- table->foreground = table->background = 0xffffffff;
- table->bg_pixmap = 0;
- table->cursor_position = 0xffff;
- table->line_spacing = 0;
- table->ic_focused = FALSE;
- table->openic_error = FALSE;
- return(table);
-}
-
-static Bool
-RegisterToVendorShell(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList table;
-
- if ((table = CreateIcTable(w, ve)) == NULL) return(FALSE);
- table->next = ve->ic.ic_table;
- ve->ic.ic_table = table;
- return(TRUE);
-}
-
-static void
-UnregisterFromVendorShell(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList *prev, p;
-
- for (prev = &ve->ic.ic_table; (p = *prev) != NULL; prev = &p->next) {
- if (p->widget == w) {
- *prev = p->next;
- XtFree((char *)p);
- break;
- }
- }
- return;
-}
-
-static void
-SetICValuesShared(Widget w, XawVendorShellExtPart *ve,
- XawIcTableList p, Bool check)
-{
- XawIcTableList pp;
-
- if ((pp = GetIcTable(w, ve)) == NULL) return;
- if (check == TRUE && CurrentSharedIcTable(ve) != pp) return;
-
- if (pp->prev_flg & CICursorP && p->cursor_position != pp->cursor_position) {
- p->cursor_position = pp->cursor_position;
- p->flg |= CICursorP;
- }
- if (pp->prev_flg & CIFontSet && p->font_set != pp->font_set) {
- p->font_set = pp->font_set;
- p->flg |= (CIFontSet|CICursorP);
- }
- if (pp->prev_flg & CIFg && p->foreground != pp->foreground) {
- p->foreground = pp->foreground;
- p->flg |= CIFg;
- }
- if (pp->prev_flg & CIBg && p->background != pp->background) {
- p->background = pp->background;
- p->flg |= CIBg;
- }
- if (pp->prev_flg & CIBgPixmap && p->bg_pixmap != pp->bg_pixmap) {
- p->bg_pixmap = pp->bg_pixmap;
- p->flg |= CIBgPixmap;
- }
- if (pp->prev_flg & CILineS && p->line_spacing != pp->line_spacing) {
- p->line_spacing = pp->line_spacing;
- p->flg |= CILineS;
- }
-}
-
-static Bool
-IsCreatedIC(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
-
- if (ve->im.xim == NULL) return(FALSE);
- if ((p = GetIcTableShared(w, ve)) == NULL) return(FALSE);
- if (p->xic == NULL) return(FALSE);
- return(TRUE);
-}
-
-static void
-SizeNegotiation(XawIcTableList p, unsigned int width, unsigned int height)
-{
- XRectangle pe_area, st_area;
- XVaNestedList pe_attr = NULL, st_attr = NULL;
- int ic_cnt = 0;
- XRectangle *pe_area_needed = NULL, *st_area_needed = NULL;
- XPointer ic_a[5];
-
- if (p->input_style & XIMPreeditArea) {
- pe_attr = XVaCreateNestedList(0, XNAreaNeeded, &pe_area_needed, NULL);
- ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++;
- }
- if (p->input_style & XIMStatusArea) {
- st_attr = XVaCreateNestedList(0, XNAreaNeeded, &st_area_needed, NULL);
- ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++;
- }
- ic_a[ic_cnt] = (XPointer) NULL;
-
- if (ic_cnt > 0) {
- XGetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], NULL);
- if (pe_attr) XFree(pe_attr);
- if (st_attr) XFree(st_attr);
- if (p->xic == NULL) {
- p->openic_error = True;
- return;
- }
- pe_attr = st_attr = NULL;
- ic_cnt = 0;
- if (p->input_style & XIMStatusArea) {
- st_area.height = st_area_needed->height;
- st_area.x = 0;
- st_area.y = height - st_area.height;
- if (p->input_style & XIMPreeditArea) {
- st_area.width = st_area_needed->width;
- } else {
- st_area.width = width;
- }
-
- XFree(st_area_needed);
- st_attr = XVaCreateNestedList(0, XNArea, &st_area, NULL);
- ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++;
- }
- if (p->input_style & XIMPreeditArea) {
- if (p->input_style & XIMStatusArea) {
- pe_area.x = st_area.width;
- pe_area.width = width - st_area.width;
- } else {
- pe_area.x = 0;
- pe_area.width = width;
- }
- pe_area.height = pe_area_needed->height;
- XFree(pe_area_needed);
- pe_area.y = height - pe_area.height;
- pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL);
- ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++;
- }
- ic_a[ic_cnt] = (XPointer) NULL;
- XSetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], NULL);
- if (pe_attr) XFree(pe_attr);
- if (st_attr) XFree(st_attr);
- if (p->xic == NULL) {
- p->openic_error = True;
- return;
- }
- }
-}
-
-static void
-CreateIC(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
- XPoint position;
- XRectangle pe_area, st_area;
- XVaNestedList pe_attr = NULL, st_attr = NULL;
- XPointer ic_a[20], pe_a[20], st_a[20];
- Dimension height = 0;
- int ic_cnt = 0, pe_cnt = 0, st_cnt = 0;
- XawTextMargin *margin;
-
- if (!XtIsRealized(w)) return;
- if (((ve->im.xim == NULL) || (p = GetIcTableShared(w, ve)) == NULL) ||
- p->xic || (p->openic_error != FALSE)) return;
-
- p->input_style = GetInputStyleOfIC(ve);
-
- if (IsSharedIC(ve)) SetICValuesShared(w, ve, p, FALSE);
- XFlush(XtDisplay(w));
-
- if (p->input_style & (XIMPreeditArea|XIMPreeditPosition|XIMStatusArea)) {
- if (p->flg & CIFontSet) {
- pe_a[pe_cnt] = (XPointer) XNFontSet; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->font_set; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNFontSet; st_cnt++;
- st_a[st_cnt] = (XPointer) p->font_set; st_cnt++;
- if (p->font_set) {
- height = maxAscentOfFontSet(p->font_set)
- + maxDescentOfFontSet(p->font_set);
- }
- height = SetVendorShellHeight(ve, height);
- }
- if (p->flg & CIFg) {
- pe_a[pe_cnt] = (XPointer) XNForeground; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->foreground; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNForeground; st_cnt++;
- st_a[st_cnt] = (XPointer) p->foreground; st_cnt++;
- }
- if (p->flg & CIBg) {
- pe_a[pe_cnt] = (XPointer) XNBackground; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->background; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNBackground; st_cnt++;
- st_a[st_cnt] = (XPointer) p->background; st_cnt++;
- }
- if (p->flg & CIBgPixmap) {
- pe_a[pe_cnt] = (XPointer) XNBackgroundPixmap; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->bg_pixmap; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNBackgroundPixmap; st_cnt++;
- st_a[st_cnt] = (XPointer) p->bg_pixmap; st_cnt++;
- }
- if (p->flg & CILineS) {
- pe_a[pe_cnt] = (XPointer) XNLineSpace; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->line_spacing; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNLineSpace; st_cnt++;
- st_a[st_cnt] = (XPointer) p->line_spacing; st_cnt++;
- }
- }
- if (p->input_style & XIMPreeditArea) {
- pe_area.x = 0;
- pe_area.y = ve->parent->core.height - height;
- pe_area.width = ve->parent->core.width;
- pe_area.height = height;
- pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++;
- }
- if (p->input_style & XIMPreeditPosition) {
- pe_area.x = 0;
- pe_area.y = 0;
- pe_area.width = w->core.width;
- pe_area.height = w->core.height;
- margin = &(((TextWidget)w)->text.margin);
- pe_area.x += margin->left;
- pe_area.y += margin->top;
- pe_area.width -= (margin->left + margin->right - 1);
- pe_area.height -= (margin->top + margin->bottom - 1);
- pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++;
- if (p->flg & CICursorP) {
- _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y);
- } else {
- position.x = position.y = 0;
- }
- pe_a[pe_cnt] = (XPointer) XNSpotLocation; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) &position; pe_cnt++;
- }
- if (p->input_style & XIMStatusArea) {
- st_area.x = 0;
- st_area.y = ve->parent->core.height - height;
- st_area.width = ve->parent->core.width;
- st_area.height = height;
- st_a[st_cnt] = (XPointer) XNArea; st_cnt++;
- st_a[st_cnt] = (XPointer) &st_area; st_cnt++;
- }
-
- ic_a[ic_cnt] = (XPointer) XNInputStyle; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) p->input_style; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) XNClientWindow; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) XtWindow(ve->parent); ic_cnt++;
- ic_a[ic_cnt] = (XPointer) XNFocusWindow; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) XtWindow(w); ic_cnt++;
-
- if (pe_cnt > 0) {
- pe_a[pe_cnt] = (XPointer) NULL;
- pe_attr = XVaCreateNestedList(0, pe_a[0], pe_a[1], pe_a[2], pe_a[3],
- pe_a[4], pe_a[5], pe_a[6], pe_a[7], pe_a[8],
- pe_a[9], pe_a[10], pe_a[11], pe_a[12],
- pe_a[13], pe_a[14], pe_a[15], pe_a[16],
- pe_a[17], pe_a[18], NULL);
- ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++;
- }
-
- if (st_cnt > 0) {
- st_a[st_cnt] = (XPointer) NULL;
- st_attr = XVaCreateNestedList(0, st_a[0], st_a[1], st_a[2], st_a[3],
- st_a[4], st_a[5], st_a[6], st_a[7], st_a[8],
- st_a[9], st_a[10], st_a[11], st_a[12],
- st_a[13], st_a[14], st_a[15], st_a[16],
- st_a[17], st_a[18], NULL);
- ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++;
- }
- ic_a[ic_cnt] = (XPointer) NULL;
-
- p->xic = XCreateIC(ve->im.xim, ic_a[0], ic_a[1], ic_a[2], ic_a[3],
- ic_a[4], ic_a[5], ic_a[6], ic_a[7], ic_a[8], ic_a[9],
- ic_a[10], ic_a[11], ic_a[12], ic_a[13], ic_a[14],
- ic_a[15], ic_a[16], ic_a[17], ic_a[18], NULL);
- if (pe_attr) XtFree(pe_attr);
- if (st_attr) XtFree(st_attr);
-
- if (p->xic == NULL) {
- p->openic_error = True;
- return;
- }
-
- SizeNegotiation(p, ve->parent->core.width, ve->parent->core.height);
-
- p->flg &= ~(CIFontSet | CIFg | CIBg | CIBgPixmap | CICursorP | CILineS);
-
- if (!IsSharedIC(ve)) {
- if (p->input_style & XIMPreeditPosition) {
- XtAddEventHandler(w, (EventMask)StructureNotifyMask, FALSE,
- (XtEventHandler)ConfigureCB, (Opaque)NULL);
- }
- }
-}
-
-static void
-SetICValues(Widget w, XawVendorShellExtPart *ve, Bool focus)
-{
- XawIcTableList p;
- XPoint position;
- XRectangle pe_area;
- XVaNestedList pe_attr = NULL, st_attr = NULL;
- XPointer ic_a[20], pe_a[20], st_a[20];
- int ic_cnt = 0, pe_cnt = 0, st_cnt = 0;
- XawTextMargin *margin;
- int height = 0;
-
- if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) ||
- (p->xic == NULL)) return;
-
- if (IsSharedIC(ve)) SetICValuesShared(w, ve, p, TRUE);
- XFlush(XtDisplay(w));
- if (focus == FALSE &&
- !(p->flg & (CIFontSet | CIFg | CIBg |
- CIBgPixmap | CICursorP | CILineS))) return;
-#ifdef SPOT
- if ((p->input_style & XIMPreeditPosition)
- && ((!IsSharedIC(ve) && ((p->flg & ~CIICFocus) == CICursorP))
- || (IsSharedIC(ve) && p->flg == CICursorP))) {
- _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y);
- _XipChangeSpot(p->xic, position.x, position.y);
- p->flg &= ~CICursorP;
- return;
- }
-#endif
-
- if (p->input_style & (XIMPreeditArea|XIMPreeditPosition|XIMStatusArea)) {
- if (p->flg & CIFontSet) {
- pe_a[pe_cnt] = (XPointer) XNFontSet; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->font_set; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNFontSet; st_cnt++;
- st_a[st_cnt] = (XPointer) p->font_set; st_cnt++;
- if (p->font_set) {
- height = maxAscentOfFontSet(p->font_set)
- + maxDescentOfFontSet(p->font_set);
- }
- height = SetVendorShellHeight(ve, height);
- }
- if (p->flg & CIFg) {
- pe_a[pe_cnt] = (XPointer) XNForeground; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->foreground; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNForeground; st_cnt++;
- st_a[st_cnt] = (XPointer) p->foreground; st_cnt++;
- }
- if (p->flg & CIBg) {
- pe_a[pe_cnt] = (XPointer) XNBackground; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->background; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNBackground; st_cnt++;
- st_a[st_cnt] = (XPointer) p->background; st_cnt++;
- }
- if (p->flg & CIBgPixmap) {
- pe_a[pe_cnt] = (XPointer) XNBackgroundPixmap; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->bg_pixmap; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNBackgroundPixmap; st_cnt++;
- st_a[st_cnt] = (XPointer) p->bg_pixmap; st_cnt++;
- }
- if (p->flg & CILineS) {
- pe_a[pe_cnt] = (XPointer) XNLineSpace; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) p->line_spacing; pe_cnt++;
- st_a[st_cnt] = (XPointer) XNLineSpace; st_cnt++;
- st_a[st_cnt] = (XPointer) p->line_spacing; st_cnt++;
- }
- }
- if (p->input_style & XIMPreeditPosition) {
- if (p->flg & CICursorP) {
- _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y);
- pe_a[pe_cnt] = (XPointer) XNSpotLocation; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) &position; pe_cnt++;
- }
- }
- if (IsSharedIC(ve)) {
- if (p->input_style & XIMPreeditPosition) {
- pe_area.x = 0;
- pe_area.y = 0;
- pe_area.width = w->core.width;
- pe_area.height = w->core.height;
- margin = &(((TextWidget)w)->text.margin);
- pe_area.x += margin->left;
- pe_area.y += margin->top;
- pe_area.width -= (margin->left + margin->right - 1);
- pe_area.height -= (margin->top + margin->bottom - 1);
- pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++;
- pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++;
- }
- }
-
- if (pe_cnt > 0) {
- pe_a[pe_cnt] = (XPointer) NULL;
- pe_attr = XVaCreateNestedList(0, pe_a[0], pe_a[1], pe_a[2], pe_a[3],
- pe_a[4], pe_a[5], pe_a[6], pe_a[7],
- pe_a[8], pe_a[9], pe_a[10], pe_a[11],
- pe_a[12], pe_a[13], pe_a[14], pe_a[15],
- pe_a[16], pe_a[17], pe_a[18], NULL);
- ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++;
- }
- if (st_cnt > 0) {
- st_a[st_cnt] = (XPointer) NULL;
- st_attr = XVaCreateNestedList(0, st_a[0], st_a[1], st_a[2], st_a[3],
- st_a[4], st_a[5], st_a[6], st_a[7],
- st_a[8], st_a[9], st_a[10], st_a[11],
- st_a[12], st_a[13], st_a[14], st_a[15],
- st_a[16], st_a[17], st_a[18], NULL);
- ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++;
- }
- if (focus == TRUE) {
- ic_a[ic_cnt] = (XPointer) XNFocusWindow; ic_cnt++;
- ic_a[ic_cnt] = (XPointer) XtWindow(w); ic_cnt++;
- }
- if (ic_cnt > 0) {
- ic_a[ic_cnt] = (XPointer) NULL;
- XSetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], ic_a[4],
- ic_a[5], ic_a[6], ic_a[7], ic_a[8], ic_a[9], ic_a[10],
- ic_a[11], ic_a[12], ic_a[13], ic_a[14], ic_a[15],
- ic_a[16], ic_a[17], ic_a[18], NULL);
- if (pe_attr) XtFree(pe_attr);
- if (st_attr) XtFree(st_attr);
- }
-
- if (IsSharedIC(ve) && p->flg & CIFontSet)
- SizeNegotiation(p, ve->parent->core.width, ve->parent->core.height);
-
- p->flg &= ~(CIFontSet | CIFg | CIBg | CIBgPixmap | CICursorP | CILineS);
-}
-
-static void
-SharedICChangeFocusWindow(Widget w, XawVendorShellExtPart *ve,
- XawIcTableList p)
-{
- XawIcTableList pp;
-
- if (w == NULL) {
- ve->ic.current_ic_table = NULL;
- return;
- }
- if ((pp = GetIcTable(w, ve)) == NULL) return;
- ve->ic.current_ic_table = pp;
- SetICValues(w, ve, TRUE);
-}
-
-static XawIcTableList
-CurrentSharedIcTable(XawVendorShellExtPart *ve)
-{
- return(ve->ic.current_ic_table);
-}
-
-static void
-SetICFocus(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList p, pp;
-
- if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) ||
- (p->xic == NULL)) return;
-
- if (IsSharedIC(ve)) {
- pp = CurrentSharedIcTable(ve);
- if (pp == NULL || pp->widget != w) {
- SharedICChangeFocusWindow(w, ve, p);
- }
- }
- if (p->flg & CIICFocus && p->ic_focused == FALSE) {
- p->ic_focused = TRUE;
- XSetICFocus(p->xic);
- }
- p->flg &= ~CIICFocus;
-}
-
-static void
-UnsetICFocus(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList p, pp;
-
- if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) ||
- (p->xic == NULL)) return;
-
- if (IsSharedIC(ve) && (pp = CurrentSharedIcTable(ve))) {
- if (pp->widget != w) {
- return;
- }
- SharedICChangeFocusWindow(NULL, ve, p);
- }
- if (p->ic_focused == TRUE) {
- XUnsetICFocus(p->xic);
- p->ic_focused = FALSE;
- }
-}
-
-static void
-SetValues(Widget w, XawVendorShellExtPart *ve,
- ArgList args, Cardinal num_args)
-{
- ArgList arg;
-
- XrmName argName;
- XrmResourceList xrmres;
- Cardinal i;
- XawIcTablePart *p, save_tbl;
-
- if ((p = GetIcTable(w, ve)) == NULL) return;
-
- memcpy(&save_tbl, p, sizeof(XawIcTablePart));
-
- for (arg = args ; num_args != 0; num_args--, arg++) {
- argName = XrmStringToName(arg->name);
- for (xrmres = (XrmResourceList)ve->im.resources, i = 0;
- i < ve->im.num_resources; i++, xrmres++) {
- if (argName == xrmres->xrm_name) {
- _XtCopyFromArg(arg->value,
- (char *)p - xrmres->xrm_offset - 1,
- xrmres->xrm_size);
- break;
- }
- }
- }
- if (p->font_set != save_tbl.font_set) {
- p->flg |= CIFontSet;
- }
- if (p->foreground != save_tbl.foreground) {
- p->flg |= CIFg;
- }
- if (p->background !=save_tbl.background) {
- p->flg |= CIBg;
- }
- if (p->bg_pixmap != save_tbl.bg_pixmap) {
- p->flg |= CIBgPixmap;
- }
- if (p->cursor_position != save_tbl.cursor_position) {
- p->flg |= CICursorP;
- }
- if (p->line_spacing != save_tbl.line_spacing) {
- p->flg |= CILineS;
- }
- p->prev_flg |= p->flg;
-}
-
-static void
-SetFocus(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
- if ((p = GetIcTableShared(w, ve)) == NULL) return;
-
- if ( p->ic_focused == FALSE || IsSharedIC(ve)) {
- p->flg |= CIICFocus;
- }
- p->prev_flg |= p->flg;
-}
-
-static void
-DestroyIC(Widget w, XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
-
- if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) ||
- (p->xic == NULL)) return;
- if (IsSharedIC(ve)) {
- if (GetIcTable(w, ve) == ve->ic.current_ic_table) {
- UnsetICFocus(w, ve);
- }
- return;
- }
- XDestroyIC(p->xic);
- if (!IsSharedIC(ve)) {
- if (p->input_style & XIMPreeditPosition) {
- XtRemoveEventHandler(w, (EventMask)StructureNotifyMask, FALSE,
- (XtEventHandler)ConfigureCB, (Opaque)NULL);
- }
- }
-}
-
-static void
-SetFocusValues(Widget inwidg, ArgList args, Cardinal num_args, Bool focus)
-{
- XawVendorShellExtPart *ve;
- VendorShellWidget vw;
-
- if ((vw = SearchVendorShell(inwidg)) == NULL) return;
- if ((ve = GetExtPart(vw)) != NULL) {
- if (num_args > 0) SetValues(inwidg, ve, args, num_args);
- if (focus) SetFocus(inwidg, ve);
- if (XtIsRealized((Widget)vw) && ve->im.xim) {
- if (IsCreatedIC(inwidg, ve)) {
- SetICValues(inwidg, ve, FALSE);
- if (focus) SetICFocus(inwidg, ve);
- } else {
- CreateIC(inwidg, ve);
- SetICFocus(inwidg, ve);
- }
- }
- }
-}
-
-static void
-UnsetFocus(Widget inwidg)
-{
- XawVendorShellExtPart *ve;
- VendorShellWidget vw;
- XawIcTableList p;
-
- if ((vw = SearchVendorShell(inwidg)) == NULL) return;
- if ((ve = GetExtPart(vw)) != NULL) {
- if ((p = GetIcTableShared(inwidg, ve)) == NULL) return;
- if (p->flg & CIICFocus) {
- p->flg &= ~CIICFocus;
- }
- p->prev_flg &= ~CIICFocus;
- if (ve->im.xim && XtIsRealized((Widget)vw) && p->xic) {
- UnsetICFocus(inwidg, ve);
- }
- }
-}
-
-static Bool
-IsRegistered(Widget w, XawVendorShellExtPart* ve)
-{
- XawIcTableList p;
-
- for (p = ve->ic.ic_table; p; p = p->next)
- {
- if (p->widget == w) return(TRUE);
- }
- return(FALSE);
-}
-
-static void
-Register(Widget inwidg, XawVendorShellExtPart* ve)
-{
- if (ve->im.xim == NULL)
- {
- OpenIM(ve);
- }
-
- if (IsRegistered(inwidg, ve)) return;
-
- if (RegisterToVendorShell(inwidg, ve) == FALSE) return;
-
- if (ve->im.xim == NULL) return;
-
- if (XtIsRealized(ve->parent))
- {
- CreateIC(inwidg, ve);
- SetICFocus(inwidg, ve);
- }
-}
-
-static Bool
-NoRegistered(XawVendorShellExtPart* ve)
-{
- if (ve->ic.ic_table == NULL) return(TRUE);
- return(FALSE);
-}
-
-static void
-Unregister(Widget inwidg, XawVendorShellExtPart *ve)
-{
- if (!IsRegistered(inwidg, ve)) return;
-
- DestroyIC(inwidg, ve);
-
- UnregisterFromVendorShell(inwidg, ve);
-
- if (NoRegistered(ve))
- {
- CloseIM(ve);
- ve->im.xim = NULL;
- /*
- * resize vendor shell to core size
- */
- (void) SetVendorShellHeight(ve, 0);
- }
-}
-
-static void
-AllCreateIC(XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
-
- if (ve->im.xim == NULL) return;
- if (IsSharedIC(ve) && ve->ic.ic_table[0].widget) {
- p = ve->ic.shared_ic_table;
- if (p->xic == NULL)
- CreateIC(ve->ic.ic_table[0].widget, ve);
- SetICFocus(ve->ic.ic_table[0].widget, ve);
- return;
- }
- for (p = ve->ic.ic_table; p; p = p->next) {
- if (p->xic == NULL)
- CreateIC(p->widget, ve);
- }
- for (p = ve->ic.ic_table; p; p = p->next) {
- SetICFocus(p->widget, ve);
- }
-}
-
-
-static void
-Reconnect(XawVendorShellExtPart *ve)
-{
- XawIcTableList p;
-
- ve->im.open_im = True;
- if (ve->im.xim == NULL) {
- OpenIM(ve);
- }
- if (ve->im.xim == NULL) return;
-
- if (IsSharedIC(ve)) {
- p = ve->ic.shared_ic_table;
- p->flg = p->prev_flg;
- p->openic_error = FALSE;
- } else {
- for (p = ve->ic.ic_table; p; p = p->next) {
- p->flg = p->prev_flg;
- p->openic_error = FALSE;
- }
- }
- AllCreateIC(ve);
-}
-
-
-static void
-CompileResourceList(XtResourceList res, unsigned int num_res)
-{
- unsigned int count;
-
-#define xrmres ((XrmResourceList) res)
- for (count = 0; count < num_res; res++, count++) {
- xrmres->xrm_name = XrmPermStringToQuark(res->resource_name);
- xrmres->xrm_class = XrmPermStringToQuark(res->resource_class);
- xrmres->xrm_type = XrmPermStringToQuark(res->resource_type);
- xrmres->xrm_offset = -res->resource_offset - 1;
- xrmres->xrm_default_type = XrmPermStringToQuark(res->default_type);
- }
-#undef xrmres
-}
-
-static Bool
-Initialize(VendorShellWidget vw, XawVendorShellExtPart *ve)
-{
- if (!XtIsVendorShell((Widget)vw)) return(FALSE);
- ve->parent = (Widget)vw;
- ve->im.xim = NULL;
- ve->im.area_height = 0;
- ve->im.resources = (XrmResourceList)XtMalloc(sizeof(resources));
- if (ve->im.resources == NULL) return(FALSE);
- memcpy((char *)ve->im.resources, (char *)resources, sizeof(resources));
- ve->im.num_resources = XtNumber(resources);
- CompileResourceList( (XtResourceList) ve->im.resources,
- ve->im.num_resources );
- if ((ve->ic.shared_ic_table = CreateIcTable( (Widget)vw, ve)) == NULL)
- return(FALSE);
- ve->ic.current_ic_table = NULL;
- ve->ic.ic_table = NULL;
- return(TRUE);
-}
-
-
-/* Destroy()
- *
- * This frees all (most?) of the resources malloced by XawIm.
- * It is called by _XawImDestroy, which is called by Vendor.c's
- * VendorExt's Destroy method. Sheeran, Omron KK, 93/08/05 */
-
-static void
-Destroy(Widget w, XawVendorShellExtPart *ve)
-{
- contextDataRec *contextData;
- contextErrDataRec *contextErrData;
-
- if (!XtIsVendorShell( w ) )
- return;
- XtFree( (char*) ve->im.resources );
-
- if (extContext != (XContext)NULL &&
- !XFindContext (XtDisplay (w), (Window)w,
- extContext, (XPointer*)&contextData))
- XtFree( (char*) contextData );
-
- if (errContext != (XContext)NULL &&
- !XFindContext (XDisplayOfIM( ve->im.xim ), (Window) ve->im.xim,
- errContext, (XPointer*) &contextErrData))
- XtFree( (char*) contextErrData );
-}
-
-/*********************************************
- *
- * SEMI-PRIVATE FUNCTIONS
- * For use by other Xaw modules
- *
- ********************************************/
-
-void
-_XawImResizeVendorShell(Widget w)
-{
- XawVendorShellExtPart *ve;
-
- if ( ( ve = GetExtPart( (VendorShellWidget) w ) ) && ve->im.xim ) {
- ResizeVendorShell( (VendorShellWidget) w, ve );
- }
-}
-
-
-Dimension
-_XawImGetShellHeight(Widget w)
-{
- XawVendorShellExtPart *ve;
-
- if (!XtIsVendorShell( w ) ) return( w->core.height );
- if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL ) {
- return( w->core.height - ve->im.area_height );
- }
- return( w->core.height );
-}
-
-void
-_XawImRealize(Widget w)
-{
- XawVendorShellExtPart *ve;
-
- if ( !XtIsRealized( w ) || !XtIsVendorShell( w ) ) return;
- if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL ) {
- XtAddEventHandler( w, (EventMask)StructureNotifyMask, FALSE,
- XawVendorStructureNotifyHandler, (XtPointer)NULL );
- AllCreateIC(ve);
- }
-}
-
-void
-_XawImInitialize(Widget w, Widget ext)
-{
- XawVendorShellExtPart *ve;
-
- if ( !XtIsVendorShell( w ) ) return;
- if ( (ve = SetExtPart( (VendorShellWidget) w, (XawVendorShellExtWidget)ext )) != NULL ) {
- if ( Initialize( (VendorShellWidget) w, ve ) == FALSE ) return;
- XtAddCallback( w, XtNdestroyCallback, VendorShellDestroyed,
- (XtPointer) NULL );
- }
-}
-
-void
-_XawImReconnect(Widget inwidg)
-{
- XawVendorShellExtPart *ve;
- VendorShellWidget vw;
-
- if ((vw = SearchVendorShell(inwidg)) == NULL) return;
- if ((ve = GetExtPart(vw)) != NULL) {
- Reconnect(ve);
- }
-}
-
-void
-_XawImRegister(Widget inwidg)
-{
- XawVendorShellExtPart *ve;
- VendorShellWidget vw;
-
- if ((vw = SearchVendorShell(inwidg)) == NULL) return;
- if ((ve = GetExtPart(vw)) != NULL) {
- Register(inwidg, ve);
- }
-}
-
-void
-_XawImUnregister(Widget inwidg)
-{
- XawVendorShellExtPart *ve;
- VendorShellWidget vw;
-
- if ((vw = SearchVendorShell(inwidg)) == NULL) return;
- if ((ve = GetExtPart(vw)) != NULL) {
- Unregister(inwidg, ve);
- }
-}
-
-void
-_XawImSetValues(Widget inwidg, ArgList args, Cardinal num_args)
-{
- SetFocusValues( inwidg, args, num_args, FALSE );
-}
-
-void
-_XawImSetFocusValues(Widget inwidg, ArgList args, Cardinal num_args)
-{
- SetFocusValues(inwidg, args, num_args, TRUE);
-}
-
-void
-_XawImUnsetFocus(Widget inwidg)
-{
- UnsetFocus(inwidg);
-}
-
-int
-_XawImWcLookupString(Widget inwidg, XKeyPressedEvent *event,
- wchar_t* buffer_return, int bytes_buffer,
- KeySym *keysym_return)
-{
- XawVendorShellExtPart* ve;
- VendorShellWidget vw;
- XawIcTableList p;
- int i, ret;
- char tmp_buf[64], *tmp_p;
- wchar_t* buf_p;
-
- if ((vw = SearchVendorShell(inwidg)) && (ve = GetExtPart(vw)) &&
- ve->im.xim && (p = GetIcTableShared(inwidg, ve)) && p->xic) {
- return(XwcLookupString(p->xic, event, buffer_return, bytes_buffer/sizeof(wchar_t),
- keysym_return, NULL));
- }
- ret = XLookupString( event, tmp_buf, sizeof(tmp_buf), keysym_return,
- NULL );
- for ( i = 0, tmp_p = tmp_buf, buf_p = buffer_return; i < ret; i++ ) {
- *buf_p++ = _Xaw_atowc(*tmp_p++);
- }
- return( ret );
-}
-
-int
-_XawLookupString(Widget w, XKeyEvent *event, char *buffer_return, int buffer_size,
- KeySym *keysym_return)
-{
- XawVendorShellExtPart *ve;
- VendorShellWidget vw;
- XawIcTableList p;
-
- if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw))
- && ve->im.xim && (p = GetIcTableShared(w, ve)) && p->xic)
- return (XmbLookupString(p->xic, event, buffer_return, buffer_size,
- keysym_return, NULL));
-
- return (XLookupString(event, buffer_return, buffer_size,
- keysym_return, NULL));
-}
-
-int
-_XawImGetImAreaHeight(Widget w)
-{
- XawVendorShellExtPart *ve;
- VendorShellWidget vw;
-
- if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw))) {
- return(ve->im.area_height);
- }
- return(0);
-}
-
-void
-_XawImCallVendorShellExtResize(Widget w)
-{
- VendorShellWidget vw;
-
- if ((vw = SearchVendorShell(w)) && GetExtPart(vw)) {
- XawVendorShellExtResize((Widget)vw);
- }
-}
-
-
-/* _XawImDestroy()
- *
- * This should be called by the VendorExt from its
- * core Destroy method. Sheeran, Omron KK 93/08/05 */
-
-void
-_XawImDestroy(Widget w, Widget ext)
-{
- XawVendorShellExtPart *ve;
-
- if ( !XtIsVendorShell( w ) ) return;
- if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL )
- Destroy( w, ve );
-}
+/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OMRON not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. OMRON makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Author: Seiji Kuwari OMRON Corporation + * kuwa@omron.co.jp + * kuwa%omron.co.jp@uunet.uu.net + */ + + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/ShellP.h> +#include <X11/Xaw/TextP.h> +#include <X11/Xaw/MultiSrc.h> +#include <X11/Xaw/MultiSinkP.h> +#include <X11/Xaw/XawImP.h> +#include <X11/Xaw/VendorEP.h> +#include "XawI18n.h" +#include <ctype.h> + +#include <stdarg.h> + +#define maxAscentOfFontSet(fontset) \ + ( - (XExtentsOfFontSet((fontset)))->max_logical_extent.y) + +#define maxHeightOfFontSet(fontset) \ + ((XExtentsOfFontSet((fontset)))->max_logical_extent.height) + +#define maxDescentOfFontSet(fontset) \ + (maxHeightOfFontSet(fontset) - maxAscentOfFontSet(fontset)) + +#define Offset(field) (XtOffsetOf(XawIcTablePart, field)) + +/***************************************************** + * + * Forward reference prototypes + * + *****************************************************/ + +/* + * Prototypes + */ +static void AllCreateIC(XawVendorShellExtPart*); +static void CloseIM(XawVendorShellExtPart*); +static void CompileResourceList(XtResourceList, unsigned int); +static void ConfigureCB(Widget, XtPointer, XEvent*, Boolean*); +static void CreateIC(Widget, XawVendorShellExtPart*); +static XawIcTableList CreateIcTable(Widget, XawVendorShellExtPart*); +static XawIcTableList CurrentSharedIcTable(XawVendorShellExtPart*); +static void Destroy(Widget, XawVendorShellExtPart*); +static void DestroyAllIM(XawVendorShellExtPart*); +static void DestroyIC(Widget, XawVendorShellExtPart*); +static void FreeAllDataOfVendorShell(XawVendorShellExtPart*, + VendorShellWidget); +static XawVendorShellExtPart *GetExtPart(VendorShellWidget); +static XawIcTableList GetIcTable(Widget, XawVendorShellExtPart*); +static XawIcTableList GetIcTableShared(Widget, XawVendorShellExtPart*); +static XIMStyle GetInputStyleOfIC(XawVendorShellExtPart*); +static Bool Initialize(VendorShellWidget, XawVendorShellExtPart*); +static Bool IsCreatedIC(Widget, XawVendorShellExtPart*); +static Bool IsRegistered(Widget, XawVendorShellExtPart*); +static Bool IsSharedIC(XawVendorShellExtPart*); +static Bool NoRegistered(XawVendorShellExtPart*); +static void OpenIM(XawVendorShellExtPart*); +static void Reconnect(XawVendorShellExtPart*); +static void Register(Widget, XawVendorShellExtPart*); +static Bool RegisterToVendorShell(Widget, XawVendorShellExtPart*); +static void ResizeVendorShell(VendorShellWidget, XawVendorShellExtPart*); +static Bool ResizeVendorShell_Core(VendorShellWidget, XawVendorShellExtPart*, + XawIcTableList); +static VendorShellWidget SearchVendorShell(Widget); +static Widget SetErrCnxt(Widget, XIM); +static XawVendorShellExtPart *SetExtPart(VendorShellWidget, + XawVendorShellExtWidget); +static void SetFocus(Widget, XawVendorShellExtPart*); +static void SetFocusValues(Widget, ArgList, Cardinal, Bool); +static void SetICFocus(Widget, XawVendorShellExtPart*); +static void SetICValues(Widget, XawVendorShellExtPart*, Bool); +static void SetICValuesShared(Widget, XawVendorShellExtPart*, XawIcTableList, + Bool); +static void SetValues(Widget, XawVendorShellExtPart*, ArgList, Cardinal); +static unsigned int SetVendorShellHeight(XawVendorShellExtPart*, + unsigned int); +static void SharedICChangeFocusWindow(Widget, XawVendorShellExtPart*, + XawIcTableList); +static void SizeNegotiation(XawIcTableList, unsigned int, unsigned int); +static void Unregister(Widget, XawVendorShellExtPart*); +static void UnregisterFromVendorShell(Widget, XawVendorShellExtPart*); +static void UnsetFocus(Widget); +static void UnsetICFocus(Widget, XawVendorShellExtPart*); +static void VendorShellDestroyed(Widget, XtPointer, XtPointer); + +/* + * From Vendor.c + */ +void XawVendorShellExtResize(Widget); +void XawVendorStructureNotifyHandler(Widget, XtPointer, XEvent*, Boolean*); + + +/* + * From Xt/Resources.c + */ +void _XtCopyFromArg(XtArgVal src, char*, unsigned int); + +static XtResource resources[] = +{ + { + XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet), + Offset (font_set), XtRString, XtDefaultFontSet + }, + { + XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + Offset (foreground), XtRString, (XtPointer)"XtDefaultForeground" + }, + { + XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), + Offset (background), XtRString, (XtPointer)"XtDefaultBackground" + }, + { + XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap), + Offset (bg_pixmap), XtRImmediate, (XtPointer) XtUnspecifiedPixmap + }, + { + XtNinsertPosition, XtCTextPosition, XtRInt, sizeof (XawTextPosition), + Offset (cursor_position), XtRImmediate, (XtPointer) 0 + } +}; +#undef Offset + + +static VendorShellWidget SearchVendorShell(Widget w) +{ + while(w && !XtIsShell(w)) w = XtParent(w); + if (w && XtIsVendorShell(w)) return((VendorShellWidget)w); + return(NULL); +} + +static XContext extContext = (XContext)NULL; + +static XawVendorShellExtPart * +SetExtPart(VendorShellWidget w, XawVendorShellExtWidget vew) +{ + contextDataRec *contextData; + + if (extContext == (XContext)NULL) extContext = XUniqueContext(); + + contextData = XtNew(contextDataRec); + contextData->parent = (Widget)w; + contextData->ve = (Widget)vew; + if (XSaveContext(XtDisplay(w), (Window)w, extContext, (char *)contextData)) { + return(NULL); + } + return(&(vew->vendor_ext)); +} + +static XawVendorShellExtPart * +GetExtPart(VendorShellWidget w) +{ + contextDataRec *contextData; + XawVendorShellExtWidget vew; + + if (XFindContext(XtDisplay(w), (Window)w, extContext, + (XPointer*)&contextData)) { + return(NULL); + } + vew = (XawVendorShellExtWidget)contextData->ve; + return(&(vew->vendor_ext)); +} + +static Bool +IsSharedIC(XawVendorShellExtPart * ve) +{ + return( ve->ic.shared_ic ); +} + +static XawIcTableList +GetIcTableShared(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList p; + + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->widget == w) { + if (IsSharedIC(ve)) { + return(ve->ic.shared_ic_table); + } else { + return(p); + } + } + } + return(NULL); +} + +static XawIcTableList +GetIcTable(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList p; + + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->widget == w) { + return(p); + } + } + return(NULL); +} + +static XIMStyle +GetInputStyleOfIC(XawVendorShellExtPart *ve) +{ + + if (!ve) return((XIMStyle)0); + return(ve->ic.input_style); +} + +/*ARGSUSED*/ +static void +ConfigureCB(Widget w, XtPointer closure, XEvent *event, Boolean *unused) +{ + XawIcTableList p; + XawVendorShellExtPart *ve; + VendorShellWidget vw; + XVaNestedList pe_attr; + XRectangle pe_area; + XawTextMargin *margin; + + if (event->type != ConfigureNotify) return; + + if ((vw = SearchVendorShell(w)) == NULL) return; + + if ((ve = GetExtPart(vw)) != NULL) { + if (IsSharedIC(ve)) return; + if ((ve->im.xim == NULL) || + ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL) || !(p->input_style & XIMPreeditPosition)) return; + pe_area.x = 0; + pe_area.y = 0; + pe_area.width = w->core.width; + pe_area.height = w->core.height; + margin = &(((TextWidget)w)->text.margin); + pe_area.x += margin->left; + pe_area.y += margin->top; + pe_area.width -= (margin->left + margin->right - 1); + pe_area.height -= (margin->top + margin->bottom - 1); + + pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL); + XSetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL); + XtFree(pe_attr); + } +} + +static XContext errContext = (XContext)NULL; + +static Widget SetErrCnxt(Widget w, XIM xim) +{ + contextErrDataRec *contextErrData; + + if (errContext == (XContext)NULL) errContext = XUniqueContext(); + + contextErrData = XtNew(contextErrDataRec); + contextErrData->widget = w; + contextErrData->xim = xim; + if (XSaveContext(XtDisplay(w), (Window)xim, errContext, + (char *)contextErrData)) { + return(NULL); + } + return(contextErrData->widget); +} + +#if 0 +static Widget +GetErrCnxt(XIM error_im) +{ + contextErrDataRec *contextErrData; + + if (XFindContext(XDisplayOfIM(error_im), (Window)error_im, errContext, + (XPointer*)&contextErrData)) { + return(NULL); + } + return(contextErrData->widget); +} +#endif + +static void +CloseIM(XawVendorShellExtPart *ve) +{ + if (ve->im.xim) + XCloseIM(ve->im.xim); +} + +static unsigned int +SetVendorShellHeight(XawVendorShellExtPart* ve, unsigned int height) +{ + Arg args[2]; + Cardinal i = 0; + + if (ve->im.area_height < height || height == 0) { + XtSetArg(args[i], XtNheight, + (ve->parent->core.height + height - ve->im.area_height)); + ve->im.area_height = height; + XtSetValues(ve->parent, args, 1); + } + return(ve->im.area_height); +} + +static void +DestroyAllIM(XawVendorShellExtPart *ve) +{ + XawIcTableList p; + contextErrDataRec *contextErrData; + + /* + * Destory all ICs + */ + if (IsSharedIC(ve)) { + if ((p = ve->ic.shared_ic_table) && p->xic) { + DestroyIC(p->widget, ve); + p->xic = NULL; + p->ic_focused = FALSE; + } + } else { + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->xic == NULL) continue; + DestroyIC(p->widget, ve); + p->xic = NULL; + p->ic_focused = FALSE; + } + } + if (!ve->im.xim) return; + /* + * Close Input Method + */ + if (!XFindContext(XDisplayOfIM(ve->im.xim), (Window)ve->im.xim, errContext, + (XPointer*)&contextErrData)) { + if (contextErrData) XtFree((char *)contextErrData); + } + XDeleteContext(XDisplayOfIM(ve->im.xim), (Window)ve->im.xim, errContext); + CloseIM(ve); + ve->im.xim = NULL; + + /* + * resize vendor shell to core size + */ + (void) SetVendorShellHeight(ve, 0); + /* + XawVendorShellExtResize(vw); + */ + return; +} + +static void +FreeAllDataOfVendorShell(XawVendorShellExtPart *ve, VendorShellWidget vw) +{ + XawIcTableList p, next; + contextErrDataRec *contextErrData; + + if (!XFindContext(XtDisplay(vw), (Window)vw, extContext, + (XPointer*)&contextErrData)) { + if (contextErrData) XtFree((char *)contextErrData); + } + XDeleteContext(XtDisplay(vw), (Window)vw, extContext); + if (ve->ic.shared_ic_table) + XtFree((char *)ve->ic.shared_ic_table); + if (ve->im.resources) XtFree((char *)ve->im.resources); + for (p = ve->ic.ic_table; p; p = next) { + next = p->next; + XtFree((char *)p); + } +} + +static void +VendorShellDestroyed(Widget w, XtPointer cl_data, XtPointer ca_data) +{ + XawVendorShellExtPart *ve; + + if ( ( ve = GetExtPart( (VendorShellWidget) w ) ) == NULL ) return; + DestroyAllIM( ve ); + FreeAllDataOfVendorShell( ve, (VendorShellWidget) w ); + return; +} + +#if 0 +static int +IOErrorHandler(XIM error_im) +{ + VendorShellWidget vw; + XawVendorShellExtPart * ve; + + if ((vw = (VendorShellWidget)GetErrCnxt(error_im)) == NULL + || (ve = GetExtPart(vw)) == NULL) return(0); + + DestroyAllIM(ve); + return(0); +} +#endif + +/* + * Attempt to open an input method + */ + +static void +OpenIM(XawVendorShellExtPart *ve) +{ + int i; + char *p, *s, *ns, *end, *pbuf, buf[32]; + XIM xim = NULL; + XIMStyles *xim_styles; + XIMStyle input_style = 0; + Boolean found; + + if (ve->im.open_im == False) return; + ve->im.xim = NULL; + if (ve->im.input_method == NULL) { + if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) + xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL); + } else { + /* no fragment can be longer than the whole string */ + Cardinal len = strlen (ve->im.input_method) + 5; + + if (len < sizeof buf) pbuf = buf; + else pbuf = XtMalloc (len); + + if (pbuf == NULL) return; + + for(ns=s=ve->im.input_method; ns && *s;) { + /* skip any leading blanks */ + while (*s && isspace(*s)) s++; + if (!*s) break; + if ((ns = end = strchr(s, ',')) == NULL) + end = s + strlen(s); + /* If there is a spurious comma end can be the same as s */ + if (end > s) { + /* strip any trailing blanks */ + while (isspace(*(end - 1))) end--; + + strcpy (pbuf, "@im="); + strncat (pbuf, s, end - s); + pbuf[end - s + 4] = '\0'; + } + + if ((p = XSetLocaleModifiers(pbuf)) != NULL && *p + && (xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL)) != NULL) + break; + + s = ns + 1; + } + + if (pbuf != buf) XtFree (pbuf); + } + if (xim == NULL) { + if ((p = XSetLocaleModifiers("")) != NULL) { + xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL); + } + } + if (xim == NULL) { + XtAppWarning(XtWidgetToApplicationContext(ve->parent), + "Input Method Open Failed"); + return; + } + if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) + || !xim_styles) { + XtAppWarning(XtWidgetToApplicationContext(ve->parent), + "input method doesn't support any style"); + XCloseIM(xim); + return; + } + found = False; + for(ns = s = ve->im.preedit_type; s && !found;) { + while (*s && isspace(*s)) s++; + if (!*s) break; + if ((ns = end = strchr(s, ',')) == NULL) + end = s + strlen(s); + else + ns++; + if (end > s) + while (isspace(*(end - 1))) end--; + + if (!strncmp(s, "OverTheSpot", end - s)) { + input_style = (XIMPreeditPosition | XIMStatusArea); + } else if (!strncmp(s, "OffTheSpot", end - s)) { + input_style = (XIMPreeditArea | XIMStatusArea); + } else if (!strncmp(s, "Root", end - s)) { + input_style = (XIMPreeditNothing | XIMStatusNothing); + } + for (i = 0; (unsigned short)i < xim_styles->count_styles; i++) + if (input_style == xim_styles->supported_styles[i]) { + ve->ic.input_style = input_style; + SetErrCnxt(ve->parent, xim); + ve->im.xim = xim; + found = True; + break; + } + + s = ns; + } + XFree(xim_styles); + + if (!found) { + XCloseIM(xim); + XtAppWarning(XtWidgetToApplicationContext(ve->parent), + "input method doesn't support my input style"); + } +} + +static Bool +ResizeVendorShell_Core(VendorShellWidget vw, XawVendorShellExtPart *ve, + XawIcTableList p) +{ + XVaNestedList pe_attr, st_attr; + XRectangle pe_area, st_area; + XRectangle *get_pe_area = NULL, *get_st_area = NULL; + + st_area.width = 0; + if (p->input_style & XIMStatusArea) { + st_attr = XVaCreateNestedList(0, XNArea, &get_st_area, NULL); + XGetICValues(p->xic, XNStatusAttributes, st_attr, NULL); + XFree(st_attr); + if (p->xic == NULL) { + return(FALSE); + } + st_area.x = 0; + st_area.y = vw->core.height - ve->im.area_height; + st_area.width = get_st_area->width; + st_area.height = get_st_area->height; + XFree(get_st_area); + st_attr = XVaCreateNestedList(0, XNArea, &st_area, NULL); + XSetICValues(p->xic, XNStatusAttributes, st_attr, NULL); + XFree(st_attr); + if (p->xic == NULL) { + return(FALSE); + } + } + if (p->input_style & XIMPreeditArea) { + pe_attr = XVaCreateNestedList(0, XNArea, &get_pe_area, NULL); + XGetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL); + XFree(pe_attr); + if (p->xic == NULL) { + return(FALSE); + } + pe_area.x = st_area.width; + pe_area.y = vw->core.height - ve->im.area_height; + pe_area.width = vw->core.width; + pe_area.height = get_pe_area->height; + if (p->input_style & XIMStatusArea) { + pe_area.width -= st_area.width; + } + XFree(get_pe_area); + pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL); + XSetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL); + XFree(pe_attr); + } + return(TRUE); +} + +static void +ResizeVendorShell(VendorShellWidget vw, XawVendorShellExtPart *ve) +{ + XawIcTableList p; + + if (IsSharedIC(ve)) { + p = ve->ic.shared_ic_table; + if (p->xic == NULL) return; + ResizeVendorShell_Core(vw, ve, p); + return; + } + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->xic == NULL) continue; + if (ResizeVendorShell_Core(vw, ve, p) == FALSE) return; + } +} + +static XawIcTableList +CreateIcTable(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList table; + + table = (XawIcTableList) XtMalloc(sizeof(XawIcTablePart)); + if (table == NULL) return(NULL); + table->widget = w; + table->xic = NULL; + table->flg = table->prev_flg = 0; + table->font_set = NULL; + table->foreground = table->background = 0xffffffff; + table->bg_pixmap = 0; + table->cursor_position = 0xffff; + table->line_spacing = 0; + table->ic_focused = FALSE; + table->openic_error = FALSE; + return(table); +} + +static Bool +RegisterToVendorShell(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList table; + + if ((table = CreateIcTable(w, ve)) == NULL) return(FALSE); + table->next = ve->ic.ic_table; + ve->ic.ic_table = table; + return(TRUE); +} + +static void +UnregisterFromVendorShell(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList *prev, p; + + for (prev = &ve->ic.ic_table; (p = *prev) != NULL; prev = &p->next) { + if (p->widget == w) { + *prev = p->next; + XtFree((char *)p); + break; + } + } + return; +} + +static void +SetICValuesShared(Widget w, XawVendorShellExtPart *ve, + XawIcTableList p, Bool check) +{ + XawIcTableList pp; + + if ((pp = GetIcTable(w, ve)) == NULL) return; + if (check == TRUE && CurrentSharedIcTable(ve) != pp) return; + + if (pp->prev_flg & CICursorP && p->cursor_position != pp->cursor_position) { + p->cursor_position = pp->cursor_position; + p->flg |= CICursorP; + } + if (pp->prev_flg & CIFontSet && p->font_set != pp->font_set) { + p->font_set = pp->font_set; + p->flg |= (CIFontSet|CICursorP); + } + if (pp->prev_flg & CIFg && p->foreground != pp->foreground) { + p->foreground = pp->foreground; + p->flg |= CIFg; + } + if (pp->prev_flg & CIBg && p->background != pp->background) { + p->background = pp->background; + p->flg |= CIBg; + } + if (pp->prev_flg & CIBgPixmap && p->bg_pixmap != pp->bg_pixmap) { + p->bg_pixmap = pp->bg_pixmap; + p->flg |= CIBgPixmap; + } + if (pp->prev_flg & CILineS && p->line_spacing != pp->line_spacing) { + p->line_spacing = pp->line_spacing; + p->flg |= CILineS; + } +} + +static Bool +IsCreatedIC(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList p; + + if (ve->im.xim == NULL) return(FALSE); + if ((p = GetIcTableShared(w, ve)) == NULL) return(FALSE); + if (p->xic == NULL) return(FALSE); + return(TRUE); +} + +static void +SizeNegotiation(XawIcTableList p, unsigned int width, unsigned int height) +{ + XRectangle pe_area, st_area; + XVaNestedList pe_attr = NULL, st_attr = NULL; + int ic_cnt = 0; + XRectangle *pe_area_needed = NULL, *st_area_needed = NULL; + XPointer ic_a[5]; + + if (p->input_style & XIMPreeditArea) { + pe_attr = XVaCreateNestedList(0, XNAreaNeeded, &pe_area_needed, NULL); + ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++; + ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++; + } + if (p->input_style & XIMStatusArea) { + st_attr = XVaCreateNestedList(0, XNAreaNeeded, &st_area_needed, NULL); + ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++; + ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++; + } + ic_a[ic_cnt] = (XPointer) NULL; + + if (ic_cnt > 0) { + XGetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], NULL); + if (pe_attr) XFree(pe_attr); + if (st_attr) XFree(st_attr); + if (p->xic == NULL) { + p->openic_error = True; + return; + } + pe_attr = st_attr = NULL; + ic_cnt = 0; + if (p->input_style & XIMStatusArea) { + st_area.height = st_area_needed->height; + st_area.x = 0; + st_area.y = height - st_area.height; + if (p->input_style & XIMPreeditArea) { + st_area.width = st_area_needed->width; + } else { + st_area.width = width; + } + + XFree(st_area_needed); + st_attr = XVaCreateNestedList(0, XNArea, &st_area, NULL); + ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++; + ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++; + } + if (p->input_style & XIMPreeditArea) { + if (p->input_style & XIMStatusArea) { + pe_area.x = st_area.width; + pe_area.width = width - st_area.width; + } else { + pe_area.x = 0; + pe_area.width = width; + } + pe_area.height = pe_area_needed->height; + XFree(pe_area_needed); + pe_area.y = height - pe_area.height; + pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL); + ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++; + ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++; + } + ic_a[ic_cnt] = (XPointer) NULL; + XSetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], NULL); + if (pe_attr) XFree(pe_attr); + if (st_attr) XFree(st_attr); + if (p->xic == NULL) { + p->openic_error = True; + return; + } + } +} + +static void +CreateIC(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList p; + XPoint position; + XRectangle pe_area, st_area; + XVaNestedList pe_attr = NULL, st_attr = NULL; + XPointer ic_a[20], pe_a[20], st_a[20]; + Dimension height = 0; + int ic_cnt = 0, pe_cnt = 0, st_cnt = 0; + XawTextMargin *margin; + + if (!XtIsRealized(w)) return; + if (((ve->im.xim == NULL) || (p = GetIcTableShared(w, ve)) == NULL) || + p->xic || (p->openic_error != FALSE)) return; + + p->input_style = GetInputStyleOfIC(ve); + + if (IsSharedIC(ve)) SetICValuesShared(w, ve, p, FALSE); + XFlush(XtDisplay(w)); + + if (p->input_style & (XIMPreeditArea|XIMPreeditPosition|XIMStatusArea)) { + if (p->flg & CIFontSet) { + pe_a[pe_cnt] = (XPointer) XNFontSet; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->font_set; pe_cnt++; + st_a[st_cnt] = (XPointer) XNFontSet; st_cnt++; + st_a[st_cnt] = (XPointer) p->font_set; st_cnt++; + if (p->font_set) { + height = maxAscentOfFontSet(p->font_set) + + maxDescentOfFontSet(p->font_set); + } + height = SetVendorShellHeight(ve, height); + } + if (p->flg & CIFg) { + pe_a[pe_cnt] = (XPointer) XNForeground; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->foreground; pe_cnt++; + st_a[st_cnt] = (XPointer) XNForeground; st_cnt++; + st_a[st_cnt] = (XPointer) p->foreground; st_cnt++; + } + if (p->flg & CIBg) { + pe_a[pe_cnt] = (XPointer) XNBackground; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->background; pe_cnt++; + st_a[st_cnt] = (XPointer) XNBackground; st_cnt++; + st_a[st_cnt] = (XPointer) p->background; st_cnt++; + } + if (p->flg & CIBgPixmap) { + pe_a[pe_cnt] = (XPointer) XNBackgroundPixmap; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->bg_pixmap; pe_cnt++; + st_a[st_cnt] = (XPointer) XNBackgroundPixmap; st_cnt++; + st_a[st_cnt] = (XPointer) p->bg_pixmap; st_cnt++; + } + if (p->flg & CILineS) { + pe_a[pe_cnt] = (XPointer) XNLineSpace; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->line_spacing; pe_cnt++; + st_a[st_cnt] = (XPointer) XNLineSpace; st_cnt++; + st_a[st_cnt] = (XPointer) p->line_spacing; st_cnt++; + } + } + if (p->input_style & XIMPreeditArea) { + pe_area.x = 0; + pe_area.y = ve->parent->core.height - height; + pe_area.width = ve->parent->core.width; + pe_area.height = height; + pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++; + pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++; + } + if (p->input_style & XIMPreeditPosition) { + pe_area.x = 0; + pe_area.y = 0; + pe_area.width = w->core.width; + pe_area.height = w->core.height; + margin = &(((TextWidget)w)->text.margin); + pe_area.x += margin->left; + pe_area.y += margin->top; + pe_area.width -= (margin->left + margin->right - 1); + pe_area.height -= (margin->top + margin->bottom - 1); + pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++; + pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++; + if (p->flg & CICursorP) { + _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y); + } else { + position.x = position.y = 0; + } + pe_a[pe_cnt] = (XPointer) XNSpotLocation; pe_cnt++; + pe_a[pe_cnt] = (XPointer) &position; pe_cnt++; + } + if (p->input_style & XIMStatusArea) { + st_area.x = 0; + st_area.y = ve->parent->core.height - height; + st_area.width = ve->parent->core.width; + st_area.height = height; + st_a[st_cnt] = (XPointer) XNArea; st_cnt++; + st_a[st_cnt] = (XPointer) &st_area; st_cnt++; + } + + ic_a[ic_cnt] = (XPointer) XNInputStyle; ic_cnt++; + ic_a[ic_cnt] = (XPointer) p->input_style; ic_cnt++; + ic_a[ic_cnt] = (XPointer) XNClientWindow; ic_cnt++; + ic_a[ic_cnt] = (XPointer) XtWindow(ve->parent); ic_cnt++; + ic_a[ic_cnt] = (XPointer) XNFocusWindow; ic_cnt++; + ic_a[ic_cnt] = (XPointer) XtWindow(w); ic_cnt++; + + if (pe_cnt > 0) { + pe_a[pe_cnt] = (XPointer) NULL; + pe_attr = XVaCreateNestedList(0, pe_a[0], pe_a[1], pe_a[2], pe_a[3], + pe_a[4], pe_a[5], pe_a[6], pe_a[7], pe_a[8], + pe_a[9], pe_a[10], pe_a[11], pe_a[12], + pe_a[13], pe_a[14], pe_a[15], pe_a[16], + pe_a[17], pe_a[18], NULL); + ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++; + ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++; + } + + if (st_cnt > 0) { + st_a[st_cnt] = (XPointer) NULL; + st_attr = XVaCreateNestedList(0, st_a[0], st_a[1], st_a[2], st_a[3], + st_a[4], st_a[5], st_a[6], st_a[7], st_a[8], + st_a[9], st_a[10], st_a[11], st_a[12], + st_a[13], st_a[14], st_a[15], st_a[16], + st_a[17], st_a[18], NULL); + ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++; + ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++; + } + ic_a[ic_cnt] = (XPointer) NULL; + + p->xic = XCreateIC(ve->im.xim, ic_a[0], ic_a[1], ic_a[2], ic_a[3], + ic_a[4], ic_a[5], ic_a[6], ic_a[7], ic_a[8], ic_a[9], + ic_a[10], ic_a[11], ic_a[12], ic_a[13], ic_a[14], + ic_a[15], ic_a[16], ic_a[17], ic_a[18], NULL); + if (pe_attr) XtFree(pe_attr); + if (st_attr) XtFree(st_attr); + + if (p->xic == NULL) { + p->openic_error = True; + return; + } + + SizeNegotiation(p, ve->parent->core.width, ve->parent->core.height); + + p->flg &= ~(CIFontSet | CIFg | CIBg | CIBgPixmap | CICursorP | CILineS); + + if (!IsSharedIC(ve)) { + if (p->input_style & XIMPreeditPosition) { + XtAddEventHandler(w, (EventMask)StructureNotifyMask, FALSE, + (XtEventHandler)ConfigureCB, (Opaque)NULL); + } + } +} + +static void +SetICValues(Widget w, XawVendorShellExtPart *ve, Bool focus) +{ + XawIcTableList p; + XPoint position; + XRectangle pe_area; + XVaNestedList pe_attr = NULL, st_attr = NULL; + XPointer ic_a[20], pe_a[20], st_a[20]; + int ic_cnt = 0, pe_cnt = 0, st_cnt = 0; + XawTextMargin *margin; + int height = 0; + + if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL)) return; + + if (IsSharedIC(ve)) SetICValuesShared(w, ve, p, TRUE); + XFlush(XtDisplay(w)); + if (focus == FALSE && + !(p->flg & (CIFontSet | CIFg | CIBg | + CIBgPixmap | CICursorP | CILineS))) return; +#ifdef SPOT + if ((p->input_style & XIMPreeditPosition) + && ((!IsSharedIC(ve) && ((p->flg & ~CIICFocus) == CICursorP)) + || (IsSharedIC(ve) && p->flg == CICursorP))) { + _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y); + _XipChangeSpot(p->xic, position.x, position.y); + p->flg &= ~CICursorP; + return; + } +#endif + + if (p->input_style & (XIMPreeditArea|XIMPreeditPosition|XIMStatusArea)) { + if (p->flg & CIFontSet) { + pe_a[pe_cnt] = (XPointer) XNFontSet; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->font_set; pe_cnt++; + st_a[st_cnt] = (XPointer) XNFontSet; st_cnt++; + st_a[st_cnt] = (XPointer) p->font_set; st_cnt++; + if (p->font_set) { + height = maxAscentOfFontSet(p->font_set) + + maxDescentOfFontSet(p->font_set); + } + height = SetVendorShellHeight(ve, height); + } + if (p->flg & CIFg) { + pe_a[pe_cnt] = (XPointer) XNForeground; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->foreground; pe_cnt++; + st_a[st_cnt] = (XPointer) XNForeground; st_cnt++; + st_a[st_cnt] = (XPointer) p->foreground; st_cnt++; + } + if (p->flg & CIBg) { + pe_a[pe_cnt] = (XPointer) XNBackground; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->background; pe_cnt++; + st_a[st_cnt] = (XPointer) XNBackground; st_cnt++; + st_a[st_cnt] = (XPointer) p->background; st_cnt++; + } + if (p->flg & CIBgPixmap) { + pe_a[pe_cnt] = (XPointer) XNBackgroundPixmap; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->bg_pixmap; pe_cnt++; + st_a[st_cnt] = (XPointer) XNBackgroundPixmap; st_cnt++; + st_a[st_cnt] = (XPointer) p->bg_pixmap; st_cnt++; + } + if (p->flg & CILineS) { + pe_a[pe_cnt] = (XPointer) XNLineSpace; pe_cnt++; + pe_a[pe_cnt] = (XPointer) p->line_spacing; pe_cnt++; + st_a[st_cnt] = (XPointer) XNLineSpace; st_cnt++; + st_a[st_cnt] = (XPointer) p->line_spacing; st_cnt++; + } + } + if (p->input_style & XIMPreeditPosition) { + if (p->flg & CICursorP) { + _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y); + pe_a[pe_cnt] = (XPointer) XNSpotLocation; pe_cnt++; + pe_a[pe_cnt] = (XPointer) &position; pe_cnt++; + } + } + if (IsSharedIC(ve)) { + if (p->input_style & XIMPreeditPosition) { + pe_area.x = 0; + pe_area.y = 0; + pe_area.width = w->core.width; + pe_area.height = w->core.height; + margin = &(((TextWidget)w)->text.margin); + pe_area.x += margin->left; + pe_area.y += margin->top; + pe_area.width -= (margin->left + margin->right - 1); + pe_area.height -= (margin->top + margin->bottom - 1); + pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++; + pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++; + } + } + + if (pe_cnt > 0) { + pe_a[pe_cnt] = (XPointer) NULL; + pe_attr = XVaCreateNestedList(0, pe_a[0], pe_a[1], pe_a[2], pe_a[3], + pe_a[4], pe_a[5], pe_a[6], pe_a[7], + pe_a[8], pe_a[9], pe_a[10], pe_a[11], + pe_a[12], pe_a[13], pe_a[14], pe_a[15], + pe_a[16], pe_a[17], pe_a[18], NULL); + ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++; + ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++; + } + if (st_cnt > 0) { + st_a[st_cnt] = (XPointer) NULL; + st_attr = XVaCreateNestedList(0, st_a[0], st_a[1], st_a[2], st_a[3], + st_a[4], st_a[5], st_a[6], st_a[7], + st_a[8], st_a[9], st_a[10], st_a[11], + st_a[12], st_a[13], st_a[14], st_a[15], + st_a[16], st_a[17], st_a[18], NULL); + ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++; + ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++; + } + if (focus == TRUE) { + ic_a[ic_cnt] = (XPointer) XNFocusWindow; ic_cnt++; + ic_a[ic_cnt] = (XPointer) XtWindow(w); ic_cnt++; + } + if (ic_cnt > 0) { + ic_a[ic_cnt] = (XPointer) NULL; + XSetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], ic_a[4], + ic_a[5], ic_a[6], ic_a[7], ic_a[8], ic_a[9], ic_a[10], + ic_a[11], ic_a[12], ic_a[13], ic_a[14], ic_a[15], + ic_a[16], ic_a[17], ic_a[18], NULL); + if (pe_attr) XtFree(pe_attr); + if (st_attr) XtFree(st_attr); + } + + if (IsSharedIC(ve) && p->flg & CIFontSet) + SizeNegotiation(p, ve->parent->core.width, ve->parent->core.height); + + p->flg &= ~(CIFontSet | CIFg | CIBg | CIBgPixmap | CICursorP | CILineS); +} + +static void +SharedICChangeFocusWindow(Widget w, XawVendorShellExtPart *ve, + XawIcTableList p) +{ + XawIcTableList pp; + + if (w == NULL) { + ve->ic.current_ic_table = NULL; + return; + } + if ((pp = GetIcTable(w, ve)) == NULL) return; + ve->ic.current_ic_table = pp; + SetICValues(w, ve, TRUE); +} + +static XawIcTableList +CurrentSharedIcTable(XawVendorShellExtPart *ve) +{ + return(ve->ic.current_ic_table); +} + +static void +SetICFocus(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList p, pp; + + if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL)) return; + + if (IsSharedIC(ve)) { + pp = CurrentSharedIcTable(ve); + if (pp == NULL || pp->widget != w) { + SharedICChangeFocusWindow(w, ve, p); + } + } + if (p->flg & CIICFocus && p->ic_focused == FALSE) { + p->ic_focused = TRUE; + XSetICFocus(p->xic); + } + p->flg &= ~CIICFocus; +} + +static void +UnsetICFocus(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList p, pp; + + if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL)) return; + + if (IsSharedIC(ve) && (pp = CurrentSharedIcTable(ve))) { + if (pp->widget != w) { + return; + } + SharedICChangeFocusWindow(NULL, ve, p); + } + if (p->ic_focused == TRUE) { + XUnsetICFocus(p->xic); + p->ic_focused = FALSE; + } +} + +static void +SetValues(Widget w, XawVendorShellExtPart *ve, + ArgList args, Cardinal num_args) +{ + ArgList arg; + + XrmName argName; + XrmResourceList xrmres; + Cardinal i; + XawIcTablePart *p, save_tbl; + + if ((p = GetIcTable(w, ve)) == NULL) return; + + memcpy(&save_tbl, p, sizeof(XawIcTablePart)); + + for (arg = args ; num_args != 0; num_args--, arg++) { + argName = XrmStringToName(arg->name); + for (xrmres = (XrmResourceList)ve->im.resources, i = 0; + i < ve->im.num_resources; i++, xrmres++) { + if (argName == xrmres->xrm_name) { + _XtCopyFromArg(arg->value, + (char *)p - xrmres->xrm_offset - 1, + xrmres->xrm_size); + break; + } + } + } + if (p->font_set != save_tbl.font_set) { + p->flg |= CIFontSet; + } + if (p->foreground != save_tbl.foreground) { + p->flg |= CIFg; + } + if (p->background !=save_tbl.background) { + p->flg |= CIBg; + } + if (p->bg_pixmap != save_tbl.bg_pixmap) { + p->flg |= CIBgPixmap; + } + if (p->cursor_position != save_tbl.cursor_position) { + p->flg |= CICursorP; + } + if (p->line_spacing != save_tbl.line_spacing) { + p->flg |= CILineS; + } + p->prev_flg |= p->flg; +} + +static void +SetFocus(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList p; + if ((p = GetIcTableShared(w, ve)) == NULL) return; + + if ( p->ic_focused == FALSE || IsSharedIC(ve)) { + p->flg |= CIICFocus; + } + p->prev_flg |= p->flg; +} + +static void +DestroyIC(Widget w, XawVendorShellExtPart *ve) +{ + XawIcTableList p; + + if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL)) return; + if (IsSharedIC(ve)) { + if (GetIcTable(w, ve) == ve->ic.current_ic_table) { + UnsetICFocus(w, ve); + } + return; + } + XDestroyIC(p->xic); + if (!IsSharedIC(ve)) { + if (p->input_style & XIMPreeditPosition) { + XtRemoveEventHandler(w, (EventMask)StructureNotifyMask, FALSE, + (XtEventHandler)ConfigureCB, (Opaque)NULL); + } + } +} + +static void +SetFocusValues(Widget inwidg, ArgList args, Cardinal num_args, Bool focus) +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw)) != NULL) { + if (num_args > 0) SetValues(inwidg, ve, args, num_args); + if (focus) SetFocus(inwidg, ve); + if (XtIsRealized((Widget)vw) && ve->im.xim) { + if (IsCreatedIC(inwidg, ve)) { + SetICValues(inwidg, ve, FALSE); + if (focus) SetICFocus(inwidg, ve); + } else { + CreateIC(inwidg, ve); + SetICFocus(inwidg, ve); + } + } + } +} + +static void +UnsetFocus(Widget inwidg) +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + XawIcTableList p; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw)) != NULL) { + if ((p = GetIcTableShared(inwidg, ve)) == NULL) return; + if (p->flg & CIICFocus) { + p->flg &= ~CIICFocus; + } + p->prev_flg &= ~CIICFocus; + if (ve->im.xim && XtIsRealized((Widget)vw) && p->xic) { + UnsetICFocus(inwidg, ve); + } + } +} + +static Bool +IsRegistered(Widget w, XawVendorShellExtPart* ve) +{ + XawIcTableList p; + + for (p = ve->ic.ic_table; p; p = p->next) + { + if (p->widget == w) return(TRUE); + } + return(FALSE); +} + +static void +Register(Widget inwidg, XawVendorShellExtPart* ve) +{ + if (ve->im.xim == NULL) + { + OpenIM(ve); + } + + if (IsRegistered(inwidg, ve)) return; + + if (RegisterToVendorShell(inwidg, ve) == FALSE) return; + + if (ve->im.xim == NULL) return; + + if (XtIsRealized(ve->parent)) + { + CreateIC(inwidg, ve); + SetICFocus(inwidg, ve); + } +} + +static Bool +NoRegistered(XawVendorShellExtPart* ve) +{ + if (ve->ic.ic_table == NULL) return(TRUE); + return(FALSE); +} + +static void +Unregister(Widget inwidg, XawVendorShellExtPart *ve) +{ + if (!IsRegistered(inwidg, ve)) return; + + DestroyIC(inwidg, ve); + + UnregisterFromVendorShell(inwidg, ve); + + if (NoRegistered(ve)) + { + CloseIM(ve); + ve->im.xim = NULL; + /* + * resize vendor shell to core size + */ + (void) SetVendorShellHeight(ve, 0); + } +} + +static void +AllCreateIC(XawVendorShellExtPart *ve) +{ + XawIcTableList p; + + if (ve->im.xim == NULL) return; + if (IsSharedIC(ve) && ve->ic.ic_table[0].widget) { + p = ve->ic.shared_ic_table; + if (p->xic == NULL) + CreateIC(ve->ic.ic_table[0].widget, ve); + SetICFocus(ve->ic.ic_table[0].widget, ve); + return; + } + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->xic == NULL) + CreateIC(p->widget, ve); + } + for (p = ve->ic.ic_table; p; p = p->next) { + SetICFocus(p->widget, ve); + } +} + + +static void +Reconnect(XawVendorShellExtPart *ve) +{ + XawIcTableList p; + + ve->im.open_im = True; + if (ve->im.xim == NULL) { + OpenIM(ve); + } + if (ve->im.xim == NULL) return; + + if (IsSharedIC(ve)) { + p = ve->ic.shared_ic_table; + p->flg = p->prev_flg; + p->openic_error = FALSE; + } else { + for (p = ve->ic.ic_table; p; p = p->next) { + p->flg = p->prev_flg; + p->openic_error = FALSE; + } + } + AllCreateIC(ve); +} + + +static void +CompileResourceList(XtResourceList res, unsigned int num_res) +{ + unsigned int count; + +#define xrmres ((XrmResourceList) res) + for (count = 0; count < num_res; res++, count++) { + xrmres->xrm_name = XrmPermStringToQuark(res->resource_name); + xrmres->xrm_class = XrmPermStringToQuark(res->resource_class); + xrmres->xrm_type = XrmPermStringToQuark(res->resource_type); + xrmres->xrm_offset = -res->resource_offset - 1; + xrmres->xrm_default_type = XrmPermStringToQuark(res->default_type); + } +#undef xrmres +} + +static Bool +Initialize(VendorShellWidget vw, XawVendorShellExtPart *ve) +{ + if (!XtIsVendorShell((Widget)vw)) return(FALSE); + ve->parent = (Widget)vw; + ve->im.xim = NULL; + ve->im.area_height = 0; + ve->im.resources = (XrmResourceList)XtMalloc(sizeof(resources)); + if (ve->im.resources == NULL) return(FALSE); + memcpy((char *)ve->im.resources, (char *)resources, sizeof(resources)); + ve->im.num_resources = XtNumber(resources); + CompileResourceList( (XtResourceList) ve->im.resources, + ve->im.num_resources ); + if ((ve->ic.shared_ic_table = CreateIcTable( (Widget)vw, ve)) == NULL) + return(FALSE); + ve->ic.current_ic_table = NULL; + ve->ic.ic_table = NULL; + return(TRUE); +} + + +/* Destroy() + * + * This frees all (most?) of the resources malloced by XawIm. + * It is called by _XawImDestroy, which is called by Vendor.c's + * VendorExt's Destroy method. Sheeran, Omron KK, 93/08/05 */ + +static void +Destroy(Widget w, XawVendorShellExtPart *ve) +{ + contextDataRec *contextData; + contextErrDataRec *contextErrData; + + if (!XtIsVendorShell( w ) ) + return; + XtFree( (char*) ve->im.resources ); + + if (extContext != (XContext)NULL && + !XFindContext (XtDisplay (w), (Window)w, + extContext, (XPointer*)&contextData)) + XtFree( (char*) contextData ); + + if (errContext != (XContext)NULL && + !XFindContext (XDisplayOfIM( ve->im.xim ), (Window) ve->im.xim, + errContext, (XPointer*) &contextErrData)) + XtFree( (char*) contextErrData ); +} + +/********************************************* + * + * SEMI-PRIVATE FUNCTIONS + * For use by other Xaw modules + * + ********************************************/ + +void +_XawImResizeVendorShell(Widget w) +{ + XawVendorShellExtPart *ve; + + if ( ( ve = GetExtPart( (VendorShellWidget) w ) ) && ve->im.xim ) { + ResizeVendorShell( (VendorShellWidget) w, ve ); + } +} + + +Dimension +_XawImGetShellHeight(Widget w) +{ + XawVendorShellExtPart *ve; + + if (!XtIsVendorShell( w ) ) return( w->core.height ); + if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL ) { + return( w->core.height - ve->im.area_height ); + } + return( w->core.height ); +} + +void +_XawImRealize(Widget w) +{ + XawVendorShellExtPart *ve; + + if ( !XtIsRealized( w ) || !XtIsVendorShell( w ) ) return; + if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL ) { + XtAddEventHandler( w, (EventMask)StructureNotifyMask, FALSE, + XawVendorStructureNotifyHandler, (XtPointer)NULL ); + AllCreateIC(ve); + } +} + +void +_XawImInitialize(Widget w, Widget ext) +{ + XawVendorShellExtPart *ve; + + if ( !XtIsVendorShell( w ) ) return; + if ( (ve = SetExtPart( (VendorShellWidget) w, (XawVendorShellExtWidget)ext )) != NULL ) { + if ( Initialize( (VendorShellWidget) w, ve ) == FALSE ) return; + XtAddCallback( w, XtNdestroyCallback, VendorShellDestroyed, + (XtPointer) NULL ); + } +} + +void +_XawImReconnect(Widget inwidg) +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw)) != NULL) { + Reconnect(ve); + } +} + +void +_XawImRegister(Widget inwidg) +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw)) != NULL) { + Register(inwidg, ve); + } +} + +void +_XawImUnregister(Widget inwidg) +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw)) != NULL) { + Unregister(inwidg, ve); + } +} + +void +_XawImSetValues(Widget inwidg, ArgList args, Cardinal num_args) +{ + SetFocusValues( inwidg, args, num_args, FALSE ); +} + +void +_XawImSetFocusValues(Widget inwidg, ArgList args, Cardinal num_args) +{ + SetFocusValues(inwidg, args, num_args, TRUE); +} + +void +_XawImUnsetFocus(Widget inwidg) +{ + UnsetFocus(inwidg); +} + +int +_XawImWcLookupString(Widget inwidg, XKeyPressedEvent *event, + wchar_t* buffer_return, int bytes_buffer, + KeySym *keysym_return) +{ + XawVendorShellExtPart* ve; + VendorShellWidget vw; + XawIcTableList p; + int i, ret; + char tmp_buf[64], *tmp_p; + wchar_t* buf_p; + + if ((vw = SearchVendorShell(inwidg)) && (ve = GetExtPart(vw)) && + ve->im.xim && (p = GetIcTableShared(inwidg, ve)) && p->xic) { + return(XwcLookupString(p->xic, event, buffer_return, bytes_buffer/sizeof(wchar_t), + keysym_return, NULL)); + } + ret = XLookupString( event, tmp_buf, sizeof(tmp_buf), keysym_return, + NULL ); + for ( i = 0, tmp_p = tmp_buf, buf_p = buffer_return; i < ret; i++ ) { + *buf_p++ = _Xaw_atowc(*tmp_p++); + } + return( ret ); +} + +int +_XawLookupString(Widget w, XKeyEvent *event, char *buffer_return, int buffer_size, + KeySym *keysym_return) +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + XawIcTableList p; + + if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw)) + && ve->im.xim && (p = GetIcTableShared(w, ve)) && p->xic) + return (XmbLookupString(p->xic, event, buffer_return, buffer_size, + keysym_return, NULL)); + + return (XLookupString(event, buffer_return, buffer_size, + keysym_return, NULL)); +} + +int +_XawImGetImAreaHeight(Widget w) +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw))) { + return(ve->im.area_height); + } + return(0); +} + +void +_XawImCallVendorShellExtResize(Widget w) +{ + VendorShellWidget vw; + + if ((vw = SearchVendorShell(w)) && GetExtPart(vw)) { + XawVendorShellExtResize((Widget)vw); + } +} + + +/* _XawImDestroy() + * + * This should be called by the VendorExt from its + * core Destroy method. Sheeran, Omron KK 93/08/05 */ + +void +_XawImDestroy(Widget w, Widget ext) +{ + XawVendorShellExtPart *ve; + + if ( !XtIsVendorShell( w ) ) return; + if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL ) + Destroy( w, ve ); +} diff --git a/libXaw/src/XawInit.c b/libXaw/src/XawInit.c index 89d339aff..c10a9b64b 100644 --- a/libXaw/src/XawInit.c +++ b/libXaw/src/XawInit.c @@ -1,97 +1,97 @@ -/*
- *
-Copyright 1989, 1998 The Open Group
-Copyright 2003-2004 Roland Mainz <roland.mainz@nrubsig.org>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- *
- * XawInitializeWidgetSet
- *
- * This routine forces a reference to vendor shell so that the one in this
- * widget is installed. Any other cross-widget set initialization should be
- * done here as well. All Athena widgets should include "XawInit.h" and
- * call this routine from their ClassInitialize procs (this routine may be
- * used as the class init proc).
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/Intrinsic.h>
-#include <X11/Vendor.h>
-#include <X11/Xaw/XawInit.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include "Private.h"
-
-void
-XawInitializeWidgetSet(void)
-{
- static Boolean firsttime = True;
-
- if (firsttime) {
- firsttime = False;
-#ifndef OLDXAW
- XawPixmapsInitialize();
- XawInitializeDefaultConverters();
-#endif
- XtInitializeWidgetClass(vendorShellWidgetClass);
- }
-}
-
-/* XawOpenApplication() - mainly identical to XtOpenApplication() but
- * takes a |Display *| and |Screen *| as arguments, too... */
-Widget XawOpenApplication(XtAppContext *app_context_return,
- Display *dpy,
- Screen *screen,
- String application_name,
- String application_class,
- WidgetClass widget_class,
- int *argc,
- String *argv)
-{
- Widget toplevel;
- Cardinal n;
- Arg args[2];
-
- XtToolkitInitialize();
- *app_context_return = XtCreateApplicationContext();
- if( *app_context_return == NULL )
- return NULL;
-
- XtDisplayInitialize(*app_context_return, dpy,
- application_name, application_class,
- NULL, 0,
- argc, argv);
-
- n = 0;
- if (screen) {
- XtSetArg(args[n], XtNscreen, screen); n++;
- }
- toplevel = XtAppCreateShell(application_name,
- application_class,
- widget_class,
- dpy,
- args, n);
-
- return toplevel;
-}
-
+/* + * +Copyright 1989, 1998 The Open Group +Copyright 2003-2004 Roland Mainz <roland.mainz@nrubsig.org> + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * + * XawInitializeWidgetSet + * + * This routine forces a reference to vendor shell so that the one in this + * widget is installed. Any other cross-widget set initialization should be + * done here as well. All Athena widgets should include "XawInit.h" and + * call this routine from their ClassInitialize procs (this routine may be + * used as the class init proc). + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/Intrinsic.h> +#include <X11/Vendor.h> +#include <X11/Xaw/XawInit.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include "Private.h" + +void +XawInitializeWidgetSet(void) +{ + static Boolean firsttime = True; + + if (firsttime) { + firsttime = False; +#ifndef OLDXAW + XawPixmapsInitialize(); + XawInitializeDefaultConverters(); +#endif + XtInitializeWidgetClass(vendorShellWidgetClass); + } +} + +/* XawOpenApplication() - mainly identical to XtOpenApplication() but + * takes a |Display *| and |Screen *| as arguments, too... */ +Widget XawOpenApplication(XtAppContext *app_context_return, + Display *dpy, + Screen *screen, + String application_name, + String application_class, + WidgetClass widget_class, + int *argc, + String *argv) +{ + Widget toplevel; + Cardinal n; + Arg args[2]; + + XtToolkitInitialize(); + *app_context_return = XtCreateApplicationContext(); + if( *app_context_return == NULL ) + return NULL; + + XtDisplayInitialize(*app_context_return, dpy, + application_name, application_class, + NULL, 0, + argc, argv); + + n = 0; + if (screen) { + XtSetArg(args[n], XtNscreen, screen); n++; + } + toplevel = XtAppCreateShell(application_name, + application_class, + widget_class, + dpy, + args, n); + + return toplevel; +} + diff --git a/libXaw/src/sharedlib.c b/libXaw/src/sharedlib.c index 31903fc4b..e892d82c2 100644 --- a/libXaw/src/sharedlib.c +++ b/libXaw/src/sharedlib.c @@ -1,173 +1,173 @@ -/*
-
-Copyright 1991, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#if defined(SUNSHLIB) && !defined(SHAREDCODE)
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/Xaw/AsciiSinkP.h>
-#include <X11/Xaw/AsciiSrcP.h>
-#include <X11/Xaw/AsciiTextP.h>
-#include <X11/Xaw/MultiSinkP.h>
-#include <X11/Xaw/MultiSrcP.h>
-#include <X11/Xaw/BoxP.h>
-#include <X11/Xaw/CommandP.h>
-#include <X11/Xaw/DialogP.h>
-#include <X11/Xaw/FormP.h>
-#include <X11/Xaw/GripP.h>
-#include <X11/Xaw/LabelP.h>
-#include <X11/Xaw/ListP.h>
-#include <X11/Xaw/MenuButtoP.h>
-#include <X11/Xaw/PanedP.h>
-#include <X11/Xaw/PannerP.h>
-#include <X11/Xaw/PortholeP.h>
-#include <X11/Xaw/RepeaterP.h>
-#include <X11/Xaw/ScrollbarP.h>
-#include <X11/Xaw/SimpleP.h>
-#include <X11/Xaw/SimpleMenP.h>
-#include <X11/Xaw/SmeP.h>
-#include <X11/Xaw/SmeBSBP.h>
-#include <X11/Xaw/SmeLineP.h>
-#include <X11/Xaw/StripCharP.h>
-#include <X11/Xaw/TextP.h>
-#include <X11/Xaw/TextSinkP.h>
-#include <X11/Xaw/TextSrcP.h>
-#include <X11/Xaw/ToggleP.h>
-#include <X11/Xaw/TreeP.h>
-#include <X11/VendorP.h>
-#include <X11/Xaw/ViewportP.h>
-
-extern AsciiSinkClassRec asciiSinkClassRec;
-WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec;
-
-extern AsciiSrcClassRec asciiSrcClassRec;
-WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec;
-
-extern AsciiTextClassRec asciiTextClassRec;
-WidgetClass asciiTextWidgetClass = (WidgetClass)&asciiTextClassRec;
-
-#ifdef ASCII_STRING
-extern AsciiStringClassRec asciiStringClassRec;
-WidgetClass asciiStringWidgetClass = (WidgetClass)&asciiStringClassRec;
-#endif
-
-#ifdef ASCII_DISK
-extern AsciiDiskClassRec asciiDiskClassRec;
-WidgetClass asciiDiskWidgetClass = (WidgetClass)&asciiDiskClassRec;
-#endif
-
-extern MultiSinkClassRec multiSinkClassRec;
-WidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec;
-
-extern MultiSrcClassRec multiSrcClassRec;
-WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec;
-
-extern BoxClassRec boxClassRec;
-WidgetClass boxWidgetClass = (WidgetClass)&boxClassRec;
-
-extern CommandClassRec commandClassRec;
-WidgetClass commandWidgetClass = (WidgetClass) &commandClassRec;
-
-extern DialogClassRec dialogClassRec;
-WidgetClass dialogWidgetClass = (WidgetClass)&dialogClassRec;
-
-extern FormClassRec formClassRec;
-WidgetClass formWidgetClass = (WidgetClass)&formClassRec;
-
-extern GripClassRec gripClassRec;
-WidgetClass gripWidgetClass = (WidgetClass) &gripClassRec;
-
-extern LabelClassRec labelClassRec;
-WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec;
-
-extern ListClassRec listClassRec;
-WidgetClass listWidgetClass = (WidgetClass)&listClassRec;
-
-extern MenuButtonClassRec menuButtonClassRec;
-WidgetClass menuButtonWidgetClass = (WidgetClass) &menuButtonClassRec;
-
-extern PanedClassRec panedClassRec;
-WidgetClass panedWidgetClass = (WidgetClass) &panedClassRec;
-WidgetClass vPanedWidgetClass = (WidgetClass) &panedClassRec;
-
-extern PannerClassRec pannerClassRec;
-WidgetClass pannerWidgetClass = (WidgetClass) &pannerClassRec;
-
-extern PortholeClassRec portholeClassRec;
-WidgetClass portholeWidgetClass = (WidgetClass) &portholeClassRec;
-
-extern RepeaterClassRec repeaterClassRec;
-WidgetClass repeaterWidgetClass = (WidgetClass) &repeaterClassRec;
-
-extern ScrollbarClassRec scrollbarClassRec;
-WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec;
-
-extern SimpleClassRec simpleClassRec;
-WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec;
-
-extern SimpleMenuClassRec simpleMenuClassRec;
-WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec;
-
-extern SmeClassRec smeClassRec;
-WidgetClass smeObjectClass = (WidgetClass) &smeClassRec;
-
-extern SmeBSBClassRec smeBSBClassRec;
-WidgetClass smeBSBObjectClass = (WidgetClass) &smeBSBClassRec;
-
-extern SmeLineClassRec smeLineClassRec;
-WidgetClass smeLineObjectClass = (WidgetClass) &smeLineClassRec;
-
-extern StripChartClassRec stripChartClassRec;
-WidgetClass stripChartWidgetClass = (WidgetClass) &stripChartClassRec;
-
-extern TextClassRec textClassRec;
-WidgetClass textWidgetClass = (WidgetClass)&textClassRec;
-
-unsigned long FMT8BIT = 0L;
-unsigned long XawFmt8Bit = 0L;
-unsigned long XawFmtWide = 0L;
-
-extern TextSinkClassRec textSinkClassRec;
-WidgetClass textSinkObjectClass = (WidgetClass)&textSinkClassRec;
-
-extern TextSrcClassRec textSrcClassRec;
-WidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec;
-
-extern ToggleClassRec toggleClassRec;
-WidgetClass toggleWidgetClass = (WidgetClass) &toggleClassRec;
-
-extern TreeClassRec treeClassRec;
-WidgetClass treeWidgetClass = (WidgetClass) &treeClassRec;
-
-extern VendorShellClassRec vendorShellClassRec;
-WidgetClass vendorShellWidgetClass = (WidgetClass) &vendorShellClassRec;
-
-extern ViewportClassRec viewportClassRec;
-WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec;
-
-#endif /* SUNSHLIB */
+/* + +Copyright 1991, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#if defined(SUNSHLIB) && !defined(SHAREDCODE) + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/Xaw/AsciiSinkP.h> +#include <X11/Xaw/AsciiSrcP.h> +#include <X11/Xaw/AsciiTextP.h> +#include <X11/Xaw/MultiSinkP.h> +#include <X11/Xaw/MultiSrcP.h> +#include <X11/Xaw/BoxP.h> +#include <X11/Xaw/CommandP.h> +#include <X11/Xaw/DialogP.h> +#include <X11/Xaw/FormP.h> +#include <X11/Xaw/GripP.h> +#include <X11/Xaw/LabelP.h> +#include <X11/Xaw/ListP.h> +#include <X11/Xaw/MenuButtoP.h> +#include <X11/Xaw/PanedP.h> +#include <X11/Xaw/PannerP.h> +#include <X11/Xaw/PortholeP.h> +#include <X11/Xaw/RepeaterP.h> +#include <X11/Xaw/ScrollbarP.h> +#include <X11/Xaw/SimpleP.h> +#include <X11/Xaw/SimpleMenP.h> +#include <X11/Xaw/SmeP.h> +#include <X11/Xaw/SmeBSBP.h> +#include <X11/Xaw/SmeLineP.h> +#include <X11/Xaw/StripCharP.h> +#include <X11/Xaw/TextP.h> +#include <X11/Xaw/TextSinkP.h> +#include <X11/Xaw/TextSrcP.h> +#include <X11/Xaw/ToggleP.h> +#include <X11/Xaw/TreeP.h> +#include <X11/VendorP.h> +#include <X11/Xaw/ViewportP.h> + +extern AsciiSinkClassRec asciiSinkClassRec; +WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec; + +extern AsciiSrcClassRec asciiSrcClassRec; +WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec; + +extern AsciiTextClassRec asciiTextClassRec; +WidgetClass asciiTextWidgetClass = (WidgetClass)&asciiTextClassRec; + +#ifdef ASCII_STRING +extern AsciiStringClassRec asciiStringClassRec; +WidgetClass asciiStringWidgetClass = (WidgetClass)&asciiStringClassRec; +#endif + +#ifdef ASCII_DISK +extern AsciiDiskClassRec asciiDiskClassRec; +WidgetClass asciiDiskWidgetClass = (WidgetClass)&asciiDiskClassRec; +#endif + +extern MultiSinkClassRec multiSinkClassRec; +WidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec; + +extern MultiSrcClassRec multiSrcClassRec; +WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec; + +extern BoxClassRec boxClassRec; +WidgetClass boxWidgetClass = (WidgetClass)&boxClassRec; + +extern CommandClassRec commandClassRec; +WidgetClass commandWidgetClass = (WidgetClass) &commandClassRec; + +extern DialogClassRec dialogClassRec; +WidgetClass dialogWidgetClass = (WidgetClass)&dialogClassRec; + +extern FormClassRec formClassRec; +WidgetClass formWidgetClass = (WidgetClass)&formClassRec; + +extern GripClassRec gripClassRec; +WidgetClass gripWidgetClass = (WidgetClass) &gripClassRec; + +extern LabelClassRec labelClassRec; +WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec; + +extern ListClassRec listClassRec; +WidgetClass listWidgetClass = (WidgetClass)&listClassRec; + +extern MenuButtonClassRec menuButtonClassRec; +WidgetClass menuButtonWidgetClass = (WidgetClass) &menuButtonClassRec; + +extern PanedClassRec panedClassRec; +WidgetClass panedWidgetClass = (WidgetClass) &panedClassRec; +WidgetClass vPanedWidgetClass = (WidgetClass) &panedClassRec; + +extern PannerClassRec pannerClassRec; +WidgetClass pannerWidgetClass = (WidgetClass) &pannerClassRec; + +extern PortholeClassRec portholeClassRec; +WidgetClass portholeWidgetClass = (WidgetClass) &portholeClassRec; + +extern RepeaterClassRec repeaterClassRec; +WidgetClass repeaterWidgetClass = (WidgetClass) &repeaterClassRec; + +extern ScrollbarClassRec scrollbarClassRec; +WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec; + +extern SimpleClassRec simpleClassRec; +WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec; + +extern SimpleMenuClassRec simpleMenuClassRec; +WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec; + +extern SmeClassRec smeClassRec; +WidgetClass smeObjectClass = (WidgetClass) &smeClassRec; + +extern SmeBSBClassRec smeBSBClassRec; +WidgetClass smeBSBObjectClass = (WidgetClass) &smeBSBClassRec; + +extern SmeLineClassRec smeLineClassRec; +WidgetClass smeLineObjectClass = (WidgetClass) &smeLineClassRec; + +extern StripChartClassRec stripChartClassRec; +WidgetClass stripChartWidgetClass = (WidgetClass) &stripChartClassRec; + +extern TextClassRec textClassRec; +WidgetClass textWidgetClass = (WidgetClass)&textClassRec; + +unsigned long FMT8BIT = 0L; +unsigned long XawFmt8Bit = 0L; +unsigned long XawFmtWide = 0L; + +extern TextSinkClassRec textSinkClassRec; +WidgetClass textSinkObjectClass = (WidgetClass)&textSinkClassRec; + +extern TextSrcClassRec textSrcClassRec; +WidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec; + +extern ToggleClassRec toggleClassRec; +WidgetClass toggleWidgetClass = (WidgetClass) &toggleClassRec; + +extern TreeClassRec treeClassRec; +WidgetClass treeWidgetClass = (WidgetClass) &treeClassRec; + +extern VendorShellClassRec vendorShellClassRec; +WidgetClass vendorShellWidgetClass = (WidgetClass) &vendorShellClassRec; + +extern ViewportClassRec viewportClassRec; +WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec; + +#endif /* SUNSHLIB */ |