/* tool_dlg.c - part of asedit program */
/*
 * 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 <ctype.h>              /* to define toupper function */


#include <Xm/MessageB.h>
#include <Xm/SelectioB.h>
#include <Xm/ToggleB.h>
#include <Xm/Frame.h>
#include <Xm/Label.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>
#include "asedit.h"




#define MAX_REASONABLE_LINE_WIDTH       4095
#define	MAX_DIGITS_IN_MOVE_DIALOGS	2
#define	MAX_DIGITS_IN_REFORMAT_DIALOG	3

/*****************************  allowOnlyNumbersCB  *********************************
**
**      Process callback from number only text widgets.
*/
#ifdef _NO_PROTO
void allowOnlyNumbersCB (w, client_data, call_data)
    Widget w;
    XtPointer client_data;
    XtPointer call_data;
#else  /* ! _NO_PROTO */

void allowOnlyNumbersCB (Widget w, XtPointer client_data, XtPointer call_data)
#endif
{

    XmTextVerifyCallbackStruct  *cbs = (XmTextVerifyCallbackStruct *) call_data;
    int    reason;              /* reason for the callback */
    unsigned char c;
    int max_len = (int)  client_data;
    int i, len = XmTextGetLastPosition (w);
    char *sel = NULL;

    reason = cbs->reason;

    switch(reason)
    {

        case XmCR_MODIFYING_TEXT_VALUE:
	    sel = XmTextGetSelection(w);	/* get the selection; we might want to clear
						   the selection by typing in (pendingDelete) */
	    if(sel)
	    {
		if(strlen(sel)) max_len++;	/* increase it by 1 to allow 1 char. long input 
						    when the text is selected and takes all the length*/
		XtFree(sel);
	    }

	    if (cbs->text->length +len > max_len)
	    { /* don't allow text longer than max_len (including clipboard/selection copies) */
                cbs->doit = False;
                return;
            }
	    /* process the following only when there is text inserted; (i.e.
               do not process when we press BkSp, Delete etc. */

	    if(cbs->text->length > 0)
            {

	      for(i=0; i < cbs->text->length; i++)
              {
                 /* don't allow non-digits */
	
		 c = (unsigned char)cbs->text->ptr[0];
                 if (!isdigit (c))      
                 {
                   cbs->doit = False;
                 }
              }
            }
            break;

        default:
            /* an unknown client_data was received and there is no setup to handle this */
            fprintf(stderr, "Warning: an unknown client_data in allowOnlyNumbersCB callback\n");
            fprintf(stderr,"Detected reason = %d \n", reason);
            return;

    }

} /* allowOnlyNumbersCB */




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

void show_moveLeft_dialog (aseditWindowStruct *win)
#endif
{
    Arg			al[5];		/*  arg list		*/
    register  int	ac = 0;		/*  arg count		*/
    Widget    dialog, text;

    if(win->moveLeft_dialog == NULL)	/* first create the dialog  */
    {
	/* create the moveLeft_dialog widget */
	ac = 0;
	/*** XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;  let the user decide if he wants
	     the dialog to stay after OK ***/
	dialog = XmCreatePromptDialog (win->menu_bar, "moveLeft_dialog",al,ac);

	XtAddCallback (dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB,     mk_asdat_w(win, DIALOG_MOVE_LEFT) );
	XtAddCallback (dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, mk_asdat_w(win, DIALOG_MOVE_LEFT) );
	XtAddCallback (dialog, XmNhelpCallback,
			(XtCallbackProc)HelpCB,         mk_asdat_w(win, DIALOG_MOVE_LEFT) );

	text = XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT);

	if(lstr.useOldColorSetup)
        {
            /* set the colour for the editable text widget */
            ac =0;
            XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
            XtSetValues(text, al, ac);
        }

        setDefaultHomeEndTranslations(text);    /* it is a child of SelectionBox so
                                                   set the translations for osfBeginLine
                                                   and osfEndLine to the same as for standard
                                                   text widgets
                                                */
	/* add modify verify callback (we will use it to allow entering only numbers) */
	XtAddCallback (text, XmNmodifyVerifyCallback,
			(XtCallbackProc)allowOnlyNumbersCB, (XtPointer)MAX_DIGITS_IN_MOVE_DIALOGS );

	/* store the dialog widget */
	win->moveLeft_dialog = dialog;
    }

    asManageDialog (win->moveLeft_dialog);

}   /*  show_moveLeft_dialog */


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

void show_moveRight_dialog (aseditWindowStruct *win)
#endif
{
    Arg			al[5];		/*  arg list		*/
    register  int	ac = 0;		/*  arg count		*/
    Widget    dialog, text;

    if(win->moveRight_dialog == NULL)	/* first create the dialog  */
    {
	/* create the moveRight_dialog widget */
	ac = 0;
	/*** XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;  let the user decide if he wants
	     the dialog to stay after OK ***/
	dialog = XmCreatePromptDialog (win->menu_bar, "moveRight_dialog",al,ac);

	XtAddCallback (dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB,     mk_asdat_w(win, DIALOG_MOVE_RIGHT) );
	XtAddCallback (dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, mk_asdat_w(win, DIALOG_MOVE_RIGHT) );
	XtAddCallback (dialog, XmNhelpCallback,
			(XtCallbackProc)HelpCB,         mk_asdat_w(win, DIALOG_MOVE_RIGHT) );

	text = XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT);

	if(lstr.useOldColorSetup)
        {
            /* set the colour for the editable text widget */
            ac =0;
            XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
            XtSetValues(text, al, ac);
        }

        setDefaultHomeEndTranslations(text);    /* it is a child of SelectionBox so
                                                   set the translations for osfBeginLine
                                                   and osfEndLine to the same as for standard
                                                   text widgets
                                                */
	/* add modify verify callback (we will use it to allow entering only numbers) */
	XtAddCallback (text, XmNmodifyVerifyCallback,
			(XtCallbackProc)allowOnlyNumbersCB, (XtPointer)MAX_DIGITS_IN_MOVE_DIALOGS );

	/* store the dialog widget */
	win->moveRight_dialog = dialog;
    }

    asManageDialog (win->moveRight_dialog);

}   /*  show_moveLeft_dialog */

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

void show_indentWith_dialog (aseditWindowStruct *win)
#endif
{
    Arg			al[5];		/*  arg list		*/
    register  int	ac = 0;		/*  arg count		*/
    Widget    dialog, text;

    if(win->indentWith_dialog == NULL)	/* first create the dialog  */
    {
	/* create the indentWith_dialog widget */
	ac = 0;
	/*** XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;  let the user decide if he wants
	     the dialog to stay after OK ***/
	dialog = XmCreatePromptDialog (win->menu_bar, "indentWith_dialog",al,ac);

	XtAddCallback (dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB,     mk_asdat_w(win, DIALOG_INDENT_WITH) );
	XtAddCallback (dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, mk_asdat_w(win, DIALOG_INDENT_WITH) );
	XtAddCallback (dialog, XmNhelpCallback,
			(XtCallbackProc)HelpCB,         mk_asdat_w(win, DIALOG_INDENT_WITH) );

	text = XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT);

	if(lstr.useOldColorSetup)
        {
            /* set the colour for the editable text widget */
            ac =0;
            XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
            XtSetValues(text, al, ac);
	}

        setDefaultHomeEndTranslations(text);    /* it is a child of SelectionBox so
                                                   set the translations for osfBeginLine
                                                   and osfEndLine to the same as for standard
                                                   text widgets
                                                */
	/* store the dialog widget */
	win->indentWith_dialog = dialog;
    }

    asManageDialog (win->indentWith_dialog);

}   /*  show_indentWith_dialog */

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

void show_reformat_dialog (aseditWindowStruct *win)
#endif
{
    Arg			al[15];		/*  arg list		*/
    register  int	ac = 0;		/*  arg count		*/
    Widget    dialog=NULL, form, left_margin_title, right_margin_title;
    Widget    kid[6];
    int	      i;
    Dimension    h_space, v_space; 	/* horizontal and vertical space used */


    if(win->reformat_dialog == NULL)	/* first create the dialog  */
    {
	/* create the reformat_dialog widget */
	ac = 0;
	/*** XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;  let the user decide if he wants
	     the dialog to stay after OK ***/
	dialog = XmCreateWarningDialog(win->menu_bar, "reformat_dialog", al, ac);

	if(dialog == NULL)  return;         /* safety check */

	/* unmanage unneeded elements */
	i = 0;
	kid[i++] = XmMessageBoxGetChild(dialog, XmDIALOG_MESSAGE_LABEL);
	kid[i++] = XmMessageBoxGetChild(dialog, XmDIALOG_SYMBOL_LABEL);
	XtUnmanageChildren (kid, i);


	/* create a form widget inside the dialog; inside that form
	   create appropriate labels and text widgets */

	ac = 0;
	form = XmCreateForm ( dialog, "form", al, ac );

	ac = 0;
	XtSetArg(al[ac], XmNhorizontalSpacing, &h_space ); ac++;
	XtSetArg(al[ac], XmNverticalSpacing, &v_space ); ac++;
	XtGetValues(form, al, ac );	/* get the spacing used */


	ac = 0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
	left_margin_title = XmCreateLabel ( form, "left_margin_title", al, ac );

	ac=0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); 	ac++;
	XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); 	ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_WIDGET); 	ac++;
	XtSetArg(al[ac], XmNleftOffset,      h_space); ac++;
	XtSetArg(al[ac], XmNleftWidget,      left_margin_title);ac++;
        XtSetArg(al[ac], XmNcolumns,  MAX_DIGITS_IN_REFORMAT_DIALOG); ac++;
	if(lstr.useOldColorSetup)
	    { XtSetArg(al[ac], XmNbackground,  select_menu_background);ac++; }
	win->left_margin = XmCreateText ( form, "left_margin", al, ac );
#if (XmVersion == 1000)
	XmAddTabGroup (win->left_margin);
#endif

	ac = 0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNtopOffset,       v_space); 		ac++;
	XtSetArg(al[ac], XmNtopWidget,       win->left_margin); ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_NONE);	ac++;
	XtSetArg(al[ac], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); 	ac++;
	XtSetArg(al[ac], XmNrightWidget,     left_margin_title); ac++;

	/*don't**XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;  ***/
	/*** @ 11.03. - Silicon Graphics - O.K. -----
		XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++; ****/


	right_margin_title = XmCreateLabel ( form, "right_margin_title", al, ac );


	ac=0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNtopOffset,       v_space); 		ac++;
	XtSetArg(al[ac], XmNtopWidget,       win->left_margin); ac++;
	XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); 	ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNleftOffset,      h_space); 		ac++;
	XtSetArg(al[ac], XmNleftWidget,      left_margin_title); ac++;
        XtSetArg(al[ac], XmNcolumns,  MAX_DIGITS_IN_REFORMAT_DIALOG); ac++;
	if(lstr.useOldColorSetup)
	    { XtSetArg(al[ac], XmNbackground,  select_menu_background);ac++; }


	win->right_margin = XmCreateText ( form, "right_margin", al, ac );
#if (XmVersion == 1000)
	XmAddTabGroup (win->right_margin);
#endif

	/* manage the widgets */

	ac = 0;
	kid[ac++] = left_margin_title;
	kid[ac++] = win->left_margin;
	kid[ac++] = right_margin_title;
	kid[ac++] = win->right_margin;
	XtManageChildren(kid, ac);
	XtManageChild(form);


	XtAddCallback (dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB,     mk_asdat_w(win, DIALOG_REFORMAT) );
	XtAddCallback (dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, mk_asdat_w(win, DIALOG_REFORMAT) );
	XtAddCallback (dialog, XmNhelpCallback,
			(XtCallbackProc)HelpCB,         mk_asdat_w(win, DIALOG_REFORMAT) );


	/* set a special callback to set the focus to the right_margin widget
	   when the dialog gets its first focus */
#ifndef XFOCUS_BUG
	XtAddCallback(dialog, XmNfocusCallback,
			(XtCallbackProc)focusCB, (XtPointer)win->right_margin);
#endif

	/* add modify verify callback (to allow entering only numbers) */
	XtAddCallback (win->left_margin, XmNmodifyVerifyCallback,
			(XtCallbackProc)allowOnlyNumbersCB, (XtPointer)MAX_DIGITS_IN_MOVE_DIALOGS );	/* allow 99 max */
	XtAddCallback (win->right_margin, XmNmodifyVerifyCallback,
			(XtCallbackProc)allowOnlyNumbersCB, (XtPointer)MAX_DIGITS_IN_REFORMAT_DIALOG );

	/* store the dialog widget */
	win->reformat_dialog = dialog;
    }

    asManageDialog (win->reformat_dialog);

    /* set the keyboard focus to the right_margin each time the dialog pops-up */
#if (XmVersion == 1000)
    _XmProcessTraversal( win->right_margin, XmTRAVERSE_CURRENT);  /** private f. in Motif 1.0***/
#else
    XmProcessTraversal( win->right_margin, XmTRAVERSE_CURRENT);
#endif


}   /*  show_reformat_dialog */



/*****************************  FilterDialogCB  *********************************
**
**      Process callback from the filter Dialog OK action.
*/
#ifdef _NO_PROTO
void FilterDialogCB (w, client_data, call_data)
    Widget w;
    XtPointer client_data;
    XtPointer call_data;
#else  /* ! _NO_PROTO */

void FilterDialogCB (Widget w, XtPointer client_data, XtPointer call_data)
#endif
{
    Arg             al[5];
    register int    ac;

    XmTextPosition left, right;
    char *filter_cmd=NULL;
    char *cmdInput  =NULL;         /* text to be filtered */
    int id                  = get_id_from_asdat(client_data);
    aseditWindowStruct *win = get_win_from_asdat(client_data);
    XmSelectionBoxCallbackStruct *scb =
			 (XmSelectionBoxCallbackStruct *) call_data;


    TurnWatchCursor(True);

    /* get the filter commnad string from the selection box */
    XmStringGetLtoR(scb->value, charset, &filter_cmd);
    if(!empty_name(filter_cmd))
    {
	/* get the selection */
	cmdInput = XmTextGetSelection(win->edit_text);
	if((cmdInput == NULL) || (strlen(cmdInput) == 0))
	{
	    /* popup the error message about non-existent selection */
	    show_error_message(win, (char *)lstr.flt_no_selection);
	    if(filter_cmd) XtFree(filter_cmd);
	    if(cmdInput) XtFree(cmdInput);

	    TurnWatchCursor(False);
	    return;

	}

	XmTextGetSelectionPosition(win->edit_text, &left, &right); /* get the selection positions */

	/*** note that we are not extending the selection here (to include the right line feed);
	     here it is the total responsibility of the user
	***/

	if(executeShellCmd(win, filter_cmd, cmdInput, left, right,
			win->filterOutDepot, NULL, NULL, 0, (XmString)NULL ));
	{

		;	/* OK, do nothing extra */
	}

	/* free allocated memory */
	if(filter_cmd != NULL) XtFree(filter_cmd);

	/* do NOT free cmdInput; its memory will be freed when all input is
	   processed (i.e. in processChildOutput)
	*/

	XtUnmanageChild(w);         /* pop-down the dialog */
    }
    else
    {
	/* popup the error message about empty filter command string */
	show_error_message(win, (char *)lstr.flt_no_filter);
	if(filter_cmd != NULL) XtFree(filter_cmd);
    }

    TurnWatchCursor(False);


}   /* FilterDialogCB */

/*****************************  FilterToggleCB ******************************
**
**      Process callbacks from toggles in the Filter dialog .
*/
#ifdef _NO_PROTO
static void FilterToggleCB (w, client_data, call_data)
    Widget w;
    XtPointer client_data;
    XtPointer call_data;
#else  /* ! _NO_PROTO */

static void FilterToggleCB (Widget w, XtPointer client_data, XtPointer call_data)
#endif
{

    int id                  = get_id_from_asdat(client_data);
    aseditWindowStruct *win = get_win_from_asdat(client_data);
    XmToggleButtonCallbackStruct *toggle_data =
	(XmToggleButtonCallbackStruct *) call_data;

    if(toggle_data->set)	/* the toggle button is set; set the dialog out flag  to the
				   supplied id value*/
	win->filterOutDepot = id;

    else
	;			/* do nothing; it is a radio box (only one button is on)*/

}   /* FilterToggleCB */


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

void setDefaultHomeEndTranslations(Widget w)
#endif
{
    static XtTranslations TransCompiled = NULL;
    static char *Trans =
"Shift <Key>osfBeginLine:       beginning-of-line(extend)\n\
 <Key>osfBeginLine:             beginning-of-line()\n\
 Shift <Key>osfEndLine:         end-of-line(extend)\n\
 <Key>osfEndLine:               end-of-line()\n";

	if(TransCompiled  == NULL)    /* compiled it first */
	    TransCompiled = XtParseTranslationTable(Trans);
	/* be sure that TransCompiled is not NULL (safety check)*/
	if(TransCompiled)
		XtOverrideTranslations(w, TransCompiled);

}   /* setDefaultHomeEndTranslations */



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

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

void show_filter_dialog (aseditWindowStruct *win)
#endif
{


    Arg                 al[10];          /*  arg list            */
    register  int       ac = 0;         /*  arg count           */
    Widget    text;             /* text widget inside the prompt dialog */

    if(win->filter_dialog == NULL)
    {
        /* create filter dialog */
        Widget depot_radio_box, form;
        Widget frame, to_current_toggle, to_new_toggle, to_dialog_toggle, depot_title;
        Widget kid[4];

        XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
        win->filter_dialog = XmCreatePromptDialog(win->menu_bar, "filter_dialog", al, ac);

        /* unmanage unneeded apply button */
        kid[0] = XmSelectionBoxGetChild(win->filter_dialog, XmDIALOG_APPLY_BUTTON);
        XtUnmanageChild (kid[0]);

        XtAddCallback (win->filter_dialog, XmNokCallback,
		(XtCallbackProc)FilterDialogCB,     mk_asdat_w(win, DIALOG_FILTER) );
        XtAddCallback (win->filter_dialog, XmNcancelCallback,
                (XtCallbackProc)DialogCancelCB, mk_asdat_w(win, DIALOG_FILTER) );
        XtAddCallback (win->filter_dialog,XmNhelpCallback,
                (XtCallbackProc)HelpCB,         mk_asdat_w(win, DIALOG_FILTER) );

        text = XmSelectionBoxGetChild(win->filter_dialog, XmDIALOG_TEXT);

	if(lstr.useOldColorSetup)
        {
            /* set the colour for the editable text widget */
	    ac =0;
            XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
            XtSetValues(text, al, ac);
        }

	setDefaultHomeEndTranslations(text);	/* it is a child of SelectionBox so
						   set the translations for osfBeginLine
					  	   and osfEndLine to the same as for standard
						   text widgets
						*/
						   
        ac = 0;
        form = XmCreateForm ( win->filter_dialog, "form", al, ac );

	ac = 0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
        XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
        depot_title = XmCreateLabel ( form, "depot_title", al, ac );

        ac=0;
        XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);  ac++;
        XtSetArg(al[ac], XmNtopWidget,       depot_title);    ac++;
        XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM);    ac++;
        XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM);    ac++;

        XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM);    ac++;


        frame = XmCreateFrame ( form, "frame", al, ac );

        ac=0;
        depot_radio_box = XmCreateRadioBox( frame, "depot_radio_box", al, ac );
#if (XmVersion == 1000)
        XmAddTabGroup (depot_radio_box);
#endif
	/* set the first button as the default ON */
	win->filterOutDepot = TO_CURRENT;

        ac=0;
	XtSetArg (al[ac], XmNset, True);  ac++;
	to_current_toggle =  XmCreateToggleButton(depot_radio_box, "to_current", al,ac);
	XtAddCallback (to_current_toggle, XmNvalueChangedCallback,
		(XtCallbackProc)FilterToggleCB,     mk_asdat_w(win, TO_CURRENT) );
	ac = 0;
	to_new_toggle    =  XmCreateToggleButton(depot_radio_box, "to_new", al,ac);
	XtAddCallback (to_new_toggle, XmNvalueChangedCallback,
		(XtCallbackProc)FilterToggleCB,     mk_asdat_w(win, TO_NEW) );

        to_dialog_toggle =  XmCreateToggleButton(depot_radio_box, "to_dialog", al,ac);
	XtAddCallback (to_dialog_toggle, XmNvalueChangedCallback,
		(XtCallbackProc)FilterToggleCB,     mk_asdat_w(win, TO_TEXT_DIALOG) );


        /* manage the children and manage the manager parents as we ascend back up*/

        ac = 0;
        kid[ac++] = to_current_toggle;
        kid[ac++] = to_new_toggle;
	kid[ac++] = to_dialog_toggle;
	XtManageChildren(kid, ac);
	XtManageChild(depot_radio_box);
	XtManageChild(frame);

	XtManageChild(depot_title);

	XtManageChild(form);


	/* set a special callback to set the focus to the text widget
	   when the dialog gets its first focus */

#ifndef XFOCUS_BUG
	XtAddCallback(win->filter_dialog, XmNfocusCallback,
			(XtCallbackProc)focusCB, (XtPointer)text);
#endif
    }
    text = XmSelectionBoxGetChild(win->filter_dialog, XmDIALOG_TEXT);
    asManageDialog(win->filter_dialog);

    /* set the keyboard focus to the text widget each time the dialog pops-up */
#if (XmVersion == 1000)
    _XmProcessTraversal( text, XmTRAVERSE_CURRENT);  /** private f. in Motif 1.0 **/
#else
    XmProcessTraversal( text, XmTRAVERSE_CURRENT);
#endif


}   /* show_filter_dialog */


/*****************************  CommandDialogCB  *********************************
**
**      Process callback from the filter Dialog OK action.
*/
#ifdef _NO_PROTO
void CommandDialogCB (w, client_data, call_data)
    Widget w;
    XtPointer client_data;
    XtPointer call_data;
#else  /* ! _NO_PROTO */

void CommandDialogCB (Widget w, XtPointer client_data, XtPointer call_data)
#endif
{
    Arg             al[5];
    register int    ac;
    char *cmd=NULL;
    XmTextPosition left, right;

    int id                  = get_id_from_asdat(client_data);
    aseditWindowStruct *win = get_win_from_asdat(client_data);
    XmSelectionBoxCallbackStruct *scb =
			 (XmSelectionBoxCallbackStruct *) call_data;


    TurnWatchCursor(True);

    /* get the commnad string from the selection box */
    XmStringGetLtoR(scb->value, charset, &cmd);
    if(!empty_name(cmd))
    {
	/* the command result will replace current selection (if it is not
	   available or its length is zero, we will put it at the current insertion point) */

	if(!XmTextGetSelectionPosition(win->edit_text, &left, &right) || left==right)
		left = right = XmTextGetInsertionPosition(win->edit_text);

	if(executeShellCmd(win, cmd, NULL, left, right,
			win->commandOutDepot, NULL, NULL, 0, (XmString)NULL ));
	{

		;	/* OK, do nothing extra */
	}

	XtUnmanageChild(w);         /* pop-down the dialog */
    }
    else
    {
	/* popup the error message about empty command string */
	show_error_message(win, (char *)lstr.flt_no_filter);
    }

    /* free allocated memory */
    if(cmd != NULL) XtFree(cmd);


    TurnWatchCursor(False);


}   /* CommandDialogCB */

/*****************************  CommandToggleCB ******************************
**
**      Process callbacks from toggles in the Command dialog .
*/
#ifdef _NO_PROTO
static void CommandToggleCB (w, client_data, call_data)
    Widget w;
    XtPointer client_data;
    XtPointer call_data;
#else  /* ! _NO_PROTO */

static void CommandToggleCB (Widget w, XtPointer client_data, XtPointer call_data)
#endif
{

    int id                  = get_id_from_asdat(client_data);
    aseditWindowStruct *win = get_win_from_asdat(client_data);
    XmToggleButtonCallbackStruct *toggle_data =
	(XmToggleButtonCallbackStruct *) call_data;

    if(toggle_data->set)	/* the toggle button is set; set the dialog out flag  to the
				   supplied id value*/
	win->commandOutDepot = id;

    else
	;			/* do nothing; it is a radio box (only one button is on)*/

}   /* CommandToggleCB */




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

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

void show_command_dialog (aseditWindowStruct *win)
#endif
{
    Widget    text;             /* text widget inside the prompt dialog */

    if(win->command_dialog == NULL)
    {
	/* create command dialog */
	Arg                 al[10];          	/*  arg list            */
	register  int       ac = 0;         	/*  arg count           */
	Widget dialog, depot_radio_box, form;
	Widget frame, to_current_toggle, to_new_toggle, to_dialog_toggle, depot_title;
	Widget kid[4];

	XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
	dialog = XmCreatePromptDialog(win->menu_bar, "command_dialog", al, ac);

	/* unmanage unneeded apply button */
	kid[0] = XmSelectionBoxGetChild(dialog, XmDIALOG_APPLY_BUTTON);
	XtUnmanageChild (kid[0]);

	XtAddCallback (dialog, XmNokCallback,
		(XtCallbackProc)CommandDialogCB,     mk_asdat_w(win, DIALOG_COMMAND) );
	XtAddCallback (dialog, XmNcancelCallback,
                (XtCallbackProc)DialogCancelCB, mk_asdat_w(win, DIALOG_COMMAND) );
	XtAddCallback (dialog,XmNhelpCallback,
                (XtCallbackProc)HelpCB,         mk_asdat_w(win, DIALOG_COMMAND) );

	text = XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT);

        if(lstr.useOldColorSetup)
        {
	    /* set the colour for the editable text widget */
            ac =0;
            XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
	    XtSetValues(text, al, ac);
	}

	setDefaultHomeEndTranslations(text);	/* it is a child of SelectionBox so
						   set the translations for osfBeginLine
						   and osfEndLine to the same as for standard
						   text widgets
						*/

	ac = 0;
	form = XmCreateForm ( dialog, "form", al, ac );

	ac = 0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
	depot_title = XmCreateLabel ( form, "depot_title", al, ac );

	ac=0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);  ac++;
	XtSetArg(al[ac], XmNtopWidget,       depot_title);    ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM);    ac++;
	XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM);    ac++;

	XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM);    ac++;


	frame = XmCreateFrame ( form, "frame", al, ac );

	ac=0;
	depot_radio_box = XmCreateRadioBox( frame, "depot_radio_box", al, ac );
#if (XmVersion == 1000)
	XmAddTabGroup (depot_radio_box);
#endif
	/* set the first button as the default ON */
	win->commandOutDepot = TO_CURRENT;

	ac=0;
	XtSetArg (al[ac], XmNset, True);  ac++;
	to_current_toggle =  XmCreateToggleButton(depot_radio_box, "to_current", al,ac);
	XtAddCallback (to_current_toggle, XmNvalueChangedCallback,
		(XtCallbackProc)CommandToggleCB,     mk_asdat_w(win, TO_CURRENT) );
	ac = 0;
	to_new_toggle    =  XmCreateToggleButton(depot_radio_box, "to_new", al,ac);
	XtAddCallback (to_new_toggle, XmNvalueChangedCallback,
		(XtCallbackProc)CommandToggleCB,     mk_asdat_w(win, TO_NEW) );

	to_dialog_toggle =  XmCreateToggleButton(depot_radio_box, "to_dialog", al,ac);
	XtAddCallback (to_dialog_toggle, XmNvalueChangedCallback,
		(XtCallbackProc)CommandToggleCB,     mk_asdat_w(win, TO_TEXT_DIALOG) );


        /* manage the children and manage the manager parents as we ascend back up*/

        ac = 0;
        kid[ac++] = to_current_toggle;
        kid[ac++] = to_new_toggle;
        kid[ac++] = to_dialog_toggle;
        XtManageChildren(kid, ac);
        XtManageChild(depot_radio_box);
	XtManageChild(frame);

        XtManageChild(depot_title);

        XtManageChild(form);


	/* set a special callback to set the focus to the text widget
	   when the dialog gets its first focus */

#ifndef XFOCUS_BUG
	XtAddCallback(dialog, XmNfocusCallback,
			(XtCallbackProc)focusCB, (XtPointer)text);
#endif

	win->command_dialog = dialog;
    }
    text = XmSelectionBoxGetChild(win->command_dialog, XmDIALOG_TEXT);
    asManageDialog(win->command_dialog);


    /***** XYZ do we need to set the keyboard focus ??? (the same for
     filter_dialog ???
    **/

    /* set the keyboard focus to the text widget each time the dialog pops-up */
#if (XmVersion == 1000)
    _XmProcessTraversal( text, XmTRAVERSE_CURRENT);  /** private f. in Motif 1.0 **/
#else
    XmProcessTraversal( text, XmTRAVERSE_CURRENT);
#endif


}   /* show_command_dialog */



/* extendRightPosToLF - extends right position to encompass the line feed;
   returns True when everything OK; note if the current selection ends in LF it is OK;
   if there are errors asks about continuing the process and returns the user answer;
   right:  margin of the current selection;
*/

#ifdef _NO_PROTO
static Boolean extendRightPosToLF (win, right)
    aseditWindowStruct *win;
    XmTextPosition *right;
#else  /* ! _NO_PROTO */

static Boolean extendRightPosToLF (aseditWindowStruct *win, XmTextPosition *right)
#endif
{
    Boolean proceed = True;
    char *txt = NULL;		/* text from the text widget */
    int i, len, lf_pos;

    txt = getTextSubstring(win->edit_text, *right-1, MAX_REASONABLE_LINE_WIDTH);
    if(txt)
    {
	len = strlen(txt);
	lf_pos = -1;

	for(i=0; i<len; i++)
	{
	    if(txt[i] == '\n')
	    {
		lf_pos = i;
		break;
	    }
	}
	if(lf_pos > 0)
	{
	    /* only change the position when we find the line feed and the
	       selection was not already finished with line feed
	    */
	    *right += lf_pos;
	}
	else if(lf_pos == -1)
	{
	    /* show an error message that we can't find the newline
	       because the line is to long or we are at the last line of a file
	       which does not have one
	    */
	    /* for simplicity use acceptChildOutput procedure */
	    proceed = acceptChildOutput(win->menu_bar, lstr.cant_find_lf, XmDIALOG_CANCEL_BUTTON);
	}
	XtFree(txt);
    }
    else
    {
	/* this shouldn't really happen, but lets take care of that */
	proceed = acceptChildOutput(win->menu_bar, lstr.cant_find_lf, XmDIALOG_CANCEL_BUTTON);
    }

    return proceed;


}   /*  extendRightPosToLF */


/* extendSelectionToLF - extends selection right to encompass the line feed;
   returns True when everything OK; note if the current selection ends in LF it is OK;
   if there are errors asks about continuing the process and returns the user answer;
   left, right:  margins of the current selection;
*/

#ifdef _NO_PROTO
Boolean  extendSelectionToLF (win, left, right)
    aseditWindowStruct *win;
    XmTextPosition *left;
    XmTextPosition *right;
#else  /* ! _NO_PROTO */

Boolean extendSelectionToLF (aseditWindowStruct *win, XmTextPosition *left, XmTextPosition *right)
#endif
{
    Boolean proceed = True;
    XmTextPosition left_orig, right_orig;

    /* extend the selection to encompass the last line feed; alternatively
       we could extend the selection to whole lines; the important bit is to
       have the final line feed (sed works on complete lines!)
    */

    left_orig = *left;
    right_orig= *right;

    if(extendRightPosToLF(win, right))
    {
	if(*right != right_orig)
	    XmTextSetSelection(win->edit_text, *left, *right, CurrentTime);
    }
    else proceed = False;

    return proceed;

}   /*  extendSelectionToLF */


/* extendLeftPosToBOL - extends left posotion to the beginning of line;
   returns True when everything OK; note if the current selection starts
   at the beginning of line - it is OK;
   if there are errors asks about continuing the process and returns the user answer;
   left:  margins of the current selection;
*/

#ifdef _NO_PROTO
static Boolean  extendLeftPosToBOL (win, left)
    aseditWindowStruct *win;
    XmTextPosition *left;
#else  /* ! _NO_PROTO */

static Boolean extendLeftPosToBOL (aseditWindowStruct *win, XmTextPosition *left)
#endif
{

    Boolean proceed = True;
    char *txt = NULL;		/* text from the text widget */
    int i, len, lf_last_pos;

    /* extend the left position to encompass the first character on the line;
    */

    if(*left == 0) return True;		/* beginning of the text */

    txt = getTextSubstring(win->edit_text, *left -MAX_REASONABLE_LINE_WIDTH, *left);
    if(txt)
    {
	len = strlen(txt);
	lf_last_pos = -1;

	/* look for the line beginning only when we check that the
	   selection does not start at the line beginning already */
	if(txt[len-1] != '\n')
	{
	    for(i=len-1; i>=0; i--)
	    {
		if(txt[i] == '\n')
		{
		    lf_last_pos = i;
		    break;
		}
	    }
	    if(lf_last_pos >= 0)  *left -= (len-1 - lf_last_pos);
	    else if(lf_last_pos == -1)
	    {
		/* check if we had not reach the beginning of file; if not
		   show an error message that we can't find the newline
		   because the line is probably to long
		*/
		if(*left == len) *left = 0; 	/* extend to the text beginning */
		else	/* show error; for simplicity use acceptChildOutput procedure */
		    proceed = acceptChildOutput(win->menu_bar, lstr.cant_find_lf, XmDIALOG_CANCEL_BUTTON);
	    }
	}
	XtFree(txt);
    }
    else
    {
	/* this shouldn't really happen, but lets take care of that */
	proceed = acceptChildOutput(win->menu_bar, lstr.cant_find_lf, XmDIALOG_CANCEL_BUTTON);
    }

    return proceed;


}   /*  extendLeftPosToBOL */


/* extendSelectionToBOL - extends selection left to beginning of line;
   returns True when everything OK; note if the current selection starts
   at the beginning of line - it is OK;
   if there are errors asks about continuing the process and returns the user answer;
   left, right:  margins of the current selection;
*/

#ifdef _NO_PROTO
Boolean  extendSelectionToBOL (win, left, right)
    aseditWindowStruct *win;
    XmTextPosition *left;
    XmTextPosition *right;
#else  /* ! _NO_PROTO */

Boolean extendSelectionToBOL (aseditWindowStruct *win, XmTextPosition *left, XmTextPosition *right)
#endif
{
    Boolean proceed = True;
    XmTextPosition left_orig, right_orig;

    left_orig = *left;
    right_orig= *right;

    if(extendLeftPosToBOL(win, left))
    {
	if(*left != left_orig)
	    XmTextSetSelection(win->edit_text, *left, *right, CurrentTime);
    }
    else proceed = False;

    return proceed;


}   /*  extendSelectionToBOL */



/* extendSelectionToLines - extends selection to encompass whole lines (including
   final line feed);
   returns True when everything OK; note if the current selection ends in LF it is OK;
   if there are errors asks about continuing the process and returns the user answer;
   left, right:  margins of the current selection;
*/

#ifdef _NO_PROTO
Boolean  extendSelectionToLines (win, left, right)
    aseditWindowStruct *win;
    XmTextPosition *left;
    XmTextPosition *right;
#else  /* ! _NO_PROTO */

Boolean extendSelectionToLines (aseditWindowStruct *win, XmTextPosition *left, XmTextPosition *right)
#endif
{
    Boolean proceed = True;
    XmTextPosition left_orig, right_orig;

    /* extend the selection to encompass the whole lines;
       we *need* the final line feed (sed works on complete lines!)
    */

    left_orig = *left;
    right_orig= *right;

    if(extendRightPosToLF(win, right) && extendLeftPosToBOL(win, left))
    {
	if(*right != right_orig || *left != left_orig)
	    XmTextSetSelection(win->edit_text, *left, *right, CurrentTime);
    }
    else proceed = False;

    return proceed;

}   /* extendSelectionToLines */

/* extendSelectionToWholeFile - extends selection to the whole file (text);
   returns True when everything OK; 
   left, right:  margins of the current selection;
*/

#ifdef _NO_PROTO
Boolean  extendSelectionToWholeFile (win, left, right)
    aseditWindowStruct *win;
    XmTextPosition *left;
    XmTextPosition *right;
#else  /* ! _NO_PROTO */

Boolean extendSelectionToWholeFile (aseditWindowStruct *win, XmTextPosition *left, XmTextPosition *right)
#endif
{
    Boolean proceed = True;
    XmTextPosition left_orig, right_orig;

    /* extend the selection to encompass the whole file;
       we *need* the final line feed (sed works on complete lines!)
    */

    left_orig = *left;
    right_orig= *right;

    *left = 0;
    *right = XmTextGetLastPosition(win->edit_text);

    if(*right != right_orig || *left != left_orig)
	    XmTextSetSelection(win->edit_text, *left, *right, CurrentTime);

    return proceed;

}   /* extendSelectionToWholeFile */


#ifdef _NO_PROTO
void changeCaseOfString(txt, change_to)
    char  *txt;
    int   change_to;
#else  /* ! _NO_PROTO */

void changeCaseOfString(char *txt, int change_to)
#endif
{
    long i, len;
    Boolean spaceOrDotBefore = True;	/* we assume that the user wants the first letter to be
					  capitalized (TO_TTILE_CASE) */
    unsigned char c;

    if(txt)
    {
	len = strlen(txt);
	switch(change_to)
	{
	    case TO_UPPER_CASE:
		for(i=0; i < len; i++)
		{
		    *txt = toupper((unsigned char) *txt);
		    txt++;
		}
		break;

	    case TO_LOWER_CASE:
		for(i=0; i < len; i++)
		{
		    *txt = tolower((unsigned char) *txt);
		    txt++;
		}
		break;

	    case TO_TITLE_CASE:
		for(i=0; i < len; i++)
		{
		    c = (unsigned char) *txt;
		    if(spaceOrDotBefore)
		    {
			if(isalpha(c)) *txt = toupper(c);
		    }
		    txt++;

		    if(isspace(c) || ispunct(c)) spaceOrDotBefore = True;
		    else		       spaceOrDotBefore = False;
		}
		break;

	    case TO_TOGGLE_CASE:
		for(i=0; i < len; i++)
		{
		    c = (unsigned char) *txt;
		    if(isupper(c))      *txt = tolower(c);
		    else if(islower(c)) *txt = toupper(c);
		    txt++;
		}
		break;

	    default:
		fprintf(stderr, "\nUnknown change_to in changeCaseOfString");
		break;
	}

    }

}   /* changeCaseOfString */


#ifdef _NO_PROTO
void changeCaseOfSelection(win, change_to)
    aseditWindowStruct 	*win;
    int 		change_to;
#else  /* ! _NO_PROTO */

void changeCaseOfSelection(aseditWindowStruct *win, int change_to)
#endif
{
    char  *txt;
    XmTextPosition left, right, insert_pos;


    /* get the selection */
    txt = XmTextGetSelection(win->edit_text);

    /* the following two checks probably would never be used;
       appropriate commands should be greyed out when there is no primary
       selection in the edit area (so this procedure would NOT be called
       when there is no selection!)
    */
    if(txt == NULL) return;	/* no selection to process */
    if(strlen(txt) == 0)
    {
	/* the widget owns primary selection but it is empty; do not process */
	XtFree(txt);
	return;
    }


    if(!XmTextGetSelectionPosition(win->edit_text, &left, &right)) return; /* get the positions and do an extra check */

    insert_pos = XmTextGetInsertionPosition(win->edit_text);

    /* OK, we have the selection and its position */

    changeCaseOfString(txt, change_to);

    disableRedisplay(win);	/* to prevent visual flashing */

    XmTextReplace(win->edit_text, left, right, txt);
    /* set the selection again */
    /* note that XmTextSelection position changes the insertion to the right pos. */
    XmTextSetSelection(win->edit_text, left, right, CurrentTime);  

    if(insert_pos != right)
    	XmTextSetInsertionPosition(win->edit_text, insert_pos);

    enableRedisplay(win);

    /* free allocated memory */
    if(txt) XtFree(txt);

}   /* changeCaseOfSelection */




