#include <windows.h>
#include <ascii.h>
#include <malloc.h>
/*

ReadMail -- offine message reader/privacy shell for MSDOS/FidoNet
copyright Tom Jennings 1992
Box 77731, San Francisco, CA 94107, USA, 1:125/111@fidonet

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
void cdecl wininit(void);	/* WINDOW4.ASM */

/*
	Tom Jennings
	new:	25 June 90
	mru:	22 Nov 91

NOTE: Compiled using PASCAL parameter passing convention.

Global screen window definitions and functions.

void init_window(w)
WINDOW *w;
	Initialize a window. This clears out the window area, draws 
	a box (as necessary), etc, if specified. If it is not already 
	in the linked list of active windows, it is added.

basic_screen(menuname,screenname)
char *menuname,*screenname;
	Closes all existing windows, clears the screen, draws the 
	basic items: status window, Fkey background, Fkey boxes, 
	screen and menu boxes.

active(w)
WINDOW *w;
	Return true if the window is active. 

deactivate(w)
WINDOW *w;
	Deactivate a window. Does not remove it from the chain.

activate(w)
WINDOW *w;
	Activate a window. Does not add to the chain.

removewindow(w)
WINDOW *w;
	Remove this window from the linked list, by clipping it out of 
	the chain (ie point window - 1 to window + 1.) If there is a 
	buffer allocated, it will be freed.

WINDOW *lastwindow(w)
WINDOW *w;
	Returns a pointer to the last window in the chain, starting at
	the given window.

unlinkchain(w)
	Remove this window and all windows below it. Calls removewindow().


 This is the top of the window list. It isn't initialized. We need it
so that screen.next_window is valid, which allows general-casing
linked-list management. 

*/

static WINDOW screen = {0,25,0,80,A_BBG};	/* entire screen */
static char one_time = 1;			/* first-time-only code */

/* Init a window. */

void init_window(w)
WINDOW *w;
{
WINDOW *k;
char far *cp;
size_t i;
int n;

	if (one_time) {
		wininit();			/* screen-mode setting stuff */
		one_time= 0;
	}
	if (! w-> buff) {			/* if it doesnt have a buffer yet */
		i= w-> window_lines * w-> window_cols;	/* amt of mem to get */
		i *= sizeof(struct _cell);	/* cells not bytes! */
		w-> buff= (char far *) _fmalloc(i); /* get it */
		cp= w-> buff;
		if (cp) w_save(w);		/* save data "under" window */
		w-> orig_height= getcursheight(); /* save old cursor */
	}

/* We need to activate it NOW -- else the low-level functions won't write
in it! */

	w-> bits= 0;				/* clear everything */
	w-> attribute= w-> def_attribute;	/* initial attribute */
	activate(w);				/* turn it on */

	box_window(w);				/* generate the box, clear the text */
	w-> cursor_height= 1;			/* default cursor height */
	w-> line= w-> col= 0;			/* starting location */

	if (w-> text) w_string(w,w-> text); /* possible default window contents */
	if (w-> text2) w_string(w,w-> text2); /* possible default window contents */

/* Add this window to the linked list by searching from the start til the
end. If we find this window already linked, exit. This also handles what
would be a special case -- the 'screen' structure itself. */

	for (k= &screen; k-> next_window != NOWINDOW; k= k-> next_window) {
		if (k == w) return;		/* (already linked in) */
	}
	k-> next_window= w;			/* point to it */
	w-> next_window= NOWINDOW;		/* is now the new end */
}

/* Unlink all windows from here down. We start at the end of the chain
and work backwards; each 'removewindow' restores the original screen
contents that it overlaid when it was added to the chain. */

void unlinkchain(w)
WINDOW *w;
{
WINDOW *k;

	while (w-> next_window) {		/* unlink all windows */
		k= lastwindow(w);		/* find last window */
		removewindow(k);		/* unlink last window */
	}
	removewindow(w);			/* then do this one */
}

/* Starting at the current window, return a pointer to the last window
in the chain. */

WINDOW *lastwindow(w)
WINDOW *w;
{
	while (w-> next_window != NOWINDOW)
		w= w-> next_window;
	return(w);
}

/* Unlink a window: find the window that points to this one, (the previous
one) and set it's next_window pointer to the current window's next_window.
ie. clip out a section of the chain. If there is an associated memory buffer,
return it to the pool. */

void removewindow(w)
WINDOW *w;
{
WINDOW *p;

	for (p= &screen; p-> next_window != NOWINDOW; p= p-> next_window) {
		if (p-> next_window == w) {
			p-> next_window= w-> next_window;
			w-> next_window= 0;
			deactivate(w);

			w-> cursor_height= w-> orig_height;
			w_cursor(w);			/* restore old shape */
			w_restore(w);			/* restore orig. screen */
			if (w-> buff) _ffree(w-> buff);	/* free up memory */
			w-> buff= 0L;			/* mark as such */
			break;
		}
	}
}

/* Return true if the window is active. */

int active(w)
WINDOW *w;
{
	return(w-> bits & W_ACTIVE);
}

/* Deactivate a window. */

void deactivate(w)
WINDOW *w;
{
	w-> bits &= ~W_ACTIVE;
}

/* Activate a window. */

void activate(w)
WINDOW *w;
{
	w-> bits |= W_ACTIVE;
}
