diff options
author | marha <marha@users.sourceforge.net> | 2011-09-12 11:27:51 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2011-09-12 11:27:51 +0200 |
commit | dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 (patch) | |
tree | bdf833cc6a4fc9035411779e10dd9e8478201885 /libXaw/src/Tip.c | |
parent | 0b40f5f4b54453a77f4b09c431f8efc6875da61f (diff) | |
download | vcxsrv-dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0.tar.gz vcxsrv-dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0.tar.bz2 vcxsrv-dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0.zip |
Synchronised line endinge with release branch
Diffstat (limited to 'libXaw/src/Tip.c')
-rw-r--r-- | libXaw/src/Tip.c | 1274 |
1 files changed, 637 insertions, 637 deletions
diff --git a/libXaw/src/Tip.c b/libXaw/src/Tip.c index bca994ca5..9f8b32ad3 100644 --- a/libXaw/src/Tip.c +++ b/libXaw/src/Tip.c @@ -1,637 +1,637 @@ -/*
- * Copyright (c) 1999 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the XFree86 Project shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from the
- * XFree86 Project.
- *
- * Author: Paulo César Pereira de Andrade
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xos.h>
-#include <X11/Xaw/TipP.h>
-#include <X11/Xaw/XawInit.h>
-#include <X11/Xmu/Converters.h>
-#include "Private.h"
-
-#define TIP_EVENT_MASK (ButtonPressMask | \
- ButtonReleaseMask | \
- PointerMotionMask | \
- ButtonMotionMask | \
- KeyPressMask | \
- KeyReleaseMask | \
- EnterWindowMask | \
- LeaveWindowMask)
-
-/*
- * Types
- */
-typedef struct _XawTipInfo {
- Screen *screen;
- TipWidget tip;
- Widget widget;
- Bool mapped;
- struct _XawTipInfo *next;
-} XawTipInfo;
-
-/*
- * Class Methods
- */
-static void XawTipClassInitialize(void);
-static void XawTipInitialize(Widget, Widget, ArgList, Cardinal*);
-static void XawTipDestroy(Widget);
-static void XawTipExpose(Widget, XEvent*, Region);
-static void XawTipRealize(Widget, Mask*, XSetWindowAttributes*);
-static Boolean XawTipSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
-
-/*
- * Prototypes
- */
-static void TipEventHandler(Widget, XtPointer, XEvent*, Boolean*);
-static void TipShellEventHandler(Widget, XtPointer, XEvent*, Boolean*);
-static XawTipInfo *CreateTipInfo(Widget);
-static XawTipInfo *FindTipInfo(Widget);
-static void ResetTip(XawTipInfo*, Bool);
-static void TipTimeoutCallback(XtPointer, XtIntervalId*);
-static void TipLayout(XawTipInfo*);
-static void TipPosition(XawTipInfo*);
-
-/*
- * Initialization
- */
-#define offset(field) XtOffsetOf(TipRec, tip.field)
-static XtResource resources[] = {
- {
- XtNforeground,
- XtCForeground,
- XtRPixel,
- sizeof(Pixel),
- offset(foreground),
- XtRString,
- XtDefaultForeground,
- },
- {
- XtNfont,
- XtCFont,
- XtRFontStruct,
- sizeof(XFontStruct*),
- offset(font),
- XtRString,
- XtDefaultFont
- },
- {
- XtNfontSet,
- XtCFontSet,
- XtRFontSet,
- sizeof(XFontSet),
- offset(fontset),
- XtRString,
- XtDefaultFontSet
- },
- {
- XtNtopMargin,
- XtCVerticalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(top_margin),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNbottomMargin,
- XtCVerticalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(bottom_margin),
- XtRImmediate,
- (XtPointer)2
- },
- {
- XtNleftMargin,
- XtCHorizontalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(left_margin),
- XtRImmediate,
- (XtPointer)6
- },
- {
- XtNrightMargin,
- XtCHorizontalMargins,
- XtRDimension,
- sizeof(Dimension),
- offset(right_margin),
- XtRImmediate,
- (XtPointer)6
- },
- {
- XtNbackingStore,
- XtCBackingStore,
- XtRBackingStore,
- sizeof(int),
- offset(backing_store),
- XtRImmediate,
- (XtPointer)(Always + WhenMapped + NotUseful)
- },
- {
- XtNtimeout,
- XtCTimeout,
- XtRInt,
- sizeof(int),
- offset(timeout),
- XtRImmediate,
- (XtPointer)500
- },
- {
- XawNdisplayList,
- XawCDisplayList,
- XawRDisplayList,
- sizeof(XawDisplayList*),
- offset(display_list),
- XtRImmediate,
- NULL
- },
-};
-#undef offset
-
-TipClassRec tipClassRec = {
- /* core */
- {
- (WidgetClass)&widgetClassRec, /* superclass */
- "Tip", /* class_name */
- sizeof(TipRec), /* widget_size */
- XawTipClassInitialize, /* class_initialize */
- NULL, /* class_part_initialize */
- False, /* class_inited */
- XawTipInitialize, /* initialize */
- NULL, /* initialize_hook */
- XawTipRealize, /* realize */
- NULL, /* actions */
- 0, /* num_actions */
- resources, /* resources */
- XtNumber(resources), /* num_resources */
- NULLQUARK, /* xrm_class */
- True, /* compress_motion */
- True, /* compress_exposure */
- True, /* compress_enterleave */
- False, /* visible_interest */
- XawTipDestroy, /* destroy */
- NULL, /* resize */
- XawTipExpose, /* expose */
- XawTipSetValues, /* set_values */
- NULL, /* set_values_hook */
- XtInheritSetValuesAlmost, /* set_values_almost */
- NULL, /* get_values_hook */
- NULL, /* accept_focus */
- XtVersion, /* version */
- NULL, /* callback_private */
- NULL, /* tm_table */
- XtInheritQueryGeometry, /* query_geometry */
- XtInheritDisplayAccelerator, /* display_accelerator */
- NULL, /* extension */
- },
- /* tip */
- {
- NULL, /* extension */
- },
-};
-
-WidgetClass tipWidgetClass = (WidgetClass)&tipClassRec;
-
-static XawTipInfo *first_tip;
-
-/*
- * Implementation
- */
-static void
-XawTipClassInitialize(void)
-{
- XawInitializeWidgetSet();
- XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
- NULL, 0);
- XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString,
- NULL, 0, XtCacheNone, NULL);
-}
-
-/*ARGSUSED*/
-static void
-XawTipInitialize(Widget req, Widget w, ArgList args, Cardinal *num_args)
-{
- TipWidget tip = (TipWidget)w;
- XGCValues values;
-
- if (!tip->tip.font) XtError("Aborting: no font found\n");
- if (tip->tip.international && !tip->tip.fontset)
- XtError("Aborting: no fontset found\n");
-
- tip->tip.timer = 0;
-
- values.foreground = tip->tip.foreground;
- values.background = tip->core.background_pixel;
- values.font = tip->tip.font->fid;
- values.graphics_exposures = False;
-
- tip->tip.gc = XtAllocateGC(w, 0, GCForeground | GCBackground | GCFont |
- GCGraphicsExposures, &values, GCFont, 0);
-}
-
-static void
-XawTipDestroy(Widget w)
-{
- XawTipInfo *info = FindTipInfo(w);
- TipWidget tip = (TipWidget)w;
-
- if (tip->tip.timer)
- XtRemoveTimeOut(tip->tip.timer);
-
- XtReleaseGC(w, tip->tip.gc);
-
- XtRemoveEventHandler(XtParent(w), KeyPressMask, False, TipShellEventHandler,
- (XtPointer)NULL);
- if (info == first_tip)
- first_tip = first_tip->next;
- else {
- XawTipInfo *p = first_tip;
-
- while (p && p->next != info)
- p = p->next;
- if (p)
- p->next = info->next;
- }
- XtFree((char*)info);
-}
-
-static void
-XawTipRealize(Widget w, Mask *mask, XSetWindowAttributes *attr)
-{
- TipWidget tip = (TipWidget)w;
-
- if (tip->tip.backing_store == Always ||
- tip->tip.backing_store == NotUseful ||
- tip->tip.backing_store == WhenMapped) {
- *mask |= CWBackingStore;
- attr->backing_store = tip->tip.backing_store;
- }
- else
- *mask &= ~CWBackingStore;
- *mask |= CWOverrideRedirect;
- attr->override_redirect = True;
-
- XtWindow(w) = XCreateWindow(DisplayOfScreen(XtScreen(w)),
- RootWindowOfScreen(XtScreen(w)),
- XtX(w), XtY(w),
- XtWidth(w) ? XtWidth(w) : 1,
- XtHeight(w) ? XtHeight(w) : 1,
- XtBorderWidth(w),
- DefaultDepthOfScreen(XtScreen(w)),
- InputOutput,
- (Visual *)CopyFromParent,
- *mask, attr);
-}
-
-static void
-XawTipExpose(Widget w, XEvent *event, Region region)
-{
- TipWidget tip = (TipWidget)w;
- GC gc = tip->tip.gc;
- char *nl, *label = tip->tip.label;
- Position y = tip->tip.top_margin + tip->tip.font->max_bounds.ascent;
- int len;
-
- if (tip->tip.display_list)
- XawRunDisplayList(w, tip->tip.display_list, event, region);
-
- if (tip->tip.international == True) {
- Position ksy = tip->tip.top_margin;
- XFontSetExtents *ext = XExtentsOfFontSet(tip->tip.fontset);
-
- ksy += XawAbs(ext->max_ink_extent.y);
-
- while ((nl = index(label, '\n')) != NULL) {
- XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset,
- gc, tip->tip.left_margin, ksy, label,
- (int)(nl - label));
- ksy += ext->max_ink_extent.height;
- label = nl + 1;
- }
- len = strlen(label);
- if (len)
- XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset, gc,
- tip->tip.left_margin, ksy, label, len);
- }
- else {
- while ((nl = index(label, '\n')) != NULL) {
- if (tip->tip.encoding)
- XDrawString16(XtDisplay(w), XtWindow(w), gc,
- tip->tip.left_margin, y,
- (XChar2b*)label, (int)(nl - label) >> 1);
- else
- XDrawString(XtDisplay(w), XtWindow(w), gc,
- tip->tip.left_margin, y, label, (int)(nl - label));
- y += tip->tip.font->max_bounds.ascent +
- tip->tip.font->max_bounds.descent;
- label = nl + 1;
- }
- len = strlen(label);
- if (len) {
- if (tip->tip.encoding)
- XDrawString16(XtDisplay(w), XtWindow(w), gc,
- tip->tip.left_margin, y, (XChar2b*)label, len >> 1);
- else
- XDrawString(XtDisplay(w), XtWindow(w), gc,
- tip->tip.left_margin, y, label, len);
- }
- }
-}
-
-/*ARGSUSED*/
-static Boolean
-XawTipSetValues(Widget current, Widget request, Widget cnew,
- ArgList args, Cardinal *num_args)
-{
- TipWidget curtip = (TipWidget)current;
- TipWidget newtip = (TipWidget)cnew;
- Boolean redisplay = False;
-
- if (curtip->tip.font->fid != newtip->tip.font->fid ||
- curtip->tip.foreground != newtip->tip.foreground) {
- XGCValues values;
-
- values.foreground = newtip->tip.foreground;
- values.background = newtip->core.background_pixel;
- values.font = newtip->tip.font->fid;
- values.graphics_exposures = False;
- XtReleaseGC(cnew, curtip->tip.gc);
- newtip->tip.gc = XtAllocateGC(cnew, 0, GCForeground | GCBackground |
- GCFont | GCGraphicsExposures, &values,
- GCFont, 0);
- redisplay = True;
- }
- if (curtip->tip.display_list != newtip->tip.display_list)
- redisplay = True;
-
- return (redisplay);
-}
-
-static void
-TipLayout(XawTipInfo *info)
-{
- XFontStruct *fs = info->tip->tip.font;
- int width = 0, height;
- char *nl, *label = info->tip->tip.label;
-
- if (info->tip->tip.international == True) {
- XFontSet fset = info->tip->tip.fontset;
- XFontSetExtents *ext = XExtentsOfFontSet(fset);
-
- height = ext->max_ink_extent.height;
- if ((nl = index(label, '\n')) != NULL) {
- /*CONSTCOND*/
- while (True) {
- int w = XmbTextEscapement(fset, label, (int)(nl - label));
-
- if (w > width)
- width = w;
- if (*nl == '\0')
- break;
- label = nl + 1;
- if (*label)
- height += ext->max_ink_extent.height;
- if ((nl = index(label, '\n')) == NULL)
- nl = index(label, '\0');
- }
- }
- else
- width = XmbTextEscapement(fset, label, strlen(label));
- }
- else {
- height = fs->max_bounds.ascent + fs->max_bounds.descent;
- if ((nl = index(label, '\n')) != NULL) {
- /*CONSTCOND*/
- while (True) {
- int w = info->tip->tip.encoding ?
- XTextWidth16(fs, (XChar2b*)label, (int)(nl - label) >> 1) :
- XTextWidth(fs, label, (int)(nl - label));
- if (w > width)
- width = w;
- if (*nl == '\0')
- break;
- label = nl + 1;
- if (*label)
- height += fs->max_bounds.ascent + fs->max_bounds.descent;
- if ((nl = index(label, '\n')) == NULL)
- nl = index(label, '\0');
- }
- }
- else
- width = info->tip->tip.encoding ?
- XTextWidth16(fs, (XChar2b*)label, strlen(label) >> 1) :
- XTextWidth(fs, label, strlen(label));
- }
- XtWidth(info->tip) = width + info->tip->tip.left_margin +
- info->tip->tip.right_margin;
- XtHeight(info->tip) = height + info->tip->tip.top_margin +
- info->tip->tip.bottom_margin;
-}
-
-#define DEFAULT_TIP_Y_OFFSET 12
-static void
-TipPosition(XawTipInfo *info)
-{
- Window r, c;
- int rx, ry, wx, wy;
- unsigned mask;
- Position x, y;
-
- XQueryPointer(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip),
- &r, &c, &rx, &ry, &wx, &wy, &mask);
- x = rx - (XtWidth(info->tip) >> 1);
- y = ry + DEFAULT_TIP_Y_OFFSET;
-
- if (x >= 0) {
- int scr_width = WidthOfScreen(XtScreen(info->tip));
-
- if (x + XtWidth(info->tip) + XtBorderWidth(info->tip) > scr_width)
- x = scr_width - XtWidth(info->tip) - XtBorderWidth(info->tip);
- }
- if (x < 0)
- x = 0;
- if (y >= 0) {
- int scr_height = HeightOfScreen(XtScreen(info->tip));
-
- if (y + XtHeight(info->tip) + XtBorderWidth(info->tip) > scr_height)
- y -= XtHeight(info->tip) + XtBorderWidth(info->tip) +
- (DEFAULT_TIP_Y_OFFSET << 1);
- }
- if (y < 0)
- y = 0;
-
- XMoveResizeWindow(XtDisplay(info->tip), XtWindow(info->tip),
- (int)(XtX(info->tip) = x), (int)(XtY(info->tip) = y),
- (unsigned)XtWidth(info->tip), (unsigned)XtHeight(info->tip));
-}
-
-static XawTipInfo *
-CreateTipInfo(Widget w)
-{
- XawTipInfo *info = XtNew(XawTipInfo);
- Widget shell = w;
-
- info->screen = XtScreen(w);
-
- while (XtParent(shell))
- shell = XtParent(shell);
-
- info->tip = (TipWidget)XtCreateWidget("tip", tipWidgetClass, shell, NULL, 0);
- XtRealizeWidget((Widget)info->tip);
- info->widget = NULL;
- info->mapped = False;
- info->next = NULL;
- XtAddEventHandler(shell, KeyPressMask, False, TipShellEventHandler,
- (XtPointer)NULL);
-
- return (info);
-}
-
-static XawTipInfo *
-FindTipInfo(Widget w)
-{
- XawTipInfo *ptip, *tip = first_tip;
- Screen *screen = XtScreenOfObject(w);
-
- if (tip == NULL)
- return (first_tip = tip = CreateTipInfo(w));
-
- for (ptip = tip; tip; ptip = tip, tip = tip->next)
- if (tip->screen == screen)
- return (tip);
-
- return (ptip->next = CreateTipInfo(w));
-}
-
-static void
-ResetTip(XawTipInfo *info, Bool add_timeout)
-{
- if (info->tip->tip.timer) {
- XtRemoveTimeOut(info->tip->tip.timer);
- info->tip->tip.timer = 0;
- }
- if (info->mapped) {
- XtRemoveGrab(XtParent((Widget)info->tip));
- XUnmapWindow(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip));
- info->mapped = False;
- }
- if (add_timeout) {
- info->tip->tip.timer =
- XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)info->tip),
- info->tip->tip.timeout, TipTimeoutCallback,
- (XtPointer)info);
- }
-}
-
-static void
-TipTimeoutCallback(XtPointer closure, XtIntervalId *id)
-{
- XawTipInfo *info = (XawTipInfo*)closure;
- Arg args[3];
-
- info->tip->tip.label = NULL;
- info->tip->tip.international = False;
- info->tip->tip.encoding = 0;
- info->tip->tip.timer = 0;
- XtSetArg(args[0], XtNtip, &info->tip->tip.label);
- XtSetArg(args[1], XtNinternational, &info->tip->tip.international);
- XtSetArg(args[2], XtNencoding, &info->tip->tip.encoding);
- XtGetValues(info->widget, args, 3);
-
- if (info->tip->tip.label) {
- TipLayout(info);
- TipPosition(info);
- XMapRaised(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip));
- XtAddGrab(XtParent((Widget)info->tip), True, True);
- info->mapped = True;
- }
-}
-
-/*ARGSUSED*/
-static void
-TipShellEventHandler(Widget w, XtPointer client_data, XEvent *event,
- Boolean *continue_to_dispatch)
-{
- ResetTip(FindTipInfo(w), False);
-}
-
-/*ARGSUSED*/
-static void
-TipEventHandler(Widget w, XtPointer client_data, XEvent *event,
- Boolean *continue_to_dispatch)
-{
- XawTipInfo *info = FindTipInfo(w);
- Boolean add_timeout;
-
- if (info->widget != w) {
- ResetTip(info, False);
- info->widget = w;
- }
-
- switch (event->type) {
- case EnterNotify:
- add_timeout = True;
- break;
- case MotionNotify:
- /* If any button is pressed, timer is 0 */
- if (info->mapped)
- return;
- add_timeout = info->tip->tip.timer != 0;
- break;
- default:
- add_timeout = False;
- break;
- }
- ResetTip(info, add_timeout);
-}
-
-/*
- * Public routines
- */
-void
-XawTipEnable(Widget w)
-{
- XtAddEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler,
- (XtPointer)NULL);
-}
-
-void
-XawTipDisable(Widget w)
-{
- XawTipInfo *info = FindTipInfo(w);
-
- XtRemoveEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler,
- (XtPointer)NULL);
- if (info->widget == w)
- ResetTip(info, False);
-}
+/* + * Copyright (c) 1999 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + * + * Author: Paulo César Pereira de Andrade + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xaw/TipP.h> +#include <X11/Xaw/XawInit.h> +#include <X11/Xmu/Converters.h> +#include "Private.h" + +#define TIP_EVENT_MASK (ButtonPressMask | \ + ButtonReleaseMask | \ + PointerMotionMask | \ + ButtonMotionMask | \ + KeyPressMask | \ + KeyReleaseMask | \ + EnterWindowMask | \ + LeaveWindowMask) + +/* + * Types + */ +typedef struct _XawTipInfo { + Screen *screen; + TipWidget tip; + Widget widget; + Bool mapped; + struct _XawTipInfo *next; +} XawTipInfo; + +/* + * Class Methods + */ +static void XawTipClassInitialize(void); +static void XawTipInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawTipDestroy(Widget); +static void XawTipExpose(Widget, XEvent*, Region); +static void XawTipRealize(Widget, Mask*, XSetWindowAttributes*); +static Boolean XawTipSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +static void TipEventHandler(Widget, XtPointer, XEvent*, Boolean*); +static void TipShellEventHandler(Widget, XtPointer, XEvent*, Boolean*); +static XawTipInfo *CreateTipInfo(Widget); +static XawTipInfo *FindTipInfo(Widget); +static void ResetTip(XawTipInfo*, Bool); +static void TipTimeoutCallback(XtPointer, XtIntervalId*); +static void TipLayout(XawTipInfo*); +static void TipPosition(XawTipInfo*); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(TipRec, tip.field) +static XtResource resources[] = { + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + offset(foreground), + XtRString, + XtDefaultForeground, + }, + { + XtNfont, + XtCFont, + XtRFontStruct, + sizeof(XFontStruct*), + offset(font), + XtRString, + XtDefaultFont + }, + { + XtNfontSet, + XtCFontSet, + XtRFontSet, + sizeof(XFontSet), + offset(fontset), + XtRString, + XtDefaultFontSet + }, + { + XtNtopMargin, + XtCVerticalMargins, + XtRDimension, + sizeof(Dimension), + offset(top_margin), + XtRImmediate, + (XtPointer)2 + }, + { + XtNbottomMargin, + XtCVerticalMargins, + XtRDimension, + sizeof(Dimension), + offset(bottom_margin), + XtRImmediate, + (XtPointer)2 + }, + { + XtNleftMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(left_margin), + XtRImmediate, + (XtPointer)6 + }, + { + XtNrightMargin, + XtCHorizontalMargins, + XtRDimension, + sizeof(Dimension), + offset(right_margin), + XtRImmediate, + (XtPointer)6 + }, + { + XtNbackingStore, + XtCBackingStore, + XtRBackingStore, + sizeof(int), + offset(backing_store), + XtRImmediate, + (XtPointer)(Always + WhenMapped + NotUseful) + }, + { + XtNtimeout, + XtCTimeout, + XtRInt, + sizeof(int), + offset(timeout), + XtRImmediate, + (XtPointer)500 + }, + { + XawNdisplayList, + XawCDisplayList, + XawRDisplayList, + sizeof(XawDisplayList*), + offset(display_list), + XtRImmediate, + NULL + }, +}; +#undef offset + +TipClassRec tipClassRec = { + /* core */ + { + (WidgetClass)&widgetClassRec, /* superclass */ + "Tip", /* class_name */ + sizeof(TipRec), /* widget_size */ + XawTipClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawTipInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawTipRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawTipDestroy, /* destroy */ + NULL, /* resize */ + XawTipExpose, /* expose */ + XawTipSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* tip */ + { + NULL, /* extension */ + }, +}; + +WidgetClass tipWidgetClass = (WidgetClass)&tipClassRec; + +static XawTipInfo *first_tip; + +/* + * Implementation + */ +static void +XawTipClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore, + NULL, 0); + XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString, + NULL, 0, XtCacheNone, NULL); +} + +/*ARGSUSED*/ +static void +XawTipInitialize(Widget req, Widget w, ArgList args, Cardinal *num_args) +{ + TipWidget tip = (TipWidget)w; + XGCValues values; + + if (!tip->tip.font) XtError("Aborting: no font found\n"); + if (tip->tip.international && !tip->tip.fontset) + XtError("Aborting: no fontset found\n"); + + tip->tip.timer = 0; + + values.foreground = tip->tip.foreground; + values.background = tip->core.background_pixel; + values.font = tip->tip.font->fid; + values.graphics_exposures = False; + + tip->tip.gc = XtAllocateGC(w, 0, GCForeground | GCBackground | GCFont | + GCGraphicsExposures, &values, GCFont, 0); +} + +static void +XawTipDestroy(Widget w) +{ + XawTipInfo *info = FindTipInfo(w); + TipWidget tip = (TipWidget)w; + + if (tip->tip.timer) + XtRemoveTimeOut(tip->tip.timer); + + XtReleaseGC(w, tip->tip.gc); + + XtRemoveEventHandler(XtParent(w), KeyPressMask, False, TipShellEventHandler, + (XtPointer)NULL); + if (info == first_tip) + first_tip = first_tip->next; + else { + XawTipInfo *p = first_tip; + + while (p && p->next != info) + p = p->next; + if (p) + p->next = info->next; + } + XtFree((char*)info); +} + +static void +XawTipRealize(Widget w, Mask *mask, XSetWindowAttributes *attr) +{ + TipWidget tip = (TipWidget)w; + + if (tip->tip.backing_store == Always || + tip->tip.backing_store == NotUseful || + tip->tip.backing_store == WhenMapped) { + *mask |= CWBackingStore; + attr->backing_store = tip->tip.backing_store; + } + else + *mask &= ~CWBackingStore; + *mask |= CWOverrideRedirect; + attr->override_redirect = True; + + XtWindow(w) = XCreateWindow(DisplayOfScreen(XtScreen(w)), + RootWindowOfScreen(XtScreen(w)), + XtX(w), XtY(w), + XtWidth(w) ? XtWidth(w) : 1, + XtHeight(w) ? XtHeight(w) : 1, + XtBorderWidth(w), + DefaultDepthOfScreen(XtScreen(w)), + InputOutput, + (Visual *)CopyFromParent, + *mask, attr); +} + +static void +XawTipExpose(Widget w, XEvent *event, Region region) +{ + TipWidget tip = (TipWidget)w; + GC gc = tip->tip.gc; + char *nl, *label = tip->tip.label; + Position y = tip->tip.top_margin + tip->tip.font->max_bounds.ascent; + int len; + + if (tip->tip.display_list) + XawRunDisplayList(w, tip->tip.display_list, event, region); + + if (tip->tip.international == True) { + Position ksy = tip->tip.top_margin; + XFontSetExtents *ext = XExtentsOfFontSet(tip->tip.fontset); + + ksy += XawAbs(ext->max_ink_extent.y); + + while ((nl = index(label, '\n')) != NULL) { + XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset, + gc, tip->tip.left_margin, ksy, label, + (int)(nl - label)); + ksy += ext->max_ink_extent.height; + label = nl + 1; + } + len = strlen(label); + if (len) + XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset, gc, + tip->tip.left_margin, ksy, label, len); + } + else { + while ((nl = index(label, '\n')) != NULL) { + if (tip->tip.encoding) + XDrawString16(XtDisplay(w), XtWindow(w), gc, + tip->tip.left_margin, y, + (XChar2b*)label, (int)(nl - label) >> 1); + else + XDrawString(XtDisplay(w), XtWindow(w), gc, + tip->tip.left_margin, y, label, (int)(nl - label)); + y += tip->tip.font->max_bounds.ascent + + tip->tip.font->max_bounds.descent; + label = nl + 1; + } + len = strlen(label); + if (len) { + if (tip->tip.encoding) + XDrawString16(XtDisplay(w), XtWindow(w), gc, + tip->tip.left_margin, y, (XChar2b*)label, len >> 1); + else + XDrawString(XtDisplay(w), XtWindow(w), gc, + tip->tip.left_margin, y, label, len); + } + } +} + +/*ARGSUSED*/ +static Boolean +XawTipSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + TipWidget curtip = (TipWidget)current; + TipWidget newtip = (TipWidget)cnew; + Boolean redisplay = False; + + if (curtip->tip.font->fid != newtip->tip.font->fid || + curtip->tip.foreground != newtip->tip.foreground) { + XGCValues values; + + values.foreground = newtip->tip.foreground; + values.background = newtip->core.background_pixel; + values.font = newtip->tip.font->fid; + values.graphics_exposures = False; + XtReleaseGC(cnew, curtip->tip.gc); + newtip->tip.gc = XtAllocateGC(cnew, 0, GCForeground | GCBackground | + GCFont | GCGraphicsExposures, &values, + GCFont, 0); + redisplay = True; + } + if (curtip->tip.display_list != newtip->tip.display_list) + redisplay = True; + + return (redisplay); +} + +static void +TipLayout(XawTipInfo *info) +{ + XFontStruct *fs = info->tip->tip.font; + int width = 0, height; + char *nl, *label = info->tip->tip.label; + + if (info->tip->tip.international == True) { + XFontSet fset = info->tip->tip.fontset; + XFontSetExtents *ext = XExtentsOfFontSet(fset); + + height = ext->max_ink_extent.height; + if ((nl = index(label, '\n')) != NULL) { + /*CONSTCOND*/ + while (True) { + int w = XmbTextEscapement(fset, label, (int)(nl - label)); + + if (w > width) + width = w; + if (*nl == '\0') + break; + label = nl + 1; + if (*label) + height += ext->max_ink_extent.height; + if ((nl = index(label, '\n')) == NULL) + nl = index(label, '\0'); + } + } + else + width = XmbTextEscapement(fset, label, strlen(label)); + } + else { + height = fs->max_bounds.ascent + fs->max_bounds.descent; + if ((nl = index(label, '\n')) != NULL) { + /*CONSTCOND*/ + while (True) { + int w = info->tip->tip.encoding ? + XTextWidth16(fs, (XChar2b*)label, (int)(nl - label) >> 1) : + XTextWidth(fs, label, (int)(nl - label)); + if (w > width) + width = w; + if (*nl == '\0') + break; + label = nl + 1; + if (*label) + height += fs->max_bounds.ascent + fs->max_bounds.descent; + if ((nl = index(label, '\n')) == NULL) + nl = index(label, '\0'); + } + } + else + width = info->tip->tip.encoding ? + XTextWidth16(fs, (XChar2b*)label, strlen(label) >> 1) : + XTextWidth(fs, label, strlen(label)); + } + XtWidth(info->tip) = width + info->tip->tip.left_margin + + info->tip->tip.right_margin; + XtHeight(info->tip) = height + info->tip->tip.top_margin + + info->tip->tip.bottom_margin; +} + +#define DEFAULT_TIP_Y_OFFSET 12 +static void +TipPosition(XawTipInfo *info) +{ + Window r, c; + int rx, ry, wx, wy; + unsigned mask; + Position x, y; + + XQueryPointer(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip), + &r, &c, &rx, &ry, &wx, &wy, &mask); + x = rx - (XtWidth(info->tip) >> 1); + y = ry + DEFAULT_TIP_Y_OFFSET; + + if (x >= 0) { + int scr_width = WidthOfScreen(XtScreen(info->tip)); + + if (x + XtWidth(info->tip) + XtBorderWidth(info->tip) > scr_width) + x = scr_width - XtWidth(info->tip) - XtBorderWidth(info->tip); + } + if (x < 0) + x = 0; + if (y >= 0) { + int scr_height = HeightOfScreen(XtScreen(info->tip)); + + if (y + XtHeight(info->tip) + XtBorderWidth(info->tip) > scr_height) + y -= XtHeight(info->tip) + XtBorderWidth(info->tip) + + (DEFAULT_TIP_Y_OFFSET << 1); + } + if (y < 0) + y = 0; + + XMoveResizeWindow(XtDisplay(info->tip), XtWindow(info->tip), + (int)(XtX(info->tip) = x), (int)(XtY(info->tip) = y), + (unsigned)XtWidth(info->tip), (unsigned)XtHeight(info->tip)); +} + +static XawTipInfo * +CreateTipInfo(Widget w) +{ + XawTipInfo *info = XtNew(XawTipInfo); + Widget shell = w; + + info->screen = XtScreen(w); + + while (XtParent(shell)) + shell = XtParent(shell); + + info->tip = (TipWidget)XtCreateWidget("tip", tipWidgetClass, shell, NULL, 0); + XtRealizeWidget((Widget)info->tip); + info->widget = NULL; + info->mapped = False; + info->next = NULL; + XtAddEventHandler(shell, KeyPressMask, False, TipShellEventHandler, + (XtPointer)NULL); + + return (info); +} + +static XawTipInfo * +FindTipInfo(Widget w) +{ + XawTipInfo *ptip, *tip = first_tip; + Screen *screen = XtScreenOfObject(w); + + if (tip == NULL) + return (first_tip = tip = CreateTipInfo(w)); + + for (ptip = tip; tip; ptip = tip, tip = tip->next) + if (tip->screen == screen) + return (tip); + + return (ptip->next = CreateTipInfo(w)); +} + +static void +ResetTip(XawTipInfo *info, Bool add_timeout) +{ + if (info->tip->tip.timer) { + XtRemoveTimeOut(info->tip->tip.timer); + info->tip->tip.timer = 0; + } + if (info->mapped) { + XtRemoveGrab(XtParent((Widget)info->tip)); + XUnmapWindow(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip)); + info->mapped = False; + } + if (add_timeout) { + info->tip->tip.timer = + XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)info->tip), + info->tip->tip.timeout, TipTimeoutCallback, + (XtPointer)info); + } +} + +static void +TipTimeoutCallback(XtPointer closure, XtIntervalId *id) +{ + XawTipInfo *info = (XawTipInfo*)closure; + Arg args[3]; + + info->tip->tip.label = NULL; + info->tip->tip.international = False; + info->tip->tip.encoding = 0; + info->tip->tip.timer = 0; + XtSetArg(args[0], XtNtip, &info->tip->tip.label); + XtSetArg(args[1], XtNinternational, &info->tip->tip.international); + XtSetArg(args[2], XtNencoding, &info->tip->tip.encoding); + XtGetValues(info->widget, args, 3); + + if (info->tip->tip.label) { + TipLayout(info); + TipPosition(info); + XMapRaised(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip)); + XtAddGrab(XtParent((Widget)info->tip), True, True); + info->mapped = True; + } +} + +/*ARGSUSED*/ +static void +TipShellEventHandler(Widget w, XtPointer client_data, XEvent *event, + Boolean *continue_to_dispatch) +{ + ResetTip(FindTipInfo(w), False); +} + +/*ARGSUSED*/ +static void +TipEventHandler(Widget w, XtPointer client_data, XEvent *event, + Boolean *continue_to_dispatch) +{ + XawTipInfo *info = FindTipInfo(w); + Boolean add_timeout; + + if (info->widget != w) { + ResetTip(info, False); + info->widget = w; + } + + switch (event->type) { + case EnterNotify: + add_timeout = True; + break; + case MotionNotify: + /* If any button is pressed, timer is 0 */ + if (info->mapped) + return; + add_timeout = info->tip->tip.timer != 0; + break; + default: + add_timeout = False; + break; + } + ResetTip(info, add_timeout); +} + +/* + * Public routines + */ +void +XawTipEnable(Widget w) +{ + XtAddEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler, + (XtPointer)NULL); +} + +void +XawTipDisable(Widget w) +{ + XawTipInfo *info = FindTipInfo(w); + + XtRemoveEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler, + (XtPointer)NULL); + if (info->widget == w) + ResetTip(info, False); +} |