diff options
author | marha <marha@users.sourceforge.net> | 2009-11-06 06:59:46 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-11-06 06:59:46 +0000 |
commit | ace7902333b6f61aab5a6035dbcb222763bff186 (patch) | |
tree | 28445e829d5f04c8d79bda2514be37d5fb29738e /libXaw/src | |
parent | c9179017c7e70703b7cac46c2df8b950506319e0 (diff) | |
download | vcxsrv-ace7902333b6f61aab5a6035dbcb222763bff186.tar.gz vcxsrv-ace7902333b6f61aab5a6035dbcb222763bff186.tar.bz2 vcxsrv-ace7902333b6f61aab5a6035dbcb222763bff186.zip |
Added libXaw-1.0.7
Diffstat (limited to 'libXaw/src')
49 files changed, 48427 insertions, 0 deletions
diff --git a/libXaw/src/Actions.c b/libXaw/src/Actions.c new file mode 100644 index 000000000..a65308b6a --- /dev/null +++ b/libXaw/src/Actions.c @@ -0,0 +1,1139 @@ +/* + * 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. + */ + +/* $XFree86: xc/lib/Xaw/Actions.c,v 3.17 2003/03/25 04:18:10 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..4d95887d1 --- /dev/null +++ b/libXaw/src/AllWidgets.c @@ -0,0 +1,127 @@ +/* $Xorg: AllWidgets.c,v 1.4 2001/02/09 02:03:42 xorgcvs Exp $ */ + +/* + +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. + +*/ +/* $XFree86: xc/lib/Xaw/AllWidgets.c,v 1.3 2001/08/23 21:49:51 tsi Exp $ */ + +#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; +#if !defined(OLDXAW) && !defined(XAW7) +extern WidgetClass xawPrintShellWidgetClass; +#endif + +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 }, +#if !defined(OLDXAW) && !defined(XAW7) +{ "printShell", &xawPrintShellWidgetClass }, +#endif +}; + +int XawWidgetCount = XtNumber(XawWidgetArray); + diff --git a/libXaw/src/AsciiSink.c b/libXaw/src/AsciiSink.c new file mode 100644 index 000000000..ad35a127c --- /dev/null +++ b/libXaw/src/AsciiSink.c @@ -0,0 +1,1951 @@ +/* $Xorg: AsciiSink.c,v 1.4 2001/02/09 02:03:42 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/AsciiSink.c,v 1.26 2001/12/14 19:54:38 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..eb569fc9f --- /dev/null +++ b/libXaw/src/AsciiSrc.c @@ -0,0 +1,1886 @@ +/* $Xorg: AsciiSrc.c,v 1.4 2001/02/09 02:03:42 xorgcvs Exp $ */ + +/* + +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. + +*/ + +/* $XFree86: xc/lib/Xaw/AsciiSrc.c,v 1.33 2002/07/04 17:04:20 paulo Exp $ */ + +/* + * 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 + || write(fd, string, length) == -1) + 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) + 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 new file mode 100644 index 000000000..7305100f6 --- /dev/null +++ b/libXaw/src/AsciiText.c @@ -0,0 +1,360 @@ +/* $Xorg: AsciiText.c,v 1.4 2001/02/09 02:03:42 xorgcvs Exp $ */ + +/* + +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. + +*/ +/* $XFree86: xc/lib/Xaw/AsciiText.c,v 3.9 2001/01/17 19:42:25 dawes Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..f4f293926 --- /dev/null +++ b/libXaw/src/Box.c @@ -0,0 +1,675 @@ +/* $Xorg: Box.c,v 1.4 2001/02/09 02:03:43 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Box.c,v 1.14 2001/01/17 19:42:25 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..845ffb8b6 --- /dev/null +++ b/libXaw/src/Command.c @@ -0,0 +1,660 @@ +/* $Xorg: Command.c,v 1.5 2001/02/09 02:03:43 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Command.c,v 1.15tsi Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..24c01ca14 --- /dev/null +++ b/libXaw/src/Converters.c @@ -0,0 +1,701 @@ +/* + * 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. + */ + +/* $XFree86: xc/lib/Xaw/Converters.c,v 3.13 1999/06/06 08:47:54 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..62d91b883 --- /dev/null +++ b/libXaw/src/Dialog.c @@ -0,0 +1,463 @@ +/* $Xorg: Dialog.c,v 1.4 2001/02/09 02:03:43 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Dialog.c,v 1.7 2001/01/17 19:42:26 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..1704286ca --- /dev/null +++ b/libXaw/src/DisplayList.c @@ -0,0 +1,2257 @@ +/* + * 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 + */ + +/* $XFree86: xc/lib/Xaw/DisplayList.c,v 3.18 2003/05/23 14:51:15 tsi Exp $ */ + +#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 new file mode 100644 index 000000000..1d162407b --- /dev/null +++ b/libXaw/src/Form.c @@ -0,0 +1,1110 @@ +/* $Xorg: Form.c,v 1.4 2001/02/09 02:03:43 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ + +/* $XFree86: xc/lib/Xaw/Form.c,v 1.20 2001/02/05 22:38:04 paulo Exp $ */ + +#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 new file mode 100644 index 000000000..c9d418368 --- /dev/null +++ b/libXaw/src/Grip.c @@ -0,0 +1,188 @@ +/* $Xorg: Grip.c,v 1.4 2001/02/09 02:03:43 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Grip.c,v 1.7 2001/01/17 19:42:26 dawes Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..0a4c6ea2a --- /dev/null +++ b/libXaw/src/Label.c @@ -0,0 +1,824 @@ +/* $Xorg: Label.c,v 1.5 2001/02/09 02:03:43 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Label.c,v 1.12 2001/01/17 19:42:27 dawes Exp $ */ + +#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 = (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 new file mode 100644 index 000000000..54ca5168f --- /dev/null +++ b/libXaw/src/List.c @@ -0,0 +1,1273 @@ +/* $Xorg: List.c,v 1.4 2001/02/09 02:03:44 xorgcvs Exp $ */ + +/* +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. +*/ +/* $XFree86: xc/lib/Xaw/List.c,v 1.16 2001/01/17 19:42:27 dawes Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..2aa99800c --- /dev/null +++ b/libXaw/src/Makefile.am @@ -0,0 +1,121 @@ +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) \ + -I${top_srcdir}/include \ + -I${top_srcdir}/include/X11/Xaw \ + -DPROJECT_ROOT=\"$(prefix)\" + +if BUILD_XAW6 + +lib_LTLIBRARIES += libXaw6.la + +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 +endif + +endif + +if BUILD_XAW7 + +lib_LTLIBRARIES += libXaw7.la + +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 +endif + +endif + +EXTRA_DIST = sharedlib.c diff --git a/libXaw/src/Makefile.in b/libXaw/src/Makefile.in new file mode 100644 index 000000000..07d3ff348 --- /dev/null +++ b/libXaw/src/Makefile.in @@ -0,0 +1,1506 @@ +# Makefile.in generated by automake 1.11 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@BUILD_XAW6_TRUE@am__append_1 = libXaw6.la +@BUILD_XAW7_TRUE@am__append_2 = libXaw7.la +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +@BUILD_XAW6_TRUE@libXaw6_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__libXaw6_la_SOURCES_DIST = 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 +am__objects_1 = libXaw6_la-Actions.lo libXaw6_la-AllWidgets.lo \ + libXaw6_la-AsciiSink.lo libXaw6_la-AsciiSrc.lo \ + libXaw6_la-AsciiText.lo libXaw6_la-Box.lo \ + libXaw6_la-Command.lo libXaw6_la-Converters.lo \ + libXaw6_la-Dialog.lo libXaw6_la-DisplayList.lo \ + libXaw6_la-Form.lo libXaw6_la-Grip.lo libXaw6_la-Label.lo \ + libXaw6_la-List.lo libXaw6_la-MenuButton.lo \ + libXaw6_la-MultiSrc.lo libXaw6_la-MultiSink.lo \ + libXaw6_la-OS.lo libXaw6_la-Paned.lo libXaw6_la-Panner.lo \ + libXaw6_la-Pixmap.lo libXaw6_la-Porthole.lo \ + libXaw6_la-Repeater.lo libXaw6_la-Scrollbar.lo \ + libXaw6_la-Simple.lo libXaw6_la-SimpleMenu.lo \ + libXaw6_la-Sme.lo libXaw6_la-SmeBSB.lo libXaw6_la-SmeLine.lo \ + libXaw6_la-StripChart.lo libXaw6_la-Text.lo \ + libXaw6_la-TextSink.lo libXaw6_la-TextSrc.lo \ + libXaw6_la-TextAction.lo libXaw6_la-TextPop.lo \ + libXaw6_la-TextTr.lo libXaw6_la-Toggle.lo libXaw6_la-Tree.lo \ + libXaw6_la-Vendor.lo libXaw6_la-Viewport.lo \ + libXaw6_la-XawIm.lo libXaw6_la-XawInit.lo \ + libXaw6_la-XawI18n.lo +@BUILD_XAW6_TRUE@am_libXaw6_la_OBJECTS = $(am__objects_1) +libXaw6_la_OBJECTS = $(am_libXaw6_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +libXaw6_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libXaw6_la_CFLAGS) \ + $(CFLAGS) $(libXaw6_la_LDFLAGS) $(LDFLAGS) -o $@ +@BUILD_XAW6_TRUE@am_libXaw6_la_rpath = -rpath $(libdir) +@BUILD_XAW7_TRUE@libXaw7_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__libXaw7_la_SOURCES_DIST = 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 Tip.c +am__objects_2 = libXaw7_la-Actions.lo libXaw7_la-AllWidgets.lo \ + libXaw7_la-AsciiSink.lo libXaw7_la-AsciiSrc.lo \ + libXaw7_la-AsciiText.lo libXaw7_la-Box.lo \ + libXaw7_la-Command.lo libXaw7_la-Converters.lo \ + libXaw7_la-Dialog.lo libXaw7_la-DisplayList.lo \ + libXaw7_la-Form.lo libXaw7_la-Grip.lo libXaw7_la-Label.lo \ + libXaw7_la-List.lo libXaw7_la-MenuButton.lo \ + libXaw7_la-MultiSrc.lo libXaw7_la-MultiSink.lo \ + libXaw7_la-OS.lo libXaw7_la-Paned.lo libXaw7_la-Panner.lo \ + libXaw7_la-Pixmap.lo libXaw7_la-Porthole.lo \ + libXaw7_la-Repeater.lo libXaw7_la-Scrollbar.lo \ + libXaw7_la-Simple.lo libXaw7_la-SimpleMenu.lo \ + libXaw7_la-Sme.lo libXaw7_la-SmeBSB.lo libXaw7_la-SmeLine.lo \ + libXaw7_la-StripChart.lo libXaw7_la-Text.lo \ + libXaw7_la-TextSink.lo libXaw7_la-TextSrc.lo \ + libXaw7_la-TextAction.lo libXaw7_la-TextPop.lo \ + libXaw7_la-TextTr.lo libXaw7_la-Toggle.lo libXaw7_la-Tree.lo \ + libXaw7_la-Vendor.lo libXaw7_la-Viewport.lo \ + libXaw7_la-XawIm.lo libXaw7_la-XawInit.lo \ + libXaw7_la-XawI18n.lo +@BUILD_XAW7_TRUE@am_libXaw7_la_OBJECTS = $(am__objects_2) \ +@BUILD_XAW7_TRUE@ libXaw7_la-Tip.lo +libXaw7_la_OBJECTS = $(am_libXaw7_la_OBJECTS) +libXaw7_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libXaw7_la_CFLAGS) \ + $(CFLAGS) $(libXaw7_la_LDFLAGS) $(LDFLAGS) -o $@ +@BUILD_XAW7_TRUE@am_libXaw7_la_rpath = -rpath $(libdir) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libXaw6_la_SOURCES) $(libXaw7_la_SOURCES) +DIST_SOURCES = $(am__libXaw6_la_SOURCES_DIST) \ + $(am__libXaw7_la_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHANGELOG_CMD = @CHANGELOG_CMD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CWARNFLAGS = @CWARNFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +GREP = @GREP@ +GROFF = @GROFF@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBEXT = @LIBEXT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XAW6_CFLAGS = @XAW6_CFLAGS@ +XAW6_LIBS = @XAW6_LIBS@ +XAW7_CFLAGS = @XAW7_CFLAGS@ +XAW7_LIBS = @XAW7_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +distcleancheck_listfiles = @distcleancheck_listfiles@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +lib_LTLIBRARIES = $(am__append_1) $(am__append_2) + +# +# 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) \ + -I${top_srcdir}/include \ + -I${top_srcdir}/include/X11/Xaw \ + -DPROJECT_ROOT=\"$(prefix)\" + +@BUILD_XAW6_TRUE@libXaw6_la_CFLAGS = \ +@BUILD_XAW6_TRUE@ $(COMMON_CFLAGS) \ +@BUILD_XAW6_TRUE@ -DOLDXAW \ +@BUILD_XAW6_TRUE@ $(XAW6_CFLAGS) + +@BUILD_XAW6_TRUE@libXaw6_la_SOURCES = \ +@BUILD_XAW6_TRUE@ $(COMMON_SOURCES) + +@BUILD_XAW6_TRUE@libXaw6_la_LDFLAGS = -version-info 6:1:0 -no-undefined +@BUILD_XAW6_TRUE@libXaw6_la_LIBADD = $(XAW6_LIBS) +@BUILD_XAW7_TRUE@libXaw7_la_CFLAGS = \ +@BUILD_XAW7_TRUE@ $(COMMON_CFLAGS) \ +@BUILD_XAW7_TRUE@ -DXAW7 \ +@BUILD_XAW7_TRUE@ $(XAW7_CFLAGS) + +@BUILD_XAW7_TRUE@libXaw7_la_SOURCES = \ +@BUILD_XAW7_TRUE@ $(COMMON_SOURCES) \ +@BUILD_XAW7_TRUE@ Tip.c + +@BUILD_XAW7_TRUE@libXaw7_la_LDFLAGS = -version-info 7:0:0 -no-undefined +@BUILD_XAW7_TRUE@libXaw7_la_LIBADD = $(XAW7_LIBS) +EXTRA_DIST = sharedlib.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libXaw6.la: $(libXaw6_la_OBJECTS) $(libXaw6_la_DEPENDENCIES) + $(AM_V_CCLD)$(libXaw6_la_LINK) $(am_libXaw6_la_rpath) $(libXaw6_la_OBJECTS) $(libXaw6_la_LIBADD) $(LIBS) +libXaw7.la: $(libXaw7_la_OBJECTS) $(libXaw7_la_DEPENDENCIES) + $(AM_V_CCLD)$(libXaw7_la_LINK) $(am_libXaw7_la_rpath) $(libXaw7_la_OBJECTS) $(libXaw7_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Actions.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-AllWidgets.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-AsciiSink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-AsciiSrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-AsciiText.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Box.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Command.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Converters.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Dialog.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-DisplayList.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Form.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Grip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Label.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-List.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-MenuButton.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-MultiSink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-MultiSrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-OS.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Paned.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Panner.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Pixmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Porthole.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Repeater.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Scrollbar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Simple.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-SimpleMenu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Sme.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-SmeBSB.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-SmeLine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-StripChart.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Text.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-TextAction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-TextPop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-TextSink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-TextSrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-TextTr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Toggle.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Tree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Vendor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-Viewport.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-XawI18n.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-XawIm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw6_la-XawInit.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Actions.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-AllWidgets.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-AsciiSink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-AsciiSrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-AsciiText.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Box.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Command.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Converters.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Dialog.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-DisplayList.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Form.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Grip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Label.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-List.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-MenuButton.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-MultiSink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-MultiSrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-OS.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Paned.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Panner.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Pixmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Porthole.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Repeater.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Scrollbar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Simple.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-SimpleMenu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Sme.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-SmeBSB.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-SmeLine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-StripChart.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Text.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-TextAction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-TextPop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-TextSink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-TextSrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-TextTr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Tip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Toggle.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Tree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Vendor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-Viewport.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-XawI18n.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-XawIm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXaw7_la-XawInit.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libXaw6_la-Actions.lo: Actions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Actions.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Actions.Tpo -c -o libXaw6_la-Actions.lo `test -f 'Actions.c' || echo '$(srcdir)/'`Actions.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Actions.Tpo $(DEPDIR)/libXaw6_la-Actions.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Actions.c' object='libXaw6_la-Actions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Actions.lo `test -f 'Actions.c' || echo '$(srcdir)/'`Actions.c + +libXaw6_la-AllWidgets.lo: AllWidgets.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-AllWidgets.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-AllWidgets.Tpo -c -o libXaw6_la-AllWidgets.lo `test -f 'AllWidgets.c' || echo '$(srcdir)/'`AllWidgets.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-AllWidgets.Tpo $(DEPDIR)/libXaw6_la-AllWidgets.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='AllWidgets.c' object='libXaw6_la-AllWidgets.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-AllWidgets.lo `test -f 'AllWidgets.c' || echo '$(srcdir)/'`AllWidgets.c + +libXaw6_la-AsciiSink.lo: AsciiSink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-AsciiSink.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-AsciiSink.Tpo -c -o libXaw6_la-AsciiSink.lo `test -f 'AsciiSink.c' || echo '$(srcdir)/'`AsciiSink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-AsciiSink.Tpo $(DEPDIR)/libXaw6_la-AsciiSink.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='AsciiSink.c' object='libXaw6_la-AsciiSink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-AsciiSink.lo `test -f 'AsciiSink.c' || echo '$(srcdir)/'`AsciiSink.c + +libXaw6_la-AsciiSrc.lo: AsciiSrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-AsciiSrc.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-AsciiSrc.Tpo -c -o libXaw6_la-AsciiSrc.lo `test -f 'AsciiSrc.c' || echo '$(srcdir)/'`AsciiSrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-AsciiSrc.Tpo $(DEPDIR)/libXaw6_la-AsciiSrc.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='AsciiSrc.c' object='libXaw6_la-AsciiSrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-AsciiSrc.lo `test -f 'AsciiSrc.c' || echo '$(srcdir)/'`AsciiSrc.c + +libXaw6_la-AsciiText.lo: AsciiText.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-AsciiText.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-AsciiText.Tpo -c -o libXaw6_la-AsciiText.lo `test -f 'AsciiText.c' || echo '$(srcdir)/'`AsciiText.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-AsciiText.Tpo $(DEPDIR)/libXaw6_la-AsciiText.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='AsciiText.c' object='libXaw6_la-AsciiText.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-AsciiText.lo `test -f 'AsciiText.c' || echo '$(srcdir)/'`AsciiText.c + +libXaw6_la-Box.lo: Box.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Box.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Box.Tpo -c -o libXaw6_la-Box.lo `test -f 'Box.c' || echo '$(srcdir)/'`Box.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Box.Tpo $(DEPDIR)/libXaw6_la-Box.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Box.c' object='libXaw6_la-Box.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Box.lo `test -f 'Box.c' || echo '$(srcdir)/'`Box.c + +libXaw6_la-Command.lo: Command.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Command.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Command.Tpo -c -o libXaw6_la-Command.lo `test -f 'Command.c' || echo '$(srcdir)/'`Command.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Command.Tpo $(DEPDIR)/libXaw6_la-Command.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Command.c' object='libXaw6_la-Command.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Command.lo `test -f 'Command.c' || echo '$(srcdir)/'`Command.c + +libXaw6_la-Converters.lo: Converters.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Converters.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Converters.Tpo -c -o libXaw6_la-Converters.lo `test -f 'Converters.c' || echo '$(srcdir)/'`Converters.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Converters.Tpo $(DEPDIR)/libXaw6_la-Converters.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Converters.c' object='libXaw6_la-Converters.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Converters.lo `test -f 'Converters.c' || echo '$(srcdir)/'`Converters.c + +libXaw6_la-Dialog.lo: Dialog.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Dialog.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Dialog.Tpo -c -o libXaw6_la-Dialog.lo `test -f 'Dialog.c' || echo '$(srcdir)/'`Dialog.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Dialog.Tpo $(DEPDIR)/libXaw6_la-Dialog.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Dialog.c' object='libXaw6_la-Dialog.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Dialog.lo `test -f 'Dialog.c' || echo '$(srcdir)/'`Dialog.c + +libXaw6_la-DisplayList.lo: DisplayList.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-DisplayList.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-DisplayList.Tpo -c -o libXaw6_la-DisplayList.lo `test -f 'DisplayList.c' || echo '$(srcdir)/'`DisplayList.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-DisplayList.Tpo $(DEPDIR)/libXaw6_la-DisplayList.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='DisplayList.c' object='libXaw6_la-DisplayList.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-DisplayList.lo `test -f 'DisplayList.c' || echo '$(srcdir)/'`DisplayList.c + +libXaw6_la-Form.lo: Form.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Form.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Form.Tpo -c -o libXaw6_la-Form.lo `test -f 'Form.c' || echo '$(srcdir)/'`Form.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Form.Tpo $(DEPDIR)/libXaw6_la-Form.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Form.c' object='libXaw6_la-Form.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Form.lo `test -f 'Form.c' || echo '$(srcdir)/'`Form.c + +libXaw6_la-Grip.lo: Grip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Grip.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Grip.Tpo -c -o libXaw6_la-Grip.lo `test -f 'Grip.c' || echo '$(srcdir)/'`Grip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Grip.Tpo $(DEPDIR)/libXaw6_la-Grip.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Grip.c' object='libXaw6_la-Grip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Grip.lo `test -f 'Grip.c' || echo '$(srcdir)/'`Grip.c + +libXaw6_la-Label.lo: Label.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Label.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Label.Tpo -c -o libXaw6_la-Label.lo `test -f 'Label.c' || echo '$(srcdir)/'`Label.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Label.Tpo $(DEPDIR)/libXaw6_la-Label.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Label.c' object='libXaw6_la-Label.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Label.lo `test -f 'Label.c' || echo '$(srcdir)/'`Label.c + +libXaw6_la-List.lo: List.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-List.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-List.Tpo -c -o libXaw6_la-List.lo `test -f 'List.c' || echo '$(srcdir)/'`List.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-List.Tpo $(DEPDIR)/libXaw6_la-List.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='List.c' object='libXaw6_la-List.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-List.lo `test -f 'List.c' || echo '$(srcdir)/'`List.c + +libXaw6_la-MenuButton.lo: MenuButton.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-MenuButton.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-MenuButton.Tpo -c -o libXaw6_la-MenuButton.lo `test -f 'MenuButton.c' || echo '$(srcdir)/'`MenuButton.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-MenuButton.Tpo $(DEPDIR)/libXaw6_la-MenuButton.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='MenuButton.c' object='libXaw6_la-MenuButton.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-MenuButton.lo `test -f 'MenuButton.c' || echo '$(srcdir)/'`MenuButton.c + +libXaw6_la-MultiSrc.lo: MultiSrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-MultiSrc.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-MultiSrc.Tpo -c -o libXaw6_la-MultiSrc.lo `test -f 'MultiSrc.c' || echo '$(srcdir)/'`MultiSrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-MultiSrc.Tpo $(DEPDIR)/libXaw6_la-MultiSrc.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='MultiSrc.c' object='libXaw6_la-MultiSrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-MultiSrc.lo `test -f 'MultiSrc.c' || echo '$(srcdir)/'`MultiSrc.c + +libXaw6_la-MultiSink.lo: MultiSink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-MultiSink.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-MultiSink.Tpo -c -o libXaw6_la-MultiSink.lo `test -f 'MultiSink.c' || echo '$(srcdir)/'`MultiSink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-MultiSink.Tpo $(DEPDIR)/libXaw6_la-MultiSink.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='MultiSink.c' object='libXaw6_la-MultiSink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-MultiSink.lo `test -f 'MultiSink.c' || echo '$(srcdir)/'`MultiSink.c + +libXaw6_la-OS.lo: OS.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-OS.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-OS.Tpo -c -o libXaw6_la-OS.lo `test -f 'OS.c' || echo '$(srcdir)/'`OS.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-OS.Tpo $(DEPDIR)/libXaw6_la-OS.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='OS.c' object='libXaw6_la-OS.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-OS.lo `test -f 'OS.c' || echo '$(srcdir)/'`OS.c + +libXaw6_la-Paned.lo: Paned.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Paned.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Paned.Tpo -c -o libXaw6_la-Paned.lo `test -f 'Paned.c' || echo '$(srcdir)/'`Paned.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Paned.Tpo $(DEPDIR)/libXaw6_la-Paned.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Paned.c' object='libXaw6_la-Paned.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Paned.lo `test -f 'Paned.c' || echo '$(srcdir)/'`Paned.c + +libXaw6_la-Panner.lo: Panner.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Panner.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Panner.Tpo -c -o libXaw6_la-Panner.lo `test -f 'Panner.c' || echo '$(srcdir)/'`Panner.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Panner.Tpo $(DEPDIR)/libXaw6_la-Panner.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Panner.c' object='libXaw6_la-Panner.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Panner.lo `test -f 'Panner.c' || echo '$(srcdir)/'`Panner.c + +libXaw6_la-Pixmap.lo: Pixmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Pixmap.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Pixmap.Tpo -c -o libXaw6_la-Pixmap.lo `test -f 'Pixmap.c' || echo '$(srcdir)/'`Pixmap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Pixmap.Tpo $(DEPDIR)/libXaw6_la-Pixmap.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Pixmap.c' object='libXaw6_la-Pixmap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Pixmap.lo `test -f 'Pixmap.c' || echo '$(srcdir)/'`Pixmap.c + +libXaw6_la-Porthole.lo: Porthole.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Porthole.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Porthole.Tpo -c -o libXaw6_la-Porthole.lo `test -f 'Porthole.c' || echo '$(srcdir)/'`Porthole.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Porthole.Tpo $(DEPDIR)/libXaw6_la-Porthole.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Porthole.c' object='libXaw6_la-Porthole.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Porthole.lo `test -f 'Porthole.c' || echo '$(srcdir)/'`Porthole.c + +libXaw6_la-Repeater.lo: Repeater.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Repeater.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Repeater.Tpo -c -o libXaw6_la-Repeater.lo `test -f 'Repeater.c' || echo '$(srcdir)/'`Repeater.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Repeater.Tpo $(DEPDIR)/libXaw6_la-Repeater.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Repeater.c' object='libXaw6_la-Repeater.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Repeater.lo `test -f 'Repeater.c' || echo '$(srcdir)/'`Repeater.c + +libXaw6_la-Scrollbar.lo: Scrollbar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Scrollbar.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Scrollbar.Tpo -c -o libXaw6_la-Scrollbar.lo `test -f 'Scrollbar.c' || echo '$(srcdir)/'`Scrollbar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Scrollbar.Tpo $(DEPDIR)/libXaw6_la-Scrollbar.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Scrollbar.c' object='libXaw6_la-Scrollbar.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Scrollbar.lo `test -f 'Scrollbar.c' || echo '$(srcdir)/'`Scrollbar.c + +libXaw6_la-Simple.lo: Simple.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Simple.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Simple.Tpo -c -o libXaw6_la-Simple.lo `test -f 'Simple.c' || echo '$(srcdir)/'`Simple.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Simple.Tpo $(DEPDIR)/libXaw6_la-Simple.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Simple.c' object='libXaw6_la-Simple.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Simple.lo `test -f 'Simple.c' || echo '$(srcdir)/'`Simple.c + +libXaw6_la-SimpleMenu.lo: SimpleMenu.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-SimpleMenu.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-SimpleMenu.Tpo -c -o libXaw6_la-SimpleMenu.lo `test -f 'SimpleMenu.c' || echo '$(srcdir)/'`SimpleMenu.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-SimpleMenu.Tpo $(DEPDIR)/libXaw6_la-SimpleMenu.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='SimpleMenu.c' object='libXaw6_la-SimpleMenu.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-SimpleMenu.lo `test -f 'SimpleMenu.c' || echo '$(srcdir)/'`SimpleMenu.c + +libXaw6_la-Sme.lo: Sme.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Sme.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Sme.Tpo -c -o libXaw6_la-Sme.lo `test -f 'Sme.c' || echo '$(srcdir)/'`Sme.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Sme.Tpo $(DEPDIR)/libXaw6_la-Sme.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Sme.c' object='libXaw6_la-Sme.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Sme.lo `test -f 'Sme.c' || echo '$(srcdir)/'`Sme.c + +libXaw6_la-SmeBSB.lo: SmeBSB.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-SmeBSB.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-SmeBSB.Tpo -c -o libXaw6_la-SmeBSB.lo `test -f 'SmeBSB.c' || echo '$(srcdir)/'`SmeBSB.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-SmeBSB.Tpo $(DEPDIR)/libXaw6_la-SmeBSB.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='SmeBSB.c' object='libXaw6_la-SmeBSB.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-SmeBSB.lo `test -f 'SmeBSB.c' || echo '$(srcdir)/'`SmeBSB.c + +libXaw6_la-SmeLine.lo: SmeLine.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-SmeLine.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-SmeLine.Tpo -c -o libXaw6_la-SmeLine.lo `test -f 'SmeLine.c' || echo '$(srcdir)/'`SmeLine.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-SmeLine.Tpo $(DEPDIR)/libXaw6_la-SmeLine.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='SmeLine.c' object='libXaw6_la-SmeLine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-SmeLine.lo `test -f 'SmeLine.c' || echo '$(srcdir)/'`SmeLine.c + +libXaw6_la-StripChart.lo: StripChart.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-StripChart.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-StripChart.Tpo -c -o libXaw6_la-StripChart.lo `test -f 'StripChart.c' || echo '$(srcdir)/'`StripChart.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-StripChart.Tpo $(DEPDIR)/libXaw6_la-StripChart.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='StripChart.c' object='libXaw6_la-StripChart.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-StripChart.lo `test -f 'StripChart.c' || echo '$(srcdir)/'`StripChart.c + +libXaw6_la-Text.lo: Text.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Text.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Text.Tpo -c -o libXaw6_la-Text.lo `test -f 'Text.c' || echo '$(srcdir)/'`Text.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Text.Tpo $(DEPDIR)/libXaw6_la-Text.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Text.c' object='libXaw6_la-Text.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Text.lo `test -f 'Text.c' || echo '$(srcdir)/'`Text.c + +libXaw6_la-TextSink.lo: TextSink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-TextSink.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-TextSink.Tpo -c -o libXaw6_la-TextSink.lo `test -f 'TextSink.c' || echo '$(srcdir)/'`TextSink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-TextSink.Tpo $(DEPDIR)/libXaw6_la-TextSink.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextSink.c' object='libXaw6_la-TextSink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-TextSink.lo `test -f 'TextSink.c' || echo '$(srcdir)/'`TextSink.c + +libXaw6_la-TextSrc.lo: TextSrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-TextSrc.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-TextSrc.Tpo -c -o libXaw6_la-TextSrc.lo `test -f 'TextSrc.c' || echo '$(srcdir)/'`TextSrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-TextSrc.Tpo $(DEPDIR)/libXaw6_la-TextSrc.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextSrc.c' object='libXaw6_la-TextSrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-TextSrc.lo `test -f 'TextSrc.c' || echo '$(srcdir)/'`TextSrc.c + +libXaw6_la-TextAction.lo: TextAction.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-TextAction.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-TextAction.Tpo -c -o libXaw6_la-TextAction.lo `test -f 'TextAction.c' || echo '$(srcdir)/'`TextAction.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-TextAction.Tpo $(DEPDIR)/libXaw6_la-TextAction.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextAction.c' object='libXaw6_la-TextAction.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-TextAction.lo `test -f 'TextAction.c' || echo '$(srcdir)/'`TextAction.c + +libXaw6_la-TextPop.lo: TextPop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-TextPop.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-TextPop.Tpo -c -o libXaw6_la-TextPop.lo `test -f 'TextPop.c' || echo '$(srcdir)/'`TextPop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-TextPop.Tpo $(DEPDIR)/libXaw6_la-TextPop.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextPop.c' object='libXaw6_la-TextPop.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-TextPop.lo `test -f 'TextPop.c' || echo '$(srcdir)/'`TextPop.c + +libXaw6_la-TextTr.lo: TextTr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-TextTr.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-TextTr.Tpo -c -o libXaw6_la-TextTr.lo `test -f 'TextTr.c' || echo '$(srcdir)/'`TextTr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-TextTr.Tpo $(DEPDIR)/libXaw6_la-TextTr.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextTr.c' object='libXaw6_la-TextTr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-TextTr.lo `test -f 'TextTr.c' || echo '$(srcdir)/'`TextTr.c + +libXaw6_la-Toggle.lo: Toggle.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Toggle.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Toggle.Tpo -c -o libXaw6_la-Toggle.lo `test -f 'Toggle.c' || echo '$(srcdir)/'`Toggle.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Toggle.Tpo $(DEPDIR)/libXaw6_la-Toggle.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Toggle.c' object='libXaw6_la-Toggle.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Toggle.lo `test -f 'Toggle.c' || echo '$(srcdir)/'`Toggle.c + +libXaw6_la-Tree.lo: Tree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Tree.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Tree.Tpo -c -o libXaw6_la-Tree.lo `test -f 'Tree.c' || echo '$(srcdir)/'`Tree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Tree.Tpo $(DEPDIR)/libXaw6_la-Tree.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Tree.c' object='libXaw6_la-Tree.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Tree.lo `test -f 'Tree.c' || echo '$(srcdir)/'`Tree.c + +libXaw6_la-Vendor.lo: Vendor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Vendor.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Vendor.Tpo -c -o libXaw6_la-Vendor.lo `test -f 'Vendor.c' || echo '$(srcdir)/'`Vendor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Vendor.Tpo $(DEPDIR)/libXaw6_la-Vendor.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Vendor.c' object='libXaw6_la-Vendor.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Vendor.lo `test -f 'Vendor.c' || echo '$(srcdir)/'`Vendor.c + +libXaw6_la-Viewport.lo: Viewport.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-Viewport.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-Viewport.Tpo -c -o libXaw6_la-Viewport.lo `test -f 'Viewport.c' || echo '$(srcdir)/'`Viewport.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-Viewport.Tpo $(DEPDIR)/libXaw6_la-Viewport.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Viewport.c' object='libXaw6_la-Viewport.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-Viewport.lo `test -f 'Viewport.c' || echo '$(srcdir)/'`Viewport.c + +libXaw6_la-XawIm.lo: XawIm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-XawIm.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-XawIm.Tpo -c -o libXaw6_la-XawIm.lo `test -f 'XawIm.c' || echo '$(srcdir)/'`XawIm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-XawIm.Tpo $(DEPDIR)/libXaw6_la-XawIm.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='XawIm.c' object='libXaw6_la-XawIm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-XawIm.lo `test -f 'XawIm.c' || echo '$(srcdir)/'`XawIm.c + +libXaw6_la-XawInit.lo: XawInit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-XawInit.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-XawInit.Tpo -c -o libXaw6_la-XawInit.lo `test -f 'XawInit.c' || echo '$(srcdir)/'`XawInit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-XawInit.Tpo $(DEPDIR)/libXaw6_la-XawInit.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='XawInit.c' object='libXaw6_la-XawInit.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-XawInit.lo `test -f 'XawInit.c' || echo '$(srcdir)/'`XawInit.c + +libXaw6_la-XawI18n.lo: XawI18n.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -MT libXaw6_la-XawI18n.lo -MD -MP -MF $(DEPDIR)/libXaw6_la-XawI18n.Tpo -c -o libXaw6_la-XawI18n.lo `test -f 'XawI18n.c' || echo '$(srcdir)/'`XawI18n.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw6_la-XawI18n.Tpo $(DEPDIR)/libXaw6_la-XawI18n.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='XawI18n.c' object='libXaw6_la-XawI18n.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw6_la_CFLAGS) $(CFLAGS) -c -o libXaw6_la-XawI18n.lo `test -f 'XawI18n.c' || echo '$(srcdir)/'`XawI18n.c + +libXaw7_la-Actions.lo: Actions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Actions.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Actions.Tpo -c -o libXaw7_la-Actions.lo `test -f 'Actions.c' || echo '$(srcdir)/'`Actions.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Actions.Tpo $(DEPDIR)/libXaw7_la-Actions.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Actions.c' object='libXaw7_la-Actions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Actions.lo `test -f 'Actions.c' || echo '$(srcdir)/'`Actions.c + +libXaw7_la-AllWidgets.lo: AllWidgets.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-AllWidgets.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-AllWidgets.Tpo -c -o libXaw7_la-AllWidgets.lo `test -f 'AllWidgets.c' || echo '$(srcdir)/'`AllWidgets.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-AllWidgets.Tpo $(DEPDIR)/libXaw7_la-AllWidgets.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='AllWidgets.c' object='libXaw7_la-AllWidgets.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-AllWidgets.lo `test -f 'AllWidgets.c' || echo '$(srcdir)/'`AllWidgets.c + +libXaw7_la-AsciiSink.lo: AsciiSink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-AsciiSink.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-AsciiSink.Tpo -c -o libXaw7_la-AsciiSink.lo `test -f 'AsciiSink.c' || echo '$(srcdir)/'`AsciiSink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-AsciiSink.Tpo $(DEPDIR)/libXaw7_la-AsciiSink.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='AsciiSink.c' object='libXaw7_la-AsciiSink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-AsciiSink.lo `test -f 'AsciiSink.c' || echo '$(srcdir)/'`AsciiSink.c + +libXaw7_la-AsciiSrc.lo: AsciiSrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-AsciiSrc.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-AsciiSrc.Tpo -c -o libXaw7_la-AsciiSrc.lo `test -f 'AsciiSrc.c' || echo '$(srcdir)/'`AsciiSrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-AsciiSrc.Tpo $(DEPDIR)/libXaw7_la-AsciiSrc.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='AsciiSrc.c' object='libXaw7_la-AsciiSrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-AsciiSrc.lo `test -f 'AsciiSrc.c' || echo '$(srcdir)/'`AsciiSrc.c + +libXaw7_la-AsciiText.lo: AsciiText.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-AsciiText.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-AsciiText.Tpo -c -o libXaw7_la-AsciiText.lo `test -f 'AsciiText.c' || echo '$(srcdir)/'`AsciiText.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-AsciiText.Tpo $(DEPDIR)/libXaw7_la-AsciiText.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='AsciiText.c' object='libXaw7_la-AsciiText.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-AsciiText.lo `test -f 'AsciiText.c' || echo '$(srcdir)/'`AsciiText.c + +libXaw7_la-Box.lo: Box.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Box.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Box.Tpo -c -o libXaw7_la-Box.lo `test -f 'Box.c' || echo '$(srcdir)/'`Box.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Box.Tpo $(DEPDIR)/libXaw7_la-Box.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Box.c' object='libXaw7_la-Box.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Box.lo `test -f 'Box.c' || echo '$(srcdir)/'`Box.c + +libXaw7_la-Command.lo: Command.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Command.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Command.Tpo -c -o libXaw7_la-Command.lo `test -f 'Command.c' || echo '$(srcdir)/'`Command.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Command.Tpo $(DEPDIR)/libXaw7_la-Command.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Command.c' object='libXaw7_la-Command.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Command.lo `test -f 'Command.c' || echo '$(srcdir)/'`Command.c + +libXaw7_la-Converters.lo: Converters.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Converters.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Converters.Tpo -c -o libXaw7_la-Converters.lo `test -f 'Converters.c' || echo '$(srcdir)/'`Converters.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Converters.Tpo $(DEPDIR)/libXaw7_la-Converters.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Converters.c' object='libXaw7_la-Converters.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Converters.lo `test -f 'Converters.c' || echo '$(srcdir)/'`Converters.c + +libXaw7_la-Dialog.lo: Dialog.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Dialog.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Dialog.Tpo -c -o libXaw7_la-Dialog.lo `test -f 'Dialog.c' || echo '$(srcdir)/'`Dialog.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Dialog.Tpo $(DEPDIR)/libXaw7_la-Dialog.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Dialog.c' object='libXaw7_la-Dialog.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Dialog.lo `test -f 'Dialog.c' || echo '$(srcdir)/'`Dialog.c + +libXaw7_la-DisplayList.lo: DisplayList.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-DisplayList.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-DisplayList.Tpo -c -o libXaw7_la-DisplayList.lo `test -f 'DisplayList.c' || echo '$(srcdir)/'`DisplayList.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-DisplayList.Tpo $(DEPDIR)/libXaw7_la-DisplayList.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='DisplayList.c' object='libXaw7_la-DisplayList.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-DisplayList.lo `test -f 'DisplayList.c' || echo '$(srcdir)/'`DisplayList.c + +libXaw7_la-Form.lo: Form.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Form.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Form.Tpo -c -o libXaw7_la-Form.lo `test -f 'Form.c' || echo '$(srcdir)/'`Form.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Form.Tpo $(DEPDIR)/libXaw7_la-Form.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Form.c' object='libXaw7_la-Form.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Form.lo `test -f 'Form.c' || echo '$(srcdir)/'`Form.c + +libXaw7_la-Grip.lo: Grip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Grip.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Grip.Tpo -c -o libXaw7_la-Grip.lo `test -f 'Grip.c' || echo '$(srcdir)/'`Grip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Grip.Tpo $(DEPDIR)/libXaw7_la-Grip.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Grip.c' object='libXaw7_la-Grip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Grip.lo `test -f 'Grip.c' || echo '$(srcdir)/'`Grip.c + +libXaw7_la-Label.lo: Label.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Label.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Label.Tpo -c -o libXaw7_la-Label.lo `test -f 'Label.c' || echo '$(srcdir)/'`Label.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Label.Tpo $(DEPDIR)/libXaw7_la-Label.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Label.c' object='libXaw7_la-Label.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Label.lo `test -f 'Label.c' || echo '$(srcdir)/'`Label.c + +libXaw7_la-List.lo: List.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-List.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-List.Tpo -c -o libXaw7_la-List.lo `test -f 'List.c' || echo '$(srcdir)/'`List.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-List.Tpo $(DEPDIR)/libXaw7_la-List.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='List.c' object='libXaw7_la-List.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-List.lo `test -f 'List.c' || echo '$(srcdir)/'`List.c + +libXaw7_la-MenuButton.lo: MenuButton.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-MenuButton.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-MenuButton.Tpo -c -o libXaw7_la-MenuButton.lo `test -f 'MenuButton.c' || echo '$(srcdir)/'`MenuButton.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-MenuButton.Tpo $(DEPDIR)/libXaw7_la-MenuButton.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='MenuButton.c' object='libXaw7_la-MenuButton.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-MenuButton.lo `test -f 'MenuButton.c' || echo '$(srcdir)/'`MenuButton.c + +libXaw7_la-MultiSrc.lo: MultiSrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-MultiSrc.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-MultiSrc.Tpo -c -o libXaw7_la-MultiSrc.lo `test -f 'MultiSrc.c' || echo '$(srcdir)/'`MultiSrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-MultiSrc.Tpo $(DEPDIR)/libXaw7_la-MultiSrc.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='MultiSrc.c' object='libXaw7_la-MultiSrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-MultiSrc.lo `test -f 'MultiSrc.c' || echo '$(srcdir)/'`MultiSrc.c + +libXaw7_la-MultiSink.lo: MultiSink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-MultiSink.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-MultiSink.Tpo -c -o libXaw7_la-MultiSink.lo `test -f 'MultiSink.c' || echo '$(srcdir)/'`MultiSink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-MultiSink.Tpo $(DEPDIR)/libXaw7_la-MultiSink.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='MultiSink.c' object='libXaw7_la-MultiSink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-MultiSink.lo `test -f 'MultiSink.c' || echo '$(srcdir)/'`MultiSink.c + +libXaw7_la-OS.lo: OS.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-OS.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-OS.Tpo -c -o libXaw7_la-OS.lo `test -f 'OS.c' || echo '$(srcdir)/'`OS.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-OS.Tpo $(DEPDIR)/libXaw7_la-OS.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='OS.c' object='libXaw7_la-OS.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-OS.lo `test -f 'OS.c' || echo '$(srcdir)/'`OS.c + +libXaw7_la-Paned.lo: Paned.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Paned.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Paned.Tpo -c -o libXaw7_la-Paned.lo `test -f 'Paned.c' || echo '$(srcdir)/'`Paned.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Paned.Tpo $(DEPDIR)/libXaw7_la-Paned.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Paned.c' object='libXaw7_la-Paned.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Paned.lo `test -f 'Paned.c' || echo '$(srcdir)/'`Paned.c + +libXaw7_la-Panner.lo: Panner.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Panner.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Panner.Tpo -c -o libXaw7_la-Panner.lo `test -f 'Panner.c' || echo '$(srcdir)/'`Panner.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Panner.Tpo $(DEPDIR)/libXaw7_la-Panner.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Panner.c' object='libXaw7_la-Panner.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Panner.lo `test -f 'Panner.c' || echo '$(srcdir)/'`Panner.c + +libXaw7_la-Pixmap.lo: Pixmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Pixmap.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Pixmap.Tpo -c -o libXaw7_la-Pixmap.lo `test -f 'Pixmap.c' || echo '$(srcdir)/'`Pixmap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Pixmap.Tpo $(DEPDIR)/libXaw7_la-Pixmap.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Pixmap.c' object='libXaw7_la-Pixmap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Pixmap.lo `test -f 'Pixmap.c' || echo '$(srcdir)/'`Pixmap.c + +libXaw7_la-Porthole.lo: Porthole.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Porthole.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Porthole.Tpo -c -o libXaw7_la-Porthole.lo `test -f 'Porthole.c' || echo '$(srcdir)/'`Porthole.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Porthole.Tpo $(DEPDIR)/libXaw7_la-Porthole.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Porthole.c' object='libXaw7_la-Porthole.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Porthole.lo `test -f 'Porthole.c' || echo '$(srcdir)/'`Porthole.c + +libXaw7_la-Repeater.lo: Repeater.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Repeater.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Repeater.Tpo -c -o libXaw7_la-Repeater.lo `test -f 'Repeater.c' || echo '$(srcdir)/'`Repeater.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Repeater.Tpo $(DEPDIR)/libXaw7_la-Repeater.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Repeater.c' object='libXaw7_la-Repeater.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Repeater.lo `test -f 'Repeater.c' || echo '$(srcdir)/'`Repeater.c + +libXaw7_la-Scrollbar.lo: Scrollbar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Scrollbar.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Scrollbar.Tpo -c -o libXaw7_la-Scrollbar.lo `test -f 'Scrollbar.c' || echo '$(srcdir)/'`Scrollbar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Scrollbar.Tpo $(DEPDIR)/libXaw7_la-Scrollbar.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Scrollbar.c' object='libXaw7_la-Scrollbar.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Scrollbar.lo `test -f 'Scrollbar.c' || echo '$(srcdir)/'`Scrollbar.c + +libXaw7_la-Simple.lo: Simple.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Simple.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Simple.Tpo -c -o libXaw7_la-Simple.lo `test -f 'Simple.c' || echo '$(srcdir)/'`Simple.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Simple.Tpo $(DEPDIR)/libXaw7_la-Simple.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Simple.c' object='libXaw7_la-Simple.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Simple.lo `test -f 'Simple.c' || echo '$(srcdir)/'`Simple.c + +libXaw7_la-SimpleMenu.lo: SimpleMenu.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-SimpleMenu.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-SimpleMenu.Tpo -c -o libXaw7_la-SimpleMenu.lo `test -f 'SimpleMenu.c' || echo '$(srcdir)/'`SimpleMenu.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-SimpleMenu.Tpo $(DEPDIR)/libXaw7_la-SimpleMenu.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='SimpleMenu.c' object='libXaw7_la-SimpleMenu.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-SimpleMenu.lo `test -f 'SimpleMenu.c' || echo '$(srcdir)/'`SimpleMenu.c + +libXaw7_la-Sme.lo: Sme.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Sme.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Sme.Tpo -c -o libXaw7_la-Sme.lo `test -f 'Sme.c' || echo '$(srcdir)/'`Sme.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Sme.Tpo $(DEPDIR)/libXaw7_la-Sme.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Sme.c' object='libXaw7_la-Sme.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Sme.lo `test -f 'Sme.c' || echo '$(srcdir)/'`Sme.c + +libXaw7_la-SmeBSB.lo: SmeBSB.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-SmeBSB.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-SmeBSB.Tpo -c -o libXaw7_la-SmeBSB.lo `test -f 'SmeBSB.c' || echo '$(srcdir)/'`SmeBSB.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-SmeBSB.Tpo $(DEPDIR)/libXaw7_la-SmeBSB.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='SmeBSB.c' object='libXaw7_la-SmeBSB.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-SmeBSB.lo `test -f 'SmeBSB.c' || echo '$(srcdir)/'`SmeBSB.c + +libXaw7_la-SmeLine.lo: SmeLine.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-SmeLine.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-SmeLine.Tpo -c -o libXaw7_la-SmeLine.lo `test -f 'SmeLine.c' || echo '$(srcdir)/'`SmeLine.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-SmeLine.Tpo $(DEPDIR)/libXaw7_la-SmeLine.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='SmeLine.c' object='libXaw7_la-SmeLine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-SmeLine.lo `test -f 'SmeLine.c' || echo '$(srcdir)/'`SmeLine.c + +libXaw7_la-StripChart.lo: StripChart.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-StripChart.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-StripChart.Tpo -c -o libXaw7_la-StripChart.lo `test -f 'StripChart.c' || echo '$(srcdir)/'`StripChart.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-StripChart.Tpo $(DEPDIR)/libXaw7_la-StripChart.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='StripChart.c' object='libXaw7_la-StripChart.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-StripChart.lo `test -f 'StripChart.c' || echo '$(srcdir)/'`StripChart.c + +libXaw7_la-Text.lo: Text.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Text.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Text.Tpo -c -o libXaw7_la-Text.lo `test -f 'Text.c' || echo '$(srcdir)/'`Text.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Text.Tpo $(DEPDIR)/libXaw7_la-Text.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Text.c' object='libXaw7_la-Text.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Text.lo `test -f 'Text.c' || echo '$(srcdir)/'`Text.c + +libXaw7_la-TextSink.lo: TextSink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-TextSink.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-TextSink.Tpo -c -o libXaw7_la-TextSink.lo `test -f 'TextSink.c' || echo '$(srcdir)/'`TextSink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-TextSink.Tpo $(DEPDIR)/libXaw7_la-TextSink.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextSink.c' object='libXaw7_la-TextSink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-TextSink.lo `test -f 'TextSink.c' || echo '$(srcdir)/'`TextSink.c + +libXaw7_la-TextSrc.lo: TextSrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-TextSrc.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-TextSrc.Tpo -c -o libXaw7_la-TextSrc.lo `test -f 'TextSrc.c' || echo '$(srcdir)/'`TextSrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-TextSrc.Tpo $(DEPDIR)/libXaw7_la-TextSrc.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextSrc.c' object='libXaw7_la-TextSrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-TextSrc.lo `test -f 'TextSrc.c' || echo '$(srcdir)/'`TextSrc.c + +libXaw7_la-TextAction.lo: TextAction.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-TextAction.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-TextAction.Tpo -c -o libXaw7_la-TextAction.lo `test -f 'TextAction.c' || echo '$(srcdir)/'`TextAction.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-TextAction.Tpo $(DEPDIR)/libXaw7_la-TextAction.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextAction.c' object='libXaw7_la-TextAction.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-TextAction.lo `test -f 'TextAction.c' || echo '$(srcdir)/'`TextAction.c + +libXaw7_la-TextPop.lo: TextPop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-TextPop.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-TextPop.Tpo -c -o libXaw7_la-TextPop.lo `test -f 'TextPop.c' || echo '$(srcdir)/'`TextPop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-TextPop.Tpo $(DEPDIR)/libXaw7_la-TextPop.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextPop.c' object='libXaw7_la-TextPop.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-TextPop.lo `test -f 'TextPop.c' || echo '$(srcdir)/'`TextPop.c + +libXaw7_la-TextTr.lo: TextTr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-TextTr.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-TextTr.Tpo -c -o libXaw7_la-TextTr.lo `test -f 'TextTr.c' || echo '$(srcdir)/'`TextTr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-TextTr.Tpo $(DEPDIR)/libXaw7_la-TextTr.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='TextTr.c' object='libXaw7_la-TextTr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-TextTr.lo `test -f 'TextTr.c' || echo '$(srcdir)/'`TextTr.c + +libXaw7_la-Toggle.lo: Toggle.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Toggle.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Toggle.Tpo -c -o libXaw7_la-Toggle.lo `test -f 'Toggle.c' || echo '$(srcdir)/'`Toggle.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Toggle.Tpo $(DEPDIR)/libXaw7_la-Toggle.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Toggle.c' object='libXaw7_la-Toggle.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Toggle.lo `test -f 'Toggle.c' || echo '$(srcdir)/'`Toggle.c + +libXaw7_la-Tree.lo: Tree.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Tree.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Tree.Tpo -c -o libXaw7_la-Tree.lo `test -f 'Tree.c' || echo '$(srcdir)/'`Tree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Tree.Tpo $(DEPDIR)/libXaw7_la-Tree.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Tree.c' object='libXaw7_la-Tree.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Tree.lo `test -f 'Tree.c' || echo '$(srcdir)/'`Tree.c + +libXaw7_la-Vendor.lo: Vendor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Vendor.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Vendor.Tpo -c -o libXaw7_la-Vendor.lo `test -f 'Vendor.c' || echo '$(srcdir)/'`Vendor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Vendor.Tpo $(DEPDIR)/libXaw7_la-Vendor.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Vendor.c' object='libXaw7_la-Vendor.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Vendor.lo `test -f 'Vendor.c' || echo '$(srcdir)/'`Vendor.c + +libXaw7_la-Viewport.lo: Viewport.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Viewport.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Viewport.Tpo -c -o libXaw7_la-Viewport.lo `test -f 'Viewport.c' || echo '$(srcdir)/'`Viewport.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Viewport.Tpo $(DEPDIR)/libXaw7_la-Viewport.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Viewport.c' object='libXaw7_la-Viewport.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Viewport.lo `test -f 'Viewport.c' || echo '$(srcdir)/'`Viewport.c + +libXaw7_la-XawIm.lo: XawIm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-XawIm.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-XawIm.Tpo -c -o libXaw7_la-XawIm.lo `test -f 'XawIm.c' || echo '$(srcdir)/'`XawIm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-XawIm.Tpo $(DEPDIR)/libXaw7_la-XawIm.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='XawIm.c' object='libXaw7_la-XawIm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-XawIm.lo `test -f 'XawIm.c' || echo '$(srcdir)/'`XawIm.c + +libXaw7_la-XawInit.lo: XawInit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-XawInit.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-XawInit.Tpo -c -o libXaw7_la-XawInit.lo `test -f 'XawInit.c' || echo '$(srcdir)/'`XawInit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-XawInit.Tpo $(DEPDIR)/libXaw7_la-XawInit.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='XawInit.c' object='libXaw7_la-XawInit.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-XawInit.lo `test -f 'XawInit.c' || echo '$(srcdir)/'`XawInit.c + +libXaw7_la-XawI18n.lo: XawI18n.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-XawI18n.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-XawI18n.Tpo -c -o libXaw7_la-XawI18n.lo `test -f 'XawI18n.c' || echo '$(srcdir)/'`XawI18n.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-XawI18n.Tpo $(DEPDIR)/libXaw7_la-XawI18n.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='XawI18n.c' object='libXaw7_la-XawI18n.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-XawI18n.lo `test -f 'XawI18n.c' || echo '$(srcdir)/'`XawI18n.c + +libXaw7_la-Tip.lo: Tip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -MT libXaw7_la-Tip.lo -MD -MP -MF $(DEPDIR)/libXaw7_la-Tip.Tpo -c -o libXaw7_la-Tip.lo `test -f 'Tip.c' || echo '$(srcdir)/'`Tip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libXaw7_la-Tip.Tpo $(DEPDIR)/libXaw7_la-Tip.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Tip.c' object='libXaw7_la-Tip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libXaw7_la_CFLAGS) $(CFLAGS) -c -o libXaw7_la-Tip.lo `test -f 'Tip.c' || echo '$(srcdir)/'`Tip.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@BUILD_XAW6_FALSE@@BUILD_XAW7_FALSE@install-exec-hook: +@PLATFORM_WIN32_TRUE@install-exec-hook: +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-exec-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-exec-hook \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +@BUILD_XAW6_TRUE@@PLATFORM_WIN32_FALSE@install-exec-hook:: +@BUILD_XAW6_TRUE@@PLATFORM_DARWIN_TRUE@@PLATFORM_WIN32_FALSE@ -rm -f $(DESTDIR)$(libdir)/libXaw.6.@LIBEXT@ +@BUILD_XAW6_TRUE@@PLATFORM_DARWIN_TRUE@@PLATFORM_WIN32_FALSE@ (cd $(DESTDIR)$(libdir) && ln -s libXaw6.6.@LIBEXT@ libXaw.6.@LIBEXT@) +@BUILD_XAW6_TRUE@@PLATFORM_DARWIN_FALSE@@PLATFORM_WIN32_FALSE@ -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.6 +@BUILD_XAW6_TRUE@@PLATFORM_DARWIN_FALSE@@PLATFORM_WIN32_FALSE@ (cd $(DESTDIR)$(libdir) && ln -s libXaw6.@LIBEXT@.6 libXaw.@LIBEXT@.6) + +@BUILD_XAW7_TRUE@@PLATFORM_WIN32_FALSE@install-exec-hook:: +@BUILD_XAW7_TRUE@@PLATFORM_DARWIN_TRUE@@PLATFORM_WIN32_FALSE@ -rm -f $(DESTDIR)$(libdir)/libXaw.7.@LIBEXT@ +@BUILD_XAW7_TRUE@@PLATFORM_DARWIN_TRUE@@PLATFORM_WIN32_FALSE@ (cd $(DESTDIR)$(libdir) && ln -s libXaw7.7.@LIBEXT@ libXaw.7.@LIBEXT@) +@BUILD_XAW7_TRUE@@PLATFORM_DARWIN_FALSE@@PLATFORM_WIN32_FALSE@ -rm -f $(DESTDIR)$(libdir)/libXaw.@LIBEXT@.7 +@BUILD_XAW7_TRUE@@PLATFORM_DARWIN_FALSE@@PLATFORM_WIN32_FALSE@ (cd $(DESTDIR)$(libdir) && ln -s libXaw7.@LIBEXT@.7 libXaw.@LIBEXT@.7) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libXaw/src/MenuButton.c b/libXaw/src/MenuButton.c new file mode 100644 index 000000000..6c5da154a --- /dev/null +++ b/libXaw/src/MenuButton.c @@ -0,0 +1,276 @@ +/* $Xorg: MenuButton.c,v 1.4 2001/02/09 02:03:44 xorgcvs Exp $ */ + +/* +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. + * + */ + +/* $XFree86: xc/lib/Xaw/MenuButton.c,v 3.9 2001/10/11 21:17:00 paulo Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..8abe2dedd --- /dev/null +++ b/libXaw/src/MultiSink.c @@ -0,0 +1,978 @@ +/* $Xorg: MultiSink.c,v 1.4 2001/02/09 02:03:44 xorgcvs Exp $ */ + +/* + * 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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/MultiSink.c,v 1.19 2001/01/17 19:42:27 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..2daf0f6e8 --- /dev/null +++ b/libXaw/src/MultiSrc.c @@ -0,0 +1,1620 @@ +/* $Xorg: MultiSrc.c,v 1.4 2001/02/09 02:03:44 xorgcvs Exp $ */ + +/* + * 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. + */ +/* $XFree86: xc/lib/Xaw/MultiSrc.c,v 1.28 2002/11/21 16:22:52 paulo Exp $ */ + +/* + +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 new file mode 100644 index 000000000..5801aebb8 --- /dev/null +++ b/libXaw/src/OS.c @@ -0,0 +1,64 @@ +/* $XFree86: xc/lib/Xaw/OS.c,v 1.1 1998/12/06 10:44:34 dawes Exp $ */ + +/* 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_GETPAGESIZE +#define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */ +#endif + +#if defined(CSRG_BASED) +#define HAS_GETPAGESIZE +#endif + +#if defined(sun) +#define HAS_GETPAGESIZE +#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 HAS_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 new file mode 100644 index 000000000..a2408ba70 --- /dev/null +++ b/libXaw/src/Paned.c @@ -0,0 +1,2067 @@ +/* $Xorg: Paned.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Paned.c,v 1.11 2001/08/23 00:03:19 dawes Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..e0ae2c20a --- /dev/null +++ b/libXaw/src/Panner.c @@ -0,0 +1,1082 @@ +/* + * $Xorg: Panner.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ + * +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 + */ + +/* $XFree86: xc/lib/Xaw/Panner.c,v 3.8 2001/07/25 15:04:49 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..a6fb5a342 --- /dev/null +++ b/libXaw/src/Pixmap.c @@ -0,0 +1,993 @@ +/* + * 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. + */ + +/* $XFree86: xc/lib/Xaw/Pixmap.c,v 3.17 2002/05/18 02:05:39 paulo Exp $ */ + +#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) + 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; + + 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 new file mode 100644 index 000000000..3bf161592 --- /dev/null +++ b/libXaw/src/Porthole.c @@ -0,0 +1,378 @@ +/* + * $Xorg: Porthole.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ + * +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. + */ +/* $XFree86: xc/lib/Xaw/Porthole.c,v 1.6 2001/01/17 19:42:29 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..a76207a4d --- /dev/null +++ b/libXaw/src/Private.h @@ -0,0 +1,154 @@ +/* + * 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. + */ + +/* $XFree86: xc/lib/Xaw/Private.h,v 3.9 1999/05/16 10:12:48 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..52ae2959e --- /dev/null +++ b/libXaw/src/Repeater.c @@ -0,0 +1,300 @@ +/* + * $Xorg: Repeater.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ + * +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. + */ +/* $XFree86: xc/lib/Xaw/Repeater.c,v 1.6 2001/01/17 19:42:29 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..e6dea9c41 --- /dev/null +++ b/libXaw/src/Scrollbar.c @@ -0,0 +1,885 @@ +/* $Xorg: Scrollbar.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Scrollbar.c,v 1.12 2001/01/17 19:42:29 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..95b7a1aa1 --- /dev/null +++ b/libXaw/src/Simple.c @@ -0,0 +1,504 @@ +/* $Xorg: Simple.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ + +/* $XFree86: xc/lib/Xaw/Simple.c,v 1.16 2001/09/29 04:36:02 paulo Exp $ */ + +#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 new file mode 100644 index 000000000..b7ed28651 --- /dev/null +++ b/libXaw/src/SimpleMenu.c @@ -0,0 +1,1834 @@ +/* $Xorg: SimpleMenu.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */ + +/* +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. + */ + +/* $XFree86: xc/lib/Xaw/SimpleMenu.c,v 3.21 2001/03/23 23:59:15 paulo Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..a4af577d8 --- /dev/null +++ b/libXaw/src/Sme.c @@ -0,0 +1,272 @@ +/* $Xorg: Sme.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */ + +/* +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. + */ +/* $XFree86: xc/lib/Xaw/Sme.c,v 1.6 2001/01/17 19:42:31 dawes Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..0d77278ab --- /dev/null +++ b/libXaw/src/SmeBSB.c @@ -0,0 +1,774 @@ +/* $Xorg: SmeBSB.c,v 1.5 2001/02/09 02:03:45 xorgcvs Exp $ */ + +/* +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. + */ + +/* $XFree86: xc/lib/Xaw/SmeBSB.c,v 1.11 2001/01/17 19:42:31 dawes Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..88a6e9ce5 --- /dev/null +++ b/libXaw/src/SmeLine.c @@ -0,0 +1,267 @@ +/* $Xorg: SmeLine.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */ + +/* +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 + */ +/* $XFree86: xc/lib/Xaw/SmeLine.c,v 1.7 2001/01/17 19:42:31 dawes Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..ada85f172 --- /dev/null +++ b/libXaw/src/StripChart.c @@ -0,0 +1,579 @@ +/* $Xorg: StripChart.c,v 1.4 2001/02/09 02:03:46 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/StripChart.c,v 1.7 2001/01/17 19:42:32 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..2fd9d3fb6 --- /dev/null +++ b/libXaw/src/Text.c @@ -0,0 +1,4162 @@ +/* $Xorg: Text.c,v 1.4 2001/02/09 02:03:46 xorgcvs Exp $ */ + +/*********************************************************** + +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. + */ + +/* $XFree86: xc/lib/Xaw/Text.c,v 3.53tsi Exp $ */ + +#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 new file mode 100644 index 000000000..062956c99 --- /dev/null +++ b/libXaw/src/TextAction.c @@ -0,0 +1,4401 @@ +/* $Xorg: TextAction.c,v 1.4 2001/02/09 02:03:46 xorgcvs Exp $ */ + +/* + +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. + +*/ +/* $XFree86: xc/lib/Xaw/TextAction.c,v 3.46tsi Exp $ */ + +#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/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 + +/* + * 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 new file mode 100644 index 000000000..dd67ef4a1 --- /dev/null +++ b/libXaw/src/TextPop.c @@ -0,0 +1,1554 @@ +/* $Xorg: TextPop.c,v 1.4 2001/02/09 02:03:46 xorgcvs Exp $ */ + +/* + +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. + +*/ + +/* $XFree86: xc/lib/Xaw/TextPop.c,v 1.20tsi Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..75f952fff --- /dev/null +++ b/libXaw/src/TextSink.c @@ -0,0 +1,1829 @@ +/* $Xorg: TextSink.c,v 1.4 2001/02/09 02:03:46 xorgcvs Exp $ */ +/* + +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. + +*/ +/* $XFree86: xc/lib/Xaw/TextSink.c,v 1.21 2002/06/03 21:39:24 paulo Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..10e819cda --- /dev/null +++ b/libXaw/src/TextSrc.c @@ -0,0 +1,2011 @@ +/* $Xorg: TextSrc.c,v 1.5 2001/02/09 02:03:47 xorgcvs Exp $ */ +/* + +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. + +*/ + +/* $XFree86: xc/lib/Xaw/TextSrc.c,v 1.33 2002/09/08 02:29:47 paulo Exp $ */ + +/* + * 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 XawtextAppend: + case XawtextRead: + buffer = XtEtextRead; + break; + 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 new file mode 100644 index 000000000..059a79201 --- /dev/null +++ b/libXaw/src/TextTr.c @@ -0,0 +1,161 @@ +/* $Xorg: TextTr.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ */ + +/* + +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. + +*/ +/* $XFree86: xc/lib/Xaw/TextTr.c,v 3.15 2001/01/17 19:42:35 dawes Exp $ */ + +/* 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 new file mode 100644 index 000000000..11f4c2661 --- /dev/null +++ b/libXaw/src/Tip.c @@ -0,0 +1,639 @@ +/* + * 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 + */ + +/* $XFree86: xc/lib/Xaw/Tip.c,v 1.4 1999/07/11 08:49:16 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..dfbcf7677 --- /dev/null +++ b/libXaw/src/Toggle.c @@ -0,0 +1,632 @@ +/* $Xorg: Toggle.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ */ + +/* + +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. + +*/ +/* $XFree86: xc/lib/Xaw/Toggle.c,v 1.8 2001/08/23 00:03:20 dawes Exp $ */ + +/* + * 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 new file mode 100644 index 000000000..c37b215b9 --- /dev/null +++ b/libXaw/src/Tree.c @@ -0,0 +1,1017 @@ +/* + * $Xorg: Tree.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ + * + +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. + */ +/* $XFree86: xc/lib/Xaw/Tree.c,v 1.9 2001/01/17 19:42:35 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..b9ffcf6ad --- /dev/null +++ b/libXaw/src/Vendor.c @@ -0,0 +1,527 @@ +/* $Xorg: Vendor.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Vendor.c,v 1.8 2001/12/14 19:54:45 dawes Exp $ */ + +/* + * 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__) +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 new file mode 100644 index 000000000..90c909e10 --- /dev/null +++ b/libXaw/src/Viewport.c @@ -0,0 +1,1102 @@ +/* $Xorg: Viewport.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ */ + +/*********************************************************** + +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. + +******************************************************************/ +/* $XFree86: xc/lib/Xaw/Viewport.c,v 1.10 2001/08/23 00:03:20 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..345bc7d87 --- /dev/null +++ b/libXaw/src/XawI18n.c @@ -0,0 +1,108 @@ +/* $Xorg: XawI18n.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ */ + +/* 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. + +*/ +/* $XFree86: xc/lib/Xaw/XawI18n.c,v 1.7 2001/01/17 19:42:36 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..8f157d19b --- /dev/null +++ b/libXaw/src/XawI18n.h @@ -0,0 +1,122 @@ +/* $XdotOrg: xc/lib/Xaw/XawI18n.h,v 1.2 2004/04/23 18:43:38 eich Exp $ */ +/* $Xorg: XawI18n.h,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ */ + +/************************************************************ + +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. + +********************************************************/ +/* $XFree86: xc/lib/Xaw/XawI18n.h,v 3.14 2001/12/14 19:54:46 dawes Exp $ */ + +#ifdef HAS_WCTYPE_H +#include <wctype.h> +#ifndef NO_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 HAS_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 new file mode 100644 index 000000000..24a60786a --- /dev/null +++ b/libXaw/src/XawIm.c @@ -0,0 +1,1612 @@ +/* $Xorg: XawIm.c,v 1.6 2001/02/09 02:03:47 xorgcvs Exp $ */ + +/* + * 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. + +*/ +/* $XFree86: xc/lib/Xaw/XawIm.c,v 1.14tsi Exp $ */ + +#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 new file mode 100644 index 000000000..79bc78a5e --- /dev/null +++ b/libXaw/src/XawInit.c @@ -0,0 +1,100 @@ +/* + * $Xorg: XawInit.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ + * +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). + */ +/* $XFree86: xc/lib/Xaw/XawInit.c,v 1.9 2001/01/17 19:42:36 dawes Exp $ */ + +#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 new file mode 100644 index 000000000..d107f9fcb --- /dev/null +++ b/libXaw/src/sharedlib.c @@ -0,0 +1,182 @@ +/* $Xorg: sharedlib.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ */ +/* + +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> +#if !defined(OLDXAW) && !defined(XAW7) +#include <X11/Xaw/PrintSP.h> +#endif + +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; + +#if !defined(OLDXAW) && !defined(XAW7) +extern XawPrintShellClassRec xawPrintShellClassRec; +WidgetClass xawPrintShellWidgetClass = (WidgetClass) &xawPrintShellClassRec; +#endif + +#endif /* SUNSHLIB */ |