diff options
author | marha <marha@users.sourceforge.net> | 2009-11-06 11:03:40 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-11-06 11:03:40 +0000 |
commit | 08cb4425442ca65ec28d6a2f023f885e35a7f0ed (patch) | |
tree | a9061a472d247bce27d7fb6c700c5b7e2755d036 /libXaw/src/Tip.c | |
parent | ccdb20929567c70c1bbdd5df275ca7bea5c747a7 (diff) | |
parent | ace7902333b6f61aab5a6035dbcb222763bff186 (diff) | |
download | vcxsrv-08cb4425442ca65ec28d6a2f023f885e35a7f0ed.tar.gz vcxsrv-08cb4425442ca65ec28d6a2f023f885e35a7f0ed.tar.bz2 vcxsrv-08cb4425442ca65ec28d6a2f023f885e35a7f0ed.zip |
Added libXaw
Diffstat (limited to 'libXaw/src/Tip.c')
-rw-r--r-- | libXaw/src/Tip.c | 639 |
1 files changed, 639 insertions, 0 deletions
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); +} |