Files
cdesktop/cde/programs/dtmail/dtmail/dtb_utils.C
2018-05-31 22:23:19 -06:00

3251 lines
70 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: dtb_utils.C /main/8 1998/10/26 17:19:11 mgreess $ */
/*
* $TOG: dtb_utils.C /main/8 1998/10/26 17:19:11 mgreess $
*
* File: dtb_utils.c
* CDE Application Builder General Utility Functions
*
* This file was generated by dtcodegen, from project dtmailopts
*
* ** DO NOT MODIFY BY HAND - ALL MODIFICATIONS WILL BE LOST **
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <Xm/Label.h>
#include <Dt/Help.h>
#include <Dt/HelpDialog.h>
#include <Dt/HelpQuickD.h>
#include <Dt/Session.h>
#include "dtb_utils.h"
#ifndef min
#define min(a,b) ((a) < (b)? (a):(b))
#endif
#ifndef max
#define max(a,b) ((a) > (b)? (a):(b))
#endif
/*
* Private functions used for dynamic centering of objects
*/
static void center_widget(
Widget form_child,
DTB_CENTERING_TYPES type
);
static void uncenter_widget(
Widget form_child,
DTB_CENTERING_TYPES type
);
static void centering_handler(
Widget widget,
XtPointer client_data,
XEvent *event,
Boolean *cont_dispatch
);
/*
* Static functions used for dynamic aligning of group objects
*/
static Widget get_label_widget(
Widget widget
);
static Position get_offset_from_ancestor(
Widget ancestor,
Widget w
);
static Dimension get_label_width(
Widget widget
);
static void get_widest_label(
WidgetList list,
int count,
Widget *child_widget,
Dimension *label_width
);
static void get_widest_value(
WidgetList list,
int count,
Widget *child_widget,
Dimension *value_width
);
static void get_widget_rect(
Widget widget,
XRectangle *rect
);
static void get_greatest_size(
Widget *list,
int count,
int *width,
int *height,
Widget *tallest,
Widget *widest
);
static void get_group_cell_size(
Widget parent,
DtbGroupInfo *group_info,
int *cell_width,
int *cell_height
);
static void get_group_row_col(
Widget parent,
DtbGroupInfo *group_info,
int *rows,
int *cols
);
static Widget get_group_child(
Widget parent,
DtbGroupInfo *group_info,
int x_pos,
int y_pos
);
static void align_children(
Widget parent,
DtbGroupInfo *group_info,
Bool init
);
static void align_handler(
Widget widget,
XtPointer client_data,
XEvent *event,
Boolean *cont_dispatch
);
static void free_group_info(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void align_rows(
Widget parent,
DtbGroupInfo *group_info,
Bool init
);
static void align_cols(
Widget parent,
DtbGroupInfo *group_info,
Bool init
);
static void align_left(
Widget parent,
DtbGroupInfo *group_info
);
static void align_right(
Widget parent,
DtbGroupInfo *group_info
);
static void align_labels(
Widget parent,
DtbGroupInfo *group_info
);
static void align_vcenter(
Widget parent,
DtbGroupInfo *group_info,
Bool init
);
static void align_top(
Widget parent,
DtbGroupInfo *group_info
);
static void align_bottom(
Widget parent,
DtbGroupInfo *group_info
);
static void align_hcenter(
Widget parent,
DtbGroupInfo *group_info,
Bool init
);
/*
* Private functions used for finding paths
*/
static int determine_exe_dir(
char *argv0,
char *buf,
int bufSize
);
static int determine_exe_dir_from_argv(
char *argv0,
char *buf,
int bufSize
);
static int determine_exe_dir_from_path (
char *argv0,
char *buf,
int bufSize
);
static Boolean path_is_executable(
char *path,
uid_t euid,
gid_t egid
);
/*
* Variable for storing client session save callback
*/
static DtbClientSessionSaveCB dtb_client_session_saveCB = NULL;
/*
* Variable for storing top level widget
*/
static Widget dtb_project_toplevel_widget = (Widget)NULL;
/*
* Variable for storing command used to invoke application
*/
static char *dtb_save_command_str = (char *)NULL;
/*
* Directory where the binary for this process whate loaded from
*/
static char *dtb_exe_dir = (char *)NULL;
/*
* Application Builder utility funcs
*/
/*
* Create/load a Pixmap given an XPM or Bitmap files
* NOTE: this allocates a server Pixmap; it is the responsibility
* of the caller to free the Pixmap
*/
int
dtb_cvt_file_to_pixmap(
String fileName,
Widget widget,
Pixmap *pixmapReturnPtr
)
{
#define pixmapReturn (*pixmapReturnPtr)
Pixmap pixmap = 0;
Screen *screen = NULL;
Pixel fgPixel = 0;
Pixel bgPixel = 0;
char *image_path = new char[MAXPATHLEN+1];
Boolean pixmap_found = FALSE;
/*
* Get default values
*/
screen = XtScreen(widget);
fgPixel = WhitePixelOfScreen(screen);
bgPixel = BlackPixelOfScreen(screen);
/*
* Get proper colors for widget
*/
XtVaGetValues(widget,
XmNforeground, &fgPixel,
XmNbackground, &bgPixel,
NULL);
/*
* In CDE, XmGetPixmap handles .xpm files, as well.
*/
if (!pixmap_found)
{
pixmap = XmGetPixmap(screen, fileName, fgPixel, bgPixel);
}
pixmap_found = ((pixmap != 0) && (pixmap != XmUNSPECIFIED_PIXMAP));
if (!pixmap_found)
{
sprintf(image_path, "%s/%s", dtb_get_exe_dir(), fileName);
pixmap = XmGetPixmap(screen, image_path, fgPixel, bgPixel);
}
pixmap_found = ((pixmap != 0) && (pixmap != XmUNSPECIFIED_PIXMAP));
if (!pixmap_found)
{
sprintf(image_path, "%s/bitmaps/%s", dtb_get_exe_dir(), fileName);
pixmap = XmGetPixmap(screen, image_path, fgPixel, bgPixel);
}
pixmap_found = ((pixmap != 0) && (pixmap != XmUNSPECIFIED_PIXMAP));
if (!pixmap_found)
{
delete [] image_path;
return -1;
}
pixmapReturn = pixmap;
pixmapReturn = pixmap;
delete [] image_path;
return 0;
#undef pixmapReturn
}
/*
* Sets both the sensitive and insensitive pixmaps
*/
int
dtb_set_label_from_bitmap_data(
Widget widget,
int width,
int height,
unsigned char *bitmapData
)
{
Display *display = NULL;
Screen *screen = NULL;
Drawable window = 0;
long bgPixel = 0;
long fgPixel = 0;
unsigned int depth = 0;
Pixmap labelPixmap = 0;
if ( (widget == NULL)
|| (width < 1)
|| (height < 1)
|| (bitmapData == NULL) )
{
return -1;
}
/*
* Get a whole slew of information X needs
*/
{
Pixel widgetBg = 0;
Pixel widgetFg = 0;
int widgetDepth = 0;
display = XtDisplay(widget);
screen = XtScreen(widget);
window = XtWindow(widget);
if (window == 0)
{
/* Widget has not been realized, yet */
window = RootWindowOfScreen(screen);
}
XtVaGetValues(widget,
XmNbackground, &widgetBg,
XmNforeground, &widgetFg,
XmNdepth, &widgetDepth,
NULL);
bgPixel = widgetBg;
fgPixel = widgetFg;
depth = widgetDepth;
}
/*
* Create the pixmap
*/
labelPixmap = XCreatePixmapFromBitmapData(
display,
window,
(char *) bitmapData,
width, height,
fgPixel, bgPixel,
depth);
if (labelPixmap == 0)
{
return -1;
}
dtb_set_label_pixmaps(widget, labelPixmap, 0);
return 0;
}
/*
* Sets the label and insensitive label pixmaps of the widget.
*
* If either (or both) pixmap is NULL, it is ignored.
*/
int
dtb_set_label_pixmaps(
Widget widget,
Pixmap labelPixmap,
Pixmap labelInsensitivePixmap
)
{
if ( (widget == NULL)
|| ((labelPixmap == 0) && (labelInsensitivePixmap == 0)) )
{
return -1;
}
/*
* Set the appropriate resources.
*/
XtVaSetValues(widget, XmNlabelType, XmPIXMAP, NULL);
if (labelPixmap != 0)
{
XtVaSetValues(widget, XmNlabelPixmap, labelPixmap, NULL);
}
if (labelInsensitivePixmap != 0)
{
XtVaSetValues(widget, XmNlabelInsensitivePixmap,
labelInsensitivePixmap, NULL);
}
return 0;
}
/*
* Returns TRUE if the fileName has the extension
*/
Boolean
dtb_file_has_extension(
String fileName,
String extension
)
{
Boolean hasExt = FALSE;
if (extension == NULL)
{
hasExt = ( (fileName == NULL) || (strlen(fileName) == 0) );
}
else
{
if (fileName == NULL)
hasExt = FALSE;
else
{
char *dotPtr= strrchr(fileName, '.');
if (dotPtr == NULL)
hasExt= FALSE;
else if (strcmp(dotPtr+1, extension) == 0)
hasExt = TRUE;
}
}
return hasExt;
}
/*
* Appends the extension to fileBase and attempts to load in
* the Pixmap
*/
int
dtb_cvt_filebase_to_pixmap(
Widget widget,
String fileBase,
String extension,
Pixmap *pixmap_ptr
)
{
char *fileName = new char[512];
int rc = 0;
strcpy(fileName, fileBase);
strcat(fileName, extension);
rc = dtb_cvt_file_to_pixmap(fileName, widget, pixmap_ptr);
delete [] fileName;
return rc;
}
int
dtb_cvt_image_file_to_pixmap(
Widget widget,
String fileName,
Pixmap *pixmap
)
{
int rc = 0; /* return code */
Pixmap tmpPixmap = 0;
int depth;
if (dtb_file_has_extension(fileName, "pm") ||
dtb_file_has_extension(fileName, "xpm") ||
dtb_file_has_extension(fileName, "bm") ||
dtb_file_has_extension(fileName, "xbm"))
{
/* If explicit filename requested, use it directly */
rc = dtb_cvt_file_to_pixmap(fileName, widget, &tmpPixmap);
}
else /* Append extensions to locate best graphic match */
{
XtVaGetValues(widget, XmNdepth, &depth, NULL);
if (depth > 1) /* Look for Color Graphics First */
{
rc = dtb_cvt_filebase_to_pixmap(widget, fileName, ".pm", &tmpPixmap);
if (rc < 0)
rc = dtb_cvt_filebase_to_pixmap(widget, fileName, ".xpm", &tmpPixmap);
if (rc < 0)
rc = dtb_cvt_filebase_to_pixmap(widget, fileName, ".bm", &tmpPixmap);
if (rc < 0)
rc = dtb_cvt_filebase_to_pixmap(widget, fileName, ".xbm", &tmpPixmap);
}
else /* Look for Monochrome First */
{
rc = dtb_cvt_filebase_to_pixmap(widget, fileName, ".bm", &tmpPixmap);
if (rc < 0)
rc = dtb_cvt_filebase_to_pixmap(widget, fileName, ".xbm", &tmpPixmap);
if (rc < 0)
rc = dtb_cvt_filebase_to_pixmap(widget, fileName, ".pm", &tmpPixmap);
if (rc < 0)
rc = dtb_cvt_filebase_to_pixmap(widget, fileName, ".xpm", &tmpPixmap);
}
}
if (rc < 0)
{
fprintf(stderr,"dtb_cvt_image_file_to_pixmap: %s :unable to load %s\n",
XtName(widget), fileName);
*pixmap = 0;
return -1;
}
*pixmap = tmpPixmap;
return 0;
}
/*
* Sets the XmNlabel from the image file (either xbitmap or xpixmap format).
*
* returns negative on error.
*/
int
dtb_set_label_from_image_file(
Widget widget,
String fileName
)
{
int rc = 0; /* return code */
Pixmap labelPixmap = 0;
Pixmap insensitivePixmap = 0;
rc = dtb_cvt_image_file_to_pixmap(widget, fileName, &labelPixmap);
if (rc < 0)
{
fprintf(stderr,"dtb_set_label_from_image_file: %s :unable to load %s\n",
XtName(widget), fileName);
return -1;
}
insensitivePixmap = dtb_create_greyed_pixmap(widget,labelPixmap);
rc = dtb_set_label_pixmaps(widget, labelPixmap, insensitivePixmap);
return 0;
}
unsigned long
dtb_cvt_resource_from_string(
Widget parent,
String res_type,
unsigned int size_of_type,
String res_str_value,
unsigned long error_value
)
{
unsigned long cvt_value_return = error_value;
unsigned char cvt_value1 = 0;
unsigned short cvt_value2 = 0;
unsigned int cvt_value3 = 0;
unsigned long cvt_value4 = 0;
XtPointer cvt_value_ptr = NULL;
int which_cvt_value = -1;
XrmValue source;
XrmValue dest;
if (size_of_type > sizeof(cvt_value_return))
{
/* Type we are converting to is too large */
return cvt_value_return;
}
/*
* Get a data object of the appropriate size
*/
if (size_of_type == sizeof(cvt_value1))
{
which_cvt_value = 1;
cvt_value_ptr = (XtPointer)&cvt_value1;
}
else if (size_of_type == sizeof(cvt_value2))
{
which_cvt_value = 2;
cvt_value_ptr = (XtPointer)&cvt_value2;
}
else if (size_of_type == sizeof(cvt_value3))
{
which_cvt_value = 3;
cvt_value_ptr = (XtPointer)&cvt_value3;
}
else if (size_of_type == sizeof(cvt_value4))
{
which_cvt_value = 4;
cvt_value_ptr = (XtPointer)&cvt_value4;
}
else
{
return cvt_value_return;
}
/*
* Actually do the conversion
*/
source.size = strlen(res_str_value) + 1;
source.addr = res_str_value;
dest.size = size_of_type;
dest.addr = (char *)cvt_value_ptr;
if (XtConvertAndStore(parent, XtRString, &source,
res_type, &dest) != 0)
{
switch (which_cvt_value)
{
case 1:
cvt_value_return = (unsigned long)cvt_value1;
break;
case 2:
cvt_value_return = (unsigned long)cvt_value2;
break;
case 3:
cvt_value_return = (unsigned long)cvt_value3;
break;
case 4:
cvt_value_return = (unsigned long)cvt_value4;
break;
}
}
return cvt_value_return;
}
/*
* For a given pixmap, create a 50% greyed version. Most likely this will
* be used where the source pixmap is the labelPixmap for a widget and an
* insensitivePixmap is needed so the widget will look right when it is
* "not sensitive" ("greyed out" or "inactive").
*
* NOTE: This routine creates a Pixmap, which is an X server resource. The
* created pixmap must be freed by the caller when it is no longer
* needed.
*/
Pixmap
dtb_create_greyed_pixmap(
Widget widget,
Pixmap pixmap
)
{
Display *dpy;
Window root;
Pixmap insensitive_pixmap;
Pixel background;
unsigned int width, height, depth, bw;
int x,y;
XGCValues gcv;
XtGCMask gcm;
GC gc;
dpy = XtDisplay(widget);
if(pixmap == XmUNSPECIFIED_PIXMAP || pixmap == (Pixmap)NULL) {
fprintf(stderr,"dtb_create_greyed_pixmap: Invalid source pixmap\n");
return((Pixmap)NULL);
}
XtVaGetValues(widget,
XmNbackground, &background,
NULL);
/* Get width/height of source pixmap */
if (!XGetGeometry(dpy,pixmap,&root,&x,&y,&width,&height,&bw,&depth)) {
fprintf(stderr,"dtb_create_greyed_pixmap: Invalid source pixmap\n");
return((Pixmap)NULL);
}
gcv.foreground = background;
gcv.fill_style = FillStippled;
gcv.stipple = XmGetPixmapByDepth(XtScreen(widget),
"50_foreground", 1, 0, 1);
gcm = GCForeground | GCFillStyle | GCStipple;
gc = XtGetGC(widget, gcm, &gcv);
/* Create insensitive pixmap */
insensitive_pixmap = XCreatePixmap(dpy, pixmap, width, height, depth);
XCopyArea(dpy, pixmap, insensitive_pixmap, gc, 0, 0, width, height, 0, 0);
XFillRectangle(dpy, insensitive_pixmap, gc, 0, 0, width, height);
XtReleaseGC(widget, gc);
return(insensitive_pixmap);
}
/*
** Routines to save and access the toplevel widget for an application.
** This is useful in dtb_ convenience functions, and also probably by
** developers in routines they provide in their _stubs.c files.
** static Widget dtb_project_toplevel_widget = (Widget) NULL;
*/
void
dtb_save_toplevel_widget(
Widget toplevel
)
{
dtb_project_toplevel_widget = toplevel;
}
Widget
dtb_get_toplevel_widget()
{
return(dtb_project_toplevel_widget);
}
/*
** Routines to save and access the command used to invoke the application.
*/
void
dtb_save_command(
char *argv0
)
{
char exe_dir[MAXPATHLEN+1];
dtb_save_command_str = argv0;
/*
* Save the path to the executable
*/
if (determine_exe_dir(argv0, exe_dir, MAXPATHLEN+1) >= 0)
{
dtb_exe_dir = (char *)malloc(strlen(exe_dir)+1);
if (dtb_exe_dir != NULL)
{
strcpy(dtb_exe_dir, exe_dir);
}
}
}
char *
dtb_get_command()
{
return(dtb_save_command_str);
}
#ifdef DEAD_WOOD
/*
** Generic callback function to be attached as XmNhelpCallback and
** provide support for on-object and Help-key help. The help text to
** be displayed is provided via a specialized data structure passed in
** as client data.
*/
void
dtb_help_dispatch(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
DtbObjectHelpData help_data = (DtbObjectHelpData)clientData;
int i;
Arg wargs[10];
char *buffer = new char[100];
Widget back_button;
static Widget Quick_help_dialog = (Widget)NULL;
static Widget MoreButton;
/*
** In order to save the more-help info (help volume & location ID) as part
** of the quick help dialog's backtrack mechanism, we have to splice the
** volume & ID strings together and save them as the help volume field.
** If there isn't supplemental help information, we save a null string.
**
** Checking the status of the more-help info also lets us decide whether
** the "More..." button should be enabled on the dialog.
*/
if( help_data->help_volume ==0 || *(help_data->help_volume) == NULL ||
help_data->help_locationID ==0 || *(help_data->help_locationID)== NULL){
buffer[0] = '\0';
}
else {
sprintf(buffer,"%s/%s",help_data->help_volume,help_data->help_locationID);
}
/*
** If this is our first time to post help, create the proper dialog and
** set its attributes to suit the current object. If not, then just
** update the attributes.
**
** (You have to be careful about gratuitous SetValues on the dialog because
** its internal stack mechanism takes repeated settings as separate items
** and updates the stack for each.)
*/
if(Quick_help_dialog == (Widget)NULL) {
/* Create shared help dialog */
i = 0;
XtSetArg(wargs[i],XmNtitle, "Application Help"); i++;
XtSetArg(wargs[i],DtNhelpType, DtHELP_TYPE_DYNAMIC_STRING); i++;
XtSetArg(wargs[i],DtNstringData,help_data->help_text); i++;
XtSetArg(wargs[i],DtNhelpVolume,buffer); i++;
Quick_help_dialog = DtCreateHelpQuickDialog(dtb_get_toplevel_widget(),
"Help",wargs,i);
/*
** Fetch out the Dialog's More button child and hook the 'more help'
** handler to its activateCallback. Set it's current status to
** indicate whether this object has supplemental help data.
*/
MoreButton = DtHelpQuickDialogGetChild(Quick_help_dialog,
DtHELP_QUICK_MORE_BUTTON);
XtManageChild(MoreButton);
XtAddCallback(MoreButton,XmNactivateCallback,dtb_more_help_dispatch,
(XtPointer)Quick_help_dialog);
if(buffer[0] == '\0') XtSetSensitive(MoreButton,False);
/*
** Fetch out the Dialog's Backtrack button child & hook a callback
** that will control button sensitivity based on the presence of more
** help data.
*/
back_button = DtHelpQuickDialogGetChild(Quick_help_dialog,
DtHELP_QUICK_BACK_BUTTON);
XtAddCallback(back_button,XmNactivateCallback,dtb_help_back_hdlr,
(XtPointer)Quick_help_dialog);
}
/* Otherwise the dialog already exists so we just set the attributes. */
else {
/*
** If we have supplemental help info, enable the more button.
** Also save this info for later use in the backtrack handler.
*/
if(buffer[0] == '\0') {
XtSetSensitive(MoreButton,False);
}
else {
XtSetSensitive(MoreButton,True);
}
XtVaSetValues(Quick_help_dialog,
DtNhelpType, DtHELP_TYPE_DYNAMIC_STRING,
DtNhelpVolume,buffer,
DtNstringData,help_data->help_text,
NULL);
}
/* Now display the help dialog */
XtManageChild(Quick_help_dialog);
delete [] buffer;
}
#endif /* DEAD_WOOD */
/*
** This callback is invoked when the user presses "More..." on the
** QuickHelpDialog. It figures out whether a help volume entry is associated
** with the displayed help text, and if so it brings up a GeneralHelpDialog
** to display the appropriate help volume information.
*/
void
dtb_more_help_dispatch(
Widget,
XtPointer clientData,
XtPointer
)
{
int i;
Arg wargs[10];
String buffer, vol, loc;
char *cp;
static Widget GeneralHelpDialog = (Widget) NULL;
Widget help_dialog = (Widget)clientData;
/* Fetch the saved volume/locationID information from the dialog widget */
XtVaGetValues(help_dialog,
DtNhelpVolume,&buffer,
NULL);
/*
** Parse the combined volume/locationID string. If that fails there
** must be no data, so don't bother displaying the GeneralHelpDialog.
** (We shouldn't be in this callback routine if that happens, though...)
*/
if( (cp=strrchr(buffer,'/')) != (char *)NULL) {
*cp++ = 0;
vol = buffer;
loc = cp;
}
if(GeneralHelpDialog == (Widget)NULL) {
/* Create General Help Dialog */
i = 0;
XtSetArg(wargs[i],XmNtitle, "Application Help"); i++;
XtSetArg(wargs[i],DtNhelpType, DtHELP_TYPE_TOPIC); i++;
XtSetArg(wargs[i],DtNhelpVolume, vol); i++;
XtSetArg(wargs[i],DtNlocationId,loc); i++;
GeneralHelpDialog = DtCreateHelpDialog(dtb_get_toplevel_widget(),
"GeneralHelp",wargs,i);
}
else {
i = 0;
XtSetArg(wargs[i],DtNhelpType, DtHELP_TYPE_TOPIC); i++;
XtSetArg(wargs[i],DtNhelpVolume,vol); i++;
XtSetArg(wargs[i],DtNlocationId,loc); i++;
XtSetValues(GeneralHelpDialog,wargs,i);
}
/* Now take down the quick help dialog and display the full help one */
XtManageChild(GeneralHelpDialog);
XtUnmanageChild(help_dialog);
}
/*
** Callback that is added to the QuickHelpDialog widget's "Backtrack" button
** and is used to control the "More.." button. At each step in the backtrack,
** this routine checks to see if there is help volume & location info stored
** in the dialog's helpVolume resource. If so, then the "More..." button is
** enabled. If not, then it is disabled.
*/
void
dtb_help_back_hdlr(
Widget,
XtPointer clientData,
XtPointer
)
{
String buffer, text;
char *cp;
Widget more_button;
Widget help_dialog = (Widget)clientData;
/* Fetch the saved volume/locationID information from the dialog widget */
XtVaGetValues(help_dialog,
DtNhelpVolume,&buffer,
DtNstringData,&text,
NULL);
/* Get a handle to the "More..." button */
more_button = DtHelpQuickDialogGetChild(help_dialog,
DtHELP_QUICK_MORE_BUTTON);
/*
** Parse the combined volume/locationID string. Disable the "More..."
** button if there isn't any help info, and enable it if there is.
*/
if( buffer == 0 || (*buffer == '\0') ||
(cp=strrchr(buffer,'/')) == (char *)NULL) {
XtSetSensitive(more_button,False);
}
else {
XtSetSensitive(more_button,True);
}
}
#ifdef DEAD_WOOD
/*
** Utility function used to provide support for on-item help.
** It is typically invoked via a callback on the "On Item" item in the
** main menubar's "Help" menu.
*/
void
dtb_do_onitem_help()
{
Widget target;
/* Call the DtHelp routine that supports interactive on-item help. */
if(DtHelpReturnSelectedWidgetId(dtb_get_toplevel_widget(),
(Cursor)NULL,&target) != DtHELP_SELECT_VALID) return;
/*
** Starting at the target widget, wander up the widget tree looking
** for one that has an XmNhelpCallback, and call the first one we
** find.
*/
while(target != (Widget)NULL) {
if( XtHasCallbacks(target,XmNhelpCallback) == XtCallbackHasSome) {
XtCallCallbacks(target,XmNhelpCallback,(XtPointer)NULL);
return;
}
else {
target = XtParent(target);
}
}
return;
}
#endif /* DEAD_WOOD */
/*
** Utility function called to display help volume information.
** It needs the name of the help volume and the location ID (both as
** strings) so it can configure the full help dialog widget properly.
*/
int
dtb_show_help_volume_info(
char *volume_name,
char *location_id
)
{
int i;
Arg wargs[10];
static Widget GeneralHelpDialog = (Widget) NULL;
if(GeneralHelpDialog == (Widget)NULL) {
/* Create General Help Dialog */
i = 0;
XtSetArg(wargs[i],XmNtitle, "Application Help"); i++;
XtSetArg(wargs[i],DtNhelpType, DtHELP_TYPE_TOPIC); i++;
XtSetArg(wargs[i],DtNhelpVolume, volume_name); i++;
XtSetArg(wargs[i],DtNlocationId,location_id); i++;
GeneralHelpDialog = DtCreateHelpDialog(dtb_get_toplevel_widget(),
"GeneralHelp",wargs,i);
}
else {
i = 0;
XtSetArg(wargs[i],DtNhelpType, DtHELP_TYPE_TOPIC); i++;
XtSetArg(wargs[i],DtNhelpVolume,volume_name); i++;
XtSetArg(wargs[i],DtNlocationId,location_id); i++;
XtSetValues(GeneralHelpDialog,wargs,i);
}
/* Now display the full help dialog */
XtManageChild(GeneralHelpDialog);
return(0);
}
#ifdef DEAD_WOOD
/*
** dtb_call_help_callback()
** Utility routine to call the help callbacks on a target widget. This
** is predominantly used to display help data on a dialog by having this
** function as the activate callback on the dialog's help button.
*/
void
dtb_call_help_callback(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
Widget target = (Widget)clientData;
XtCallCallbacks(target,XmNhelpCallback,(XtPointer)NULL);
}
#endif /* DEAD_WOOD */
/*
* dtb_session_save()
* Callback that is called when the application (top level
* widget of application) gets a WM_SAVE_YOURSELF ClientMessage
* This callback will call the client/application's session
* save callback.
*/
void
dtb_session_save(
Widget widget,
XtPointer,
XtPointer
)
{
int new_argc,
client_argc = 0,
new_argc_counter,
i;
char **new_argv,
**client_argv = NULL,
*session_file_path,
*session_file_name,
*app_name = NULL;
Boolean status = False;
DtbClientSessionSaveCB session_saveCB;
/*
* Return if no widget passed in.
*/
if (!widget)
return;
/*
* Get session file path/name to store application's state
*/
if (DtSessionSavePath(widget, &session_file_path, &session_file_name) == False)
return;
/*
* Get client session save callback
*/
session_saveCB = dtb_get_client_session_saveCB();
/*
* Call client session save callback
*/
if (session_saveCB)
/*
* client_argv and client_argc are the variables that
* will contain any extra command line options
* that need to be used when invoking the application
* to bring it to the current state.
*/
status = session_saveCB(widget, session_file_path,
&client_argv, &client_argc);
/*
* Generate the reinvoking command and add it as the property value
*/
/*
* Fetch command used to invoke application
*/
app_name = dtb_get_command();
/*
* new_argc and new_argc are the variables used to reconstruct
* the command to re-invoke the application
*/
/*
* Start new_argc with:
* 1 for argv[0], normally the application
* client_argc any extra command line options as
* returned from client session save
* callback
*/
new_argc = 1 + client_argc;
/*
* If the status returned from session save callback is 'True',
* the session file was actually used. This means we need to
* add:
* -session <session file name>
* to the command saved, which is 2 more strings.
*/
if (status)
new_argc += 2;
/*
* Allocate vector
*/
new_argv = (char **)XtMalloc((sizeof(char **) * new_argc));
/*
* Set new_argv[0] to be the application name
*/
new_argc_counter = 0;
new_argv[new_argc_counter] = app_name;
new_argc_counter++;
/*
* Proceed to copy every command line option from
* client_argv. Skip -session, if found.
*/
for (i=0; i < client_argc;)
{
if (strcmp(client_argv[i], "-session"))
{
new_argv[new_argc_counter] = client_argv[i];
new_argc_counter++;
}
else
{
/*
* Skip "-session"
* The next increment below will skip the session file.
*/
++i;
}
++i;
}
/*
* If session file used, add
* -session <session file name>
*/
if (status)
{
new_argv[new_argc_counter] = "-session";
new_argc_counter++;
new_argv[new_argc_counter] = session_file_name;
}
else
{
/*
* otherwise, destroy session file
*/
(void)unlink(session_file_path);
}
/*
* Set WM_COMMAND property with vector constructed
*/
XSetCommand(XtDisplay(widget), XtWindow(widget),
new_argv, new_argc);
/*
* Free argument vector
*/
XtFree ((char *)new_argv);
/*
* CDE Sessioning API states that the path/name
* strings have to be free'd by the application.
*/
XtFree ((char *)session_file_path);
XtFree ((char *)session_file_name);
}
/*
* dtb_get_client_session_saveCB()
*/
DtbClientSessionSaveCB
dtb_get_client_session_saveCB()
{
return(dtb_client_session_saveCB);
}
#ifdef DEAD_WOOD
/*
* This function will center all the passed form's children.
* The type of centering depends on what 'type' is.
*/
void
dtb_children_center(
Widget form,
DTB_CENTERING_TYPES type
)
{
WidgetList children_list;
int i,
num_children;
if (!form || (type == DTB_CENTER_NONE))
return;
/*
* Get children list
*/
XtVaGetValues(form,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
/*
* Center all children
*/
for (i=0; i < num_children; ++i)
{
dtb_center(children_list[i], type);
}
}
/*
* This function 'uncenters' the children of the passed
* form widget.
*/
void
dtb_children_uncenter(
Widget form,
DTB_CENTERING_TYPES type
)
{
WidgetList children_list;
int i;
int num_children;
if (!form || (type == DTB_CENTER_NONE))
return;
/*
* Get children list
*/
XtVaGetValues(form,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
/*
* Center all children
*/
for (i=0; i < num_children; ++i)
{
dtb_uncenter(children_list[i], type);
}
}
#endif /* DEAD_WOOD */
/*
* This function centers the passed widget.
* This is done by setting the proper offsets.
* Dynamic centering is accomplished by attaching an event handler
* which detect resizes and recomputes and sets the appropriate offset.
*/
void
dtb_center(
Widget form_child,
DTB_CENTERING_TYPES type
)
{
if (!form_child || (type == DTB_CENTER_NONE))
return;
center_widget(form_child, type);
XtAddEventHandler(form_child,
StructureNotifyMask, False,
centering_handler, (XtPointer)type);
}
/*
* This function 'uncenters' the passed widget.
* This involves resetting the attachment offsets
* and removing the resize event handler.
*/
void
dtb_uncenter(
Widget form_child,
DTB_CENTERING_TYPES type
)
{
if (!form_child || (type == DTB_CENTER_NONE))
return;
uncenter_widget(form_child, type);
XtRemoveEventHandler(form_child,
StructureNotifyMask, False,
centering_handler, (XtPointer)type);
}
/*
* This function centers the passed widget.
* This is done by making the appropriate offset equal
* to the negative half of it's width/height (depending
* on whether horizontal or vertical centering was chosen.
*/
static void
center_widget(
Widget form_child,
DTB_CENTERING_TYPES type
)
{
Widget parent;
Dimension width = 0,
height = 0;
int center_offset;
unsigned char left_attach = XmATTACH_NONE,
top_attach = XmATTACH_NONE;
if (!form_child || !XtIsManaged(form_child) || !XtIsRealized(form_child))
return;
parent = XtParent(form_child);
if (!parent || !XtIsSubclass(parent, xmFormWidgetClass))
return;
XtVaGetValues(form_child,
XmNwidth, &width,
XmNheight, &height,
XmNleftAttachment, &left_attach,
XmNtopAttachment, &top_attach,
NULL);
switch (type) {
case DTB_CENTER_POSITION_VERT:
if (left_attach != XmATTACH_POSITION)
return;
center_offset = -(width/2);
XtVaSetValues(form_child,
XmNleftOffset, center_offset,
NULL);
break;
case DTB_CENTER_POSITION_HORIZ:
if (top_attach != XmATTACH_POSITION)
return;
center_offset = -(height/2);
XtVaSetValues(form_child,
XmNtopOffset, center_offset,
NULL);
break;
case DTB_CENTER_POSITION_BOTH:
{
int left_offset,
top_offset;
if ((left_attach != XmATTACH_POSITION) &&
(top_attach != XmATTACH_POSITION))
return;
left_offset = -(width/2);
top_offset = -(height/2);
XtVaSetValues(form_child,
XmNleftOffset, left_offset,
XmNtopOffset, top_offset,
NULL);
}
break;
default:
break;
}
}
/*
* This function 'uncenters' the passed widget.
* It merely resets the offsets of the top/left attachments to 0.
*/
static void
uncenter_widget(
Widget form_child,
DTB_CENTERING_TYPES type
)
{
Widget parent;
unsigned char left_attach = XmATTACH_NONE,
top_attach = XmATTACH_NONE;
if (!form_child || !XtIsManaged(form_child) || !XtIsRealized(form_child))
return;
parent = XtParent(form_child);
if (!parent || !XtIsSubclass(parent, xmFormWidgetClass))
return;
XtVaGetValues(form_child,
XmNleftAttachment, &left_attach,
XmNtopAttachment, &top_attach,
NULL);
switch (type) {
case DTB_CENTER_POSITION_VERT:
if (left_attach != XmATTACH_POSITION)
return;
XtVaSetValues(form_child,
XmNleftOffset, 0,
NULL);
break;
case DTB_CENTER_POSITION_HORIZ:
if (top_attach != XmATTACH_POSITION)
return;
XtVaSetValues(form_child,
XmNtopOffset, 0,
NULL);
break;
case DTB_CENTER_POSITION_BOTH:
if ((left_attach != XmATTACH_POSITION) &&
(top_attach != XmATTACH_POSITION))
return;
XtVaSetValues(form_child,
XmNleftOffset, 0,
XmNtopOffset, 0,
NULL);
break;
default:
break;
}
}
/*
* Event handler to center a widget
* The type of centering needed is passed in as client_data
*/
static void
centering_handler(
Widget widget,
XtPointer client_data,
XEvent *event,
Boolean *
)
{
XConfigureEvent *xcon = &event->xconfigure;
Widget resized_child;
DTB_CENTERING_TYPES type = (DTB_CENTERING_TYPES)((long)client_data);
if ((event->type != ConfigureNotify) && (event->type != MapNotify))
return;
resized_child = XtWindowToWidget(XtDisplay(widget), xcon->window);
if (!resized_child)
return;
center_widget(resized_child, type);
}
/*
* Given a widget, return it's label widget.
*/
static Widget
get_label_widget(
Widget widget
)
{
WidgetList children_list;
Widget label_widget = NULL;
int num_children = 0;
char *subobj_name = NULL,
*label_name = NULL;
if (XtIsSubclass(widget, xmLabelWidgetClass)) {
return(widget);
}
subobj_name = XtName(widget);
label_name = (char *)XtMalloc(1 + strlen(subobj_name) + strlen("_label") + 1);
sprintf(label_name, "*%s_label", subobj_name);
label_widget = XtNameToWidget(widget, label_name);
XtFree((char *)label_name);
if (label_widget)
return(label_widget);
/*
* How to look for 1st child of group object ??
* How do we know if 'widget' is a group object ??
* For now, just check if it is a form
*/
if (XtIsSubclass(widget, xmFormWidgetClass) ||
XtIsSubclass(widget, xmFrameWidgetClass))
XtVaGetValues(widget,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children > 0)
return(get_label_widget(children_list[0]));
return (NULL);
}
static Position
get_offset_from_ancestor(
Widget ancestor,
Widget w
)
{
Widget cur = w;
Widget cur_parent = NULL;
Position offset = 0;
if (!ancestor || !w || (w == ancestor))
return (0);
XtVaGetValues(cur, XmNx, &offset, NULL);
cur_parent = XtParent(cur);
while (cur_parent != ancestor)
{
Position tmp_offset = 0;
cur = cur_parent;
XtVaGetValues(cur, XmNx, &tmp_offset, NULL);
offset += tmp_offset;
cur_parent = XtParent(cur);
}
return (offset);
}
static Dimension
get_label_width(
Widget widget
)
{
Widget lbl_widget = NULL;
Dimension lbl_width = 0;
lbl_widget = get_label_widget(widget);
if (lbl_widget)
{
Position offset = 0;
XtVaGetValues(lbl_widget,
XmNwidth, &lbl_width,
NULL);
offset = get_offset_from_ancestor(widget, lbl_widget);
lbl_width += (Dimension)offset;
}
return (lbl_width);
}
static void
get_widest_label(
WidgetList list,
int count,
Widget *child_widget,
Dimension *label_width
)
{
Widget cur_widest = NULL;
Dimension cur_width = 0;
int i;
for (i = 0; i < count; ++i)
{
Dimension tmp;
tmp = get_label_width(list[i]);
if (tmp > cur_width)
{
cur_width = tmp;
cur_widest = list[i];
}
}
*child_widget = cur_widest;
*label_width = cur_width;
}
static void
get_widest_value(
WidgetList list,
int count,
Widget *child_widget,
Dimension *value_width
)
{
Widget cur_widest = NULL;
Dimension cur_width = 0;
int i;
for (i = 0; i < count; ++i)
{
Dimension tmp, label_width, obj_width = 0;
label_width = get_label_width(list[i]);
XtVaGetValues(list[i], XmNwidth, &obj_width, NULL);
tmp = obj_width - label_width;
if (tmp > cur_width)
{
cur_width = tmp;
cur_widest = list[i];
}
}
*child_widget = cur_widest;
*value_width = cur_width;
}
static void
get_widget_rect(
Widget widget,
XRectangle *rect
)
{
if (!rect)
return;
XtVaGetValues(widget,
XtNwidth, (XtArgVal)&(rect->width),
XtNheight, (XtArgVal)&(rect->height),
XtNx, (XtArgVal)&(rect->x),
XtNy, (XtArgVal)&(rect->y),
NULL);
}
static void
get_greatest_size(
Widget *list,
int count,
int *width,
int *height,
Widget *tallest,
Widget *widest
)
{
XRectangle w_rect;
int i;
int previous_width, previous_height;
if (!list || (count < 0))
return;
get_widget_rect(list[0], &w_rect);
*width = w_rect.width;
previous_width = *width;
*height = w_rect.height;
previous_height = *height;
if (tallest != NULL)
*tallest = list[0];
if (widest != NULL)
*widest = list[0];
for (i=0; i < count; i++)
{
get_widget_rect(list[i], &w_rect);
*width = max((int) w_rect.width, (int) *width);
if (widest != NULL && *width > previous_width)
*widest = list[i];
*height = max((int) w_rect.height, (int)*height);
if (tallest != NULL && *height > previous_height)
*tallest = list[i];
}
}
static void
get_group_cell_size(
Widget parent,
DtbGroupInfo *,
int *cell_width,
int *cell_height
)
{
WidgetList children_list = NULL;
int num_children = 0;
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
get_greatest_size(children_list, num_children,
cell_width, cell_height,
(Widget *)NULL, (Widget *)NULL);
}
static void
get_group_row_col(
Widget parent,
DtbGroupInfo *group_info,
int *rows,
int *cols
)
{
WidgetList children_list = NULL;
int num_rows,
num_cols,
num_children;
if (!parent || !group_info)
{
*rows = *cols = -1;
return;
}
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
num_rows = group_info->num_rows;
num_cols = group_info->num_cols;
if ((num_rows <= 0) && (num_cols <= 0))
{
*rows = *cols = -1;
return;
}
if (num_cols <= 0)
num_cols = (num_children/num_rows) + ((num_children % num_rows) ? 1 : 0);
if (num_rows <= 0)
num_rows = (num_children/num_cols) + ((num_children % num_cols) ? 1 : 0);
*rows = num_rows;
*cols = num_cols;
}
static Widget
get_group_child(
Widget parent,
DtbGroupInfo *group_info,
int x_pos,
int y_pos
)
{
DTB_GROUP_TYPES group_type;
WidgetList children_list = NULL;
Widget ret_child = NULL;
int num_children = 0,
num_rows,
num_columns,
i = -1;
if (!parent || !group_info ||
(x_pos < 0) || (y_pos < 0))
return (NULL);
group_type = group_info->group_type;
num_rows = group_info->num_rows;
num_columns = group_info->num_cols;
/*
* Get number of children
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return (NULL);
switch (group_type)
{
case DTB_GROUP_NONE:
break;
case DTB_GROUP_ROWS:
/*
* num_rows = 1
* y_pos is ignored
*/
i = x_pos;
break;
case DTB_GROUP_COLUMNS:
/*
* num_columns = 1
* x_pos is ignored
*/
i = y_pos;
break;
case DTB_GROUP_ROWSCOLUMNS:
if (!num_rows && !num_columns)
break;
if (num_rows > 0)
{
/*
* ROWFIRST
*/
if (y_pos < num_rows)
i = (x_pos * num_rows) + y_pos;
}
else
{
/*
* COLFIRST
*/
if (x_pos < num_columns)
i = x_pos + (y_pos * num_columns);
}
break;
default:
break;
}
if ((i >= 0) && (i < num_children))
{
ret_child = children_list[i];
}
return (ret_child);
}
void
dtb_children_align(
Widget parent,
DTB_GROUP_TYPES group_type,
DTB_ALIGN_TYPES row_align,
DTB_ALIGN_TYPES col_align,
int margin,
int num_rows,
int num_cols,
int hoffset,
int voffset
)
{
DtbGroupInfo *group_info;
switch (group_type)
{
case DTB_GROUP_COLUMNS:
num_rows = 0;
num_cols = 1;
break;
case DTB_GROUP_ROWS:
num_rows = 1;
num_cols = 0;
break;
}
#ifdef DTB_GROUP_USERDATA
XtVaGetValues(parent, XmNuserData, (XtPointer)&group_info, NULL);
if (group_info)
{
XtRemoveEventHandler(parent,
SubstructureNotifyMask, False,
align_handler, (XtPointer)group_info);
XtRemoveCallback(parent, XtNdestroyCallback,
free_group_info, (XtPointer)group_info);
XtFree((char *)group_info);
}
#endif
group_info = (DtbGroupInfo *)XtMalloc(sizeof(DtbGroupInfo));
group_info->group_type = group_type;
group_info->row_align = row_align;
group_info->col_align = col_align;
group_info->margin = margin;
group_info->num_rows = num_rows;
group_info->num_cols = num_cols;
group_info->hoffset = hoffset;
group_info->voffset = voffset;
group_info->ref_widget = NULL;
#ifdef DTB_GROUP_USERDATA
XtVaSetValues(parent, XmNuserData, (XtPointer)group_info, NULL);
#endif
align_children(parent, group_info, True);
switch(group_info->group_type)
{
case DTB_GROUP_NONE:
break;
case DTB_GROUP_ROWS:
if (group_info->row_align == DTB_ALIGN_HCENTER)
XtAddEventHandler(parent,
SubstructureNotifyMask, False,
align_handler, (XtPointer)group_info);
break;
case DTB_GROUP_COLUMNS:
if ((group_info->col_align == DTB_ALIGN_LABELS) ||
(group_info->col_align == DTB_ALIGN_VCENTER))
XtAddEventHandler(parent,
SubstructureNotifyMask, False,
align_handler, (XtPointer)group_info);
break;
case DTB_GROUP_ROWSCOLUMNS:
if ((group_info->row_align == DTB_ALIGN_HCENTER) ||
(group_info->col_align == DTB_ALIGN_LABELS) ||
(group_info->col_align == DTB_ALIGN_VCENTER))
XtAddEventHandler(parent,
SubstructureNotifyMask, False,
align_handler, (XtPointer)group_info);
break;
}
XtAddCallback(parent, XtNdestroyCallback,
free_group_info, (XtPointer)group_info);
}
static void
align_children(
Widget parent,
DtbGroupInfo *group_info,
Bool init
)
{
WidgetList children_list = NULL;
int num_children = 0;
if (!parent || !group_info)
return;
if (group_info->group_type != DTB_GROUP_NONE)
{
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
XtUnmanageChildren(children_list, num_children);
}
switch(group_info->group_type)
{
case DTB_GROUP_NONE:
break;
case DTB_GROUP_ROWS:
align_rows(parent, group_info, init);
align_left(parent, group_info);
break;
case DTB_GROUP_COLUMNS:
align_cols(parent, group_info, init);
align_top(parent, group_info);
break;
case DTB_GROUP_ROWSCOLUMNS:
align_rows(parent, group_info, init);
align_cols(parent, group_info, init);
break;
}
if (group_info->group_type != DTB_GROUP_NONE)
{
XtManageChildren(children_list, num_children);
}
}
static void
align_handler(
Widget widget,
XtPointer client_data,
XEvent *event,
Boolean *
)
{
DtbGroupInfo *group_info = (DtbGroupInfo *)client_data;
WidgetList children_list;
int num_children = 0;
Boolean relayout_all = False;
/*
* Get children list
*/
XtVaGetValues(widget,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return;
XtRemoveEventHandler(widget,
SubstructureNotifyMask, False,
align_handler, (XtPointer)client_data);
if (event->type == ConfigureNotify) {
XConfigureEvent *xcon = &event->xconfigure;
Widget resized_child;
if (xcon->window != xcon->event)
{
resized_child = XtWindowToWidget(XtDisplay(widget), xcon->window);
switch(group_info->group_type)
{
case DTB_GROUP_NONE:
break;
case DTB_GROUP_ROWS:
if (group_info->row_align == DTB_ALIGN_HCENTER)
relayout_all = True;
break;
case DTB_GROUP_COLUMNS:
if ((group_info->col_align == DTB_ALIGN_LABELS) ||
(group_info->col_align == DTB_ALIGN_VCENTER))
relayout_all = True;
break;
case DTB_GROUP_ROWSCOLUMNS:
if ((group_info->row_align == DTB_ALIGN_HCENTER) ||
(group_info->col_align == DTB_ALIGN_LABELS) ||
(group_info->col_align == DTB_ALIGN_VCENTER))
relayout_all = True;
break;
}
}
}
/*
* Comment out for now
* This is causing way too many calls to align_children()
if (event->type == CreateNotify) {
XCreateWindowEvent *xcreate = &event->xcreatewindow;
Widget new_child;
new_child = XtWindowToWidget(XtDisplay(widget), xcreate->window);
fprintf(stderr, "align_handler(%s) - child %s created\n",
XtName(widget),
XtName(new_child));
relayout_all = True;
}
*/
if (event->type == DestroyNotify) {
XDestroyWindowEvent *xdestroy = &event->xdestroywindow;
Widget destroyed_child;
destroyed_child = XtWindowToWidget(XtDisplay(widget),
xdestroy->window);
relayout_all = True;
}
if (relayout_all)
{
align_children(widget, group_info, False);
}
XtAddEventHandler(widget,
SubstructureNotifyMask, False,
align_handler, (XtPointer)client_data);
}
static void
free_group_info(
Widget ,
XtPointer client_data,
XtPointer
)
{
DtbGroupInfo *group_info = (DtbGroupInfo *)client_data;;
XtFree((char *)group_info);
}
static void
align_rows(
Widget parent,
DtbGroupInfo *group_info,
Bool init
)
{
if (!parent || !group_info || (group_info->group_type == DTB_GROUP_COLUMNS))
return;
switch (group_info->row_align)
{
case DTB_ALIGN_TOP:
align_top(parent, group_info);
break;
case DTB_ALIGN_HCENTER:
align_hcenter(parent, group_info, init);
break;
case DTB_ALIGN_BOTTOM:
align_bottom(parent, group_info);
break;
default:
break;
}
}
static void
align_cols(
Widget parent,
DtbGroupInfo *group_info,
Bool init
)
{
if (!parent || !group_info || (group_info->group_type == DTB_GROUP_ROWS))
return;
switch (group_info->col_align)
{
case DTB_ALIGN_LEFT:
align_left(parent, group_info);
break;
case DTB_ALIGN_LABELS:
align_labels(parent, group_info);
break;
case DTB_ALIGN_VCENTER:
align_vcenter(parent, group_info, init);
break;
case DTB_ALIGN_RIGHT:
align_right(parent, group_info);
break;
default:
break;
}
}
static void
align_left(
Widget parent,
DtbGroupInfo *group_info
)
{
WidgetList children_list;
Widget child,
previous_child;
int num_children = 0,
num_columns,
num_rows,
cell_width,
cell_height,
i,
j;
if (!parent || !group_info)
return;
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return;
get_group_cell_size(parent, group_info, &cell_width, &cell_height);
get_group_row_col(parent, group_info, &num_rows, &num_columns);
for (j = 0; j < num_rows; j++)
{
for (i = 0; i < num_columns; i++)
{
Arg args[12];
int n = 0;
child = get_group_child(parent, group_info, i, j);
if (!child)
continue;
if ((i == 0) && (j == 0))
{
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftOffset, 0); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
continue;
}
if (j == 0)
{
int offset = group_info->hoffset;
DTB_GROUP_TYPES group_type = group_info->group_type;
previous_child = get_group_child(parent, group_info, i-1, j);
if (!previous_child)
continue;
if (group_type == DTB_GROUP_ROWSCOLUMNS)
{
Dimension width = 0;
XtVaGetValues(previous_child, XmNwidth, &width, NULL);
offset += (cell_width - (int)(width));
}
XtSetArg(args[n], XmNleftAttachment,
XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, previous_child); n++;
XtSetArg(args[n], XmNleftOffset, offset); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
continue;
}
previous_child = get_group_child(parent, group_info, i, j-1);
if (previous_child)
{
XtSetArg(args[n], XmNleftAttachment,
XmATTACH_OPPOSITE_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, previous_child); n++;
XtSetArg(args[n], XmNleftOffset, 0); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
}
}
}
}
static void
align_right(
Widget parent,
DtbGroupInfo *group_info
)
{
WidgetList children_list;
Widget child,
previous_child;
int num_children = 0,
num_columns,
num_rows,
cell_width,
cell_height,
offset,
i,
j;
if (!parent || !group_info)
return;
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return;
get_group_cell_size(parent, group_info, &cell_width, &cell_height);
get_group_row_col(parent, group_info, &num_rows, &num_columns);
for (j = 0; j < num_rows; j++)
{
for (i = 0; i < num_columns; i++)
{
Arg args[12];
int n = 0;
child = get_group_child(parent, group_info, i, j);
if (!child)
continue;
if ((i == 0) && (j == 0))
{
Dimension width = 0;
XtVaGetValues(child, XmNwidth, &width, NULL);
offset = (cell_width - width);
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftOffset, offset); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
continue;
}
if (j == 0)
{
previous_child = get_group_child(parent, group_info, i-1, j);
if (!previous_child)
continue;
offset = group_info->hoffset;
if (group_info->group_type == DTB_GROUP_ROWSCOLUMNS)
{
Dimension width = 0;
XtVaGetValues(child, XmNwidth, &width, NULL);
offset += (cell_width - width);
}
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, previous_child); n++;
XtSetArg(args[n], XmNleftOffset, offset); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
continue;
}
previous_child = get_group_child(parent, group_info, i, j-1);
if (previous_child)
{
XtSetArg(args[n], XmNrightAttachment,
XmATTACH_OPPOSITE_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, previous_child); n++;
XtSetArg(args[n], XmNrightOffset, 0); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
}
}
}
}
static void
align_labels(
Widget parent,
DtbGroupInfo *group_info
)
{
WidgetList children_list = NULL,
one_col;
Widget previous_child = NULL,
child,
previous_ref_widget = NULL;
Dimension ref_lbl_width = 0,
max_label_width = 0,
max_value_width = 0;
int num_children = 0,
num_rows,
num_columns,
cell_width,
cell_height,
offset,
i,
j;
if (!parent || !group_info)
return;
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return;
get_group_cell_size(parent, group_info, &cell_width, &cell_height);
get_widest_label(children_list, num_children, &child, &max_label_width);
get_widest_value(children_list, num_children, &child, &max_value_width);
if (cell_width < (int)(max_label_width + max_value_width))
cell_width = (int)(max_label_width + max_value_width);
get_group_row_col(parent, group_info, &num_rows, &num_columns);
if (num_rows > 0)
one_col = (WidgetList)XtMalloc(num_rows * sizeof(WidgetList));
for (i = 0; i < num_columns; i++)
{
Widget ref_widget;
Dimension ref_width;
Arg args[12];
int n = 0;
for (j = 0; j < num_rows; j++)
one_col[j] = get_group_child(parent, group_info, i, j);
get_widest_label(one_col, num_rows, &ref_widget, &ref_width);
if (!ref_widget)
continue;
if (previous_ref_widget)
offset = (i * (group_info->hoffset + cell_width));
else
offset = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftOffset, offset); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
XtSetValues(ref_widget, args, n);
for (j = 0; j < num_rows; j++)
{
child = get_group_child(parent, group_info, i, j);
if (!child || (child == ref_widget))
continue;
offset = (i * (group_info->hoffset + cell_width));
offset += (int)(ref_width - get_label_width(child));
n = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftOffset, offset); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
}
previous_ref_widget = ref_widget;
}
}
static void
align_vcenter(
Widget parent,
DtbGroupInfo *group_info,
Bool init
)
{
WidgetList children_list;
Widget child;
DTB_GROUP_TYPES group_type;
int num_children = 0,
num_columns,
num_rows,
cell_width,
cell_height,
group_width,
offset,
gridline,
i,
j;
if (!parent || !group_info)
return;
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return;
get_group_cell_size(parent, group_info, &cell_width, &cell_height);
get_group_row_col(parent, group_info, &num_rows, &num_columns);
offset = group_info->hoffset;
group_type = group_info->group_type;
if (group_type == DTB_GROUP_ROWSCOLUMNS)
{
group_width = (num_columns * cell_width) + ((num_columns-1) * offset);
}
for (i = 0; i < num_columns; i++)
{
if (group_type == DTB_GROUP_ROWSCOLUMNS)
gridline = (((i * (cell_width + offset)) + (cell_width/2)) * 100)/group_width;
else
gridline = 50;
for (j = 0; j < num_rows; j++)
{
Arg args[12];
int n = 0;
Dimension width = 0;
child = get_group_child(parent, group_info, i, j);
if (!child)
continue;
XtVaGetValues(child, XmNwidth, &width, NULL);
if (init)
{
int offset = 0;
if (!XtIsSubclass(child, compositeWidgetClass))
{
offset = (cell_width - (int)width)/2;
if (group_type == DTB_GROUP_ROWSCOLUMNS)
offset += (i * (cell_width + group_info->hoffset));
}
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftOffset, offset); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
}
else
{
XtSetArg(args[n], XmNleftAttachment,
XmATTACH_POSITION); n++;
XtSetArg(args[n], XmNleftPosition, gridline); n++;
XtSetArg(args[n], XmNleftOffset, (int)(-(width/2))); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
}
XtSetValues(child, args, n);
}
}
}
static void
align_top(
Widget parent,
DtbGroupInfo *group_info
)
{
WidgetList children_list;
Widget previous_child = NULL,
child;
int num_children = 0,
num_columns,
num_rows,
cell_width,
cell_height,
i,
j;
if (!parent || !group_info)
return;
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return;
get_group_cell_size(parent, group_info, &cell_width, &cell_height);
get_group_row_col(parent, group_info, &num_rows, &num_columns);
for (j = 0; j < num_rows; j++)
{
for (i = 0; i < num_columns; i++)
{
Arg args[12];
int n = 0;
child = get_group_child(parent, group_info, i, j);
if (!child)
continue;
if ((i == 0) && (j == 0))
{
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNtopOffset, 0); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
continue;
}
if (i == 0)
{
previous_child = get_group_child(parent, group_info, 0, j-1);
if (previous_child)
{
DTB_GROUP_TYPES group_type = group_info->group_type;
int offset = group_info->voffset;
if (group_type == DTB_GROUP_ROWSCOLUMNS)
{
Dimension height = 0;
XtVaGetValues(previous_child, XmNheight, &height, NULL);
offset += (cell_height - (int)(height));
}
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, previous_child); n++;
XtSetArg(args[n], XmNtopOffset, offset); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
}
continue;
}
previous_child = get_group_child(parent, group_info, i-1, j);
if (previous_child)
{
XtSetArg(args[n], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, previous_child); n++;
XtSetArg(args[n], XmNtopOffset, 0); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
}
}
}
}
static void
align_bottom(
Widget parent,
DtbGroupInfo *group_info
)
{
WidgetList children_list;
Widget child,
previous_child;
int num_children = 0,
num_columns,
num_rows,
cell_height,
cell_width,
offset,
i,
j;
if (!parent || !group_info)
return;
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return;
get_group_cell_size(parent, group_info, &cell_width, &cell_height);
get_group_row_col(parent, group_info, &num_rows, &num_columns);
for (j = 0; j < num_rows; j++)
{
for (i = 0; i < num_columns; i++)
{
Arg args[12];
int n = 0;
child = get_group_child(parent, group_info, i, j);
if (!child)
continue;
if ((i == 0) && (j == 0))
{
Dimension height = 0;
XtVaGetValues(child, XmNheight, &height, NULL);
offset = cell_height - height;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNtopOffset, offset); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
continue;
}
if (i == 0)
{
previous_child = get_group_child(parent, group_info, 0, j-1);
if (previous_child)
{
Dimension height = 0;
XtVaGetValues(child, XmNheight, &height, NULL);
offset = group_info->voffset;
if (group_info->group_type == DTB_GROUP_ROWSCOLUMNS)
offset += (cell_height - height);
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, previous_child); n++;
XtSetArg(args[n], XmNtopOffset, offset); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
}
continue;
}
previous_child = get_group_child(parent, group_info, i-1, j);
if (child && previous_child)
{
XtSetArg(args[n], XmNbottomAttachment,
XmATTACH_OPPOSITE_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, previous_child); n++;
XtSetArg(args[n], XmNbottomOffset, 0); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_NONE); n++;
XtSetValues(child, args, n);
}
}
}
}
static void
align_hcenter(
Widget parent,
DtbGroupInfo *group_info,
Bool init
)
{
WidgetList children_list = NULL;
Widget child;
DTB_GROUP_TYPES group_type;
int num_children = 0,
num_columns,
num_rows,
cell_width,
cell_height,
group_height,
offset,
gridline,
i,
j;
if (!parent || !group_info)
return;
/*
* Get children list
*/
XtVaGetValues(parent,
XmNnumChildren, &num_children,
XmNchildren, &children_list,
NULL);
if (num_children <= 0)
return;
group_type = group_info->group_type;
get_group_cell_size(parent, group_info, &cell_width, &cell_height);
get_group_row_col(parent, group_info, &num_rows, &num_columns);
offset = group_info->voffset;
if (group_type == DTB_GROUP_ROWSCOLUMNS)
{
group_height = (num_rows * cell_height) + ((num_rows-1) * offset);
}
for (j = 0; j < num_rows; j++)
{
if (group_type == DTB_GROUP_ROWSCOLUMNS)
gridline =
(((j * (cell_height + offset)) + (cell_height/2)) * 100)/group_height;
else
gridline = 50;
for (i = 0; i < num_columns; i++)
{
Arg args[12];
int n = 0;
Dimension height = 0;
child = get_group_child(parent, group_info, i, j);
if (!child)
continue;
XtVaGetValues(child, XmNheight, &height, NULL);
if (init)
{
int init_offset = 0;
if (!XtIsSubclass(child, compositeWidgetClass))
{
init_offset = (cell_height - (int)height)/2;
if (group_type == DTB_GROUP_ROWSCOLUMNS)
init_offset += (j * (cell_height + group_info->voffset));
}
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNtopOffset, init_offset); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
}
else
{
XtSetArg(args[n], XmNtopAttachment,
XmATTACH_POSITION); n++;
XtSetArg(args[n], XmNtopPosition, gridline); n++;
XtSetArg(args[n], XmNtopOffset, (int)(-(height/2))); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_NONE); n++;
}
XtSetValues(child, args, n);
}
}
}
/*
* Returns the directory that the executable for this process was loaded
* from.
*/
String
dtb_get_exe_dir(void)
{
return dtb_exe_dir;
}
/*
* Determines the directory the executable for this process was loaded from.
*/
static int
determine_exe_dir(
char *argv0,
char *buf,
int bufSize
)
{
Boolean foundDir= False;
if ((buf == NULL) || (bufSize < 1))
{
return -1;
}
if (determine_exe_dir_from_argv(argv0, buf, bufSize) >= 0)
{
foundDir = True;
}
if (!foundDir)
{
if (determine_exe_dir_from_path(argv0, buf, bufSize) >= 0)
{
foundDir = True;
}
}
/*
* Convert relative path to absolute, so that directory changes will
* not affect us.
*/
if (foundDir && (buf[0] != '/'))
{
char cwd[MAXPATHLEN+1];
char *env_pwd = NULL;
char *path_prefix = NULL;
if (getcwd(cwd, MAXPATHLEN+1) != NULL)
{
path_prefix = cwd;
}
else
{
env_pwd = getenv("PWD");
if (env_pwd != NULL)
{
path_prefix = env_pwd;
}
}
if (path_prefix != NULL)
{
char *abs_exe_dir = new char[MAXPATHLEN+1];
if (strcmp(buf, ".") != 0) {
snprintf(abs_exe_dir, MAXPATHLEN+1, "%s/%s", path_prefix, buf);
} else {
snprintf(abs_exe_dir, MAXPATHLEN+1, "%s", path_prefix);
}
strcpy(buf, abs_exe_dir);
delete [] abs_exe_dir;
}
}
return foundDir? 0:-1;
}
/*
* Looks for absolute path in arv[0].
*/
static int
determine_exe_dir_from_argv(
char *argv0,
char *buf,
int bufSize
)
{
int i= 0;
Boolean foundit= False;
for (i= strlen(argv0)-1; (i >= 0) && (argv0[i] != '/'); --i)
{
}
if (i >= 0)
{
int maxStringSize= min(i, bufSize);
strncpy(buf, argv0, maxStringSize);
buf[min(maxStringSize, bufSize-1)]= 0;
foundit = True;
}
return foundit? 0:-1;
}
/*
* Assumes: bufSize > 0
*/
static int
determine_exe_dir_from_path (
char *argv0,
char *buf,
int bufSize
)
{
Boolean foundDir= False;
Boolean moreDirs= True;
char *szExeName= argv0;
int iExeNameLen= strlen(szExeName);
char *szTemp= NULL;
char *szPathVar = new char[MAXPATHLEN+1];
int iPathVarLen= 0;
char *szCurrentPath = new char[MAXPATHLEN+1];
int iCurrentPathLen= 0;
int iCurrentPathStart= 0;
int i = 0;
uid_t euid= geteuid();
uid_t egid= getegid();
szTemp= getenv("PATH");
if (szTemp == NULL)
{
moreDirs= False;
}
else
{
strncpy(szPathVar, szTemp, MAXPATHLEN);
szPathVar[MAXPATHLEN]= 0;
iPathVarLen= strlen(szPathVar);
}
while ((!foundDir) && (moreDirs))
{
/* find the current directory name */
for (i= iCurrentPathStart; (i < iPathVarLen) && (szPathVar[i] != ':');
)
{
++i;
}
iCurrentPathLen= i - iCurrentPathStart;
if ((iCurrentPathLen + iExeNameLen + 2) > MAXPATHLEN)
{
iCurrentPathLen= MAXPATHLEN - (iExeNameLen + 2);
}
/* create a possible path to the executable */
strncpy(szCurrentPath, &szPathVar[iCurrentPathStart], iCurrentPathLen);
szCurrentPath[iCurrentPathLen]= 0;
strcat(szCurrentPath, "/");
strcat(szCurrentPath, szExeName);
/* see if the executable exists (and we can execute it) */
if (path_is_executable(szCurrentPath, euid, egid))
{
foundDir= True;
}
/* skip past the current directory name */
if (!foundDir)
{
iCurrentPathStart+= iCurrentPathLen;
while ( (iCurrentPathStart < iPathVarLen)
&& (szPathVar[iCurrentPathStart] != ':') )
{
++iCurrentPathStart; /* find : */
}
if (iCurrentPathStart < iPathVarLen)
{
++iCurrentPathStart; /* skip : */
}
if (iCurrentPathStart >= iPathVarLen)
{
moreDirs= False;
}
}
} /* while !foundDir */
if (foundDir)
{
szCurrentPath[iCurrentPathLen]= 0;
strncpy(buf, szCurrentPath, bufSize);
buf[bufSize-1]= 0;
}
delete [] szPathVar;
delete [] szCurrentPath;
return foundDir? 0:-1;
}
/*
* returns False is path does not exist or is not executable
*/
static Boolean
path_is_executable(
char *path,
uid_t euid,
gid_t egid
)
{
Boolean bExecutable= False;
struct stat sStat;
if (stat(path, &sStat) == 0)
{
Boolean bDetermined= False;
if (!bDetermined)
{
if (!S_ISREG(sStat.st_mode))
{
/* not a regular file */
bDetermined= True;
bExecutable= False;
}
}
if (!bDetermined)
{
if ( (euid == 0)
&& ( ((sStat.st_mode & S_IXOTH) != 0)
|| ((sStat.st_mode & S_IXGRP) != 0)
|| ((sStat.st_mode & S_IXUSR) != 0) )
)
{
bDetermined= True;
bExecutable= True;
}
}
if (!bDetermined)
{
if ( (((sStat.st_mode & S_IXOTH) != 0) )
|| (((sStat.st_mode & S_IXGRP) != 0) && (sStat.st_gid == egid))
|| (((sStat.st_mode & S_IXUSR) != 0) && (sStat.st_gid == euid))
)
{
bDetermined= True;
bExecutable= True;
}
}
} /* if stat */
return bExecutable;
}