blob: 5d426fc6f691b9dbe26e3579941bbdb1133e51c2 [file] [log] [blame]
/* $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);
}