
/* asutil.c  -  some Motif utilities used in the asedit program
		Last revision 23.02.1994
*/

/*
 * Copyright 1991 - 1994,  Andrzej Stochniol, London, UK
 *
 * ASEDIT text editor, both binary and source (hereafter, Software) is
 * copyrighted by Andrzej Stochniol (hereafter, AS) and ownership remains
 * with AS.
 *
 * AS grants you (hereafter, Licensee) a license to use the Software
 * for academic, research and internal business purposes only, without a
 * fee.  Licensee may distribute the binary and source code (if released)
 * to third parties provided that the copyright notice and this statement
 * appears on all copies and that no charge is associated with such copies.
 *
 * Licensee may make derivative works.  However, if Licensee distributes
 * any derivative work based on or derived from the Software, then
 * Licensee will:
 * (1) notify AS regarding its distribution of the derivative work, and
 * (2) clearly notify users that such derivative work is a modified version
 *      and not the original ASEDIT distributed by AS.
 *
 * Any Licensee wishing to make commercial use of the Software should
 * contact AS to negotiate an appropriate license for such commercial use.
 * Commercial use includes:
 * (1) integration of all or part of the source code into a product for sale
 *     or license by or on behalf of Licensee to third parties, or 
 * (2) distribution of the binary code or source code to third parties that
 *     need it to utilize a commercial product sold or licensed by or on 
 *     behalf of Licensee.
 *
 * A. STOCHNIOL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS
 * SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR
 * IMPLIED WARRANTY.  IN NO EVENT SHALL A. STOCHNIOL 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.
 *
 * By using or copying this Software, Licensee agrees to abide by the
 * copyright law and all other applicable laws, and the terms of this
 * license.
 * AS shall have the right to terminate this license immediately by
 * written notice upon Licensee's breach of, or non-compliance with, any
 * of its terms.  Licensee may be held legally responsible for any
 * copyright infringement that is caused or encouraged by Licensee's
 * failure to abide by the terms of this license.
 *
 *
 * 	Andrzej Stochniol	(A.Stochniol@ic.ac.uk)
 * 	30 Hatch Road
 * 	London SW16 4PN
 * 	UK
 */



#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>		/* for isspace definition */

#include <X11/Intrinsic.h>

#include <Xm/Xm.h>
#include <Xm/MessageB.h>
#include <Xm/SelectioB.h>
#include <Xm/Label.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>

#include <Xm/AtomMgr.h> 	/* for XmInternAtom */

#if (XmVersion == 1000)
/*  for Motif 1.0  all TRAVERSE constants are defined in a private Header XmP.h
    (at least this is the case for our IBM RS/6000). Since Motif 1.1 they are defined
    in Xm.h.
*/
#include <Xm/XmP.h>
#endif  /* XmVersion... */

#if (XmVersion < 1002)
/* for Motif < 1.2 we use a private function  _XmStringSourceGetString & _XmTextDisableRedisplay; include TextP.h */
#include <Xm/TextP.h>
#endif


#include "asedit.h"		/* for new  aseditWindowStruct definitions ... */
#include "asedit.ico"

#if defined(__alpha) || defined(GET_PIXMAP_BUG)
#   include "warning.xbm"
#endif


/*
**	create_4buttons_dialog
**		create special 4 buttons  dialog box out of a
**		selection box and supports graphical pixmap.
**		The message contains of the pixmap and string
**		If you do not want use any pixmap
**		specify None  pixmap like this:  None
*/
#ifdef _NO_PROTO
Widget create_4buttons_dialog (parent, name, pixmap, message, arglist, argcount)
	Widget parent;
	String name;
	Pixmap pixmap;
	String message;
	Arg arglist[];
	int argcount;
#else  /* _NO_PROTO */
Widget create_4buttons_dialog (Widget parent, String name, Pixmap pixmap,
	String message, Arg arglist[], int argcount)
#endif
{
	Widget 		message_dialog;	/*  special message selection box */
	Widget		apply_button;	/*  4th button which should be managed */
	Widget          kid[5];         /*  children		          */
	Arg             al[10];         /*  arg list		          */
	register int    ac;             /*  arg count		          */
	XmString  	label_string;   /*  work string */
	Widget 		work_area;	/*  rowcolumn for pixmap and text */
	Widget 		pixmap_label;	/*  pixmap label 		  */
	Widget 		text_label;	/*  text label 			  */


	message_dialog = XmCreatePromptDialog(parent, name, arglist, argcount);


	ac = 0;
	XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
	work_area = XmCreateRowColumn(message_dialog, "workarea", al, ac);
	XtManageChild(work_area);

	if(pixmap != None)
	{
		ac = 0;
		XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
		XtSetArg(al[ac], XmNlabelPixmap, pixmap); ac++;
		pixmap_label = XmCreateLabel(work_area, "pixmap_label", al, ac);
		XtManageChild(pixmap_label);
	}

	ac = 0;
	label_string = XmStringCreateLtoR(message, charset);
	XtSetArg(al[ac], XmNlabelString, label_string ); ac++;
	text_label = XmCreateLabel(work_area, "text_label", al, ac);
	XtManageChild(text_label);
	XmStringFree(label_string);

        /* store the text_label widget in the userData !!!, that will allow us to change
           dynamically the message string !!!
        */
        ac = 0;
        XtSetArg(al[ac], XmNuserData, text_label);  ac++;
        XtSetValues(message_dialog, al, ac);

	/* manage the apply button */
	apply_button = XmSelectionBoxGetChild (message_dialog,
						 XmDIALOG_APPLY_BUTTON);
	XtManageChild(apply_button);

	/*      Unmanage unneeded children.    */
	ac = 0;
	kid[ac++] = XmSelectionBoxGetChild (message_dialog, XmDIALOG_TEXT);
	kid[ac++] = XmSelectionBoxGetChild (message_dialog,
						     XmDIALOG_SELECTION_LABEL);
	XtUnmanageChildren (kid, ac);

	return(message_dialog);

}	/* create_4buttons_dialog */



/*-------------------------------------------------------------
**	create_4buttons_image_dialog
**		Create special 4 button message box out of a
**	Selection box.
*/
#ifdef _NO_PROTO
Widget create_4buttons_image_dialog (parent, name,
	image_string, message, arglist, argcount)
	Widget parent;
	String name;
	String image_string;
	String message;
	Arg arglist[];
	int argcount;
#else  /* _NO_PROTO */
Widget create_4buttons_image_dialog (Widget parent, String name,
	String image_string, String message, Arg arglist[], int argcount)
#endif
{
	Widget 		warning_dialog;	/*  special warning selection box */
	Widget 		work_area;	/*  rowcolumn for pixmap and text */
	Widget 		pixmap_label;	/*  pixmap label 		  */
	Widget 		text_label;	/*  text label 			  */
	Widget 		apply_button;	/*  apply button		  */
	Widget          kid[5];         /*  buttons		          */
	Pixel		foreground;	/*  dialog foreground		  */
	Pixel		background;	/*  dialog background		  */
	Pixmap		pixmap;		/*  dialog pixmap		  */
	register int    i;              /*  kid index			  */
	Arg             al[10];         /*  arg list		          */
	register int    ac;             /*  arg count		          */
	XmString  	label_string;   /*  work string */


	warning_dialog = XmCreatePromptDialog(parent, name, arglist, argcount);

	ac = 0;
	XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
	work_area = XmCreateRowColumn(warning_dialog, "workarea", al, ac);
	XtManageChild(work_area);

	ac = 0;
	XtSetArg(al[ac], XmNforeground, &foreground); ac++;
	XtSetArg(al[ac], XmNbackground, &background); ac++;
	XtGetValues(warning_dialog, al, ac);

	ac = 0;
	XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
#if !defined(__alpha) && !defined(GET_PIXMAP_BUG)
	pixmap = XmGetPixmap(XtScreen(warning_dialog), image_string,
			     foreground, background);
#else
        /* a hack to avoid DEC ALPHA/OSF problem with caching images (needed by XmGetPixmap) */
        /* we use a standard "as" warning bitmap  and create pixmap explicitly */
        pixmap =XCreatePixmapFromBitmapData(display, DefaultRootWindow (display),
              warning_bits, warning_width, warning_height,
              foreground, background,
              DefaultDepthOfScreen (DefaultScreenOfDisplay (display)));
#endif /* !GET_PIXMAP_BUG */

	XtSetArg(al[ac], XmNlabelPixmap, pixmap); ac++;
	pixmap_label = XmCreateLabel(work_area, "pixmap_label", al, ac);
	XtManageChild(pixmap_label);

	ac = 0;
	label_string = XmStringCreateLtoR(message, charset);
	XtSetArg(al[ac], XmNlabelString, label_string ); ac++;
	text_label = XmCreateLabel(work_area, "text_label", al, ac);
	XtManageChild(text_label);
	/* because XmString is copied into an internal area by the label widget
	   we can free the storage associated with the string by calling XmStringFree
	   (after XtCreateManagedWidget or XtSetValues (etc.) are finished) */
	XmStringFree(label_string);

	/* store the text_label widget in the userData !!!, that will allow us to change
           dynamically the message string !!!
 	*/
	ac = 0;
	XtSetArg(al[ac], XmNuserData, text_label);  ac++;
	XtSetValues(warning_dialog, al, ac);

	apply_button = XmSelectionBoxGetChild (warning_dialog,
						 XmDIALOG_APPLY_BUTTON);
	XtManageChild(apply_button);



	/*      Unmanage unneeded children.    */
	i = 0;
	kid[i++] = XmSelectionBoxGetChild (warning_dialog, XmDIALOG_TEXT);
	kid[i++] = XmSelectionBoxGetChild (warning_dialog,
						     XmDIALOG_SELECTION_LABEL);
	XtUnmanageChildren (kid, i);

	return(warning_dialog);

}	/* create_4buttons_image_dialog */

/************************************************************************
 *
 *  CreateDefaultImage - create a default images for warning symbol.
 *
 **********************************<->***********************************/
#ifdef _NO_PROTO
XImage * CreateDefaultImage (bits, width, height)
    char *bits;
    int width;
    int height;
#else  /* _NO_PROTO */
XImage * CreateDefaultImage (char *bits, int width, int height)
#endif
{
    XImage *image;

    image = (XImage *) XtMalloc (sizeof (XImage));
    image->width = width;
    image->height = height;
    image->data = bits;
    image->depth = 1;
    image->xoffset = 0;
    image->format = XYBitmap;
    image->byte_order = LSBFirst;
    image->bitmap_unit = 8;
    image->bitmap_bit_order = LSBFirst;
    image->bitmap_pad = 8;
    image->bytes_per_line = (width+7)/8;
    return (image);
}   /* CreateDefaultImage */


#ifdef _NO_PROTO
void show_error_message(win, message)
	aseditWindowStruct *win;
	char *message;
#else  /* _NO_PROTO */
void show_error_message(aseditWindowStruct *win, char *message)
#endif
{
    /* procedure is used to show the error message widget with the current
	message using the preset character set "charset";
	if the error_message widget is not available yet create it first
	as a child of menu_bar */

    Arg			al[5];		/*  arg list		*/
    register    int	ac = 0;		/*  arg count		*/
    XmString  message_string =XmStringCreateLtoR(message, charset);

    if(win->error_message == NULL)		/* create error_message widget first */
    {
	Widget 		kids[3];	/*  children widgets 	*/
	int     	i;

	XtSetArg(al[ac], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ac++;
	/* we are using the Cancel button for the closing of that message
	   mainly because that button will be automatically centered */
	/* The default button needs to be set now to the Cancel button. Otherwise
	   when we press Enter the button won't change the colour to the select
	   colour etc. (the standard defaults to OK button) */
	XtSetArg(al[ac], XmNdefaultButtonType, XmDIALOG_CANCEL_BUTTON); ac++;

	win->error_message = XmCreateErrorDialog (win->menu_bar, "error_message",al,ac);

	/* unmanage the unneeded buttons */
	i=0;
	kids[i++] = XmMessageBoxGetChild(win->error_message, XmDIALOG_HELP_BUTTON);
	kids[i++] = XmMessageBoxGetChild(win->error_message, XmDIALOG_OK_BUTTON);
	XtUnmanageChildren (kids, i);
	/* let's add the proper callback (just in case that somebody set
	   wrongly the autoUnmanage to False ....) */
	XtAddCallback (win->error_message, XmNcancelCallback,
		(XtCallbackProc)DialogCancelCB,  mk_asdat(ERROR_MESSAGE) );
    }

    ac = 0;
    XtSetArg(al[ac], XmNmessageString, message_string);  ac++;
    XtSetValues(win->error_message, al, ac);
    XmStringFree(message_string);	/* free memory allocated for XmString */

    asManageDialog (win->error_message);

}   /* show_error_message */


static Pixmap icon_pixmap = (Pixmap)NULL;	/* globally accessible for about program message */



/*
**	CreateAboutProgramMessage	- create simple message widget
*/
#ifdef _NO_PROTO
Widget CreateAboutProgramMessage (parent)
	Widget parent;
#else  /* _NO_PROTO */
Widget CreateAboutProgramMessage (Widget parent)
#endif
{
	Widget		button;
	Widget		message_box;	/*  Message Dialog 	*/
	Arg		al[10];		/*  arg list		*/
	register int	n;		/*  arg count		*/

	char		message[1000];	/*  help text	*/

	XmString	title_string = NULL;
	XmString	message_string = NULL;
	XmString	button_string = NULL;
	char 		work[128];



	/*	Generate message to display.
	*/

#undef ABOUT_M_SET



#ifndef ABOUT_M_SET
	sprintf (message, "\
ASEDIT editor\n\
Version 1.3.2 (non-commercial)\n\
Copyright (C) A. Stochniol, 1992-94.\n\
(A.Stochniol@ic.ac.uk)");
#endif

	message_string = XmStringCreateLtoR (message, charset);

	/*	Create MessageBox dialog.	*/
	n = 0;
	/* specify the icon_pixmap as the symbol pixmap */
	if(icon_pixmap != (Pixmap)NULL)
	{
	    XtSetArg(al[n], XmNsymbolPixmap, icon_pixmap);  n++;
	}

	/* let's unmanage OK and Help button so the
	   original cancel button will be positioned in the centre of the widget
	   i.e. in the visually recommended position ... */
	/* The default button needs to be set now to the Cancel button. Otherwise
	   when we press Enter the button won't change the colour to the select
	   colour etc. (the standard defaults to OK button) */
	XtSetArg(al[n], XmNdefaultButtonType, XmDIALOG_CANCEL_BUTTON); n++;

	XtSetArg (al[n], XmNmessageString, message_string);  n++;
	XtSetArg (al[n], XmNmessageAlignment, XmALIGNMENT_CENTER); n++;
	message_box = XmCreateMessageDialog (parent, "about", al, n);

	/* unmanage OK and Help buttons */
	button = XmMessageBoxGetChild (message_box, XmDIALOG_OK_BUTTON);
	XtUnmanageChild (button);
	button = XmMessageBoxGetChild (message_box, XmDIALOG_HELP_BUTTON);
	XtUnmanageChild (button);


	/*	Free strings and return MessageBox.	*/

	XmStringFree(  title_string);
	XmStringFree(message_string);
	XmStringFree( button_string);

	return (message_box);

}	/* CreateAboutProgramMessage */


/*****************************  show_about_message  **************************
**
**  Show about_program_message for the specified asedit window. If it does not exist yet
**  create it first as a child of menu_bar.
*/

#ifdef _NO_PROTO
void show_about_message (win)
        aseditWindowStruct *win;
#else  /* ! _NO_PROTO */

void show_about_message (aseditWindowStruct *win)
#endif
{
    if(win->about_program_message == NULL)        /* first create the widget  */
    {
            /*  create an About message (we need the icon_pixmap; already available) */
        win->about_program_message = CreateAboutProgramMessage (win->menu_bar);

        /* add the help callback to accept F1 (help key) press inside the message */
        XtAddCallback (win->about_program_message,  XmNhelpCallback,
                         (XtCallbackProc) HelpCB, mk_asdat(MENU_H_ABOUT));
    }

    asManageDialog (win->about_program_message);

}   /* show_about_message */



/****************************  set_appl_icon_pixmap  ***********************
 *
 * Set the icon for the application shell widget (top level) to the icon_pixmap.
 * Use the modern method of setting pixmap.
 * This version is better suited for SGI bigger icons.
 *
 * For some old window managers you might use set_appl_icon_pixmap_uni; 
 * you also should use the other
 * method if you want to draw something dynamically into the icon window.
 *
*/

#ifdef _NO_PROTO
static void set_appl_icon_pixmap (shell, icon_pixmap)
    Widget shell;
    Pixmap icon_pixmap;
#else  /* _NO_PROTO */
static void set_appl_icon_pixmap (Widget shell, Pixmap icon_pixmap)
#endif
{
    Arg al[4];
    register int ac;

    /* use a modern method using XmNiconPixmap and
       hope that the window managers understand it */
    ac = 0;
    XtSetArg(al[ac], XmNiconPixmap, icon_pixmap);  ac++;
    XtSetValues(shell, al, ac);
    return;

}   /* set_appl_icon_pixmap */


/****************************  set_appl_icon_pixmap_uni  ***********************
 *
 * Set the icon for the application shell widget (top level) to the icon_pixmap.
 * For the best results in portability into environments where the user may
 * not be running the most up-to-date window manager (that supports setting
 * iconPixmap directly) the icon window is created directly. Additionally, once
 * done we can paint whatever image we like in that window ! So, the function
 * may also be called repeatedly to dynamically update shell's icon window.
 *
*/

#ifdef _NO_PROTO
static void set_appl_icon_pixmap_uni (shell, icon_pixmap)
    Widget shell;
    Pixmap icon_pixmap;
#else  /* _NO_PROTO */
static void set_appl_icon_pixmap_uni (Widget shell, Pixmap icon_pixmap)
#endif
{
    Window icon_window, root_window;
    int x, y;
    unsigned int width, height, border_width, depth;
    Status status;
    Arg al[4];
    register int ac;
    Display *display = XtDisplay(shell);

    /* get the current icon window associated with the shell */
    ac = 0;
    XtSetArg(al[ac], XmNiconWindow, &icon_window );  ac++;
    XtGetValues(shell, al, ac);

    /* if there is no window associated with the shell create one.
       (first call - shell has not yet had its icon window set).
    */
    if(!icon_window)
    {
	/* get the size of the icon_pixmap, then create an InputOutput window */
	status = XGetGeometry(display, icon_pixmap, &root_window, &x, &y,
			&width, &height, &border_width, &depth);

	if(!status || !(icon_window = XCreateSimpleWindow (display, root_window,
				0, 0, width, height, border_width,
				CopyFromParent, CopyFromParent)))
	{
	    /* in the unlikely event that XGetGeometry or XCreateSimpleWindow
	       fails, we fall back on a modern method using XmNiconPixmap and
	       hope that the window managers understand it */
	    ac = 0;
	    XtSetArg(al[ac], XmNiconPixmap, icon_pixmap);  ac++;
	    XtSetValues(shell, al, ac);
	    return;
	}
	/* set the window created as the icon window */
	ac = 0;
	XtSetArg(al[ac], XmNiconWindow, icon_window);  ac++;
	XtSetValues(shell, al, ac);
    }
    /* set the current icon_pixmap as the window's background pixmap */
    XSetWindowBackgroundPixmap(display, icon_window, icon_pixmap);
    XClearWindow(display, icon_window);		/* to redisplay this window */

}   /* set_appl_icon_pixmap_uni */

/****************************  set_asedit_icon  *****************************
    procedure first creates a pixmap from bitmap then calls procedure to create
    an icon for the application
*/
#ifdef _NO_PROTO
void set_asedit_icon(shell, colours_source, icon_name)
    Widget shell;
    Widget colours_source;
    char *icon_name;
#else  /* _NO_PROTO */
void set_asedit_icon(Widget shell, Widget colours_source, char *icon_name)
#endif
{
    /**Pixmap icon_pixmap; ** making it globally accessible for CreateAboutProgram .. */
    Pixel background, foreground;
    Arg al[4];
    register int ac;

    /* get the foreground and background colours from colours_source widget;
       from a shell widget only background can be obtained (foreground is not
       defined); for asedit the most appropriate colours are those from the
       edit_text window (set that widget on a call for this procedure) */

    ac = 0;
    XtSetArg(al[ac], XmNforeground, &foreground );  ac++;
    XtSetArg(al[ac], XmNbackground, &background);   ac++;
    XtGetValues(colours_source, al, ac);

    /* create a pixmap from a bitmap using colours just obtained */
    icon_pixmap = XCreatePixmapFromBitmapData (XtDisplay(shell),
	    RootWindowOfScreen(XtScreen(shell)),
	    (char *)asedit_icon_bits, asedit_icon_width, asedit_icon_height,
	    foreground, background,
	    DefaultDepthOfScreen(XtScreen(shell)));

    /* there are still many windows manager around that do NOT understand the modern
       way of setting the ICON; let's return to the old way of setting it, i.e. instead
       of using "set_appl_icon_pixmap" we use "set_appl_icon_pixmap_uni" (16 June 1994)
    */
    set_appl_icon_pixmap_uni (shell, icon_pixmap);

    /* finally set the icon name */
    ac = 0;
    XtSetArg (al[ac], XmNiconName, icon_name);     ac++;
    XtSetValues (shell, al, ac);

}   /* set_asedit_icon */


#ifdef _NO_PROTO
void set_dialog_title(w, title)
    Widget w;
    char *title;
#else  /* _NO_PROTO */
void set_dialog_title(Widget w, char *title)
#endif
{	/* sets the dialogTitle of the widget w using character set 'charset'
	   and adding in front of the 'title' string PROGRAM_NAME and a dash */

    register int  ac;		/* arg count		    */
    Arg 	  al[3];	/* arg list		    */
    XmString  	  xmstr;	/* work XmString */
    char	  work[256];

    ac = 0;
    sprintf(work, "%s", title);
    xmstr =XmStringCreateLtoR(work, charset);
    XtSetArg (al[ac], XmNdialogTitle, xmstr);   ac++;

    XtSetValues(w, al, ac);
    XmStringFree(xmstr);	/* free memory allocated for XmString */

}   /* set_dialog_title */


#ifdef _NO_PROTO
void set_titles_mwindow_icon(win, filename, extra)
	   aseditWindowStruct *win;
	   char *filename;
	   char *extra;
#else  /* ! _NO_PROTO */

void set_titles_mwindow_icon(aseditWindowStruct *win, char *filename, char *extra)
#endif
{
    /* 	setting a new title of the main window. It includes the name
	of just opened file (when it is different from NULL);
	For the icon we set only the name of the file and without the path
	(if the file name is NULL we set the PROGRAM_NAME instead)
    */
    char main_title[286];		/* program_name + file name + extra*/
    char icon_name[276];
    char *filename_without_path;
    char *filename_without_home;
    register int ac;			/* arg count		    */
    Arg al[10];				/* widget arg list	    */
    char *home_dir = NULL;
    int len;
    Atom string_atom;		/* used to fix sun 8-bit problem */


    if(filename)
    {
	/* main title consists of a program name, a dash and a file name */
	sprintf(main_title,"%s - %s",PROGRAM_NAME, filename);
	/*      Get filename without leading path    */
	if (( filename_without_path = strrchr(filename, (int) '/')) == NULL)
		filename_without_path = filename;
	else
		filename_without_path++;
	strcpy(icon_name, filename_without_path);

	/* if the file name include home directory skip it and replace
	   it with the "~" symbol
	*/
	home_dir = getenv("HOME");
	if(home_dir) 
	{
	    len = strlen(home_dir);
	    if(strncmp(filename, home_dir, len) == 0)
	    {
		filename_without_home = filename+len;
		sprintf(main_title, "%s - ~%s",PROGRAM_NAME, filename_without_home);
	    }
 	}

	/* now check if the extra string is not empty; if not add it with a leading space
	   to the titles 
	*/
	if(extra && (strlen(extra) > (size_t)0) )
	{
	    strcat(main_title, " ");
	    strcat(main_title, extra);

	    strcat(icon_name, " ");
	    strcat(icon_name, extra);
	}

    }
    else
    {
	strcpy(icon_name, PROGRAM_NAME);
	strcpy(main_title, PROGRAM_NAME);
    }
    ac=0;
    XtSetArg(al[ac], XmNtitle, 	main_title); ac++;
    XtSetArg(al[ac], XmNiconName,icon_name); ac++;


    XtSetValues(win->topshell, al, ac);

}   /* set_titles_mwindow_icon */




#ifdef _NO_PROTO
static void focusTO(data, dummy)
    void *data;
    XtIntervalId *dummy;
#else  /* ! _NO_PROTO */

static void focusTO(void *data, XtIntervalId *dummy)
#endif
{
#if (XmVersion == 1000)
    /* in Motif 1.0 traversal was private and may not work (it does not always
       on my IBM RS/6000) ;
       a right version of it appears in Motif 1.1 */
    _XmProcessTraversal((Widget) data, XmTRAVERSE_CURRENT);
#else
    XmProcessTraversal((Widget) data, XmTRAVERSE_CURRENT);
#endif

}   /* focusTO */


#ifdef _NO_PROTO
void focusCB(w, data, dummy)
    Widget w;
    XtPointer data;
    XtPointer dummy;
#else  /* ! _NO_PROTO */

void focusCB(Widget w, XtPointer data, XtPointer dummy)
#endif
{
    XtRemoveCallback(w, XmNfocusCallback,
		(XtCallbackProc)focusCB, data);
    XtAppAddTimeOut(XtWidgetToApplicationContext(w), 10L,
		(XtTimerCallbackProc)focusTO, data);

}   /* focusCB */



#ifdef _NO_PROTO
static XFontStruct *saveLoadQFont (name)
    char *name;
#else  /* ! _NO_PROTO */

static XFontStruct *saveLoadQFont (char *name)
#endif
{
  XFontStruct *font = XLoadQueryFont (display, name);
  if (font == NULL)
    {
      fprintf (stderr, (char *)lstr.load_font_err, name);
      font = XLoadQueryFont (display, "fixed");
    }
  return (font);

} /* saveLoadQFont */



#ifdef _NO_PROTO
void create_set_font_list(w, font_name)
    Widget w;
    char *font_name;
#else  /* ! _NO_PROTO */

void create_set_font_list(Widget w, char *font_name)
#endif
{
    register int ac;            /* arg count                */
    Arg al[10];                 /* arg list                 */
    XmFontList font_list;
    font_list = XmFontListCreate((saveLoadQFont(font_name)), charset);
    ac = 0;
    XtSetArg(al[ac], XmNfontList, font_list); ac++;
    XtSetValues(w, al, ac);
    /* now we can free the font list because the widget had
       copied it already using XmFontListCopy ...
    */
    XmFontListFree(font_list);

}   /* create_set_font_list */


#ifdef _NO_PROTO
void create_set2_font_list(w, w2, font_name)
    Widget w;
    Widget w2;
    char *font_name;
#else  /* ! _NO_PROTO */

void create_set2_font_list(Widget w, Widget w2, char *font_name)
#endif
{
    register int ac;            /* arg count                */
    Arg al[10];                 /* arg list                 */
    XmFontList font_list;
    font_list = XmFontListCreate((saveLoadQFont(font_name)), charset);
    ac = 0;
    XtSetArg(al[ac], XmNfontList, font_list); ac++;
    XtSetValues(w, al, ac);
    XtSetValues(w2, al, ac);
    /* now we can free the font list because the widget had
       copied it already using XmFontListCopy ...
    */
    XmFontListFree(font_list);

}   /* create_set2_font_list */



#ifdef _NO_PROTO
void asManageDialog(w)
    Widget w;
#else  /* ! _NO_PROTO */

void asManageDialog(Widget w)
#endif
{
    /* use this procedure instead of XtManageChild when you would like to
       raise the dialog to the top of the window stack even when the
       dialog is already managed
    */
    Atom string_atom;           /* used to fix sun 8-bit problem */
    register int ac;            /* arg count                */
    Arg al[2];                 /* arg list                 */


    if (XtIsManaged (w))
	XMapRaised (XtDisplay (w), XtWindow (XtParent(w)));
    else
	XtManageChild (w);


}   /* asManageDialog */



/*** L_tmpnam is defined in stdio.h on ANSI systems (but let's be sure...)
     for the make_tmpnam following include files should be used: stdio.h,
     stdlib.h, string.h
***/

#ifndef L_tmpnam
#define L_tmpnam 32
#endif


#ifdef _NO_PROTO
char *make_tmpnam ()
#else  /* ! _NO_PROTO */

char *make_tmpnam (void)
#endif
{
    char *tempname = (char *)XtMalloc (sizeof (char) * L_tmpnam);
    char *tmpdir = NULL;

    tmpnam (tempname);		/* get the default temp name */


    /* asedit temp file is created in a directory specified by
       (listed by decreasing priority):
       (i)   *tmpDir X resource (stored in lstr.tmpDir);
       (ii)  TMPDIR environmental variable;
       (iii) wide system default place (you get here where both the above
	     are NULL)
    */

    tmpdir = (char *)lstr.tmpDir;
    /*   check if lstr.tmpDir is NULL; if so check the TMPDIR environmet;
	 if one of them  is not NULL, use it & create a temp file name there */
    
    if(!tmpdir)
    {
	tmpdir = getenv("TMPDIR");	/* we might get NULL here ... */
    }

    if(!tmpdir)	return(tempname);	/* temp file in system default place */
    else
    {
	/* put the tempfile in the user specified place ...*/
	char *tmp;
	char *just_name = NULL;
	/*  Get just the name (without path)  (for DOS you should use '\')  */
	if (( just_name = strrchr(tempname, (int) '/')) == NULL)
		just_name = tempname;
	else
		just_name++;

	tmp = (char *)XtMalloc (sizeof (char) * (strlen (tmpdir) +
					     strlen (just_name) + 2));
	if (tmpdir[strlen(tmpdir)-1] == '/')
	{
	    /* Trailing slash in temp directory */
	    sprintf (tmp, "%s%s", tmpdir, just_name);
	}
	else
	{
	    /* No trailing slash (so put it explicitly). */
	    sprintf (tmp, "%s/%s", tmpdir, just_name);
	}


	XtFree (tempname);
	return tmp;
    }

}   /* make_tmpnam */


#ifdef _NO_PROTO
Boolean empty_name(str)
   char *str;
#else  /* ! _NO_PROTO */

Boolean empty_name(char *str)
#endif
{
    int i, len;
    Boolean res=True;

    if(str == NULL) return(res);
    else
    {
	/* check if the string has a zero length or consists of spaces only */
	len = strlen(str);
	if(len == 0) return(res);

	for(i=0; i < len; i++)
	{
	    if(!isspace((int) ((unsigned char)str[i]) )) { res = False; break; }
	}
    }
    return(res);

}   /* empty_name */

   
#ifdef _NO_PROTO
Boolean checkSyntax(argc, argv, program_name, introStr, syntaxStr)
   unsigned int argc;
   char *argv[];
   char *program_name;
   char *introStr;
   char *syntaxStr;
#else  /* ! _NO_PROTO */

Boolean checkSyntax(unsigned int argc, char *argv[], char *program_name, 
		char *introStr, char *syntaxStr)
#endif
{
    /* check the syntax of the command line (if all command
       switches were properly processed);
       if not show the syntax error message and return error code
    */

    int i, ierr;
    Boolean error=False;

    for (i=1; i < argc; i++)
    {
	if(argv[i][0] == '-' || argv[i][0] == '=' || argv[i][0] == '+') { ierr= i; error= True; }
    }


    if(error)
    {
	fprintf(stderr,"\n%s: ", program_name);
	if(strcmp(argv[ierr], "-help") != 0) fprintf(stderr, introStr, argv[ierr]);
	fprintf(stderr, syntaxStr);		/* print out the syntax */
    }
    return(error);

} /* checkSyntax */


   
#ifdef _NO_PROTO
Boolean checkCommandForOption(argc, argv, option)
   unsigned int argc;
   char *argv[];
   char *option;
#else  /* ! _NO_PROTO */

Boolean checkCommandForOption(unsigned int argc, char *argv[], char *option )
#endif
{
    /* check the syntax of the command line for the option;
       it is is there - return True; 
    */

    int i, ierr;
    Boolean found=False;

    for (i=1; i < argc; i++)
    {
	if(strcmp(argv[i], option)  == 0 ) { found= True;  break;}
    }

    return(found);

} /* checkCommandForOption */


#ifdef _NO_PROTO
void disableRedisplay(win)
        aseditWindowStruct *win;
#else  /* _NO_PROTO */
void disableRedisplay(aseditWindowStruct *win)
#endif
{
    /* used in conjunction with enableRedisplay to prevent visual flashing
       when multiple updates of edit widget(s) occur
    */
#if (XmVersion > 1001)
#  define disableRedisplayScrolledText(stext) if(stext  && XtIsManaged(XtParent(stext)))       \
	XmTextDisableRedisplay(stext);
#else
#  define disableRedisplayScrolledText(stext) if(stext  && XtIsManaged(XtParent(stext)))       \
	_XmTextDisableRedisplay((XmTextWidget)stext, False);
#endif /* Motif 1.2 */

    disableRedisplayScrolledText(win->edit_text);


}   /* disableRedisplay */


#ifdef _NO_PROTO
void enableRedisplay(win)
        aseditWindowStruct *win;
#else  /* _NO_PROTO */
void enableRedisplay(aseditWindowStruct *win)
#endif
{
    /* used in conjunction with enableRedisplay to prevent visual flashing
       when multiple updates of edit widget(s) occur
    */

#if (XmVersion > 1001)
#   define enableRedisplayScrolledText(stext) if(stext  && XtIsManaged(XtParent(stext)))       \
	XmTextEnableRedisplay(stext);
#else
#   define enableRedisplayScrolledText(stext) if(stext  && XtIsManaged(XtParent(stext)))       \
	_XmTextEnableRedisplay((XmTextWidget)stext);
#endif /* Motif 1.2 */

    enableRedisplayScrolledText(win->edit_text);


}   /* enableRedisplay */

#ifdef _NO_PROTO
char *getTextSubstring(w, start, num_chars)
    Widget w;
    XmTextPosition start;
    int num_chars;
#else  /* _NO_PROTO */
char *getTextSubstring(Widget w, XmTextPosition start, int num_chars)
#endif
{
    /* get the substring from the text widget; the calling procedure should
       free the allocated memory
    */
    int buffer_size, status;
    char *buffer=NULL;
    XmTextPosition last;

    if(start < 0) start = 0;		/* auto correction */

    last = XmTextGetLastPosition(w);
    if(start >= last ) return NULL;	/* sanity check */

    /* correct the num_chars if neccessary */
    if(start+num_chars > last) num_chars = last - start;


#if (XmVersion >= 1002)
    /* use Motif 1.2 new GetSubstring routine (note we have to allocate memory for it) */

    buffer_size = (num_chars +1) * sizeof(char);	/* for multibyte characters use (num_chars * MB_CUR_MAX) + 1 */
    buffer = XtMalloc(buffer_size);
    status = XmTextGetSubstring(w, start, num_chars, buffer_size, buffer);
    if(status == XmCOPY_FAILED)
    {
	/* return nothing */
	XtFree(buffer);
	buffer = NULL;
    }

#   else
    /* use internal Motif routine (here Motif 1.0 might have been different, but
       I can't check it because none is available around any more; anyway I don't
       know anybody still using Motif 1.0 today, January 1994)
    */

    buffer = _XmStringSourceGetString((XmTextWidget)w, start, (XmTextPosition)(start+num_chars));

#   endif /* Motif 1.2 */

    return buffer;

}   /* getTextSubstring */


#ifdef _NO_PROTO
void checkRadioBoxSetting(w, deflt)
    Widget w;
    int deflt;
#else  /* _NO_PROTO */
void checkRadioBoxSetting(Widget w, int deflt)
#endif
{
        /* the default radio button is set via resources (since 1.32); check
           for a not unique setup (and correct it if needed); the correction is
           mainly implemented to use the 1.3 and 1.31 app-defs without any
           corrections;
        */
	
	Arg                 al[3];          /*  arg list            */
	register  int       ac = 0;         /*  arg count           */
	WidgetList	buttons;	/* radio buttons */	
        Cardinal	n;		/* number of buttons */
	Boolean   	*state;
	int 	  	i, counter=0;

	
	/* make sure that the widget w is a subclass of RowColumn */
	if(!XmIsRowColumn(w))
 	{
	    fprintf(stderr, "Error: checkRadioBoxSetting requires RowColumn widget!\n");
	    return;
	}
	ac = 0;
	XtSetArg(al[ac], XmNchildren, &buttons);	ac++;
	XtSetArg(al[ac], XmNnumChildren, &n);		ac++;

	XtGetValues(w, al, ac);
	
	if(n <= 0) return;		/* do nothing; no children */

	/* allocate memory for the state array */
	state = (Boolean *) XtMalloc(n * sizeof(Boolean));

	/* get the state of all buttons */
	ac = 0;
	for (i=0; i < n; i++)
	{
	    XtSetArg(al[0], XmNset, &(state[i]));
	    XtGetValues(buttons[i], al, 1);
	}


	/* count the number of buttons that are set to on; if it is different
	   than one, the setup is wrong; set than the default button on
	*/
	
	for(i=0; i<n; i++) if(state[i]) counter++;

        
	if(counter != 1)
	{
	    if(deflt < 0 || deflt >=n) deflt = 0;	/* correct the wrong default */
	    for(i=0; i<n; i++)
	    {
		if(i == deflt) XtSetArg(al[0], XmNset, True);
		else		 XtSetArg(al[0], XmNset, False);
		XtSetValues(buttons[i], al, 1);
	    }
	}

	XtFree((char *)state);


} 	/* check RadioBoxSetting */


/* extra addition for the NEXTSTEP (undert co-Xist) */

#if defined (NeXT)
char *getcwd (char *pathname)
{
  return (getwd(pathname));
}
#endif

