Fri Sep 3 11:52:18 1993 Bob Amstadt * [windows/timer.c] Changed to use CallWindowProc() rather directly calling callback. * [windows/event.c] Implemented SetCapture() and ReleaseCapture() * [windows/keyboard.c] Created stub for GetKeyState() * [objects/linedda.c] Created stub for LineDDA() * [if1632/callback.c] Created callback handler for LineDDA callback procedure. * [if1632/callback.c] Created FreeProcInstance() Fri Sep 3 08:36:52 1993 David Metcalfe * [loader/signal.c] Patch to and code for INT 1A Thu Sep 2 00:31:54 1993 Alexandre Julliard * [objects/font.c] [objects/text.c] More text support: implemented justification and underlining. * [windows/clipping.c] [objects/clipping.c] Moved low-level clipping functions to objects/clipping.c. * [windows/clipping.c] [windows/event.c] [windows/message.c] Implemented window update regions. * [windows/dc.c] [objects/dcvalues.c] Moved some device-independent DC functions to objects/dcvalues.c. * [windows/graphics.c] Implemented InvertRect() and GetPixel(). Sat Aug 28 08:40:23 1993 Eric Youngdale * [include/neexe.h] [loader/wine.c] Added code to handle relocation type 4. * [loader/signal.h] [loader/wine.c] [loader/selector.c] Added support for dos interrupts. Thu 26 Aug 19:15:00 1993 Eric Youngdale * [loader/selector.c] Fixed bug dealing with loading DLLs. Thu Aug 26 19:22:40 1993 Alexandre Julliard * [include/gdi.h] [objects/font.c] [windows/dc.c] Beginning of real font support. * [windows/graphics.c] Implemented PatBlt(). * [memory/global.c] Corrected a bug with linked list handling in GlobalAlloc(). * [objects/bitmap.c] Corrected a bug in BITMAP_SelectObject(). Tue Aug 24 19:22:40 1993 David Metcalfe * [controls/Command*] [controls/Label*] [controls[MenuButto*] [controls/SmeMenuButt*] Change code to support & as a special character in menu item text. Tue Aug 24 19:22:40 1993 Alexandre Julliard * [include/gdi.h] [windows/dc.c] Heavily modified the DC structure for better device-independence. * [objects/bitmap.c] Implemented bitmap dimensions. * [windows/dc.c] [windows/dce.c] Implemented DC state saving and restoring. * [windows/dc.c] Implemented ROP mode. * [windows/graphics.c] Implemented FillRect(). Mon Aug 23 22:08:34 1993 Bob Amstadt (bob at pooh) * [misc/xt.c] Fixed bug in InvalidateRect(). Solitaire attempted to clear window before it was realized. * [loader/resource.c] Began rewrite of LoadBitmap(). * [loader/wine.c] Fixed code which set Argv and Argc global variables. * [loader/selector.c] Added code to set up command line arguments. * [include/neexe.h] Fixed error in PSP structure. Tue Aug 17 20:41:12 1993 Alexandre Julliard * [include/gdi.h] [windows/dc.c] Implemented device capabilities. * [objects/region.c] Implemented EqualRgn() and CombineRgn(). * [windows/clipping.c] Implemented Save/RestoreVisRgn(). * [windows/graphics.c] Implemented PaintRgn() and FillRgn(). * [windows/mapping.c] Implemented mapping modes. Tue Aug 10 14:07:38 1993 Alexandre Julliard * [if1632/user.spec] [misc/rect.c] Implemented rectangle API functions. * [if1632/gdi.spec] [include/gdi.h] [objects/region.c] Implemented regions. * [windows/class.c] Corrected a typo in UnregisterClass(). * [windows/clipping.c] [windows/dc.c] Implemented DC clipping and visible region. Tue Aug 10 20:57:56 1993 Bob Amstadt (bob at pooh) * [controls/menu.c] [windows/win.c] SetMenu(), GetMenu(), CheckMenuItem() implemented Thu Aug 5 22:33:22 1993 Bob Amstadt (bob at pooh) * [controls/menu.c] [windows/win.c] Many improvements menus. LoadMenu() should work. Wed Aug 4 14:55:36 1993 Alexandre Julliard * [objects/dib.c] Started the implementation of device-independent bitmaps. * [objects/bitmap.c] Added support for multiple bitmap depths. * [objects/brush.c] Implemented pattern brushes. * [windows/dc.c] [windows/graphics.c] Implemented some GDI graphics primitives. Tue Aug 3 21:16:47 1993 Bob Amstadt (bob at pooh) * [controls/menu.c] [windows/win.c] [include/menu.h] Code to load class menus from executable file. * [if1632/user.spec] Fixed specification of SendMessage() and PostMessage. Mon Jul 26 21:53:24 1993 Alexandre Julliard * [if1632/call.S] Corrected a bug in KERNEL_InitTask(). * [include/windows.h] Added a lot of constants. * [loader/selector.c] Corrected a bug in segment allocation in CreateSelectors(). * [objects/bitmap.c] Implemented SelectObject() for bitmaps. * [objects/brush.c] Implemented hatched brushes and SelectObject(). * [objects/gdiobj.c] Removed linked list (not needed). * [objects/palette.c] Implemented system palette creation and misc. palette API functions. * [windows/timer.c] Implemented timers. * [windows/dc.c] Implemented memory device contexts. Tue Jul 20 10:38:59 1993 Bob Amstadt (bob at pooh) * [dos.c] Split DOS3Call() out of kernel.c. Added support for get date and time functions. * [call.S] Added function ReturnFromRegisterFunc() to allow DOS calls to return values in registers. * [regfunc.h] Macros to access registers saved on stack. Tue Jul 20 10:38:59 1993 Alexandre Julliard * [win.c] Corrected allocation of the WM_CREATE data structure. * [dce.c] [dce.h] Implemented DCE handling. * [bitmap.c] [brush.c] [dc.c] [font.c] [gdi.h] [gdi.spec] [gdiobj.c] [palette.c] [pen.c] Implemented the GDI objects data structures and allocation. * [windows.h] Added several structures and constants for GDI objects. Mon Jul 19 12:51:10 1993 Bob Amstadt (bob at pooh) * [ldtlib.c] Modified system calls to match Linus' new interface for the LDT modification. * [win.c] Fixed bug with WM_CREATE message. * [heap.c] [kernel.spec] Completed local heap allocation functions. * [global.c] Created function GlobalQuickAlloc() for easy allocation from DLLs
758 lines
22 KiB
C
758 lines
22 KiB
C
/* $XConsortium: SmeMenuButton.c,v 1.16 91/03/15 15:59:41 gildea Exp $ */
|
|
|
|
/*
|
|
* Copyright 1989 Massachusetts Institute of Technology
|
|
*
|
|
* 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 M.I.T. not be used in advertising or
|
|
* publicity pertaining to distribution of the software without specific,
|
|
* written prior permission. M.I.T. makes no representations about the
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*
|
|
* M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
|
|
* 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.
|
|
*/
|
|
|
|
/*
|
|
* SmeMenuButton.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
|
|
*
|
|
* Modifications for Wine
|
|
*
|
|
* 8/23/93 David Metcalfe (david@prism.demon.co.uk)
|
|
* Added code to translate ampersand to underlined char
|
|
*/
|
|
|
|
#include <X11/IntrinsicP.h>
|
|
#include <X11/StringDefs.h>
|
|
#include <X11/Xos.h>
|
|
|
|
#include <X11/Xmu/Drawing.h>
|
|
|
|
#include <X11/Xaw/XawInit.h>
|
|
#include <X11/Xaw/SimpleMenu.h>
|
|
#include "SmeMenuButtP.h"
|
|
#include <X11/Xaw/Cardinals.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#define ONE_HUNDRED 100
|
|
|
|
#define offset(field) XtOffsetOf(SmeMenuButtonRec, 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) 15},
|
|
{XtNrightMargin, XtCHorizontalMargins, XtRDimension, sizeof(Dimension),
|
|
offset(right_margin), XtRImmediate, (XtPointer) 5},
|
|
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
|
|
offset(foreground), XtRString, XtDefaultForeground},
|
|
{XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
|
|
offset(font), XtRString, XtDefaultFont},
|
|
{XtNmenuName, XtCMenuName, XtRString, sizeof(String),
|
|
offset(menu_name), XtRString, (XtPointer) NULL},
|
|
{XtNinactive, XtCInactive, XtRBoolean, sizeof(Boolean),
|
|
offset(inactive), XtRImmediate, (XtPointer) FALSE },
|
|
};
|
|
#undef offset
|
|
|
|
/*
|
|
* Semi Public function definitions.
|
|
*/
|
|
|
|
static void Redisplay(), Destroy(), Initialize(), FlipColors();
|
|
static void ClassInitialize();
|
|
static void PopupMenu(), Unhighlight();
|
|
static Boolean SetValues();
|
|
static XtGeometryResult QueryGeometry();
|
|
|
|
/*
|
|
* Private Function Definitions.
|
|
*/
|
|
|
|
static void GetDefaultSize(), DrawBitmaps(), GetBitmapInfo();
|
|
static void CreateGCs(), DestroyGCs();
|
|
static void RemoveAmpersand();
|
|
|
|
#define superclass (&smeClassRec)
|
|
SmeMenuButtonClassRec smeMenuButtonClassRec = {
|
|
{
|
|
/* superclass */ (WidgetClass) superclass,
|
|
/* class_name */ "SmeMenuButton",
|
|
/* size */ sizeof(SmeMenuButtonRec),
|
|
/* class_initializer */ ClassInitialize,
|
|
/* class_part_initialize*/ NULL,
|
|
/* Class init'ed */ FALSE,
|
|
/* initialize */ Initialize,
|
|
/* initialize_hook */ NULL,
|
|
/* realize */ NULL,
|
|
/* actions */ NULL,
|
|
/* num_actions */ ZERO,
|
|
/* resources */ resources,
|
|
/* resource_count */ XtNumber(resources),
|
|
/* xrm_class */ NULLQUARK,
|
|
/* compress_motion */ FALSE,
|
|
/* compress_exposure */ FALSE,
|
|
/* compress_enterleave*/ FALSE,
|
|
/* visible_interest */ FALSE,
|
|
/* destroy */ Destroy,
|
|
/* resize */ NULL,
|
|
/* expose */ Redisplay,
|
|
/* set_values */ SetValues,
|
|
/* 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 */ QueryGeometry,
|
|
/* display_accelerator*/ NULL,
|
|
/* extension */ NULL
|
|
},{
|
|
/* Menu Entry Fields */
|
|
|
|
/* highlight */ FlipColors,
|
|
/* unhighlight */ Unhighlight,
|
|
/* notify */ XtInheritNotify,
|
|
/* extension */ NULL
|
|
}, {
|
|
/* BSB Menu entry Fields */
|
|
|
|
/* extension */ NULL
|
|
}
|
|
};
|
|
|
|
WidgetClass smeMenuButtonObjectClass = (WidgetClass) &smeMenuButtonClassRec;
|
|
|
|
/************************************************************
|
|
*
|
|
* Semi-Public Functions.
|
|
*
|
|
************************************************************/
|
|
|
|
/* Function Name: ClassInitialize
|
|
* Description: Initializes the SmeMenuButtonObject.
|
|
* Arguments: none.
|
|
* Returns: none.
|
|
*/
|
|
|
|
static void
|
|
ClassInitialize()
|
|
{
|
|
XawInitializeWidgetSet();
|
|
XtAddConverter( XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0 );
|
|
}
|
|
|
|
/* Function Name: Initialize
|
|
* Description: Initializes the simple menu widget
|
|
* Arguments: request - the widget requested by the argument list.
|
|
* new - the new widget with both resource and non
|
|
* resource values.
|
|
* Returns: none.
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
Initialize(request, new)
|
|
Widget request, new;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) new;
|
|
|
|
if (entry->sme_bsb.label == NULL)
|
|
entry->sme_bsb.label = XtName(new);
|
|
else
|
|
entry->sme_bsb.label = XtNewString( entry->sme_bsb.label );
|
|
|
|
RemoveAmpersand(new);
|
|
|
|
GetDefaultSize(new, &(entry->rectangle.width), &(entry->rectangle.height));
|
|
CreateGCs(new);
|
|
|
|
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(new, TRUE); /* Left Bitmap Info */
|
|
GetBitmapInfo(new, FALSE); /* Right Bitmap Info */
|
|
}
|
|
|
|
/* Function Name: Destroy
|
|
* Description: Called at destroy time, cleans up.
|
|
* Arguments: w - the simple menu widget.
|
|
* Returns: none.
|
|
*/
|
|
|
|
static void
|
|
Destroy(w)
|
|
Widget w;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) w;
|
|
|
|
DestroyGCs(w);
|
|
if (entry->sme_bsb.label != XtName(w))
|
|
XtFree(entry->sme_bsb.label);
|
|
}
|
|
|
|
/* Function Name: Redisplay
|
|
* Description: Redisplays the contents of the widget.
|
|
* Arguments: w - the simple menu widget.
|
|
* event - the X event that caused this redisplay.
|
|
* region - the region the needs to be repainted.
|
|
* Returns: none.
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
Redisplay(w, event, region)
|
|
Widget w;
|
|
XEvent * event;
|
|
Region region;
|
|
{
|
|
GC gc;
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) w;
|
|
int font_ascent, font_descent, y_loc;
|
|
int ul_x_loc, ul_y_loc, ul_width;
|
|
|
|
entry->sme_bsb.set_values_area_cleared = FALSE;
|
|
font_ascent = entry->sme_bsb.font->max_bounds.ascent;
|
|
font_descent = entry->sme_bsb.font->max_bounds.descent;
|
|
|
|
y_loc = entry->rectangle.y;
|
|
|
|
if (XtIsSensitive(w) && XtIsSensitive( XtParent(w) ) ) {
|
|
if ( w == XawSimpleMenuGetActiveEntry(XtParent(w)) ) {
|
|
XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
|
|
entry->sme_bsb.norm_gc, 0, y_loc,
|
|
(unsigned int) entry->rectangle.width,
|
|
(unsigned int) entry->rectangle.height);
|
|
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;
|
|
|
|
switch(entry->sme_bsb.justify) {
|
|
int width, t_width;
|
|
|
|
case XtJustifyCenter:
|
|
t_width = XTextWidth(entry->sme_bsb.font, label, len);
|
|
width = entry->rectangle.width - (entry->sme_bsb.left_margin +
|
|
entry->sme_bsb.right_margin);
|
|
x_loc += (width - t_width)/2;
|
|
break;
|
|
case XtJustifyRight:
|
|
t_width = XTextWidth(entry->sme_bsb.font, label, len);
|
|
x_loc = entry->rectangle.width - (entry->sme_bsb.right_margin +
|
|
t_width);
|
|
break;
|
|
case XtJustifyLeft:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
y_loc += ((int)entry->rectangle.height -
|
|
(font_ascent + font_descent)) / 2 + font_ascent;
|
|
|
|
XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), gc,
|
|
x_loc, y_loc, label, len);
|
|
|
|
if (entry->sme_bsb.ul_pos != -1)
|
|
{
|
|
ul_x_loc = x_loc + XTextWidth(entry->sme_bsb.font,
|
|
entry->sme_bsb.label, entry->sme_bsb.ul_pos);
|
|
ul_y_loc = entry->rectangle.y + (entry->rectangle.height +
|
|
font_ascent + font_descent) / 2;
|
|
ul_width = XTextWidth(entry->sme_bsb.font,
|
|
entry->sme_bsb.label + entry->sme_bsb.ul_pos, 1);
|
|
|
|
XDrawLine(XtDisplayOfObject(w), XtWindowOfObject(w), gc,
|
|
ul_x_loc, ul_y_loc, ul_x_loc + ul_width - 1, ul_y_loc);
|
|
}
|
|
}
|
|
|
|
DrawBitmaps(w, gc);
|
|
}
|
|
|
|
|
|
/* Function Name: SetValues
|
|
* Description: Relayout the menu when one of the resources is changed.
|
|
* Arguments: current - current state of the widget.
|
|
* request - what was requested.
|
|
* new - what the widget will become.
|
|
* Returns: none
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
static Boolean
|
|
SetValues(current, request, new)
|
|
Widget current, request, new;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) new;
|
|
SmeMenuButtonObject old_entry = (SmeMenuButtonObject) current;
|
|
Boolean ret_val = FALSE;
|
|
|
|
if (old_entry->sme_bsb.label != entry->sme_bsb.label) {
|
|
if (old_entry->sme_bsb.label != XtName( new ) )
|
|
XtFree( (char *) old_entry->sme_bsb.label );
|
|
|
|
if (entry->sme_bsb.label != XtName(new) )
|
|
entry->sme_bsb.label = XtNewString( entry->sme_bsb.label );
|
|
|
|
RemoveAmpersand(new);
|
|
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(new, TRUE);
|
|
ret_val = TRUE;
|
|
}
|
|
|
|
if (entry->sme_bsb.right_bitmap != old_entry->sme_bsb.right_bitmap) {
|
|
GetBitmapInfo(new, FALSE);
|
|
ret_val = TRUE;
|
|
}
|
|
|
|
if ( (old_entry->sme_bsb.font != entry->sme_bsb.font) ||
|
|
(old_entry->sme_bsb.foreground != entry->sme_bsb.foreground) ) {
|
|
DestroyGCs(current);
|
|
CreateGCs(new);
|
|
ret_val = TRUE;
|
|
}
|
|
|
|
if (ret_val) {
|
|
GetDefaultSize(new,
|
|
&(entry->rectangle.width), &(entry->rectangle.height));
|
|
entry->sme_bsb.set_values_area_cleared = TRUE;
|
|
}
|
|
return(ret_val);
|
|
}
|
|
|
|
/* Function Name: QueryGeometry.
|
|
* Description: Returns the preferred geometry for this widget.
|
|
* Arguments: w - the menu entry object.
|
|
* itended, return_val - the intended and return geometry info.
|
|
* Returns: A Geometry Result.
|
|
*
|
|
* See the Intrinsics manual for details on what this function is for.
|
|
*
|
|
* I just return the height and width of the label plus the margins.
|
|
*/
|
|
|
|
static XtGeometryResult
|
|
QueryGeometry(w, intended, return_val)
|
|
Widget w;
|
|
XtWidgetGeometry *intended, *return_val;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) 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 == entry->rectangle.width)) &&
|
|
((mode & CWHeight) && (height == entry->rectangle.height)) )
|
|
return(XtGeometryNo);
|
|
}
|
|
|
|
return(ret_val);
|
|
}
|
|
|
|
/* Function Name: FlipColors
|
|
* Description: Invert the colors of the current entry.
|
|
* Arguments: w - the bsb menu entry widget.
|
|
* Returns: none.
|
|
*/
|
|
|
|
static void
|
|
FlipColors(w)
|
|
Widget w;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) w;
|
|
|
|
if (entry->sme_bsb.set_values_area_cleared || entry->sme_bsb.inactive)
|
|
return;
|
|
|
|
XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
|
|
entry->sme_bsb.invert_gc, 0, (int) entry->rectangle.y,
|
|
(unsigned int) entry->rectangle.width,
|
|
(unsigned int) entry->rectangle.height);
|
|
}
|
|
|
|
/************************************************************
|
|
*
|
|
* Private Functions.
|
|
*
|
|
************************************************************/
|
|
|
|
/* Function Name: GetDefaultSize
|
|
* Description: Calculates the Default (preferred) size of
|
|
* this menu entry.
|
|
* Arguments: w - the menu entry widget.
|
|
* width, height - default sizes (RETURNED).
|
|
* Returns: none.
|
|
*/
|
|
|
|
static void
|
|
GetDefaultSize(w, width, height)
|
|
Widget w;
|
|
Dimension * width, * height;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) w;
|
|
|
|
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 Name: DrawBitmaps
|
|
* Description: Draws left and right bitmaps.
|
|
* Arguments: w - the simple menu widget.
|
|
* gc - graphics context to use for drawing.
|
|
* Returns: none
|
|
*/
|
|
|
|
static void
|
|
DrawBitmaps(w, gc)
|
|
Widget w;
|
|
GC gc;
|
|
{
|
|
int x_loc, y_loc;
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) 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 = (int)(entry->sme_bsb.left_margin -
|
|
entry->sme_bsb.left_bitmap_width) / 2;
|
|
|
|
y_loc = entry->rectangle.y + (int)(entry->rectangle.height -
|
|
entry->sme_bsb.left_bitmap_height) / 2;
|
|
|
|
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 = entry->rectangle.width -
|
|
(int)(entry->sme_bsb.right_margin +
|
|
entry->sme_bsb.right_bitmap_width) / 2;
|
|
|
|
y_loc = entry->rectangle.y + (int)(entry->rectangle.height -
|
|
entry->sme_bsb.right_bitmap_height) / 2;
|
|
|
|
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 Name: GetBitmapInfo
|
|
* Description: Gets the bitmap information from either of the bitmaps.
|
|
* Arguments: w - the bsb menu entry widget.
|
|
* is_left - TRUE if we are testing left bitmap,
|
|
* FALSE if we are testing the right bitmap.
|
|
* Returns: none
|
|
*/
|
|
|
|
static void
|
|
GetBitmapInfo(w, is_left)
|
|
Widget w;
|
|
Boolean is_left;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) w;
|
|
unsigned int depth, bw;
|
|
Window root;
|
|
int x, y;
|
|
unsigned int width, height;
|
|
char buf[BUFSIZ];
|
|
|
|
if (is_left) {
|
|
if (entry->sme_bsb.left_bitmap != None) {
|
|
if (!XGetGeometry(XtDisplayOfObject(w),
|
|
entry->sme_bsb.left_bitmap, &root,
|
|
&x, &y, &width, &height, &bw, &depth)) {
|
|
sprintf(buf, "SmeMenuButton Object: %s %s \"%s\".", "Could not",
|
|
"get Left Bitmap geometry information for menu entry ",
|
|
XtName(w));
|
|
XtAppError(XtWidgetToApplicationContext(w), buf);
|
|
}
|
|
if (depth != 1) {
|
|
sprintf(buf, "SmeMenuButton Object: %s \"%s\"%s.",
|
|
"Left Bitmap of entry ",
|
|
XtName(w), " is not one bit deep.");
|
|
XtAppError(XtWidgetToApplicationContext(w), buf);
|
|
}
|
|
entry->sme_bsb.left_bitmap_width = (Dimension) width;
|
|
entry->sme_bsb.left_bitmap_height = (Dimension) height;
|
|
}
|
|
}
|
|
else if (entry->sme_bsb.right_bitmap != None) {
|
|
if (!XGetGeometry(XtDisplayOfObject(w),
|
|
entry->sme_bsb.right_bitmap, &root,
|
|
&x, &y, &width, &height, &bw, &depth)) {
|
|
sprintf(buf, "SmeMenuButton Object: %s %s \"%s\".", "Could not",
|
|
"get Right Bitmap geometry information for menu entry ",
|
|
XtName(w));
|
|
XtAppError(XtWidgetToApplicationContext(w), buf);
|
|
}
|
|
if (depth != 1) {
|
|
sprintf(buf, "SmeMenuButton Object: %s \"%s\"%s.",
|
|
"Right Bitmap of entry ", XtName(w),
|
|
" is not one bit deep.");
|
|
XtAppError(XtWidgetToApplicationContext(w), buf);
|
|
}
|
|
entry->sme_bsb.right_bitmap_width = (Dimension) width;
|
|
entry->sme_bsb.right_bitmap_height = (Dimension) height;
|
|
}
|
|
}
|
|
|
|
/* Function Name: CreateGCs
|
|
* Description: Creates all gc's for the simple menu widget.
|
|
* Arguments: w - the simple menu widget.
|
|
* Returns: none.
|
|
*/
|
|
|
|
static void
|
|
CreateGCs(w)
|
|
Widget w;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) w;
|
|
XGCValues values;
|
|
XtGCMask mask;
|
|
|
|
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 | GCFont | GCGraphicsExposures;
|
|
entry->sme_bsb.rev_gc = XtGetGC(w, mask, &values);
|
|
|
|
values.foreground = entry->sme_bsb.foreground;
|
|
values.background = XtParent(w)->core.background_pixel;
|
|
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;
|
|
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 Name: DestroyGCs
|
|
* Description: Removes all gc's for the simple menu widget.
|
|
* Arguments: w - the simple menu widget.
|
|
* Returns: none.
|
|
*/
|
|
|
|
static void
|
|
DestroyGCs(w)
|
|
Widget w;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) 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);
|
|
}
|
|
|
|
static void
|
|
PopupMenu(w)
|
|
Widget w;
|
|
{
|
|
SmeMenuButtonObject mbw = (SmeMenuButtonObject) w;
|
|
Widget menu, temp;
|
|
Arg arglist[2];
|
|
Cardinal num_args;
|
|
int menu_x, menu_y, menu_width, menu_height, button_width;
|
|
Position button_x, button_y;
|
|
|
|
if (mbw->sme_bsb.menu_name == NULL || strlen(mbw->sme_bsb.menu_name) == 0)
|
|
return;
|
|
|
|
temp = w;
|
|
while(temp != NULL) {
|
|
menu = XtNameToWidget(temp, mbw->sme_bsb.menu_name);
|
|
if (menu == NULL)
|
|
temp = XtParent(temp);
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (menu == NULL) {
|
|
char error_buf[BUFSIZ];
|
|
sprintf(error_buf, "MenuButton: %s %s.",
|
|
"Could not find menu widget named", mbw->sme_bsb.menu_name);
|
|
XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
|
|
return;
|
|
}
|
|
if (!XtIsRealized(menu))
|
|
XtRealizeWidget(menu);
|
|
|
|
menu_width = menu->core.width + 2 * menu->core.border_width;
|
|
button_width = mbw->rectangle.width + 2 * mbw->rectangle.border_width;
|
|
menu_height = menu->core.height + 2 * menu->core.border_width;
|
|
|
|
XtTranslateCoords(w, 0, 0, &button_x, &button_y);
|
|
menu_x = button_x + button_width;
|
|
menu_y = button_y;
|
|
|
|
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;
|
|
|
|
if (menu_y >= 0) {
|
|
int scr_height = HeightOfScreen(XtScreen(menu));
|
|
if (menu_y + menu_height > scr_height)
|
|
menu_y = scr_height - menu_height;
|
|
}
|
|
if (menu_y < 0)
|
|
menu_y = 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);
|
|
}
|
|
|
|
static void
|
|
Unhighlight(w)
|
|
Widget w;
|
|
{
|
|
SmeMenuButtonObject mbw = (SmeMenuButtonObject) w;
|
|
Display *display;
|
|
Screen *screen;
|
|
Window win, rootwin;
|
|
int rootwin_x, rootwin_y;
|
|
int win_x, win_y;
|
|
unsigned int mask;
|
|
Position left, right, top, bottom;
|
|
|
|
if (mbw->sme_bsb.inactive)
|
|
return;
|
|
|
|
display = XtDisplayOfObject(w);
|
|
screen = XtScreenOfObject(w);
|
|
XQueryPointer(display, RootWindowOfScreen(screen),
|
|
&rootwin, &win, &rootwin_x, &rootwin_y,
|
|
&win_x, &win_y, &mask);
|
|
|
|
XtTranslateCoords(w, 0, 0, &left, &top);
|
|
XtTranslateCoords(w, mbw->rectangle.width, mbw->rectangle.height,
|
|
&right, &bottom);
|
|
|
|
if (rootwin_x >= right && rootwin_y >= top && rootwin_y < bottom)
|
|
{
|
|
PopupMenu(w);
|
|
}
|
|
|
|
FlipColors(w);
|
|
}
|
|
|
|
static void
|
|
RemoveAmpersand(w)
|
|
Widget w;
|
|
{
|
|
SmeMenuButtonObject entry = (SmeMenuButtonObject) w;
|
|
|
|
entry->sme_bsb.ul_pos = strcspn(entry->sme_bsb.label, "&");
|
|
if (entry->sme_bsb.ul_pos == strlen(entry->sme_bsb.label))
|
|
{
|
|
entry->sme_bsb.ul_pos = -1;
|
|
return;
|
|
}
|
|
|
|
/* Remove ampersand from label */
|
|
strcpy(entry->sme_bsb.label + entry->sme_bsb.ul_pos,
|
|
entry->sme_bsb.label + entry->sme_bsb.ul_pos + 1);
|
|
}
|
|
|