From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- libXaw/src/Tip.c | 1274 +++++++++++++++++++++++++++--------------------------- 1 file changed, 637 insertions(+), 637 deletions(-) (limited to 'libXaw/src/Tip.c') 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 -#endif -#include -#include -#include -#include -#include -#include -#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 +#endif +#include +#include +#include +#include +#include +#include +#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); +} -- cgit v1.2.3