
static char sccsid[] = "@(#)asedit.c	1.11  asedit, 26.01.1993";
/*
 * asedit - Motif based editor
 *
 * (C) COPYRIGHT A. Stochniol, 1991 - 1993
 * All Rights Reserved
 *
 * Author:
 * Dr. Andrzej Stochniol
 * Department of Mechanical Engineering
 * Imperial College of Science, Technology and Medicine
 * London, SW7 2BX, UK
 *
 *    E-mail:  A.Stochniol@ic.ac.uk
 *
 * Telephone: +44-(0)71-589 5111 ext. 6151
 *       Fax: +44-(0)71-584 1560
 *
 *
 * Last changes: 26.01.1993
 *
*/

/* asedit is an user friendly editor for programmers working under X-Windows.
   A Motif Text widget is used as a base for the editor.
   Another text widget is used as a base for the hypertext system
   The interesting part of the help is localized in the TextCB
   We use a text widget as emulation of a future (if any) help widget

*/

#ifdef AMIGA
#include "amiga.h"
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <X11/Xatom.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>

#include <Xm/Xm.h>
#include <Xm/CascadeB.h>
#include <Xm/DialogS.h>
#include <Xm/BulletinB.h>
#include <Xm/FileSB.h>
#include <Xm/MainW.h>
#include <Xm/MessageB.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/SelectioB.h>
#include <Xm/ToggleB.h>
#include <Xm/ToggleBG.h>
#include <Xm/Text.h>

#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/PanedW.h>


#ifndef X11R3
#include <Xm/Protocols.h>	/* needed because of XmAddWMProtocolCallback;
				   available since X11R4 */
#endif

#ifdef X11R3
/*  for X11R3  all TRAVERSE constants are defined in a private Header XmP.h
    (at least this is the case for our IBM RS/6000). In X11R4 they are defined
    in Xm.h.
*/
#include <Xm/XmP.h>
#endif  /* X11R3 */

#ifdef X11R5
/* include Xaw EditRes protocol .... */
#include <X11/Xmu/Editres.h>
#endif


#include "asedit.h"
#include "clipbrd.h"

/* the following include is needed only where we are using a simpler way
   of setting the icon (i.e. we are not using the set_asedit_icon procedure)
   (see the main program)
*/
#include "asedit_icon"

/*
  Widget and non-widget resources if the application defaults file can't be
  found.  Generated automatically from Asedit.ad by "ad2c".  Comment out the
  include line (but not the NULL) if you don't want any resources compiled
  in.
*/

#ifndef X11R3
/* fallbackResources are only used from Motif 1.1  **/
static String fallbackResources[] = {
#include "Asedit.ad.h"
    NULL
};
#endif  /* X11R3 */




/*****************************	Forward Declarations  ***********************/

/* I am commited to use ANSI compliant function prototypes. This is the proper
   way to handle function declarations and signatures (declaring the types of
   the parameters to the function). This convention is good style (and save
   a lot of debugging time!).

   Unfortunately there are still systems that do not support ANSI function
   prototypes. Because of that to make asedit portable to those systems I was
   forced to use conditional compilation. So, where appropriate I am using
   Motif based  #ifdef _NO_PROTO. It makes the code less readable, but there
   is really no other choice (sorry!).
*/
#ifdef _NO_PROTO	/* prototypes for non-ANSI systems follow ... */

static Widget CreateMenus (/*  Widget parent  */);
void CreateFileDialogs (/*  Widget menu_bar  */);
void CreateSearchDialogs (/*  Widget menu_bar  */);
static Widget CreateEditWorkArea(/*  Widget parent  */);
static Widget CreateScrolledText (/*  Widget parent  */);
Boolean SaveFile(/*  void  */);
char * ReadFile(/*  char *file_name, Boolean *read_only  */);
Boolean OpenFile(/*  Boolean only_existing_files  */);
void CloseFile(/*  void  */);
Boolean WriteFile(/*  char *file_name, char *file_string  */);
long find_line_pos(/*  long line, char *buf, long *found_lines  */);
long find_string_pos_in_buffer(/*  char *searchstring, char *buf,
			long startpos, long endpos, Boolean forward,
			Boolean case_sensitive, Boolean whole_words_only  */);
void textPosToLineColumn(/*  char *buf, long buf_size, long pos, long *line, long *column  */);
void find_string(/*  long *first_pos, long *last_pos  */);
Widget CreateSorryHelp (/*  Widget parent  */);
void set_asedit_icon(/*  Widget shell, Widget colours_source, char *icon_name  */);

Widget CreateReplaceDialog(/*  Widget parent, String name, Arg arglist[], int argcount  */);
Widget create_4buttons_dialog (/*  Widget parent, String name, Pixmap pixmap,
	String message, Arg arglist[], int argcount  */);
Widget create_4buttons_image_dialog (/*  Widget parent, String name,
	String image_string, String message, Arg arglist[], int argcount  */);
XImage * CreateDefaultImage (/*  char *bits, int width, int height  */);
Widget CreateAboutProgramMessage (/*  Widget parent  */);
void set_change_buttons_sensitivity(/*  Boolean state  */);
void change_all_found_strings(/*  Boolean start  */);
void set_dialog_title(/*  Widget w, char *title  */);
void MenuCB (/*  Widget w, caddr_t client_data, caddr_t call_data  */);
void HelpCB (/*  Widget w, caddr_t client_data, caddr_t call_data  */);
void set_titles_mwindow_icon(/*  char *filename  */);
void TurnWatchCursor(/*  Boolean turn_on  */);
void DialogOkCB (/*  Widget w, caddr_t client_data, caddr_t call_data  */);

void UndoRedo (/*  int action_type  */);
void reset_undo_redo(/*  void  */);
void SaveActionForUndo(/*  Widget w, caddr_t client_data, caddr_t call_data  */);

void HelpTextCB (/*  Widget w, caddr_t client_data, caddr_t call_data  */);
Widget CreateHyperTextHelp(/*  Widget parent, String name,
		Arg arglist[], int argcount  */);
void TurnOffSashTraversal(/*  Widget pane  */);
void focusCB(/*  Widget w, caddr_t data, caddr_t dummy  */);
void as_create_menuh(/*  char *title, Widget menu, as_menuh_struct *menulist, int nitems,
		       XmStringCharSet charset  */);

void FinalCleanupCB(/*  Widget w, caddr_t client_data, caddr_t call_data  */);

void ByeBye(/*  void  */);		/* for the time being */

#else  /* ! _NO_PROTO, ANSI prototypes follow */

static Widget CreateMenus (Widget parent);
void CreateFileDialogs (Widget menu_bar);
void CreateSearchDialogs (Widget menu_bar);
static Widget CreateEditWorkArea(Widget parent);
static Widget CreateScrolledText (Widget parent);
Boolean SaveFile(void);
char * ReadFile(char *file_name, Boolean *read_only);
Boolean OpenFile(Boolean only_existing_files);
void CloseFile(void);
Boolean WriteFile(char *file_name, char *file_string);
long find_line_pos(long line, char *buf, long *found_lines);
long find_string_pos_in_buffer(char *searchstring, char *buf,
			long startpos, long endpos, Boolean forward,
			Boolean case_sensitive, Boolean whole_words_only);
void textPosToLineColumn(char *buf, long buf_size, long pos, long *line, long *column);
void find_string(long *first_pos, long *last_pos);
Widget CreateSorryHelp (Widget parent);
void set_asedit_icon(Widget shell, Widget colours_source, char *icon_name);

Widget CreateReplaceDialog( Widget parent, String name, Arg arglist[], int argcount);
Widget create_4buttons_dialog (Widget parent, String name, Pixmap pixmap,
	String message, Arg arglist[], int argcount);
Widget create_4buttons_image_dialog (Widget parent, String name,
	String image_string, String message, Arg arglist[], int argcount);
XImage * CreateDefaultImage (char *bits, int width, int height);
Widget CreateAboutProgramMessage (Widget parent);
void set_change_buttons_sensitivity(Boolean state);
void change_all_found_strings(Boolean start);
void set_dialog_title(Widget w, char *title);
void MenuCB (Widget w, caddr_t client_data, caddr_t call_data);
void HelpCB (Widget w, caddr_t client_data, caddr_t call_data);
void set_titles_mwindow_icon(char *filename);
void TurnWatchCursor(Boolean turn_on);
void DialogOkCB (Widget w, caddr_t client_data, caddr_t call_data);



void UndoRedo (int action_type);
void reset_undo_redo(void);
void SaveActionForUndo(Widget w, caddr_t client_data, caddr_t call_data);

void HelpTextCB (Widget w, caddr_t client_data, caddr_t call_data);
Widget CreateHyperTextHelp( Widget parent, String name,
		Arg arglist[], int argcount );
void TurnOffSashTraversal(Widget pane);
void focusCB(Widget w, caddr_t data, caddr_t dummy);
void as_create_menuh(char *title, Widget menu, as_menuh_struct *menulist, int nitems,
		       XmStringCharSet charset );

void FinalCleanupCB(Widget w, caddr_t client_data, caddr_t call_data);

void ByeBye(void);		/* for the time being */

#endif	/* end of conditional _NO_PROTO prototypes  compilation */

/*****************************	Global Data   *******************************/


/* following definition set Line and Column line visible */
#define _SHOW_LINE_COLUMN


/* special hypertext link definitions  ***/

#define HTEXT_KEYS              8000
#define HTEXT_INDEX             8001
#define HTEXT_HELP              8002
#define HTEXT_ABOUT             8003


#define MENU_FILE		  10
#define MENU_OPEN		1000
#define MENU_NEW                1001
#define MENU_CLOSE		1002
#define MENU_SAVE		1003
#define MENU_SAVE_AS		1004
#define MENU_PRINT		1005
#define MENU_EXIT		1006

#define MENU_EDIT		  20
#define MENU_UNDO	        2000
#define MENU_REDO               2001
#define MENU_CUT		2002
#define MENU_COPY		2003
#define MENU_PASTE		2004
#define MENU_CLEAR		2005

#define MENU_SEARCH		  30
#define	MENU_FIND		3000
#define	MENU_REPEAT_FIND	3001
#define	MENU_CHANGE		3002
#define	MENU_GOTOLINE		3003

#define MENU_HELP		  80

#define	MENU_H_ON_KEYS		HTEXT_KEYS
#define	MENU_H_INDEX            HTEXT_INDEX
#define	MENU_H_ON_HELP          HTEXT_HELP
#define	MENU_H_ABOUT            HTEXT_ABOUT


#define DIALOG_OPEN		100000
#define DIALOG_NEW		100100
#define DIALOG_SAVE_AS		100400
#define DIALOG_PRINT		100500
#define DIALOG_SAVE_CHANGES	100001
#define QUESTION_OVERWRITE      100401
#define DIALOG_FIND_OR_CHANGE	300000
#define DIALOG_GOTOLINE		300300
#define DIALOG_CHANGE_PROMPT	 30020001
#define QUESTION_CONTINUE_SEARCH 30020002
#define MESSAGE_SEARCH_END	 30020003
#define ERROR_MESSAGE		 7777



static as_menuh_struct File_menu[] ={
	 {"Open...",  MenuCB, HelpCB, (caddr_t)MENU_OPEN,    'O', "F3", "<Key>F3:", NULL},
	 {"New...",     MenuCB, HelpCB, (caddr_t)MENU_NEW,     'N', NULL},
	 {"Close",    MenuCB, HelpCB, (caddr_t)MENU_CLOSE,   'C', NULL},
	 {"Save",     MenuCB, HelpCB, (caddr_t)MENU_SAVE,    'S', "F2", "<Key>F2:", NULL},
	 {"Save As...",MenuCB, HelpCB,(caddr_t)MENU_SAVE_AS, 'A', NULL},
	 {NULL},				/* separator */
	 {"Print",    MenuCB, HelpCB, (caddr_t)MENU_PRINT,   'P', NULL},
	 {NULL},				/* separator */
	 {"Exit",     MenuCB, HelpCB, (caddr_t)MENU_EXIT,    'x', "Alt+x", "Meta<Key>x:",NULL},
	 };


#ifdef hpux
/* hpux differently call Delete key "DeleteChar" etc... (???? check the name
	for BackSpace - 21.03.1992 !!!) */

static as_menuh_struct Edit_menu[] ={
	 {"Undo",     MenuCB, HelpCB, (caddr_t)MENU_UNDO,     'U',
				 "Alt+BkSp","~Shift Meta <Key>BackSpace:" , NULL},
	 {"Redo",     MenuCB, HelpCB, (caddr_t)MENU_REDO,     'R',
				 "Shift+Alt+BkSp","Shift Meta <Key>BackSpace:" , NULL},
	 {NULL},
	 {"Cut",      MenuCB, HelpCB, (caddr_t)MENU_CUT,     't',
				 "Shift+Del", "Shift<Key>DeleteChar:" , NULL},
	 {"Copy",     MenuCB, HelpCB, (caddr_t)MENU_COPY,    'C',
				"Ctrl+Ins",   "Ctrl<Key>InsertChar:"  , NULL},
	 {"Paste",    MenuCB, HelpCB, (caddr_t)MENU_PASTE,   'P',
				"Shift+Ins",  "Shift<Key>InsertChar:" , NULL},
	 {NULL},					/* separator */
	 {"Clear",    MenuCB, HelpCB, (caddr_t)MENU_CLEAR, 'e',
			"Del",  NULL , NULL}
			/* above  there is a pseudo accelerator - Text widget
			   already handles this action appropriately */
	 };
#else /* no hpux */

static as_menuh_struct Edit_menu[] ={
	 {"Undo",     MenuCB, HelpCB, (caddr_t)MENU_UNDO,     'U',
				 "Alt+BkSp","~Shift Meta <Key>BackSpace:" , NULL},
	 {"Redo",     MenuCB, HelpCB, (caddr_t)MENU_REDO,     'R',
				 "Shift+Alt+BkSp","Shift Meta <Key>BackSpace:" , NULL},
	 {NULL},
	 {"Cut",      MenuCB, HelpCB, (caddr_t)MENU_CUT,     't',
				 "Shift+Del","Shift<Key>Delete:" , NULL},
	 {"Copy",     MenuCB, HelpCB, (caddr_t)MENU_COPY,    'C',
				"Ctrl+Ins",   "Ctrl<Key>Insert:"  , NULL},
	 {"Paste",    MenuCB, HelpCB, (caddr_t)MENU_PASTE,   'P',
				"Shift+Ins",  "Shift<Key>Insert:" , NULL},
	 {NULL},					/* separator */
	 {"Clear",    MenuCB, HelpCB, (caddr_t)MENU_CLEAR, 'e',
			"Del",  NULL , NULL}
			/* above  there is a pseudo accelerator - Text widget
			   already handles this action appropriately */
	 };
#endif  /* hpux */

static as_menuh_struct Search_menu[] ={
	 {"Find...",          MenuCB, HelpCB, (caddr_t)MENU_FIND,    'F', NULL},
	 {"Repeat last Find", MenuCB, HelpCB, (caddr_t)MENU_REPEAT_FIND,  'R', NULL, "Ctrl<Key>l:", NULL},
	 {"Change... ",       MenuCB, HelpCB, (caddr_t)MENU_CHANGE, 'C', NULL},
	 {"Go to line ...",   MenuCB, HelpCB, (caddr_t)MENU_GOTOLINE,'G', NULL,}
	 };


/* Describe the menu bar, giving only the names to appear in
 * the menu bar and pointers to each pulldown pane, already defined.
 */

static as_menuh_struct Main_menu[] ={
	 {"File",   NULL, HelpCB, (caddr_t)MENU_FILE,  'F', NULL, NULL, File_menu,
		XtNumber(File_menu),NULL},
	 {"Edit",   NULL, HelpCB, (caddr_t)MENU_EDIT,  'E', NULL, NULL, Edit_menu,
		XtNumber(Edit_menu),NULL},
	 {"Search", NULL, HelpCB, (caddr_t)MENU_SEARCH,'S', NULL, NULL, Search_menu,
		XtNumber(Search_menu),NULL}
	 };


/* Describe the structures for the help menu */

static as_menuh_struct Help_menu[] ={
	 {"On Keys",	HelpCB, HelpCB, (caddr_t)MENU_H_ON_KEYS,    'K', NULL},
	 {"Index", 	HelpCB, HelpCB, (caddr_t)MENU_H_INDEX,      'I', NULL},
	 {"On Help",    HelpCB, HelpCB, (caddr_t)MENU_H_ON_HELP,    'H', NULL},
	 {NULL},			/* separator */
	 {"About...",   MenuCB, HelpCB, (caddr_t)MENU_H_ABOUT,	    'A', NULL}
	 };

/* Describe the Help button in the menu bar */

static as_menuh_struct help_Main_menu[] ={
	 {"Help",   NULL, HelpCB, (caddr_t)MENU_HELP,  'H', NULL, NULL, Help_menu,
		XtNumber(Help_menu),NULL}
	 };



Display		*display;	/*  Display		*/
Widget toplevel;		/* application shell (top level) (such a name
				   is used inside the clipboard functions ! )*/

Widget edit_text;		/* multi-line main editable text widget	    */

Widget menu_cut_button;         /* some menu_... widgets follows:		*/
Widget menu_copy_button;	/*   they represent buttons in the pull-down menus */
Widget menu_paste_button;	/*   that must be globally accessible (to change   */
Widget menu_clear_button;	/*   their sensitivity etc. )			 */
Widget menu_undo_button;
Widget menu_redo_button;

Widget menu_save_button;
Widget menu_save_as_button;
Widget menu_close_button;
Widget menu_print_button;

Widget menu_find_button;
Widget menu_replace_button;
Widget menu_find_again_button;
Widget menu_gotoline_button;

Widget open_dialog;		/* file selection dialog used to open a file	*/
Widget new_dialog;		/* new file name prompt dialog 		    	*/
Widget save_as_dialog;		/* save as prompt dialog	 	    */
Widget save_changes_dialog;	/* question if save file before opening a new one,
				   starting a new one, closing the file or exiting the
				   program, asked when the changes has not been saved */
Widget print_warning;		/* print warning dialog (when changes were made)*/
Widget overwrite_question;	/* question if write over an existing file for save as option */
Widget error_message;		/* general error message; should be accessed
				   via show_error_message procedure */

Widget gotoline_dialog;		/* go to line prompt dialog 			*/
Widget replace_dialog;		/* replace (change) 4-buttons prompt dialog;
				   the same dialog after dynamic changes
				   is used for the find dialog 	*/
Widget change_prompt;		/* prompt for change action: Change | Skip | Cancel | Help */
Widget continue_search_question;/* a widget to pop-up when the end or the beginning of
				   the file has been reached during the search */
Widget search_end_message;	/* message about end of the search */

Widget help_dialog;		/* simple help message */
Widget about_program_message;	/* widget with the message about the program*/

Widget changes_status;		/* widget displaying asterisk when file has been changed */
Widget line_number;		/* widget displaying line number */
Widget column_number;		/* widget displaying column number */


Widget text_to_find;		/* following 8 widgets are initialized in CreateReplaceDialog */
Widget new_text_title;
Widget new_text;
Widget case_sensitive_toggle;
Widget prompt_on_replace_toggle;
Widget whole_words_only_toggle;
Widget forward_toggle;
Widget change_all_button;
Widget change_verify_button;
Widget cancel_replace_dialog_button;

char *PROGRAM_CLASS = "Asedit";  /* should be declared as const char * -
				    but SUN does not recognize const
				    declaration yet !!!
				    */
char   *PROGRAM_NAME;		/* will be assigned from the command line */

long    changes_counter = 0L;	/* counter of changes made to a file since last
				   save; if != 0 the present file is not saved;
				   replaces file_saved for the version without
				   undo/redo */
Boolean	clipboard_filled=False; 	/* to show if there is something
					   in clipbboard to paste from */
Boolean file_read_only = False;	/* status of the read in file */
char *filename = NULL;		/* string containing file name 		    */
int reason_save_question;	/* gives the reason for prompting save_changes_dialog
				   (i.e. is equal to MENU_OPEN, MENU_NEW etc.) */
char *search_string=NULL;       /*  string to be searched for */
char *new_string=NULL;		/*  a new string after replacement */
long  start_search_position=0;  /*  starting position for a new search or change */

Pixel	text_edit_background;	/* background colour of the main text widget
				   ( it is the colour of a recessed widget) */
Pixel   text_read_only_background;	/* a lighter colour to show that the file
					   is read only */
Pixel	select_menu_background;	/* background for editable widgets pop down
				   from the menus; it is equal to the menu buttons
				   arm colour */
Pixmap	xm_question_mark;	/* Motif question mark pixmap (initialized in
				   CreateFileDialogs) */
Time	timestamp_search_request;	/* timestamp from an event that trigerred
					   the search request (used to set the
					   selection i.e. highlighting of the found text) */
int 	search_reason;
long	found_string_start_pos,
	found_string_end_pos;		/* start and end position of the found string */
long    line, column;			/* current position of a cursor */

Boolean   do_undo_redo_action = False;


#ifndef PRINT_CMD
#ifndef AMIGA
    char print_cmd[128] = "lp";
#else
    char print_cmd[128] = "type >prt:";
#endif
#else
    char print_cmd[128] = PRINT_CMD;
#endif  /* PRINT_CMD */


XmStringCharSet charset = (XmStringCharSet) XmSTRING_DEFAULT_CHARSET;
				/* used to set up XmStrings */

extern char warningBits[];	/* bits for exclamation point in dialogs; it is
				   a little bit bigger than the standard Motif one*/



XtAppContext app_context;	/* application context */


/*****************************  main  ***************************************
**
*/
#ifdef _NO_PROTO
void main (argc, argv)
	unsigned int argc;
	char *argv[];
#else  /* ! _NO_PROTO */

void main (unsigned int argc, char *argv[])
#endif
{

	Widget		main;		/*  MainWindow	 	*/
	Widget		menu_bar;	/*  RowColumn	 	*/
	Widget		work_area;	/*  work area in the main widget */

	Arg		al[10];		/*  arg list		*/
	register int	ac;		/*  arg count		*/
	char 		*work;		/* work string */
	char 		*error_open = "Error: unable to open file:\n";
	Boolean		set_signals = False;	/***!!!!!should be False; **/
	Atom            wm_delete_window;       /* used with for WM_DELETE_WINDOW */
	Atom		wm_quit_appl;		/* used with _WM_QUIT_APPL on SGI */
	Atom		clipboard_atom;		/* to check if we have something						in the clipboard */

#ifdef AMIGA
INIT_AMIWIN_MOTIF(&argc,argv);
#endif

	/* Ignore signals for now, but record whether they were already
	   ignored or not so we can catch them later if need be.
	*/
#ifndef AMIGA
	if ((signal(SIGQUIT, SIG_IGN) != SIG_IGN) &&
	    (signal(SIGINT,  SIG_IGN) != SIG_IGN))	set_signals = True;
#else
	if ((signal(SIGINT,  SIG_IGN) != SIG_IGN))	set_signals = True;
#endif


	/* 	Get application name 	*/
	if (( PROGRAM_NAME = strrchr(argv[0], (int) '/')) == NULL)
		PROGRAM_NAME = argv[0];
	else
		PROGRAM_NAME++;

	/*	Initialize toolkit and open display (!!! version dependent).	*/
#ifdef X11R3
	XtToolkitInitialize ();
	app_context = XtCreateApplicationContext();
       /* now set of fallback resources can be created by calling XtAppSetFallbackResources
	 (Motif 1.1) */

	display = XtOpenDisplay (app_context, NULL, PROGRAM_NAME, PROGRAM_CLASS,
			NULL, 0, &argc, argv);
	if (!display)
	{
		XtWarning ("can't open display, exiting...");
		exit (1);
	}
	/*	Create ApplicationShell.	*/
	toplevel = XtAppCreateShell (PROGRAM_NAME, PROGRAM_CLASS,
			applicationShellWidgetClass, display, NULL, 0);

#elif defined(X11R5)

	/* there is a subtle difference in declaration of XtAppInitialize in X11R4
	and in X11R5; in X11R4 argc_in_out is declared as Cardinal* (i.e. in
	practice unsigned int*) but in X11R5 it is declared as int *  !!!
	So to avoid messages when prototypes are used we have to differentiate
	this situation (I hate small "improvements")
	*/
	toplevel = XtAppInitialize(&app_context, (String)PROGRAM_CLASS,
			NULL, 0, (int *)&argc, argv, fallbackResources, NULL, 0);
	display = XtDisplay(toplevel);

#else
	toplevel = XtAppInitialize(&app_context, (String)PROGRAM_CLASS,
			NULL, 0, (unsigned *)&argc, argv, fallbackResources, NULL, 0);
	display = XtDisplay(toplevel);

	/* we don't have to check for a valid display because it is done in
	   XtAppInitialize (on error a message "Error: Can't Open Display" is shown )
	*/
#endif

#ifdef X11R5
	/***** X11R5 editres addition ...... *****/
        XtAddEventHandler(toplevel, (EventMask)0, True, _XEditResCheckMessages, NULL);
#endif
	/* If we need to handle keyboard signals, do it now */
#ifndef AMIGA
	if (set_signals) { signal(SIGQUIT, ByeBye);	signal(SIGINT, ByeBye); }
#endif
	/* always handle the following */
	signal(SIGTERM, ByeBye);
#ifndef AMIGA
	signal(SIGHUP,  ByeBye);
#endif

	/* Get application resources (if any) */

	/*	Create MainWindow.      */
	ac = 0;
	XtSetArg (al[ac], XmNshadowThickness, 0);  ac++;
	main = XmCreateMainWindow (toplevel, "main", al, ac);
	XtManageChild (main);


	/*	Create and manage all menus 	*/
	menu_bar = CreateMenus (main);

	/* 	Create all dialogs as children of the menu_bar	*/
	CreateFileDialogs(  menu_bar);
	CreateSearchDialogs(menu_bar);

	/* create work area in main widget */
	work_area = CreateEditWorkArea(main);

	/*	Set areas of MainWindow 	*/
	XmMainWindowSetAreas (main, menu_bar, NULL, NULL, NULL,
					work_area);


	/* create a bitmap from the data and set it as the program icon */
	/*  the easiest way of setting the icon is as follows:
	    (but it does not support different colours and it may not work on
	    some older window managers )

	  ac = 0;
	  XtSetArg(al[ac], XmNiconPixmap,
	     XCreateBitmapFromData (display,
				    XtScreen(toplevel)->root, asedit_icon_bits,
				    asedit_icon_width, asedit_icon_height));  ac++;
	  XtSetValues(toplevel, al, ac);
	***********/

	/* set asedit icon in a way that supports the best portability into
	   environments where user may not be running the most up-to-date
	   window manager; as a background and foreground colours appropriate
	   colours of the edit_text widget are used; icon_title <--- PROGRAM_NAME;
	   (in fact the icon name will be dynamically changed to show
	   the name of currently edited file - see set_titles_mwindow_icon procedure )
	 */

	set_asedit_icon(toplevel, edit_text, PROGRAM_NAME);

	/* create an About message - we create it here because we need the icon_pixmap */
        about_program_message = CreateAboutProgramMessage (menu_bar);
	/* add the help callback to accept F1 (help key) press inside the message */
	XtAddCallback (about_program_message,  XmNhelpCallback,
			 (XtCallbackProc) HelpCB, (caddr_t) MENU_H_ABOUT);

	/*	Realize toplevel widgets.	*/
	XtRealizeWidget (toplevel);


#ifndef X11R3
	/* in X11R4 we can use WM protocol callback to catch when user presses
	   the "Close" item on the system menu attached to the top-level shell
	   and make some clenup before exiting the application
	   Additionally we intercept _WM_QUIT_APP if it exists (SGI case)
	*/
	wm_delete_window = XmInternAtom(display, "WM_DELETE_WINDOW", False);
	wm_quit_appl = XmInternAtom(display, "_WM_QUIT_APP", False);
	XmAddWMProtocolCallback(toplevel, wm_delete_window,
			(XtCallbackProc) FinalCleanupCB, NULL);
	XmAddWMProtocolCallback(toplevel, wm_quit_appl,
			(XtCallbackProc) FinalCleanupCB, NULL);

	/* for the "Close" to be properly intercepted we have to set
	   XmNdeleteResponse on the toplevel shell to XmDO_NOTHING
	   (otherwise the application will still be killed!)
	*/
	ac = 0;
	XtSetArg (al[ac], XmNdeleteResponse,XmDO_NOTHING);  ac++;
	XtSetValues(toplevel, al, ac);

#endif

	/* now check if the desktop clipboard is filled ...
	   if yes enable paste button !!!
	*/
	clipboard_atom = XmInternAtom(display, "CLIPBOARD", False);
	if(XGetSelectionOwner(display, clipboard_atom))
	{
		/* the clipboard is filled ..... */
		clipboard_filled = True;
	}


	/* if a file name was specified in the command line open it */
	if(argc > 1)
	{   /* assume that the specified parameter is a filename */
	    filename = XtMalloc(strlen(argv[1])+1);
	    strcpy(filename, argv[1]);

	    /* open file; if file can't be opened or created (e.g. irregular)
	       show message and set name to NULL;  if file exists
	       open it, if does not but can be created  set the empty text */
	    if (!OpenFile(False))	/* OpenFile is called with
					only_existing_files = False */
	    {
		work = XtMalloc(strlen(error_open) + strlen(filename) +1);
		strcpy(work, error_open);
		strcat(work, filename);
		show_error_message(work);
		XtFree(filename);	filename = NULL;
		XtFree(work);
	    }
	}


	/*	Process events 	*/

	XtAppMainLoop(app_context);

} /* main */



/* Definitions of functions that accept a variable number of arguments.
   There are separate definitions for macros compatible with UNIX System V
   (<varargs.h>) and for ANSI C (<stdarg.h>).
   Use STDARG.H for ANSI C compatibility (whenever possible).
   NOTE: You can't include both STDARG.H and VARARGS.H
   A symbol _NO_STDARG is defined by me in the Imakefile !!!
*/

#ifndef _NO_STDARG
#include <stdarg.h>

#ifdef _NO_PROTO
void write_lw(/*  Widget label, XmStringCharSet charset, va_list arg_list, ...  */);

#else   /* ! _NO_PROTO */
void write_lw(Widget label, XmStringCharSet charset, va_list arg_list, ...);
#endif
#else	/*  ( _NO_STDARG) now version for non-ANSI C (UNIX system V varargs)  */

#include <varargs.h>

#ifdef _NO_PROTO
void write_lw(/* va_alist */);
#else  /* ! _NO_PROTO */
void write_lw(va_list va_alist);
#endif

#endif	/* _NO_STDARG */


/*****************************  MenuCB  *************************************
**
**	Process callbacks from PushButtons in PulldownMenus.
*/
#ifdef _NO_PROTO
void MenuCB (w, client_data, call_data)
    Widget w;
    caddr_t client_data;
    caddr_t call_data;
#else  /* ! _NO_PROTO */

void MenuCB (Widget w, caddr_t client_data, caddr_t call_data)
#endif
/*    Comment for novice users:
**    in Motif standard callback parameters are as follows:
**    Widget		w;		-   widget id
**    caddr_t		client_data;	-   data from application
**    caddr_t		call_data;	-   data from widget class
*/
{

    register int ac;		/* arg count		    */
    Arg al[10];			/* arg list		    */
    char *command;		/* command used in printing */
    XmString  xmstr;		/* work XmString */
    char      work[326];	/* work string: max. file name ~256 + strings ... */
    char      *unable_to_save_file = "Error: unable to save file:\n";

    TurnWatchCursor(True);
    switch ((int)client_data)
    {
	case MENU_OPEN:
	    /* first check if the present file has  been saved since
	       the last modification */

	    if(changes_counter == 0L)  /* OK - display the file selection dialog */
		XtManageChild (open_dialog);
	    else
	    {   /* the current file has not been saved !! Display the 'save ?'
		   question dialog. The process of displaying the open_dialog was
		   moved to the appriopriate callback of save_changes_dialog (DIALOG_SAVE_CHANGES) !!!
		   To recognize that save_changes_dialog was called from MENU_OPEN
		   the reason_save_question variable is set. */
		XtManageChild (save_changes_dialog);
		reason_save_question = MENU_OPEN;
	    }
	    break;

	    case MENU_NEW:
		if(changes_counter == 0L)  /* OK - display the prompt dialog */
			XtManageChild (new_dialog);
		else
		{    /* display the 'save ?' question dialog and ... (as above) */
		     XtManageChild (save_changes_dialog);
		     reason_save_question = MENU_NEW;
		}
		break;

	    case MENU_CLOSE:
		if (changes_counter != 0L) /* display the 'save' message dialog */
		{
		   XtManageChild (save_changes_dialog);
		   reason_save_question = MENU_CLOSE;
		}
		else	CloseFile();
		break;

	    case MENU_SAVE:
		/* create a backup file and write the current text to a file */
		if(!SaveFile())
		{	/* generate error message that file can't be saved */
		    strcpy(work, unable_to_save_file);
		    strcat(work, filename);
		    show_error_message(work);
		}
		break;

	    case MENU_SAVE_AS:
		/* Display the 'save as' dialog with the
		   present filename displayed in it. */
		ac = 0;
		xmstr = XmStringCreateLtoR (filename, charset);
		XtSetArg(al[ac], XmNtextString, xmstr);  ac++;
		XtSetValues(save_as_dialog, al, ac);
		XtManageChild (save_as_dialog);
		XmStringFree(xmstr);	/* free memory allocated for XmString */
		break;

	    case MENU_PRINT:
		if (changes_counter != 0L)   XtManageChild(print_warning);
		else if (filename != NULL)
		{
		    /* malloc space for the command name */
		    command = XtMalloc(strlen(filename) + strlen(print_cmd) + 2);
		    sprintf(command, "%s %s", print_cmd, filename);
		    if (system(command) != NULL) show_error_message("Print failed !");
		    XtFree(command);
		}
		break;

	    case MENU_EXIT:
		/* exit if there is no files open */
		if (changes_counter != 0L) /* display the 'save' message dialog */
		{
		   XtManageChild (save_changes_dialog);
		   reason_save_question = MENU_EXIT;
		}
		else
		{
		   CloseFile();	/* close up the file */
		   exit (0);	/* exit this program */
		}
		break;

	    case MENU_UNDO:
	    case MENU_REDO:
		UndoRedo((int)client_data);
		break;


#ifdef X11R3
	    /* for X11R3 functions dealing with clipboard do not exist
	       - use my old functions */
	    case MENU_CUT:
	    case MENU_COPY:	/* action is the same, except that for MENU_CUT
				   the primary selection is deleted also */
		{
		   /* needed to get the event time */
		   XmAnyCallbackStruct * cb = (XmAnyCallbackStruct *) call_data;
		   char *selected_string = XmTextGetSelection (edit_text); /* text selection    */

		   /* call a routine to copy a selection to the clipboard */
		   /* allow pasting when an item is sucessfully copied to the clipboard */
		   if( CopyStringToClipboard(selected_string,cb->event->xbutton.time) )
		   {
			clipboard_filled = True;
			/* for read only files the paste button is insensitive */
			if(!file_read_only) XtSetSensitive(menu_paste_button, True);
		   }
		   if(selected_string != NULL)
			XtFree(selected_string);   /* free allocated memory */
		   /* call routine to delete primary selection (only for the cut option)*/
		   if( (int)client_data == MENU_CUT)	DeletePrimarySelection(edit_text);
		}
		break;

	    case MENU_PASTE:
		/* call the routine that paste the text at the cursor position */
		PasteItemFromClipboard(edit_text);
		break;

	    case MENU_CLEAR:
		/* call routine to delete primary selection */
		DeletePrimarySelection(edit_text);
		break;
#else
	    /* in X11R4 text clipboard functions are defined as standard - use them */

	    case MENU_CUT:
		if( XmTextCut(edit_text, CurrentTime) )
		{   /* cut successful */
		    clipboard_filled = True;
		    /* for read only files the paste button is insensitive */
		    if(!file_read_only) XtSetSensitive(menu_paste_button, True);
		}
		break;

	    case MENU_COPY:
		if( XmTextCopy(edit_text, CurrentTime) )
		{   /* copy successful */
		    clipboard_filled = True;
		    /* for read only files the paste button is insensitive */
		    if(!file_read_only) XtSetSensitive(menu_paste_button, True);
		}
		break;
	    case MENU_PASTE:
		XmTextPaste(edit_text);
		break;

	    case MENU_CLEAR:
		XmTextClearSelection(edit_text, CurrentTime);
		break;
#endif


	    case MENU_FIND:
		/* unmanage unneeded elements inside replace_dialog widgets */
		XtUnmanageChild( new_text);
		XtUnmanageChild( new_text_title);
		XtUnmanageChild( change_all_button);
		/* not in this version:  XtUnmanageChild( prompt_on_replace_toggle);  **/
		/* set appropriate title for the "OK" button ... */
		write_lw(change_verify_button, charset, " Find Next ");

		/* set the starting position for the search */
		ac = 0;
		XtSetArg(al[ac], XmNcursorPosition, &start_search_position); ac++;
		XtGetValues(edit_text, al, ac);

		set_dialog_title(replace_dialog, "Find");
		XtManageChild(replace_dialog);

		/* set the reason for managing replace_dialog  (it is important
		   because this dialog is shared with find option, so only
		   one callback for each button was registered) */
		search_reason = MENU_FIND;
		break;

	    case MENU_CHANGE:
		set_dialog_title(replace_dialog, "Change");
		/* set appropriate title for the "OK" button ... */
		write_lw(change_verify_button, charset, "Find & Verify");

		/* set the starting position for the search */
		ac = 0;
		XtSetArg(al[ac], XmNcursorPosition, &start_search_position); ac++;
		XtGetValues(edit_text, al, ac);
		/* manage some elements inside replace_dialog which
		   might have been unmanaged when used as a find option */

		XtManageChild( new_text);
		XtManageChild( new_text_title);
		/* not in this version: XtManageChild( prompt_on_replace_toggle); */
		XtManageChild( change_all_button);
		XtManageChild(replace_dialog);
		search_reason = MENU_CHANGE;
		break;

	    case MENU_REPEAT_FIND:
		/* the last find action is repeated */
		find_string(&found_string_start_pos, &found_string_end_pos);
		break;

	    case MENU_GOTOLINE:
		XtManageChild (gotoline_dialog);
		break;

	    case MENU_H_ABOUT:
		XtManageChild (about_program_message);
		break;

	    default:
		/* an unknown client_data was received and there is no setup to handle this */
		fprintf(stderr, "Warning: an unknown client_data in menu callback\n");
		break;
    }
    TurnWatchCursor(False);

} /* MenuCB */


/*****************************  DialogOkCB  *********************************
**
**	Process callback from Dialog OK actions.
*/
#ifdef _NO_PROTO
static void DialogOkCB (w, client_data, call_data)
    Widget w;
    caddr_t client_data;
    caddr_t call_data;
#else  /* ! _NO_PROTO */

static void DialogOkCB (Widget w, caddr_t client_data, caddr_t call_data)
#endif
{
    FILE *fout;		/* used to test if the specified file exists */
    static char *save_as_filename=NULL;  /* new file name; temporary pointer -
			- the allocated memory should not be freed if
			this pointer is assigned later on to the filename */
    char 		work[326];	/* work string: max. file name ~256 + strings ... */
    XmString        xmstr;          /*  work XmString */
    Arg		    al[5];
    register int    ac;
    char	*unable_to_save_file = "Error: unable to save file:\n";

    TurnWatchCursor(True);
    switch ((int)client_data)
    {
	case DIALOG_OPEN:
	    /* open the file and read it into the text widget */
	    if (filename != NULL) { XtFree(filename); filename = NULL; }

	    {	/* grouping brackets to use local *fcb */
		XmFileSelectionBoxCallbackStruct *fcb =
			 (XmFileSelectionBoxCallbackStruct *) call_data;

		/* get the filename from the file selection box */
		XmStringGetLtoR(fcb->value, charset, &filename);
	    }

	    /* Open file, print error if it does not exist & close the previous
	       one because its name was already lost. */
	    if (!OpenFile(True))
	    {
		strcpy(work,"Error: unable to open file:\n");
		strcat(work, filename);
		/* popdown the file selection box - it is important
		   to do that before popup of the error_message  because
		   otherwise the current window lose focus !! */
		XtUnmanageChild (w);
		CloseFile();        	/* close the previous file */

		show_error_message(work);
	    }
	    else XtUnmanageChild (w);	/* popdown the file selection box */
	    break;

	case DIALOG_NEW:
	    /* open the file and read it into the text widget */
	    if (filename != NULL) { XtFree(filename); filename = NULL; }

	    { 	/* grouping brackets to use local *scb */
		XmSelectionBoxCallbackStruct *scb =
			 (XmSelectionBoxCallbackStruct *) call_data;
		/* get the filename string from the file name prompt box */
		XmStringGetLtoR(scb->value, charset, &filename);
	    }

	    /* open file if it exists, if not set the empty text;
	       if file can't be opened or created show error message and
	       close the previous file */

	    if (!OpenFile(False))    /* OpenFile is called with only_existing_files = False */
	    {
		strcpy(work,"Error: unable to open file:\n");
		strcat(work, filename);
		/* popdown the selection box - it is important
		   to do that before popup of the error_message  because
		   otherwise the current window lose focus !! */
		XtUnmanageChild (w);
		CloseFile();        	/* close the previous file */
		show_error_message(work);
	    }
	    else XtUnmanageChild (w);	/* popdown the selection box */
	    break;

	case DIALOG_SAVE_CHANGES:
	    /* save the current file, unmanage the dialog and simply proceed
	       with the action that prompted the save_changes_dialog */
	    if(!SaveFile())
	    {	/* generate error message that file can't be saved */
		strcpy(work, unable_to_save_file);
		strcat(work, filename);
		if( reason_save_question == MENU_CLOSE)
			strcat(work,	" .\nFile not closed!");
		if( reason_save_question == MENU_EXIT)
			strcat(work,	" .\nExit aborted!");
		XtUnmanageChild (w);
		show_error_message(work);
		if( reason_save_question == MENU_EXIT ||
		    reason_save_question == MENU_CLOSE)
			break;		/* do not proceed the original action */
	    }
	    else XtUnmanageChild (w);		/* popdown the save question */

	    switch(reason_save_question)
	    {
		case MENU_OPEN:
		    XtManageChild (open_dialog);
		    break;

		case MENU_NEW:
		    XtManageChild (new_dialog);
		    break;

		case MENU_CLOSE:
		    CloseFile();
		    break;

		case MENU_EXIT:
		    exit(0);
		    break;

		default:
		    /* an unknown reason_save_question */
		    fprintf (stderr, "Warning: an unknown reason_save_question in accept callback \n");
		    break;
	    }
	    break;


	case DIALOG_SAVE_AS:
	    { /* grouping brackets to use local *scb */
		XmSelectionBoxCallbackStruct *scb =
			 (XmSelectionBoxCallbackStruct *) call_data;
		/* free the memory .. (it happens when save as was selected,
		   a file with such a name existed already and the user
		   answered Cancel to overwrite question )  */
		if (save_as_filename != NULL)
			{ XtFree(save_as_filename); save_as_filename = NULL; }
		/* get the new filename string from the file selection box */
		XmStringGetLtoR(scb->value, charset, &save_as_filename);
	    }

	    /* check  if such a file already exists; if it exists
	       ask if it should be overwritten or not; if such a file
	       does not exist just save the file with the new name */

	    if ((fout = fopen(save_as_filename, "r")) != NULL)
	    {	/* file already exist ... - popup appropriate dialog */
		fclose(fout);
		XtUnmanageChild (w);
		ac = 0;
        	strcpy(work,"Overwrite existing file:\n");
        	strcat(work, save_as_filename);
        	xmstr = XmStringCreateLtoR(work, charset);
        	XtSetArg(al[ac], XmNmessageString, xmstr );  ac++;
		XtSetValues(overwrite_question, al, ac);
		XmStringFree(xmstr);
		XtManageChild (overwrite_question);
	    }
	    else
	    {   /* save as .... */
		/* free the old file name memory */
		if (filename != NULL) { XtFree(filename); filename = NULL; }
		filename = save_as_filename;	/* use this name */
			save_as_filename = NULL;
		/* setting a new title of the main window and the icon name.
		   They include the new name of the file */
		set_titles_mwindow_icon(filename);

		if(!SaveFile())
		{	/* generate error message that file can't be saved */
		    strcpy(work, unable_to_save_file);
		    strcat(work, filename);
		    XtUnmanageChild (w);
		    show_error_message(work);
		}
		else XtUnmanageChild(w);
	    }
	    break;

	case QUESTION_OVERWRITE:
	    /* overwrite the existing file ... */
	    /* free the old file name memory */
	    if (filename != NULL) { XtFree(filename); filename = NULL; }
	    filename = save_as_filename;	/* use this name */
	    save_as_filename = NULL;        /* set to NULL in order
					not to free memory allocated
					for save_as_filename (now it
					is used by filename !) */
	    /* setting a new title of the main window and the icon name.
	       They include the new name of the file */
	    set_titles_mwindow_icon(filename);

	    if(!SaveFile())
	    {	/* generate error message that file can't be saved */
		strcpy(work, unable_to_save_file);
		strcat(work, filename);
		XtUnmanageChild (w);
		show_error_message(work);
	    }
	    else XtUnmanageChild (w);
	    break;

	case DIALOG_PRINT:
	    /* save the file */
	    if (SaveFile())
	    {
		if (filename != NULL)
		{
		    sprintf(work, "%s %s", print_cmd, filename);
		    XtUnmanageChild(w);
		    if (system(work) != NULL) show_error_message("Print failed !");
		}
	    }
	    else
	    {
		strcpy(work,	unable_to_save_file);
		strcat(work, 	filename);
		strcat(work,	" .\nFile not printed.");
		XtUnmanageChild(w);
		show_error_message(work);
	    }
	    break;


	case DIALOG_FIND_OR_CHANGE:
	    /* there may be two reasons for this callback:
	       one comes from find option and the second from change
	       option; therefore we treat them separately */

	    if(search_string) { XtFree(search_string); search_string=NULL; }
	    /* get the search string */
	    search_string = (char *)XmTextGetString(text_to_find);
	    { /* grouping brackets to use local *scb */
		XmSelectionBoxCallbackStruct *scb =
			 (XmSelectionBoxCallbackStruct *) call_data;

		/* set the timestamp needed to set selection (it is
		   needed for the Search option as well ) */
		timestamp_search_request = scb->event->xkey.time;
	    }

	    /* let's set the search again button to sensitive no matter (!)
	       if the search or change actions happened */
	    if(search_string != NULL)
		XtSetSensitive(menu_find_again_button,   True);

	    if(search_reason == MENU_FIND)   /* find operation */
	    {
		find_string(&found_string_start_pos, &found_string_end_pos);
	    }
	    else
	    {		/* find & confirm change operation */
		if(new_string)  { XtFree(new_string);  new_string=NULL; }
		new_string = (char *)XmTextGetString(new_text);
		find_string(&found_string_start_pos, &found_string_end_pos);
		/* if the string was found prompt up the change prompt */
		if(found_string_start_pos >= 0L )
		{
		    /* make the buttons insensitive ...*/
		    set_change_buttons_sensitivity(False);
		    XtManageChild(change_prompt);
		}
	    }
	    break;

	case DIALOG_GOTOLINE:
	    { /* grouping brackets to use local *scb */
		XmSelectionBoxCallbackStruct *scb =
			 (XmSelectionBoxCallbackStruct *) call_data;
		long line_no, position, found_lines;
		String text_buffer;
		Arg    al[2];
		char   *line_string=NULL;

		/* get the line number string from the gotoline prompt box */
		XmStringGetLtoR(scb->value, charset, &line_string);

		line_no = atol(line_string);	/* convert the string into the line number */
		/* free the memory allocated for line_string, because it is no longer needed */
		XtFree(line_string);

		/* get the address of the internally stored text */
		XtSetArg(al[0], XmNvalue, &text_buffer);
		XtGetValues(edit_text, al, 1);

		/* find a position of the line in the text widget buffer;
		     if the position is < 0 the line has not been found,
		     therefore pop up appriopriate dialog;
		     if position >= 0 OK go there ... */
		position = find_line_pos(line_no, text_buffer, &found_lines);

#ifndef	GET_TEXT_VALUE_BUG_FIXED
		/* There is a misdesign in the current implementation of the Text
		   widget. A method of obtaining XmNvalue by calling XtGetValues()
		   or XtVaGetValues() (in the appropriate way) should return
		   a pointer to internal data stored in the Text widget. In reality
		   the Text widget responds by allocating memory and returning
		   a copy of the text just like XmTextGetString(). Currently
		   this data MUST be freed after use (otherwise we get memory
		   leakage!). If that design misfeature is fixed in a feature
		   release of the Motif toolkit we should define
		   		GET_TEXT_VALUE_BUG_FIXED
		   in the Imakefile/Makefile/source or get rid of appropriate
		   "ifndef's" altogether ! (they appears in 2 files: asedit.c
		   and undo.c).
		*/
		XtFree(text_buffer);
#endif	/* GET_TEXT_VALUE_BUG_FIXED */
		if(position >= 0L)
		{
		    XtSetArg(al[0], XmNcursorPosition, position);
		    XtSetValues(edit_text, al, 1);

		    /* display the line & column numbare (column = 1) - !!!
			this is available only for the version with _SHOW_LINE_COLUMN
			defined */
#ifdef _SHOW_LINE_COLUMN
			line = line_no;	/* global value of line & column */
			column = 1;
			write_lw(line_number,   charset, "%ld", line);
			write_lw(column_number, charset, "1");
#endif
		}
		else
		{
		    sprintf(work,
			 "Line number is not within the legal range.\nLegal range is:\n               1 - %ld",
			 found_lines);
		    show_error_message(work);
		}
	    }
	    break;

	case DIALOG_CHANGE_PROMPT:
	    /* the first and last position of the string to change
	       has been set already so just use them ... */
	    XmTextReplace(edit_text, found_string_start_pos, found_string_end_pos, new_string);

	    /**  there is a very strange bug/behauviour (?)  of text widget
	      (Motif 1.0, Motif 1.1 ...?) that appears when I use
	      replace during the backward search: when the new text is longer
	      than the previous one the cursor position internally seems to
	      be greater then it should be for that difference; when we activate
	      the text widget then everything is O.K. but when we go straight
	      to further search that difference exists!! (and it may cause
	      annoyance in case when you change for example 'test' into 'tests';
	      this will cause 1 position difference in a new search and this is
	      enough to spoil it - the word test will be found again and again,
	      as long as we answer OK to replace !!! & and changed to testsss... )
	      (a starting position for a search is found as a current cursor
	      position !)
	      To correct that wrong start I introduce a hack as follow
	    ***/
	    /* set the cursor position; next search will start from that place (if any) */
	    /******   TO BE WRITTEN !!!!!  XtSetArg(al[0], XmNcursorPosition, position);
		    XtSetValues(edit_text, al, 1);
	    ****** TO BE WRITTEN ********************/


	    /* now the find and verify should be continued .... */
	    find_string(&found_string_start_pos, &found_string_end_pos);
	    if(found_string_start_pos < 0L )
	    {
		XtUnmanageChild(w);
		/* restore the sensitivity of the buttons  */
		set_change_buttons_sensitivity(True);
	    }
	    break;

	case QUESTION_CONTINUE_SEARCH:
	    XtUnmanageChild(w);
#ifndef AMIGA
	    XFlush(display);	/*  because the search options may take a long while 
				    and the cursor is timed out lets explicitly flush the display*/
#endif
	    change_all_found_strings(False);	/* continue the previous change
						all process (do not start a new one) */
	    break;

	default:
	    /* an unknown callback type */
	    fprintf (stderr, "Warning: in accept callback\n");
	    break;
    }
    TurnWatchCursor(False);
} /* DialogOkCB */


/*****************************  DialogApplyCB  ******************************
**
**	Process callbacks from Dialog apply actions.
**	(often this action is equivalent to the No answer !)
*/
#ifdef _NO_PROTO
static void DialogApplyCB (w, client_data, call_data)
    Widget w;
    caddr_t client_data;
    caddr_t call_data;
#else  /* ! _NO_PROTO */

static void DialogApplyCB (Widget w, caddr_t client_data, caddr_t call_data)
#endif
{
    char *command;			/* command used in printing */

    TurnWatchCursor(True);
    switch ((int)client_data)
    {
	case DIALOG_SAVE_CHANGES:
	    /* "NO" answer: do not save the current file, simply proceed with
		the action that prompted the save_changes_dialog (first pop
		down the save changes dialog) */
	    XtUnmanageChild (w);
	    switch(reason_save_question)
	    {
		case MENU_OPEN:
		    XtManageChild (open_dialog);
		    break;

		case MENU_NEW:
		    XtManageChild (new_dialog);
		    break;

		case MENU_CLOSE:
		    CloseFile();
		    break;

		case MENU_EXIT:
		    exit(0);
		    break;

		default:
		    /* an unknown reason_save_question */
		    fprintf (stderr, "Warning: an unknown reason_save_question in cancel callback \n");
		    break;
	    }
	    break;

	case DIALOG_PRINT:
	    if (filename != NULL)
	    {
		/* malloc space for the command name */
		command = XtMalloc(strlen(filename) + strlen(print_cmd) + 2);
		sprintf(command, "%s %s", print_cmd, filename);
		if (system(command) != NULL) show_error_message("Print failed !");
		XtFree(command);
	    }
	    else XtUnmanageChild(w);
	    break;

	case DIALOG_FIND_OR_CHANGE:
	    if(search_reason == MENU_CHANGE)  /* change all options */
	    {
		/* get the strings ... */
		if(search_string) { XtFree(search_string); search_string=NULL; }
		/* get the search string */
		search_string = (char *)XmTextGetString(text_to_find);

		if(new_string)  { XtFree(new_string);  new_string=NULL; }
		new_string = (char *)XmTextGetString(new_text);

		{ /* grouping brackets to use local *scb */
		    XmSelectionBoxCallbackStruct *scb =
			 (XmSelectionBoxCallbackStruct *) call_data;

		    /* set the timestamp needed to set selection (it is
		       needed for the Search option as well ) */
		    timestamp_search_request = scb->event->xkey.time;
		}

		  /* let's set the search again button to sensitive */
		if(search_string != NULL)
		    XtSetSensitive(menu_find_again_button,   True);


		/* we make insensitive the "Find & Verify" and "Change All" buttons
		   to show the user which dialog he should concentrate on
		   and not to confuse him */
		set_change_buttons_sensitivity(False);

		change_all_found_strings(True);

		/* the buttons sensitivity will be restored as a response
		   to a message ending the change all process **/
	    }
	    break;

	case DIALOG_CHANGE_PROMPT:
	    /* skip the replace but continue the search */
	    find_string(&found_string_start_pos, &found_string_end_pos);
	    if(found_string_start_pos < 0L )
	    {
		XtUnmanageChild(w);
		/* restore the buttons sensitivity */
		set_change_buttons_sensitivity(True);
	    }
	    break;

	default:
	    /* an unknown client_data was received and there is no setup to handle this */
	    fprintf (stderr, "Warning: an unknown client_data in apply callback\n");
	    break;

    }
    TurnWatchCursor(False);
} /* DialogApplyCB */


/*****************************  DialogCancelCB  *****************************
**
**	Process callbacks from Dialog cancel actions.
**
**	(because we access that procedure from inside ht_help we didn't declare
**	it as static)
*/
#ifdef _NO_PROTO
void DialogCancelCB (w, client_data, call_data)
    Widget w;
    caddr_t client_data;
    caddr_t call_data;
#else  /* ! _NO_PROTO */

void DialogCancelCB (Widget w, caddr_t client_data, caddr_t call_data)
#endif
{

    switch ((int)client_data)
    {

	case DIALOG_OPEN:
	case DIALOG_NEW:
	case DIALOG_SAVE_AS:
	case DIALOG_PRINT:
	case DIALOG_SAVE_CHANGES:
	case QUESTION_OVERWRITE:
	case DIALOG_FIND_OR_CHANGE:
	case DIALOG_GOTOLINE:
	case ERROR_MESSAGE:

	    /* popdown the dialog (important when autoUnmanage set to False ) **/
	    XtUnmanageChild (w);
	    break;

	case HTEXT_HELP:
	/* !!!!!! remember to change this in asedit !!!!!!! */
	    /* unmanage specifically help_dialog (in one of version of ht_help
	        the close button must unmanage the parent shell !!!) */
	    XtUnmanageChild(help_dialog);
	    break; 

	case DIALOG_CHANGE_PROMPT:
	case QUESTION_CONTINUE_SEARCH:
	case MESSAGE_SEARCH_END:	/* Close option */
	    XtUnmanageChild (w);
	    /* restore the sensitivity of the change buttons */
	    set_change_buttons_sensitivity(True);
	    break;

	default:
	    /* an unknown client_data was received and
	       there is no setup to handle this */
	    fprintf (stderr, "Warning: an unknown client_data in cancel callback\n");
	    break;
    }
} /* DialogCancelCB */



/*****************************  TextCB  *************************************
**
**	Process callbacks from edit_text widget.
**	 i.e. modifyVerifyCallback and motionVerifyCallback
*/
#ifdef _NO_PROTO
void TextCB (w, client_data, call_data)
    Widget w;
    caddr_t client_data;
    caddr_t call_data;
#else  /* ! _NO_PROTO */

void TextCB (Widget w, caddr_t client_data, caddr_t call_data)
#endif
{

    XmTextVerifyCallbackStruct  *txt_data = (XmTextVerifyCallbackStruct *) call_data;
    long pos;			/* in Motif XmTextPosition is defined as long */
    String text_buffer;
    Arg    al[2];
    int    reason;		/* reason for the callback */






    reason = txt_data->reason;

#ifdef _AS_DEBUG
    fprintf(stderr,"\nText: %s:\n",
		reason == XmCR_MODIFYING_TEXT_VALUE ? "MODIFYING_TEXT_VALUE" :
		reason == XmCR_MOVING_INSERT_CURSOR ? "MOVING_INSERT_CURSOR" : "unknown"
		);
#endif

    switch(reason)
    {
	case XmCR_MODIFYING_TEXT_VALUE:
	    /* increase the changes_counter to indicate that the file has been modified
	       and the user should be notified before loading a new one, closing
	       this one, exiting from the program etc.. */
	    if(!do_undo_redo_action)
	    {
		if(changes_counter < 0L) changes_counter = 0L;
		changes_counter ++;
#ifdef _SHOW_LINE_COLUMN
		if(changes_counter == 1L)	/* show asterisk changes_status widget */
			write_lw(changes_status, charset, "*");
#endif

	    }

	    break;

	case XmCR_MOVING_INSERT_CURSOR:
	    break;

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


    if(!do_undo_redo_action)
	SaveActionForUndo( w, client_data, call_data);  /* save the action for undo */
    do_undo_redo_action = False;


    /* for all reasons ... */

    /* get the address of the internally stored text */
    XtSetArg(al[0], XmNvalue, &text_buffer);
    XtGetValues(w, al, 1);

    pos = txt_data->newInsert;

    /* for MODIFYING_TEXT_VALUE because the changes have not been done yet it
       is better to use the startPos instead of newInsert . It is exactly
       the same for entering information but it is more appropriate for deleting
       information !!!!*/
    if(reason == XmCR_MODIFYING_TEXT_VALUE && txt_data->startPos < txt_data->newInsert)
		pos = txt_data->startPos;

    /****!!!!!! try instead of the previous line .....
      (this if is compulsory because for moving reason startPos is not defined !!)
	    if(reason == XmCR_MODIFYING_TEXT_VALUE ) pos = txt_data->startPos;
     ******/


#ifdef _SHOW_LINE_COLUMN
    {
      long buf_size;		/* size of the text buffer */
      /****March 92  long     line, column;  ***/
      /* only for version which shows line and column during editing:
       (remember current implementation of this slows the editing
	considerably)
      */
      /* convert the current position into line and column and write them into
       appropriate widgets */

      buf_size = (long) strlen(text_buffer);

      /* for the MODIFYING_TEXT_VALUE  (when the text is entered) the
	increment of the column and line number will be calculated
	on the basis what text is entered;
      */
      if(reason == XmCR_MODIFYING_TEXT_VALUE && txt_data->text->length > 0)
      {

	/* there is some extra text to enter; usually it is one character from
	   the keyboard but it may be more than one character from the paste
	   operation. Therefore call a procedure to find how many extra lines
	   and/or columns will be added (taking into accounts tab characters) */
	long extra_column, extra_line;
	textPosToLineColumn(txt_data->text->ptr, (long)txt_data->text->length,
		 (long)txt_data->text->length, &extra_line, &extra_column);
	if(extra_line <= 1)	/* there was no extra line */
		column += extra_column-1 ;
	else			/* there were extra lines so column value is reset */
	{
		column = extra_column;
		line  += extra_line - 1;
	}

      }
      else  textPosToLineColumn(text_buffer, buf_size, pos, &line, &column);

      write_lw(line_number,   charset, "%ld", line);
      write_lw(column_number, charset, "%ld", column);

#ifdef _AS_DEBUG
	fprintf(stderr, "Position: %ld  line: %ld column: %ld\n", pos, line, column);
	fprintf(stderr, "callback el.: currInsert %ld newInsert %ld startPos %ld endPos %ld\n",
			txt_data->currInsert, txt_data->newInsert,
			txt_data->startPos,   txt_data->endPos);
	/* for modifying data print what's in the text block */
	if(reason == XmCR_MODIFYING_TEXT_VALUE && txt_data->text != NULL)
	{
	    fprintf(stderr,"Text block length & 1st byte: %d %c", txt_data->text->length,
					txt_data->text->ptr[0]);

	}

#endif	/* end of conditional _AS_DEBUG */
    }

#endif	/* end of conditional asedit _SHOW_LINE_COLUMN version */

#ifndef	GET_TEXT_VALUE_BUG_FIXED
    XtFree(text_buffer);
#endif	/* GET_TEXT_VALUE_BUG_FIXED */
} /* TextCB*/

/*****************************	OpenFile  ************************************
**
**	Calls ReadFile to read the file. Returns true if file
** 	exists and open is sucessful (for only_existing_files).
**	Parameter only_existing_files gives a way of using this
**	procedure for both file options: Load (only_existing_files=True)
**	and New (only_existing_files parameter should be False).
**	Adds file contents to the
**	appropriate widget, makes appropriate items sensitive etc.
**	Calls a procedure to set the title ot the main window (toplevel widget)
**      and the icon name.
*/
#ifdef _NO_PROTO
Boolean OpenFile(only_existing_files)
   Boolean only_existing_files;
#else  /* ! _NO_PROTO */

Boolean OpenFile(Boolean only_existing_files)
#endif
{
   char * file_string=NULL;	/* Contents of file. 	  */
   Boolean         read_only;		/* shows the file read only status */
   register int ac;			/* arg count		    */
   Arg al[10];				/* widget arg list	    */
   struct stat statbuf;			/* Information on a file. */

   /* make sure the file is a regular text file (if not return FALSE
      immediately)*/
   if(stat(filename, &statbuf) == 0  &&
	(statbuf.st_mode & S_IFMT) != S_IFREG )
   {
	/*!!!!! temporary output .... */
	fprintf(stderr, "\n%s: not a regular file.", filename);
	return(FALSE);
   }


   if( (file_string = ReadFile(filename, &read_only)) != NULL  ||
		!only_existing_files)
   {
	   file_read_only = read_only;


	   ac = 0;
	   XtSetArg(al[ac], XmNeditable, !file_read_only); ac++; /* if file is read only
						editable is set to False & vice versa */
	   /* set appropriate colour for the text widget to distinguish between
	      editable and read-only files */
	   if(file_read_only) XtSetArg(al[ac], XmNbackground, text_read_only_background);
	   else		      XtSetArg(al[ac], XmNbackground, text_edit_background);
	   ac++;
	   XtSetArg(al[ac], XmNsensitive, True);	ac++;	/* make text sensitive */
	   XtSetValues(edit_text, al, ac);

	   /* we have to use XmTextSetString to set the string; when I use
	      XtSetArg(al[ac], XmNvalue, (char *) file_string); etc... it does not
	      work properly when file_string was empty and the rest was the same
	      probably;  it does not work occasionally during loading of a file (comments
	      from Kennan (i.e. the there is an inconsistent behaviour );
	   ****/
	   XmTextSetString(edit_text, (char *)file_string);  /* add the file string to the text widget */

	   /* free the memory associated with the file_string */
	   if(file_string != NULL) XtFree(file_string);

	   /* reinitialize the changes counter, reset undo/redo stacks */
	   changes_counter = 0L;
	   reset_undo_redo();
#ifdef _SHOW_LINE_COLUMN
	   /* write appropriate info into changes_status widget */
	   if(!file_read_only)   write_lw(changes_status, charset, " ");
	   else 		 write_lw(changes_status, charset, "R");
#endif


	   /* make undo/redo buttons insensitive */
	   XtSetSensitive(menu_undo_button,  False);
	   XtSetSensitive(menu_redo_button,  False);
#ifndef AMIGA
	   XFlush(display);		/* make sure that these buttons are
					   insensitive before processing any keyboard
					   actions (for very busy systems)*/
#endif


	   /* make appropriate items sensitive */
	   XtSetSensitive(menu_copy_button, True);
	   /* set the sensitivity of buttons dependend only on read_only
	      status of the file (cut button, clear button, replace button)
	   */
	   if(!file_read_only)
	   {
		XtSetSensitive(menu_cut_button, 	True);
		XtSetSensitive(menu_clear_button, 	True);
		XtSetSensitive(menu_replace_button, 	True);
	   }
	   else
	   {
		XtSetSensitive(menu_cut_button, 	False);
		XtSetSensitive(menu_clear_button, 	False);
		XtSetSensitive(menu_replace_button, 	False);
	   }
	   /* set the sensitivity of the paste button */
	   if(!file_read_only && clipboard_filled)
			XtSetSensitive(menu_paste_button, True);
	   else   	XtSetSensitive(menu_paste_button, False);

	   /* set appropriate file buttons to sensitive */
	   XtSetSensitive(menu_close_button,	True);
	   XtSetSensitive(menu_save_as_button, 	True);
	   XtSetSensitive(menu_print_button,	True);
	   /* menu_save_button will be insensitive for read only files .... */
	   if(!file_read_only)	XtSetSensitive(menu_save_button, True);
	   else			XtSetSensitive(menu_save_button, False);

	   /* set appropriate search buttons to sensitive */
	   XtSetSensitive(menu_find_button,         True);
	   XtSetSensitive(menu_gotoline_button,     True);
	   if( search_string != NULL)
		   XtSetSensitive(menu_find_again_button,   True);
	   else    XtSetSensitive(menu_find_again_button,   False);

	   /* setting a new title of the main window and the icon name.
	       They include the name of the file just opened */
	   set_titles_mwindow_icon(filename);
	   return(True);
   }
   else
   {
	   /* setting a new title (name of the program only) */
	   set_titles_mwindow_icon(NULL);
	   return(False);
   }

}  /* OpenFile */



/*****************************  SaveFile  ************************************
**  	Save the currently edited file.
*/
#ifdef _NO_PROTO
Boolean SaveFile()
#else  /* ! _NO_PROTO */

Boolean SaveFile(void)
#endif
{
    char * file_string = NULL;	   /* Contents of file.		      */
    Boolean	    result;

    /* get the text string */
    file_string = XmTextGetString(edit_text);

    result = WriteFile(filename, file_string);

    if (file_string != NULL)  XtFree(file_string); /* free the text string */

    if(result)
    {
	changes_counter = 0L;
#ifdef _SHOW_LINE_COLUMN
	write_lw(changes_status, charset, " ");
#endif
	return(True);
    }
    else return(False);

}   /* SaveFile */


/*****************************  CloseFile  ***********************************
**
**  	Close the present file. Set sensitivity of appropriate menu items.
*/
#ifdef _NO_PROTO
void CloseFile()
#else  /* ! _NO_PROTO */

void CloseFile(void)
#endif
{
    /* zero out the text string in the text widget.
       Warning: it causes a value changed callback. */
    Arg al[5];
    register int ac;

    /* we use Motif convenience function  to zero out the text instead of setting the resources in one
       go  i.e. using additionally XtSetArg(al[ac], XmNvalue , "");  ac++; because we have some problems
       with the other method in the ReadFile procedure; so to be on a safe side .... */
    XmTextSetString(edit_text, "");
    ac = 0;
    XtSetArg(al[ac], XmNsensitive, False);	ac++;	/* set text to insensitive */
    /* set the colour of the text background to read only colour */
    XtSetArg(al[ac], XmNbackground, text_read_only_background);	ac++;
    XtSetValues(edit_text, al, ac);

    /* reinitialize the changes counter, reset redo/undo stacks */
#ifdef _SHOW_LINE_COLUMN
    changes_counter = 0L;  write_lw(changes_status, charset, " ");
#endif
    reset_undo_redo();




    /* free the file name */
    if (filename != NULL) { XtFree(filename);	filename = NULL; }

#ifdef _SHOW_LINE_COLUMN
    /* blank the line & column number display  */
	write_lw(line_number,   charset, " ");
	write_lw(column_number, charset, " ");
#endif

    /* unmanage replace_dialog & save_as_dialog if they are active (they
       may be on the screen and they do not make any sense when no file is open) */
    XtUnmanageChild( replace_dialog );
    XtUnmanageChild( save_as_dialog );



    /* set appropriate file buttons to insensitive */
    XtSetSensitive(menu_close_button,   False);
    XtSetSensitive(menu_save_button,    False);
    XtSetSensitive(menu_save_as_button, False);
    XtSetSensitive(menu_print_button,   False);

    XtSetSensitive(menu_undo_button,  False);
    XtSetSensitive(menu_redo_button,  False);
    XtSetSensitive(menu_cut_button,   False);
    XtSetSensitive(menu_copy_button,  False);
    XtSetSensitive(menu_paste_button, False);
    XtSetSensitive(menu_clear_button, False);

    XtSetSensitive(menu_find_button,         False);
    XtSetSensitive(menu_replace_button,      False);
    XtSetSensitive(menu_find_again_button,   False);
    XtSetSensitive(menu_gotoline_button,     False);

    /* setting a new title of the main window (name of the program only) */
    set_titles_mwindow_icon(NULL);

}   /* CloseFile */




/*****************************  CreateMenus  *********************************
**
**		Create all menus as children of a MenuBar
**		Returns the MenuBar
*/
#ifdef _NO_PROTO
static Widget CreateMenus (parent)
	Widget parent;
#else  /* ! _NO_PROTO */

static Widget CreateMenus (Widget parent)
#endif
{
	Widget		menu_bar;	/*  RowColumn	 		*/
	Widget		help_button;	/*  cascade help button		*/

	Arg		al[10];		/*  arg list			*/
	register int	ac;		/*  arg count			*/
	Pixel		background;	/* used for proper set up of mono screens */
	Pixel		foreground;



	/*  Create and manage a menu bar (menu area). */
	menu_bar = XmCreateMenuBar(parent, "menu_bar", NULL, 0);

	/* Create the menu from the description */

	as_create_menuh(NULL, menu_bar, Main_menu,
			 XtNumber(Main_menu), charset);

	XtManageChild(menu_bar);

	/* setting the global widgets (they must be accessible from other
	   procedures) to widgets created in the as_create_menuh procedure */
	/*****  watch out to set these properly !!!!! */

	menu_undo_button  = Edit_menu[0].w;
	menu_redo_button  = Edit_menu[1].w;
	/*                            2  - separator in the menu */
	menu_cut_button   = Edit_menu[3].w;
	menu_copy_button  = Edit_menu[4].w;
	menu_paste_button = Edit_menu[5].w;
	/* 			      6  - separator ... */
	menu_clear_button = Edit_menu[7].w;

	menu_close_button  = File_menu[2].w;
	menu_save_button   = File_menu[3].w;
	menu_save_as_button= File_menu[4].w;
	menu_print_button  = File_menu[6].w;

	menu_find_button  	=	Search_menu[0].w;
	menu_find_again_button 	= 	Search_menu[1].w;
	menu_replace_button	=	Search_menu[2].w;
	menu_gotoline_button    = 	Search_menu[3].w;


	/* turn off sensitivity of undo, redo, cut, copy, paste and clear buttons */
	XtSetSensitive(menu_undo_button,  False);
	XtSetSensitive(menu_redo_button,  False);
	XtSetSensitive(menu_cut_button,   False);
	XtSetSensitive(menu_copy_button,  False);
	XtSetSensitive(menu_paste_button, False);
	XtSetSensitive(menu_clear_button, False);

	/* set appropriate file buttons to insensitive */
	XtSetSensitive(menu_close_button,   False);
	XtSetSensitive(menu_save_button,    False);
	XtSetSensitive(menu_save_as_button, False);
	XtSetSensitive(menu_print_button,   False);

	/* set all search buttons to insensitive */
	XtSetSensitive(menu_find_button,         False);
	XtSetSensitive(menu_replace_button,      False);
	XtSetSensitive(menu_find_again_button,   False);
	XtSetSensitive(menu_gotoline_button,     False);


	/* get a colour to be used for editable text widgets; the colour
	   will be the same as a colour of an armed button */
	ac = 0;
	XtSetArg(al[ac],  XmNbackground, &background);          ac++;
	XtSetArg(al[ac],  XmNforeground, &foreground);          ac++;
	XtSetArg(al[ac],  XmNarmColor, &select_menu_background); 	ac++;
	XtGetValues(menu_find_button, al, ac);
	/* now check if the select_menu_background is not by chance identical
	   with the background (it happens on mono screens or for a black/white
	   setup); if so do not apply it, but use the standard background.
	 */
	if(select_menu_background == foreground)
		select_menu_background = background;
#ifdef AMIGA
        select_menu_background=background;
#endif


	/* create the Help button and help pulldown menu using a predefined
	   structure and my procedure */

	as_create_menuh(NULL, menu_bar, help_Main_menu,
			 XtNumber(help_Main_menu), charset);

	/* setting the help cascade button */
	help_button   = help_Main_menu[0].w;

	ac = 0;
	XtSetArg (al[ac], XmNmenuHelpWidget, help_button);  ac++;
	XtSetValues (menu_bar, al, ac);


	/* create a hypertext help dialog */

	ac=0;
	help_dialog =  CreateHyperTextHelp(menu_bar, "help window", al, ac);

	/* the title of a help_dialog created as above can't be set
	   using our standard procedure set_dialog_tile; we have to use
	   XmNtitle resource ....
	*/
	{
	     char	  work[256];
	     sprintf(work, "%s - %s", PROGRAM_NAME, "Help");
	     ac=0;
	     XtSetArg (al[ac], XmNtitle, work);   ac++;
	     XtSetValues(XtParent(help_dialog), al, ac);
	}

	return (menu_bar);
} /* CreateMenus */


/*****************************  CreateFileDialogs  **************************
**
**		Create all dialogs related to file operations as a
**		children of parent (usually the menu_bar)
*/
#ifdef _NO_PROTO
void CreateFileDialogs (menu_bar)
	Widget menu_bar;
#else  /* ! _NO_PROTO */

void CreateFileDialogs (Widget menu_bar)
#endif
{
	Widget 		kids[3];	/*  children widget */

	XImage		*image;		/*  image for warning pixmap	*/

	Arg		al[10];		/*  arg list			*/
	register int	ac;		/*  arg count			*/
	char 		work[326];
	int 		i;
	XmString	xmstr;		/*  work XmString */


	image = CreateDefaultImage (warningBits, 32, 32);
	XmInstallImage (image, "warning_image");


	/* create a dialog for opening a file  */
	ac=0;
	open_dialog = XmCreateFileSelectionDialog(menu_bar,
			   "file selection dialog", al, ac);
	set_dialog_title(open_dialog, "Load a File");

	XtAddCallback (open_dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB,    (caddr_t)DIALOG_OPEN);
	XtAddCallback (open_dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB,(caddr_t)DIALOG_OPEN);
	XtAddCallback (open_dialog, XmNhelpCallback,
			(XtCallbackProc)HelpCB,        (caddr_t)DIALOG_OPEN);

	/* set the colours for editable widgets */
	kids[0] = XmFileSelectionBoxGetChild(open_dialog, XmDIALOG_TEXT);
	kids[1] = XmFileSelectionBoxGetChild(open_dialog, XmDIALOG_FILTER_TEXT);
	ac =0;
	XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
	XtSetValues(kids[0], al, ac);
	XtSetValues(kids[1], al, ac);


	/* create a new dialog */
	ac = 0;
	xmstr =XmStringCreateLtoR("Enter name of a new file.", charset);
	XtSetArg(al[ac], XmNselectionLabelString, xmstr );  ac++;
	XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
	new_dialog = XmCreatePromptDialog(menu_bar,
			   "new file dialog", al, ac);
	XmStringFree(xmstr);		/* free memory allocated for XmString */
	set_dialog_title(new_dialog, "New File");

	XtAddCallback (new_dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB,    	(caddr_t)DIALOG_NEW);
	XtAddCallback (new_dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB,	(caddr_t)DIALOG_NEW);
	XtAddCallback (new_dialog, XmNhelpCallback,
			(XtCallbackProc)HelpCB,	    	(caddr_t)DIALOG_NEW);

	/* set the colour for the editable text widget */
	kids[0] = XmSelectionBoxGetChild(new_dialog, XmDIALOG_TEXT);
	ac =0;
	XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
	XtSetValues(kids[0], al, ac);
        /* set a special callback which will set the focus to the text widget
	   when the dialog gets its first focus */

	/* unfortunately the idea of setting the keyboard focus to a specific
	    widget when the dialog gets the focus for the first time (using
	    two functions: focusCB, focusTO) DOES NOT work properly on DEC
	    computers with X11R4 and Motif 1.1 !!! so we are making conditional
	    compilation for all such calls.
	    (I have tried also the idea when we register the focus callbacks
	     AFTER all widgets have been managed, but UNFORTUNATELY it didn't
	     work either. Other ways of setting the focus into a predefined
	     widget using keyboard traversal failed as well, mainly because the
	     widget, and all of its ancestors,  does need to be realized BEFORE
	     you call XmProcessTraversal !
	     So I have reluctantly decided to use conditional compilation
	     #ifndef XFOCUS_BUG whenever necessary).
	**/

#ifndef XFOCUS_BUG
	XtAddCallback(new_dialog, XmNfocusCallback,
			(XtCallbackProc)focusCB, (caddr_t)kids[0]);
#endif



	/* create special error_message widget used to display error messages
	   using show_error_message procedure */
	ac = 0;
	XtSetArg(al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ac++;
	XtSetArg(al[ac], XmNmessageString, XmStringCreateLtoR
		   ("Error message", charset));  ac++;
	/* we are using the Cancel button for the closing of that message
	   mainly because that button will be automatically centered */
	XtSetArg (al[ac], XmNcancelLabelString, XmStringCreateLtoR
		(" OK ", charset)); ac++;
	/* 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++;

	error_message = XmCreateErrorDialog (menu_bar, "error_message",al,ac);
	set_dialog_title(error_message, "Error!");

	/* unmanage the unneeded buttons */
	i=0;
	kids[i++] = XmMessageBoxGetChild(error_message, XmDIALOG_HELP_BUTTON);
	kids[i++] = XmMessageBoxGetChild(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 (error_message, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB,  (caddr_t)ERROR_MESSAGE);



	/* create save changes warning dialog */
	ac = 0;
	XtSetArg(al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ac++;
	XtSetArg (al[ac], XmNokLabelString, XmStringCreateLtoR
			(" Yes ", charset));  	ac++;
	XtSetArg (al[ac], XmNapplyLabelString, XmStringCreateLtoR
			(" No ", charset));  	ac++;
	XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;

	save_changes_dialog = create_4buttons_image_dialog(menu_bar, "save_warning",
				      "warning_image", "Save Current Changes?", al, ac);
	set_dialog_title(save_changes_dialog, "File not Saved!");

	XtAddCallback (save_changes_dialog, XmNokCallback,
		       (XtCallbackProc)DialogOkCB, 	(caddr_t)DIALOG_SAVE_CHANGES);
	XtAddCallback (save_changes_dialog, XmNapplyCallback,		/* No answer */
		       (XtCallbackProc)DialogApplyCB, 	(caddr_t)DIALOG_SAVE_CHANGES);
	XtAddCallback (save_changes_dialog, XmNcancelCallback,
		       (XtCallbackProc)DialogCancelCB,  (caddr_t)DIALOG_SAVE_CHANGES);
	XtAddCallback (save_changes_dialog, XmNhelpCallback,
		       (XtCallbackProc)HelpCB, (caddr_t)DIALOG_SAVE_CHANGES);



	/* create save as dialog */
	ac = 0;
	XtSetArg(al[ac], XmNselectionLabelString, XmStringCreateLtoR
			   ("Save File As", charset));  ac++;
	XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
	save_as_dialog = XmCreatePromptDialog(menu_bar, "save_dialog", al, ac);
	set_dialog_title(save_as_dialog, "Save As");
	XtAddCallback (save_as_dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB, 	(caddr_t)DIALOG_SAVE_AS);
	XtAddCallback (save_as_dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, (caddr_t)DIALOG_SAVE_AS);
	XtAddCallback (save_as_dialog,XmNhelpCallback,
			(XtCallbackProc)HelpCB, 	(caddr_t)DIALOG_SAVE_AS);

	/* set the colour for the editable text widget */
	kids[0] = XmSelectionBoxGetChild(save_as_dialog, XmDIALOG_TEXT);
	ac =0;
	XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
	XtSetValues(kids[0], al, ac);
	/* set a special callback to set the focus to the text widget
	   when the dialog gets its first focus */
#ifndef XFOCUS_BUG
	XtAddCallback(save_as_dialog, XmNfocusCallback,
			(XtCallbackProc)focusCB, (caddr_t)kids[0]);
#endif


	/* create the overwrite_question widget */
	ac = 0;
	strcpy(work,"Overwrite existing file:\n");
	/* !!!!!! in the next line on the SG an error was happenning !!!!! */
	/* there is apparently bug on SG when you try to strcat NULL string,
	   so I make conditional strcat .... (11.03.92) */
	if(filename) strcat(work, filename);
	xmstr = XmStringCreateLtoR(work, charset);
	XtSetArg(al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ac++;
	XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
	XtSetArg(al[ac], XmNmessageString, xmstr );  ac++;
	XtSetArg(al[ac], XmNokLabelString, XmStringCreateLtoR
	   (" Yes ", charset));  ac++;
	XtSetArg(al[ac], XmNcancelLabelString, XmStringCreateLtoR
	   (" Cancel ", charset));  ac++;
	overwrite_question = XmCreateQuestionDialog (menu_bar, "overwrite_question",al,ac);
	XmStringFree(xmstr);		/* free memory allocated for XmString */
	set_dialog_title(overwrite_question, "Overwrite ?");

	XtAddCallback (overwrite_question, XmNokCallback,
			(XtCallbackProc)DialogOkCB,     (caddr_t)QUESTION_OVERWRITE);
	XtAddCallback (overwrite_question, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, (caddr_t)QUESTION_OVERWRITE);
	XtAddCallback (overwrite_question, XmNhelpCallback,
			(XtCallbackProc)HelpCB,         (caddr_t)QUESTION_OVERWRITE);



	/* get the Motif question mark pixmap from above box ... - GLOBAL data */
	ac = 0;
	XtSetArg(al[ac], XmNsymbolPixmap, &xm_question_mark);  ac++;
        XtGetValues(overwrite_question, al, ac);


	/* create a print warning dialog */
	ac = 0;
	XtSetArg(al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ac++;
	XtSetArg (al[ac], XmNokLabelString, XmStringCreateLtoR
				(" Yes ", charset));  		ac++;
	XtSetArg (al[ac], XmNapplyLabelString, XmStringCreateLtoR
				(" No ", charset));  		ac++;
	XtSetArg (al[ac], XmNautoUnmanage, False);    		ac++;

	print_warning = create_4buttons_image_dialog(menu_bar, "print_warning",
			 "warning_image", "Save file before printing?", al, ac);
	set_dialog_title(print_warning, "Print");
	XtAddCallback (print_warning, XmNokCallback,
			(XtCallbackProc)DialogOkCB, 	(caddr_t)DIALOG_PRINT);
	XtAddCallback (print_warning, XmNapplyCallback,		/* No answer */
			(XtCallbackProc)DialogApplyCB, (caddr_t)DIALOG_PRINT);
	XtAddCallback (print_warning, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, (caddr_t)DIALOG_PRINT);
	XtAddCallback (print_warning, XmNhelpCallback,
			(XtCallbackProc)HelpCB, 	(caddr_t)DIALOG_PRINT);


}	/* CreateFileDialogs */



/*****************************  CreateSearchDialogs  ************************
**
**		Create all dialogs related to search operations as
**		children of a parent (usually the menu_bar)
*/
#ifdef _NO_PROTO
void CreateSearchDialogs (menu_bar)
	Widget menu_bar;
#else  /* ! _NO_PROTO */

void CreateSearchDialogs (Widget menu_bar)
#endif
{
	Widget 		kids[3];	/*  children widgets */

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


	/* create a replace dialog; the find dialog is obtained from the
	   replace dialog simply by unmanaging some widgets !!!
	   The title is dynamically assigned just before managing the widget!! */

	ac=0;
	XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
	XtSetArg (al[ac], XmNcancelLabelString, XmStringCreateLtoR
			("Close", charset));  ac++;
	replace_dialog = CreateReplaceDialog( menu_bar, "replace_dialog", al, ac);

	XtAddCallback (replace_dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB, 	(caddr_t)DIALOG_FIND_OR_CHANGE);
	XtAddCallback (replace_dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB,(caddr_t)DIALOG_FIND_OR_CHANGE);
	XtAddCallback (replace_dialog, XmNhelpCallback,
			(XtCallbackProc)HelpCB, 	(caddr_t)DIALOG_FIND_OR_CHANGE);
	XtAddCallback (replace_dialog, XmNapplyCallback,
			(XtCallbackProc)DialogApplyCB, (caddr_t)DIALOG_FIND_OR_CHANGE);
        /* set a special callback to set the focus to the text_to_find widget
	   when the dialog gets its first focus */
#ifndef XFOCUS_BUG
	XtAddCallback(replace_dialog, XmNfocusCallback,
			(XtCallbackProc)focusCB, (caddr_t)text_to_find);
#endif



	/*    Create  change prompt   */
	ac = 0;
	XtSetArg(al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ac++;
	/* set the appropriate titles for buttons (let's don;t worry about
	   few bytes allocated for XmStrings and not freed */
	XtSetArg (al[ac], XmNokLabelString, XmStringCreateLtoR
				("Change", charset));  	ac++;
	XtSetArg (al[ac], XmNapplyLabelString, XmStringCreateLtoR
				("Skip", charset));  	ac++;
	XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;

	change_prompt = create_4buttons_dialog (menu_bar, "change_prompt",
			xm_question_mark, /* if you do not want use any pixmap
				specify NULL pixmap like this:  (Pixmap) NULL, ***/
			 "Change this occurrence ?", al, ac);
	set_dialog_title(change_prompt, "Change Prompt");

	XtAddCallback (change_prompt, XmNokCallback,
			(XtCallbackProc)DialogOkCB,	(caddr_t)DIALOG_CHANGE_PROMPT);
	XtAddCallback (change_prompt, XmNapplyCallback,
			(XtCallbackProc)DialogApplyCB,	(caddr_t)DIALOG_CHANGE_PROMPT);
	XtAddCallback (change_prompt, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, (caddr_t)DIALOG_CHANGE_PROMPT);
	XtAddCallback (change_prompt, XmNhelpCallback,
			(XtCallbackProc)HelpCB,		(caddr_t)DIALOG_CHANGE_PROMPT);


	/* create continue_search_question widget */
	ac = 0;
	strcpy(work,"Continue...\n");	/* text will be set dynamically */
	xmstr = XmStringCreateLtoR(work, charset);
	XtSetArg(al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ac++;
        XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
	XtSetArg(al[ac], XmNmessageString, xmstr );  ac++;
	XtSetArg(al[ac], XmNokLabelString, XmStringCreateLtoR
	   (" Yes ", charset));  ac++;
	XtSetArg(al[ac], XmNcancelLabelString, XmStringCreateLtoR
	   (" No ", charset));  ac++;
	continue_search_question = XmCreateQuestionDialog (menu_bar, "continue_search_question",al,ac);
	XmStringFree(xmstr);		/* free memory allocated for XmString */
	set_dialog_title(continue_search_question, "Search");

	XtAddCallback (continue_search_question, XmNokCallback,
			(XtCallbackProc)DialogOkCB, 	(caddr_t)QUESTION_CONTINUE_SEARCH);
	XtAddCallback (continue_search_question, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, (caddr_t)QUESTION_CONTINUE_SEARCH);
	XtAddCallback (continue_search_question, XmNhelpCallback,
			(XtCallbackProc)HelpCB, 	(caddr_t)QUESTION_CONTINUE_SEARCH);



	/* create search_end_message */
	ac = 0;
	strcpy(work,"Change...\n");	/* text will be set dynamically */
	xmstr = XmStringCreateLtoR(work, charset);
	XtSetArg(al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ac++;
        XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
	XtSetArg(al[ac], XmNmessageString, xmstr );  ac++;
	XtSetArg(al[ac], XmNcancelLabelString, XmStringCreateLtoR
		   (" Close ", charset));  ac++;
        /* 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)  - important for Motif 1.0*/
        XtSetArg(al[ac], XmNdefaultButtonType, XmDIALOG_CANCEL_BUTTON); ac++;

	search_end_message = XmCreateInformationDialog (menu_bar, "search_end_message",al,ac);
	XmStringFree(xmstr);		/* free memory allocated for XmString */
	set_dialog_title(search_end_message, "Change All");
	/* unmanage unneeded buttons */
	ac=0;
	kids[ac++] = XmMessageBoxGetChild(search_end_message, XmDIALOG_HELP_BUTTON);
	kids[ac++] = XmMessageBoxGetChild(search_end_message, XmDIALOG_OK_BUTTON);
	XtUnmanageChildren (kids, ac);
	XtAddCallback (search_end_message, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, (caddr_t)MESSAGE_SEARCH_END);
	/* lets add the help callback; because the help button is not managed this help
	   is only accessible with F1 (Help) key */
	XtAddCallback (search_end_message, XmNhelpCallback,
			(XtCallbackProc)HelpCB, (caddr_t)MESSAGE_SEARCH_END);



	/* Create go to line dialog ... */
	ac = 0;
	xmstr =XmStringCreateLtoR("Enter new line number:", charset);
	XtSetArg(al[ac], XmNselectionLabelString, xmstr );  ac++;
	XtSetArg (al[ac], XmNtextColumns, 6);   ac++;
	XtSetArg (al[ac], XmNautoUnmanage, False);    ac++;
	gotoline_dialog = XmCreatePromptDialog(menu_bar,"go_to_line", al, ac);
	XmStringFree(xmstr);		/* free memory allocated for XmString */
	set_dialog_title(gotoline_dialog, "Go to Line");
	XtAddCallback (gotoline_dialog, XmNokCallback,
			(XtCallbackProc)DialogOkCB, (caddr_t)DIALOG_GOTOLINE);
	XtAddCallback (gotoline_dialog, XmNcancelCallback,
			(XtCallbackProc)DialogCancelCB, (caddr_t)DIALOG_GOTOLINE);
	XtAddCallback (gotoline_dialog, XmNhelpCallback,
			(XtCallbackProc)HelpCB, (caddr_t)DIALOG_GOTOLINE);
	/* set the colour for the editable text widget */
	kids[0] = XmSelectionBoxGetChild(gotoline_dialog, XmDIALOG_TEXT);
	ac =0;
	XtSetArg(al[ac], XmNbackground, select_menu_background); ac++;
	XtSetValues(kids[0], al, ac);

	/* none of the following ways of setting traaversal works:
	  XmProcessTraversal( kids[0], XmTRAVERSE_HOME);
					XmTRAVERSE_CURRENT
					XmTRAVERSE_NEXT_TAB_GROUP
	  They do not work because the dialog widget (and all of its ancestors)
	  does need to be realized BEFORE you call XmProcessTraversal !
	  The way around it is to register a special focus callback */
	/* set a special callback which will set the focus to the text widget
	   when the dialog gets its first focus */
#ifndef XFOCUS_BUG
	XtAddCallback(gotoline_dialog, XmNfocusCallback,
			(XtCallbackProc)focusCB, (caddr_t)kids[0]);
#endif


}	/* CreateSearchDialogs */



/*****************************  CreateReplaceDialog  ************************
*
*	creates replace dialog out of a selection box
*/
#ifdef _NO_PROTO
static Widget CreateReplaceDialog(parent, name, arglist, argcount)
	Widget parent;
	String name;
	Arg arglist[];
	int argcount;
#else  /* ! _NO_PROTO */

static Widget CreateReplaceDialog( Widget parent, String name,
		Arg arglist[], int argcount )
#endif
{
	Widget kid[11];      		/* Children to manage */
	Arg al[15];         		/* Arg List */
	register int ac = 0;      	/* Arg Count */
	Dimension    h_space, v_space; 	/* horizontal and vertical space used
					   inside a form; !!! It *must* be defined as
					   Dimension! (when it was defined as int it worked
					   on RS6000 (X11R3) but id did not work on Silicon Graphics
					   (X11R4)  */

	/* following widgets are defined as global:
		text_to_find, new_text,
		case_sensitive_toggle, prompt_on_replace_toggle, whole_words_only_toggle,
		new_text_title, forward_toggle,
		change_all_button(i.e. apply button in prompt dialog)
	*/


	Widget form_text;	/* special form for label and text widgets
				   it consist of two rows "label - text" lines;
				   the second line is unmanagable to use that dialog
				   as a search dialog; this give us a unique set
				   of text to find plus switches like forward etc. */

	Widget replace_dialog;		/* replace widget  - procedure returns it */
	Widget form;          		/* main form widget */
	Widget text_to_find_title;
	Widget options_title;
	Widget frame1;			/* frame used for option toggles */
	Widget options_row_column;
	Widget direction_title;
	Widget frame2;         		/* frame used for direction toggles */
	Widget direction_radio_box;
	Widget backward_toggle;

	XmString	label_string;


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

	/* manage the 4th button of prompt dialog */
	change_all_button = XmSelectionBoxGetChild (replace_dialog,
						 XmDIALOG_APPLY_BUTTON);

	ac = 0;
	label_string = XmStringCreateLtoR("Change All", charset);
	XtSetArg(al[ac], XmNlabelString, label_string ); ac++;
	XtSetValues(change_all_button, al, ac);
	XmStringFree(label_string);
	XtManageChild(change_all_button);

	/* the title for the change_verify_button will be dynamically set
	   according to the use of the button in "Find" dialog or "Change" dialog */
	change_verify_button = XmSelectionBoxGetChild (replace_dialog,
						 XmDIALOG_OK_BUTTON);
	ac = 0;
	label_string = XmStringCreateLtoR("Find & Verify", charset);
	XtSetArg(al[ac], XmNlabelString, label_string); ac++;
	XtSetValues(change_verify_button, al, ac);
	XmStringFree(label_string);

	/* get the cancel button .... */
	cancel_replace_dialog_button = XmSelectionBoxGetChild (replace_dialog,
						 XmDIALOG_CANCEL_BUTTON);



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



	/* create a form widget inside prompt dialog; inside that form
	   create appropriate control elements */

	ac = 0;
	form = XmCreateForm ( replace_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 */


	/* when the 2 lines which contain a label and a text widget
	   each, were directly created inside a form and later the second
	   line was managed and unmanaged, when needed, we had problems and
	   the behaviour was inconsistent;
	   Therefore additional form (form_text) is created to "envelope" the
	   widgets mentioned above (19.11.1991) */
	ac = 0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNrightAttachment,   XmATTACH_FORM); ac++;
	form_text = XmCreateForm ( form, "form_text", al, ac );

	ac = 0;
	label_string = XmStringCreateLtoR("Text to Find:", charset);
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNlabelString, label_string ); ac++;
	text_to_find_title = XmCreateLabel ( form_text, "text_to_find_title", al, ac );
	XmStringFree(label_string);		/* free memory allocated for XmString */

	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,      text_to_find_title);ac++;
	XtSetArg(al[ac], XmNbackground,      select_menu_background);ac++;
	text_to_find = XmCreateText ( form_text, "text_to_find", al, ac );
#ifdef X11R3
	XmAddTabGroup (text_to_find);
#endif

	ac = 0;
	label_string = XmStringCreateLtoR("Change To:", charset);
	XtSetArg(al[ac], XmNlabelString, label_string ); 	ac++;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNtopOffset,       v_space); 		ac++;
	XtSetArg(al[ac], XmNtopWidget,       text_to_find); ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_NONE);	ac++;
	XtSetArg(al[ac], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); 	ac++;
	XtSetArg(al[ac], XmNrightWidget,     text_to_find_title); ac++;

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


	new_text_title = XmCreateLabel ( form_text, "new_text_title", al, ac );
	XmStringFree(label_string);


	ac=0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNtopOffset,       v_space); 		ac++;
	XtSetArg(al[ac], XmNtopWidget,       text_to_find); 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,      text_to_find_title); ac++;
	XtSetArg(al[ac], XmNbackground,      select_menu_background);ac++;

	/** ? maybe bug in Motif 1.0 - when we attached both bottoms of
	    widgets in the "second" line (unmanagable) there are problems
	    so we don't do that XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++; **/
	/*** !!! Silicon Graphics --- 11.03.1992  O.K.
		XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++; ****/


	new_text = XmCreateText ( form_text, "new_text", al, ac );
#ifdef X11R3
	XmAddTabGroup (new_text);
#endif

	ac = 0;
	label_string = XmStringCreateLtoR("Options", charset);
	XtSetArg(al[ac], XmNlabelString, label_string ); ac++;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNtopOffset,       v_space); 		ac++;
	XtSetArg(al[ac], XmNtopWidget,       form_text); 	ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); 	ac++;
	options_title = XmCreateLabel ( form, "options_title", al, ac );
	XmStringFree(label_string);


	ac=0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNtopWidget,       options_title); 	ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); 	ac++;
	XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE);	ac++;
	/* !! when I attach bottom to the form I never obtained all 3 options; it was
	   always reduced to the length of direction frame - maybe it is a bug ???
	XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); 	ac++; */
	/**** !!!! Silicon Graphics  --- 11.03.92  O.K.
		XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM);    ac++; ****/



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

	ac=0;
	/**XtSetArg (al[ac], XmNpacking, XmPACK_COLUMN);  ac++;
	XtSetArg (al[ac], XmNnumColumns, 1);  ac++; ***/
	options_row_column = XmCreateRowColumn(frame1, "options_row_column", al, ac );
#ifdef X11R3
	XmAddTabGroup (options_row_column);
#endif

	ac=0;
	XtSetArg (al[ac], XmNset, True);  ac++;

	case_sensitive_toggle   = XmCreateToggleButton( options_row_column, "Case sensitive", al, ac );
	ac=0;
	whole_words_only_toggle = XmCreateToggleButton( options_row_column, "Whole words only", al, ac );
	ac=0;
	XtSetArg (al[ac], XmNset, True);  ac++;
	prompt_on_replace_toggle = XmCreateToggleButton( options_row_column, "Prompt on replace", al, ac );

	ac = 0;
	label_string = XmStringCreateLtoR("Direction", charset);
	XtSetArg(al[ac], XmNlabelString, label_string ); ac++;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNtopOffset,       v_space); 		ac++;
	XtSetArg(al[ac], XmNtopWidget,       /*new_text*/
					     form_text); 	ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_WIDGET); 	ac++;
	XtSetArg(al[ac], XmNleftOffset,      20); 		ac++;
	XtSetArg(al[ac], XmNleftWidget,      frame1); 		ac++;

	direction_title = XmCreateLabel ( form, "direction_title", al, ac );
	XmStringFree(label_string);

	ac=0;
	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_WIDGET);	ac++;
	XtSetArg(al[ac], XmNtopWidget,       direction_title); 	ac++;
	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_WIDGET); 	ac++;
	XtSetArg(al[ac], XmNleftOffset,      20); 		ac++;
	XtSetArg(al[ac], XmNleftWidget,      frame1); 		ac++;
	XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); 	ac++;
	frame2 = XmCreateFrame ( form, "frame2", al, ac );
	ac=0;

	direction_radio_box = XmCreateRadioBox( frame2, "direction_radio_box", al, ac );
#ifdef X11R3
	XmAddTabGroup (direction_radio_box);
#endif
	ac=0;
	XtSetArg (al[ac], XmNset, True);  ac++;
	forward_toggle =  XmCreateToggleButtonGadget( direction_radio_box, "Forward", al, ac );
	ac=0;
	backward_toggle = XmCreateToggleButtonGadget( direction_radio_box, "Backward", al, ac );


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

	ac = 0;
	kid[ac++] = case_sensitive_toggle;
	kid[ac++] = whole_words_only_toggle;
	/* in this version we are not using prompt_on_replace (old design - design 2)
		kid[ac++] = prompt_on_replace_toggle;
	***/
	XtManageChildren(kid, ac);
	XtManageChild(options_row_column);

	ac = 0;
	kid[ac++] = forward_toggle;
	kid[ac++] = backward_toggle;
	XtManageChildren(kid, ac);
	XtManageChild(direction_radio_box);

	ac = 0;
	kid[ac++] = text_to_find_title;
	kid[ac++] = text_to_find;
	kid[ac++] = new_text;
	kid[ac++] = new_text_title;
	XtManageChildren(kid, ac);
	XtManageChild(form_text);

	ac = 0;
	kid[ac++] = options_title;
	kid[ac++] = frame1;
	kid[ac++] = direction_title;
	kid[ac++] = frame2;
	XtManageChildren(kid, ac);

	/* now manage the whole form (it is always better to manage the manager
	   widgets after creating all theirs children) */
	XtManageChild(form);

	return(replace_dialog);

}	/* CreateReplaceDialog */



/*****************************  CreateScrolledText  **************************
**
**	Create Scrolled Text widget and set the colour of recessed windows.
*/
#ifdef _NO_PROTO
static Widget CreateScrolledText (parent)
	Widget parent;
#else  /* ! _NO_PROTO */

static Widget CreateScrolledText (Widget parent)
#endif
{
	Arg		al[10];		/*  arg list		*/
	register int	ac;		/*  arg count		*/
	Pixel		foreground;	/* used for a proper set up of mono screens */
	Widget		text;


	/* create scrolled text widget */
	ac = 0;
	XtSetArg (al[ac], XmNresizeWidth, False);  ac++;
	XtSetArg (al[ac], XmNresizeHeight, False);  ac++;
	XtSetArg (al[ac], XmNscrollVertical, True);  ac++;
	XtSetArg (al[ac], XmNscrollHorizontal, True);  ac++;
	XtSetArg (al[ac], XmNeditMode, XmMULTI_LINE_EDIT);  ac++;

	text = XmCreateScrolledText (parent, "edit_text", al, ac);

	/* add value changed callback  - we do not use that now
	   XtAddCallback (text, XmNvalueChangedCallback,
			(XtCallbackProc)TextCB, (caddr_t)NULL);   ***/

	/* add modify verify callback (may be used to check changes) */
	XtAddCallback (text, XmNmodifyVerifyCallback,
			(XtCallbackProc)TextCB, (caddr_t)NULL);
	/* add motion callback */
	XtAddCallback (text, XmNmotionVerifyCallback,
			(XtCallbackProc)TextCB, NULL);
	/* add the help callback - TEMP we use XTEXT_HELP as a call data */
	XtAddCallback (text, XmNhelpCallback,
			(XtCallbackProc)HelpCB, (caddr_t)HTEXT_HELP);
	
	/* get the standard colour of the scrolled background */
	ac = 0;
	XtSetArg(al[ac], XmNbackground, &text_edit_background);	ac++;
	XtSetArg(al[ac], XmNforeground, &foreground);		ac++;
	XtGetValues(text, al, ac);
	text_read_only_background = text_edit_background;

	/*	Set colours of recessed widgets (text & scrollbars)
		We are doing that only for screens supporting more than 16
		colours (theoritically it should be done if the colour
		display is available, but practically if we have less than 16
		colours all of them probably have been already used up
		and the nearest available colour which will be assigned
		maybe inappropriate )*/

	if (DefaultDepthOfScreen(XDefaultScreenOfDisplay(display)) > 4)
	{
	   Widget 		scrolled_window;
	   Widget		hsbar, vsbar;	/*  ScrollBars		*/
	   XrmValue		pixel_data;

	   scrolled_window = XtParent(text);
	   XtSetArg (al[ac], XmNhorizontalScrollBar, &hsbar);	ac++;
	   XtSetArg (al[ac], XmNverticalScrollBar, &vsbar);	ac++;
	   XtGetValues (scrolled_window, al, ac);	/* get scroll bars .. */

	   /* get a colour to be used for editable text widgets and remember it */
	   _XmSelectColorDefault (scrolled_window, NULL, &pixel_data);
	   text_edit_background = *((Pixel *) pixel_data.addr);

	   /* now check if the text_edit_background is not by chance identical
	      with the foreground (it happens on mono screens or for a black/white
	      setup); if so do not apply it, but use the standard background.
	   */
	   if(text_edit_background == foreground)
		text_edit_background = text_read_only_background;

	   XtSetArg (al[0], XmNbackground, text_edit_background);

	   /* XtSetValues (text, al, 1);  -  do not set it now; if the text
		is editable this colour will be assigned when a file is read in */
	   XtSetValues (hsbar, al, 1);
	   XtSetValues (vsbar, al, 1);

	}

	return(text);

} /* CreateScrolledText */


/*****************************  CreateEditWorkArea  *************************
   create work area form. Inside the form
   scrolled text widget and a row of labels below it are created.

   !!!! THERE are 2 versions of the CreateEditWorkArea:
	1 - my original design that all the time during the edit process
	    the line and column are shown; unfortunately for big documents the
	    time spent to calculate the line and column might be to high and
	    even unacceptable (the time may be minimized by writing a
	    "more sophisticated"/"clever" algorithm for obtaining these
	    numbers).
	    To obtain this version of the asedit program you have to define
	    _SHOW_LINE_COLUMN (at the beginning of the program !). This
	    version is a default version for asedit Release 1.1.
	    In future, if there is a request for that, I am going to implement
	    a menu option to switch on/off the line & column widgets.
	2 - a simpler design than 1, without showing the line and column (i.e.
	    the current editing position). This version is quite fast and it is
	    the default version of the asedit program (for Release 1.0).
*/
#ifdef _NO_PROTO
static Widget CreateEditWorkArea(parent)
	Widget parent;
#else  /* ! _NO_PROTO */

static Widget CreateEditWorkArea(Widget parent)
#endif
{

#ifdef _SHOW_LINE_COLUMN

/* Version 1 - when _SHOW_LINE_COLUMN is defined
    <<<<<<<<<<<<<<<<<<
 */

	Widget		row_column;	 	/*  RowColumn		*/
	Widget		pane;			/*  Pane		*/
	Widget		frame_bottom;		/*  Frame	*/
	Widget 		line,  column;

	Arg		al[10];			/*  arg list		*/
	register int	ac;			/*  arg count		*/
	Dimension	height;


	/*	Create paned window. 	*/
	/* make the sash as small as possible, so the user doesn't try to resize
	   the paned window (PanedWindow won't let us set these to 0 !) */

	ac = 0;
    	XtSetArg(al[ac], XmNsashWidth, 1);  ac++;
    	XtSetArg(al[ac], XmNsashHeight,1);  ac++;

	pane = XtCreateManagedWidget ("pane", xmPanedWindowWidgetClass,
		parent, al, ac);

	/*	Create Text inside a pane	*/
	edit_text = CreateScrolledText (pane);
	XtManageChild (edit_text);

#ifdef X11R3
	XmAddTabGroup(edit_text);
#endif

	XtSetSensitive(edit_text, False);

	/* create a frame for the bottom row of edit informations ... */
	ac = 0;

	XtSetArg (al[ac], XmNshadowThickness, 2);  ac++;
	XtSetArg (al[ac], XmNshadowType, XmSHADOW_IN);  ac++;

	frame_bottom = XmCreateFrame (pane, "frame_bottom_row", al, ac);


	/* create an XmRowColumn widget containing 4 XmLabelwidgets */
	ac = 0;
	/* do NOT make them equal length: XtSetArg (al[ac], XmNpacking, XmPACK_COLUMN);  ac++; **/
	XtSetArg (al[ac], XmNadjustLast, False);  ac++;  /* to stop stretching
						of the last widget */

	XtSetArg (al[ac], XmNnumColumns, 5);  ac++;

	row_column = XmCreateRowColumn (frame_bottom, "bottom_row", al, ac);

	ac = 0;
	changes_status = XmCreateLabel (row_column, " ", al, ac); /* 1 space */
	XtManageChild (changes_status);

	ac = 0;
	line =	XmCreateLabel (row_column, "Line:", al, ac);
	XtManageChild (line);

	ac = 0;
	line_number =	XmCreateLabel (row_column, "       ", al, ac); /* space
					reserved for numbers as big as: " 99999 "
					plus a leading and trailing space */

	XtManageChild (line_number);

	ac = 0;
	column =   XmCreateLabel (row_column, "Col.:", al, ac);
	XtManageChild (column);

	ac = 0;
	column_number =   XmCreateLabel (row_column, "     ", al, ac);  /* space
					reserved for numbers as big as: " 999 "
					plus a leading and trailing space */
	XtManageChild (column_number);

	XtManageChild (row_column);


	/* now manage the bottom frame  and fix that status area to its current
	   height  -- never let it resize !! */
	XtManageChild (frame_bottom);

	{   /* just grouping brackets */
	    Dimension h, margin_height;
	    ac = 0;
	    XtSetArg (al[ac], XmNheight, &h);	ac++;
	    XtGetValues(column, al, ac);
	    /* we have to add the margins for the row column ...; when I use
	       only row_column it is not enough ... */
	    ac = 0;
	    XtSetArg (al[ac], XmNmarginHeight, &margin_height); ac++;
            XtGetValues(row_column, al, ac);
	    h += 3*margin_height;
#ifdef X11R3
	    /* there is probably small bug in X11R3, correct the size */
	    h += 2*margin_height;
#endif
	
	    ac = 0;
	    XtSetArg (al[ac], XmNpaneMaximum, h);	ac++;
	    XtSetArg (al[ac], XmNpaneMinimum, h);	ac++;
	    XtSetValues(frame_bottom, al, ac);
	}

	/* turn off traversal on the sash */
	TurnOffSashTraversal(pane);



	/* probably the best idea is to change the design and do not
	  use the pane widget - otherwise the size of the second pane may
	  be changed by the user. During the initial state of this design
	  minimum and maximum height of the second pane were simply set */


	return(pane);

#else

/* Version 2 - when _SHOW_LINE_COLUMN is not defined; the default of asedit
   (for Release 1.0).
    <<<<<<<<<<<<<<<<<<
 */


	/*	Create Text inside a parent	*/
	edit_text = CreateScrolledText (parent);
	XtManageChild (edit_text);

#ifdef X11R3
	XmAddTabGroup(edit_text);
#endif

	XtSetSensitive(edit_text, False);

	return(XtParent(edit_text));

#endif


} /* CreateEditWorkArea */


/*****************************  find_string  ********************************
*
*	finds the string search_string in the text widget "edit_text"
*/
#ifdef _NO_PROTO
void find_string(first_pos, last_pos)
    long *first_pos;
    long *last_pos;
#else  /* ! _NO_PROTO */

void find_string(long *first_pos, long *last_pos)
#endif
{
    /* first_pos, last_pos - are set to show the position of the
       found text */

    long len, position, start_position;

    String text_buffer;
    Arg    al[2];
    Boolean search_forward=   True;	/* search direction */
    Boolean case_sensitive=   True;
    Boolean whole_words_only= False;


    len = strlen(search_string);

    if(len == 0L)
    {
	show_error_message("You have to enter a string to search for!");
	return;
    }
    /* get the state of search_forward toggle gadget */
    search_forward   = XmToggleButtonGadgetGetState (forward_toggle);
    /* get the state of case_sensitive and whole_words_only toggles */
    case_sensitive   = XmToggleButtonGetState (case_sensitive_toggle);
    whole_words_only = XmToggleButtonGetState (whole_words_only_toggle);

    /* get the address of the internally stored text
       and the cursor position (i.e. starting position) */
    XtSetArg(al[0], XmNvalue, &text_buffer);
    XtSetArg(al[1], XmNcursorPosition, &start_position);
    XtGetValues(edit_text, al, 2);



    /* find a search string position in the text widget buffer;
       if the position is < 0 the string has not been found,
       therefore pop up appriopriate dialog;
       if position >= 0 OK go there ... */
    position =  find_string_pos_in_buffer(search_string, text_buffer,
					start_position, -1L, search_forward,
					case_sensitive, whole_words_only);
    if(position >= 0L)
    {

	/* set the first and last position of the text found */
	*first_pos = position;
	*last_pos  = position + len;

	/* for the forward search set the cursor to be posittioned after
	   the string found, for the backward search - before the string found */
	if(search_forward)  position += len;
	/*? do we need clear selection before setting it ..==> no we do not !!
	    XmTextClearSelection(edit_text, timestamp_search_request); ****/

	/* set the selection for the text found */
	/* XmTextSetSelection also sets the position of the insert cursor to
	   last_pos and then invokes the widget's XmNmotionVerifyCallback */
	XmTextSetSelection(edit_text, *first_pos, *last_pos, timestamp_search_request);

	/* lets highlight the text found (without actually selecting it);
		XmTextSetHighlight(edit_text, *first_pos, *last_pos, XmHIGHLIGHT_SELECTED);
	*** not available in X11R3 */

	/* set the cursor position; next search will start from that place */
	XmTextSetInsertionPosition(edit_text, position);

	/* convert the position to the line & column number and display them */

#ifdef _SHOW_LINE_COLUMN
	{
	    /*march  '92 long line, buf_size, column; ***/
	    long buf_size;
	    buf_size = (long) strlen(text_buffer);
	    textPosToLineColumn(text_buffer, buf_size, position, &line, &column);
	    write_lw(line_number,   charset, "%ld", line);
	    write_lw(column_number, charset, "%ld", column);
	}
#endif

    }
    else
    {
	*first_pos = *last_pos = -1;	/* the search was unsuccessful */
	show_error_message("Search string not found");
    }
#ifndef	GET_TEXT_VALUE_BUG_FIXED
    XtFree(text_buffer);
#endif	/* GET_TEXT_VALUE_BUG_FIXED */
    return;

} /* find_string */


/*****************************  change_all_found_strings  *******************
*
*	find all strings in the text widget and change them to a new string
*	without	asking for confirmation
*/
#ifdef _NO_PROTO
void change_all_found_strings(start)
    Boolean start;
#else  /* ! _NO_PROTO */

void change_all_found_strings(Boolean start)
#endif
{
    /* "start" must be True when this procedure is called to start the process
       of changing of all text occurrences;
       and it must be False when it is called second time when the bottom or top
       of the file has been reached in the previous call */

    long len, position, start_position, end_position;
    long first_pos, last_pos;		/* positions of the text found */
    long buf_size, new_string_len;
    String text_buffer;
    Arg    al[2];
    register int ac;
    char   work[256];
    XmString  xmstr;		/* work XmString */
    static Boolean search_forward=   True;	/* search direction */
    static Boolean case_sensitive=   True;
    static Boolean whole_words_only= False;
    static int items_changed=0;
    static  long change_all_start_position;	/* it remembers the starting position
			and it is used to detect that the change has been finished;
			thi value is updated to take into account replacement
			with different length of the new string */



    len = strlen(search_string);
    new_string_len = strlen(new_string);

    if(len == 0L)
    {
	show_error_message("You have to enter a string to search for!");
	return;
    }
    if(start)
    {
	/* get the state of search_forward toggle gadget - only when the whole
	   search is started (we don't allow the user to change it during the whole
	   process; otherwise it would be difficult to find out when
	   the whole process is finished) */
	search_forward   = XmToggleButtonGadgetGetState (forward_toggle);
	/* get the state of case_sensitive and whole_words_only toggles */
	case_sensitive   = XmToggleButtonGetState (case_sensitive_toggle);
	whole_words_only = XmToggleButtonGetState (whole_words_only_toggle);

	/* get the address of the internally stored text
	   and the cursor position (i.e. starting position) */
	XtSetArg(al[0], XmNvalue, &text_buffer);
	XtSetArg(al[1], XmNcursorPosition, &start_position);
	XtGetValues(edit_text, al, 2);
	items_changed = 0;
	change_all_start_position = start_position;
	end_position	= -1;		/* search up to the edge of the file (i.e.
					up to the end for forward search, up to the
					beginning for the backward search */
    }
    else
    {
	/* get the address of the internally stored text */
	XtSetArg(al[0], XmNvalue, &text_buffer);
	XtGetValues(edit_text, al, 1);
	start_position = -1;	/* start at the beginning or at the end of the
				   file (dependent on the search direction) */
	end_position   = change_all_start_position;	/* do not go beyond
							   the overall start position;
							   finish off the search */
    }

    /* find a search string position in the text widget buffer;
       if the position is < 0 the string has not been found,
       therefore pop up appriopriate dialog;
       if position >= 0 OK go there ... */
    position =  find_string_pos_in_buffer(search_string, text_buffer,
					start_position, end_position, search_forward,
					case_sensitive, whole_words_only);
    while (position >= 0L)
    {
	/* the position returned always shows the first character of the string
	   found, no matter if we search forward or backward so we can set
	   the first and last position of the text found as follows: */

	/* set the first and last position of the found text */
	first_pos = position;
	last_pos  = position+len;

	/* to speed the process of changing we do not mark the found text
	   nor we change the cursor position during the substitution process */

	XmTextReplace(edit_text, first_pos, last_pos, new_string);
	items_changed++;	/* increase the counter */

	/* move the starting position of the search to start a new search
	   just after the text changed (or before it for a backward search) */
	if(search_forward) start_position = last_pos + (new_string_len - len);
	else		   start_position = first_pos;

	/* update the change_all_start_position in the case when the text was
	   changed before it (take into account a difference in the length)*/
	if(position < change_all_start_position)
		change_all_start_position += (new_string_len - len);
	if(change_all_start_position < 0) change_all_start_position = 0;

#ifndef	GET_TEXT_VALUE_BUG_FIXED
	XtFree(text_buffer);
#endif	/* GET_TEXT_VALUE_BUG_FIXED */
	/* get the address of the internally stored text (it may have been changed)
	   and search again */
	XtSetArg(al[0], XmNvalue, &text_buffer);
	XtGetValues(edit_text, al, 1);

	/* set the end_position of the search appropriately
	   to the mode of the search (up to the edge of the file or finish off
	   the search beyond the edge of the file) */
	if(!start) end_position = change_all_start_position;  /* else = -1 */

	position =  find_string_pos_in_buffer(search_string, text_buffer,
					start_position, end_position, search_forward,
					case_sensitive, whole_words_only);

    }
    /* convert the the last found position (that is = the start  of the
    unsuccessful search) into the line & column number and display them;
    set the cursor position to it */
    XtSetArg(al[0], XmNcursorPosition, start_position);
    XtSetValues(edit_text, al, 1);

    buf_size = (long) strlen(text_buffer);

#ifdef _SHOW_LINE_COLUMN
    {
	/***march '92 long line, column; ****/
	textPosToLineColumn(text_buffer, buf_size, start_position, &line, &column);
	write_lw(line_number,   charset, "%ld", line);
	write_lw(column_number, charset, "%ld", column);
    }
#endif

#ifndef	GET_TEXT_VALUE_BUG_FIXED
    XtFree(text_buffer);
#endif	/* GET_TEXT_VALUE_BUG_FIXED */

    if(!start  ||  (search_forward && change_all_start_position == 0L) ||
		   (!search_forward && change_all_start_position == buf_size))
    {
	/* 3 situations may generate the end of the search message:
	   - it was a second call to this procedure to finish off the previous
	     search starting from the beginning (or the end) up to the overall start
	   - it was a forward search  started right from the text beginning,
	   - it was a backward search started right from the text end
	*/

	sprintf(work,
		 "Change All has been completed.\nNumber of items changed: %d.",
			 items_changed);
	xmstr = XmStringCreateLtoR(work, charset);
	ac = 0;
	XtSetArg(al[ac], XmNmessageString, xmstr );  ac++;
	XtSetValues(search_end_message, al, ac);
	XmStringFree(xmstr);	/* free memory allocated for XmString */
	XtManageChild(search_end_message);

    }
    else
    {	/* a question about continuing the change process is asked */
	if(search_forward) strcpy(work, "Reached end of document.\nContinue search at beginning ?");
	else        strcpy(work, "Reached beginning of document.\nContinue search at end ?");
	xmstr = XmStringCreateLtoR(work, charset);
	ac = 0;
	XtSetArg(al[ac], XmNmessageString, xmstr );  ac++;
	XtSetValues(continue_search_question, al, ac);
	XtManageChild(continue_search_question);
	XmStringFree(xmstr);	/* free memory allocated for XmString */
    }
    return;

} /* change_all_found_strings */


/* some simple utility functions ..... (self explanatory)  */

#ifdef _NO_PROTO
void set_change_buttons_sensitivity(state)
     Boolean state;
#else  /* ! _NO_PROTO */

void set_change_buttons_sensitivity(Boolean state)
#endif
{
     /* when state = False - turn off the sensitivity of the "action" buttons
			     of the change dialog and set the default button
			     the cancel ("Close") button;
	when state = True  - restore the default sensitive state of the "action"
			     buttons and restore the default button to the Ok
     */
     Arg al[2];
     register int ac;

     /* set the sensitivity of the change buttons sensitivity */
     XtSetSensitive(change_verify_button, state);
     XtSetSensitive(change_all_button, state);
     /* set the appropriate default button  */
     ac = 0;
     if(state == True)
	{ XtSetArg(al[ac], XmNdefaultButton, change_verify_button); ac++; }
     else
	 /* set the deafult button to the Cancel button;
	    otherwise when we press Enter the "change_verify_button" is activated
	    no matter that it is actually insensitive */
	{ XtSetArg(al[ac], XmNdefaultButton, cancel_replace_dialog_button); ac++; }

     XtSetValues(replace_dialog, al, ac);

}    /* set_change_buttons_sensitivity */

#ifdef _NO_PROTO
void set_titles_mwindow_icon(filename)
	   char *filename;
#else  /* ! _NO_PROTO */

void set_titles_mwindow_icon(char *filename)
#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[266];		/* program_name + file name */
	   char icon_name[256];
	   char *filename_without_path;
	   register int ac;			/* arg count		    */
	   Arg al[10];				/* widget arg list	    */


	   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);
	   }
	   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(toplevel, al, ac);

} /* set_titles_mwindow_icon */



void FinalCleanupCB(w, client_data, call_data)
Widget   w;
caddr_t  client_data, call_data;
{
    /* call another procedure doing the same ...*/
    ByeBye();

}   /* FinalCleanupCB */


/*
 * ByeBye - clean up and exit.
 */
#ifdef _NO_PROTO
void ByeBye()
#else  /* ! _NO_PROTO */

void ByeBye(void)
#endif
{
  /* exit if there is no files open */
		if (changes_counter != 0L) /* display the 'save' message dialog */
		{
		   XtManageChild (save_changes_dialog);
		   reason_save_question = MENU_EXIT;
		}
		else
		{
		   CloseFile(); /* close up the file */
		   XtUnmapWidget(toplevel);
		   XCloseDisplay(display);
		   exit (0);    /* exit this program */
		}
} /* ByeBye */


#include <X11/cursorfont.h>

/****************************	TurnWatchCursor	*****************************
  TurnWatchCursor turns on/off the "watch" cursor over the application
  to provide feedback for the user that he is going to be waiting
  a while before he can intercat with the application again.
*/
#ifdef _NO_PROTO
void TurnWatchCursor(turn_on)
    Boolean turn_on;
#else  /* ! _NO_PROTO */

void TurnWatchCursor(Boolean turn_on)
#endif
{
    static int locked;
    static Cursor cursor;
    XSetWindowAttributes attrs;
    XEvent	event;

    /* "locked" keeps track if we've already called the function.
       This allows recursion and is necessary for most situations;
    */
    turn_on ? locked++ : locked--;
    if(locked > 1 || ( locked ==1 && turn_on == False ))
		return;		/* already locked and we're not unlocking */

    if(!cursor)		/* if not initialized do it */
	cursor = XCreateFontCursor(display, XC_watch);
    /* if "turn_on" is true, then turn on watch cursor, otherwise, return
       the shell's cursor to normal
    */
    attrs.cursor = turn_on ? cursor : None;
    /* change the main application shell's cursor to the timeout cursor
       (or reset it to normal). Do the same to all other shells except those
       created as XmDIALOG_APPLICATION_MODAL (the last can't be active
       during such activities that needs setting timeout for the cursor)
    */
    if(XtIsRealized(toplevel))	/* a widget must be realized to have its window; here
				   it is practically not needed (toplevel must have
				   been realized) but for other widgets this is
				   compulsory !!! */
	    XChangeWindowAttributes(display, XtWindow(toplevel), CWCursor, &attrs);

#ifndef AMIGA
    XFlush(display);		/* to get the change in the main window as quickly
					as possible */
#endif
    if(XtIsRealized(open_dialog))
	XChangeWindowAttributes(display, XtWindow(open_dialog), CWCursor, &attrs);
    if(XtIsRealized(new_dialog))
	XChangeWindowAttributes(display, XtWindow(new_dialog), CWCursor, &attrs);
    if(XtIsRealized(save_as_dialog))
	XChangeWindowAttributes(display, XtWindow(save_as_dialog), CWCursor, &attrs);
    if(XtIsRealized(gotoline_dialog))
	XChangeWindowAttributes(display, XtWindow(gotoline_dialog), CWCursor, &attrs);
    if(XtIsRealized(replace_dialog))
	XChangeWindowAttributes(display, XtWindow(replace_dialog), CWCursor, &attrs);
    if(XtIsRealized(help_dialog))
	XChangeWindowAttributes(display, XtWindow(help_dialog), CWCursor, &attrs);
    if(XtIsRealized(about_program_message))
	XChangeWindowAttributes(display, XtWindow(about_program_message), CWCursor, &attrs);
#ifndef AMIGA
    XFlush(display);
#endif
    if(turn_on)
    {	/* we are timing out - in some cases that's the place to put up a
	   a working_dialog to show explicite to the user that he has to wait ...
	*/
	;
    }
    else
    {
	/* get rid of all button and keyboard events that occured during the
	   time out. The user shouldn't have done anything during this time,
	   so flush for button and keypress events. HeyRelease events are not
	   discarded because accelerators require the corresponding release
	   event before normal input can continue.
	*/
	while (XCheckMaskEvent(display, ButtonPressMask | ButtonReleaseMask |
		ButtonMotionMask | PointerMotionMask | KeyPressMask, &event))
	{
		/* do nothing */
	}
	/* if you used a working_dialog you should destroy it now ... */
    }
}   /* TurnWatchCursor */


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

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

}   /* focusTO */


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

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

}   /* focusCB */

