/* mk_asdat.c - part of asedit program;
   asdat - a structure wrapping the client_data with the structure containing
   all information about an instance of asedit (or any other as... application)

*/

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

#include "asedit.h"


/**** GLOBALLY defined */
extern aseditWindowStruct *asedit_last_window;

#ifdef _NO_PROTO
XtPointer mk_asdat(client_data)
int client_data;
#else  /* _NO_PROTO */
XtPointer mk_asdat(int client_data)
#endif
{
    /* to avoid making many duplicate structures we immplement simple cache;
       (mk_asdat is often called several times in succession)
    */
    asClientDataStruct *asdat =NULL;
    static asClientDataStruct *asdat_cache = NULL;
    static int                id_cache     = -777777;
    static aseditWindowStruct *win_cache   = NULL;

    if(asdat_cache == NULL   ||                 /* first entry (nothing in cache) */
       id_cache != client_data || win_cache != asedit_last_window)      /* not in cache */
    {
        asdat      = (asClientDataStruct *)XtMalloc(sizeof(asClientDataStruct));
        asdat->id  = client_data;
        asdat->win = asedit_last_window;

        id_cache   = asdat->id;         /* cache id & win for a future use */
        win_cache  = asdat->win;
        asdat_cache = asdat;
    }
    return((XtPointer)asdat_cache);


}   /* mk_asdat */

#ifdef _NO_PROTO
XtPointer mk_asdat_w(win, client_data)
aseditWindowStruct *win;
int client_data;
#else  /* _NO_PROTO */
XtPointer mk_asdat_w(aseditWindowStruct *win , int client_data)
#endif
{
    /* to avoid making many duplicate structures we immplement simple cache;
       (mk_asdat_w is often called several times in succession)
    */
    asClientDataStruct *asdat =NULL;
    static asClientDataStruct *asdat_cache = NULL;
    static int                id_cache     = -777777;
    static aseditWindowStruct *win_cache   = NULL;

    if(asdat_cache == NULL   ||                 /* first entry (nothing in cache) */
       id_cache != client_data || win_cache != win)      /* not in cache */
    {
        asdat      = (asClientDataStruct *)XtMalloc(sizeof(asClientDataStruct));
        asdat->id  = client_data;
	asdat->win = win;

        id_cache   = asdat->id;         /* cache id & win for a future use */
        win_cache  = asdat->win;
        asdat_cache = asdat;
    }
    return((XtPointer)asdat_cache);

}   /* mk_asdat_w */


#ifdef _NO_PROTO
int get_id_from_asdat(as_client_data)
    XtPointer as_client_data;
#else  /* _NO_PROTO */
int get_id_from_asdat(XtPointer as_client_data)
#endif
{
    asClientDataStruct *asdat = (asClientDataStruct *) as_client_data;
    return(asdat->id);
}

#ifdef _NO_PROTO
aseditWindowStruct *get_win_from_asdat(as_client_data)
    XtPointer as_client_data;
#else  /* _NO_PROTO */
aseditWindowStruct *get_win_from_asdat(XtPointer as_client_data)
#endif
{
    asClientDataStruct *asdat = (asClientDataStruct *) as_client_data;
    return(asdat->win);
}

#ifdef _NO_PROTO
aseditWindowStruct *new_asedit_win(win_prev)
    aseditWindowStruct *win_prev;
#else  /* _NO_PROTO */
aseditWindowStruct *new_asedit_win(aseditWindowStruct *win_prev)
#endif
{
    /* creates a new asedit window structure */

    aseditWindowStruct *win=NULL;

    win = (aseditWindowStruct *) XtMalloc(sizeof(aseditWindowStruct));

    /* initialize properly the chain .... */
    win->prev = win_prev;

    /* initialize some values */
    win->changes_counter = 0L;	/* counter of changes made to a file since last
				   save; if != 0 the present file is not saved; */
    win->file_read_only = False;	/* status of the read in file */
    win->filename = NULL;		/* string containing file name 		    */
    win->search_string=NULL;       /*  string to be searched for */
    win->new_string=NULL;		/*  a new string after replacement */
    win->start_search_position=0;  /*  starting position for a new search or change */

    /* set NULL widgets to recognize if appropriate dialogs had been created */
    win->open_dialog		 = NULL;
    win->save_as_dialog		 = NULL;
    win->save_changes_dialog	 = NULL;
    win->print_dialog		 = NULL;
    win->insert_dialog		 = NULL;
    win->overwrite_question	 = NULL;
    win->error_message		 = NULL;
    win->gotoline_dialog	 = NULL;
    win->replace_dialog		 = NULL;
    win->change_prompt  	 = NULL;
    win->continue_search_question= NULL;
    win->search_end_message	 = NULL;
    win->help_dialog		 = NULL;
    win->about_program_message	 = NULL;

    win->view_only_toggle	 = NULL;
    win->print_complete_toggle   = NULL;

    win->forward_toggle		 = NULL;	/* !! */
    win->case_sensitive_toggle	 = NULL;	/* !! */
    win->whole_words_only_toggle = NULL;	/* !! */

    win->quick_access_popup	 = NULL;
    win->filter_dialog   	 = NULL;
    win->command_dialog   	 = NULL;

    win->moveLeft_dialog	 = NULL;
    win->moveRight_dialog	 = NULL;
    win->indentWith_dialog	 = NULL;
    win->reformat_dialog	 = NULL;


    win->line=1L;
    win->do_undo_redo_action = False;
    win->status_line_on = True; 

    win->changes_status 	= NULL;
    win->line_number		= NULL;
    win->column_number		= NULL;

    win->file_just_loaded = True;

    /* initialize undo/redo data ... */
    win->can_undo = win->can_redo = False;	/* new in 1.27 */
    win->undo_stack.bottom = win->undo_stack.top = 0;
    win->redo_stack.bottom = win->redo_stack.top = 0;
    win->edit_history_initialized = False;

    win->nToolsSelNeeded = 0;

    win->tabsize = 8;			/* must be 8; we will set the tabsize to the
					   user specified value if the widget/version allows
					   that in the setUserTabSizes
					*/
    win->nextSelectionSearch   = False;
    win->weOwnPrimarySelection = False;


    return(win);

}

/* remove asedit window from the chain */
#ifdef _NO_PROTO
void remove_asedit_win (win)
    aseditWindowStruct *win;
#else  /* _NO_PROTO */
void remove_asedit_win (aseditWindowStruct *win)
#endif
{
    aseditWindowStruct *wc=NULL, *next=NULL;	/* current & next windows */

    /* first find it in the chain and remove it nicely */

    wc = asedit_last_window;		/* start from the last */

    if(wc == NULL)  return;		/* sanity check */

    do		/* loop until we find it or there is no previous window */
    {
	if(win == wc)		/* remove it nicely */
	{
	    if(next == NULL)	/* it is the last window in the chain  */
	    {
		asedit_last_window = wc->prev;
		/* after removing check  if the new aseditLlast_window is
		   NULL if that is the case there are no windows left ...
		   and exit action should be called
		*/
	    }
	    else		/* a window somewhere in the middle of the chain */
	    {
		next->prev = wc->prev;
	    }
	    /* free all widgets and allocated data .... */
	    if(win->save_changes_dialog)  XtDestroyWidget(win->save_changes_dialog); /* independent top  widget */

	    if(win->search_string)  XtFree(win->search_string);
	    if(win->new_string)     XtFree(win->new_string);

	    XtDestroyWidget(win->topshell);
	    /* we should take care of freeing all other data as well ..!!! */
	    XtFree((char *)win);
	    aseditWinCount--;		/* decrease the count of active windows */
	    break;	
	}

	next = wc;		/* not found yet, prepare for another step back */
	wc   = wc->prev;

    } while(wc);

}   /* remove_asedit_win */


