/* =======================================================================
    WINDOWS.C - A DOS-based windowing system for C25SIM
    Copyright (C) 1995 Will Ware

    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.

   ======================================================================= */

/*
 * The other source files should compile under either the Microsoft C
 * compiler (originally compiled with version 5.1) or the Borland Turbo C
 * compiler (originally compiled with version 2.0). But *THIS* file uses
 * pecularities of Microsoft, and must be compiled with the Microsoft C
 * compiler. (Hint, hint: a good project for anybody interested would be
 * to port this to the DJGPP compiler.)
 */

#include "stdio.h"
#include "stdlib.h"
#include "graph.h"
#include "windows.h"
#include "dos.h"
#define X(z)

char toprint[100];
int num_windows;
unsigned char cursor_x, cursor_y;
struct rccoord rccoord;
static union REGS regs;
static int previous_window = -1;

#define MAX_NUM_WINDOWS 10
static int row[MAX_NUM_WINDOWS], col[MAX_NUM_WINDOWS],
    left[MAX_NUM_WINDOWS], right[MAX_NUM_WINDOWS], top[MAX_NUM_WINDOWS],
    bottom[MAX_NUM_WINDOWS];
#define _MK_FP(seg,ofs)	((void far *) \
			   (((unsigned long)(seg) << 16) | (unsigned)(ofs)))
#define pokeb(a,b,c)	(*((char far*)_MK_FP((a),(b))) = (char)(c))
#define peekb(a,b)	(*((char far*)_MK_FP((a),(b))))

/* ======================================================================= */
/*                            Windowing Functions                          */
/* ======================================================================= */

void full_screen(void)
    {
    cursor_position();
    _settextwindow(1, 1, 25, 80);
    }

void clear_n(int n)
    {
    _settextwindow(top[n], left[n], bottom[n], right[n]);
    _clearscreen(_GWINDOW);
    row[n] = 1;
    col[n] = 1;
    }

int create_window(int L, int R, int T, int B)
    {
    row[num_windows] = 1;
    col[num_windows] = 1;
    left[num_windows] = L;
    right[num_windows] = R;
    top[num_windows] = T;
    bottom[num_windows] = B;
    clear_n(num_windows);
    return num_windows++;
    }

void select_window(int n)
    {
    if (previous_window != -1)
        {
        rccoord = _gettextposition();
        row[previous_window] = rccoord.row;
        col[previous_window] = rccoord.col;
        }
    _settextwindow(top[n], left[n], bottom[n], right[n]);
    _wrapon(_GWRAPOFF);
    rccoord.row = row[n];
    rccoord.col = col[n];
    _settextposition(rccoord.row, rccoord.col);
    previous_window = n;
    }

void __write_rc(char *s, int r, int c)
    {
    rccoord.row = r;
    rccoord.col = c;
    _settextposition(rccoord.row, rccoord.col);
    _outtext(s);
    rccoord = _gettextposition();
    row[previous_window] = rccoord.row;
    col[previous_window] = rccoord.col;
    }

void get_row_column(void)
    {
    rccoord = _gettextposition();
    }

void __write(char *s)
    {
    __write_rc(s, row[previous_window], col[previous_window]);
    }

void delete_char(void)
    {
    col[previous_window]--;
    __write(" ");
    col[previous_window]--;
    rccoord.col--;
    _settextposition(rccoord.row, rccoord.col);
    }

/* ======================================================================= */
/*                      goto_xy(), cursor_position()                       */
/* ======================================================================= */

void goto_xy(unsigned char x, unsigned char y)
    {
    regs.h.ah = 2;
    regs.h.bh = 0;
    regs.h.dh = y - 1;
    regs.h.dl = x - 1;
    int86(0x10, &regs, &regs);
    }

void cursor_position(void)
    {
    regs.h.ah = 3;
    regs.h.bh = 0;
    int86(0x10, &regs, &regs);
    cursor_x = regs.h.dl + 1;
    cursor_y = regs.h.dh + 1;
    }

/* ======================================================================= */
/*                         Screen Buffering Functions                      */
/* ======================================================================= */

void save_screen_buffer(screen_buffer b)
    {
    unsigned int i;

    cursor_position();
    for (i = 0; i < 2000; i++)
        b[i] = peekb(0xB800, 2 * i);
    b[2000] = cursor_y;
    b[2001] = cursor_x;
    }

void restore_screen_buffer(screen_buffer b)
    {
    unsigned int i;

    for (i = 0; i < 2000; i++)
        pokeb(0xB800, 2 * i, b[i]);
    goto_xy(b[2001], b[2000]);
    }

void clear_screen(void)
    {
    unsigned int i;

    for (i = 0; i < 2000; i++)
        pokeb(0xB800, 2 * i, ' ');
    goto_xy(1, 26);
    }
