/*
 *  CopyRight 1995. Nicholas Poljakov all rights reserved.
 */
#include <dos.h>
#include <bios.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

#define BORDER 1
#define REV_VID 0x70
#define NORM_VID 0x1E
#define MAX_FRAME 31
#define BKSP 8
#define F1 59
#define F2 60
#define F3 61
#define F4 62
#define F5 63
#define F6 64
#define F7 65
#define F8 66
#define F9 67
#define F10 68
#define HM  71   /* Home key     */
#define UP  72   /* Up Arrow     */
#define PU  73   /* Page Up      */
#define LT  75   /* Left Arrow   */
#define RT  77   /* Right Arrow  */
#define END 79   /* End key      */
#define DN  80   /* Down Arrow   */
#define PD  81   /* Page Down    */
#define ESC '\033'
#define DIR 0x10

#define ROWS1 19
#define ROWS2 23
#define ROWS  25
#define COLS 78
#define L_W 20
#define M_W 36
#define R_W 20
#define SCRNSIZE ((ROWS)*(COLS+2)*2)
#define LAST (24 * 80)*2

#define M0C  4     /* Files maping col.s */
#define M0L  14    /* Files maping rows  */
#define M0F (((80 * 5) + 9)) * 2
#define INTR 18*2

extern unsigned char cur_off;
extern unsigned int attr1b;
extern unsigned int *ptrs;
extern int size;
extern unsigned char row, col;
extern int adapter;
extern unsigned char far *videomem;
extern int offset;
extern int sw;
extern char *path;
extern char file[12];
extern char tpname[31];
extern char luname[8];
extern char mode_name[8];
extern char rcv_file[12];
extern char dta[128];

extern char far *sv;
extern char far *vid_mem;
extern short cur_ln;

extern struct menu_frame {
    int startx, endx, starty, endy;
    unsigned char *p;
    char **menu;
    char *keys;
    int border;
    int count;
    unsigned char attrib;
    int active;
    int curx, cury;
    char *header;
    unsigned char shd;
    } frame[MAX_FRAME];

extern char p_dcl[21];
extern unsigned char dr_ind[80];
extern char c_pt[60];
extern int drive_ind[10];

sfs(t, f)
char far *t;
char far *f;
{
    unsigned fs;
    unsigned fo;
    unsigned ts;
    unsigned to;

    fs = FP_SEG( f );
    fo = FP_OFF( f );

    ts = FP_SEG( t );
    to = FP_OFF( t );

    _asm {
            push si
            push di
            push ds
            mov  si, word ptr fo[0]
            mov  di, word ptr to[0]
            mov  ax, word ptr ts[0]
            mov  es, ax
            mov  ax, word ptr fs[0]
            mov  ds, ax
	    mov  cx, 2000
            cld
	    rep  movsw
            pop  ds
            pop  di
            pop  si
    }

    return 0;
}
window(num)
int num;
{
    int choice, x, y;
    int dl;

    if (!frame[num].active) {
	sfs(sv, vid_mem);
        if (frame[num].shd) {
            dl = 1;
        }
        else
            dl = 0;
        if ((frame[num].p = malloc(2*(frame[num].endx-frame[num].startx+1+dl)*(frame[num].endy-frame[num].starty+1+dl))) == NULL) {
            return -1;
        }
        save_video(num);
        if (frame[num].border) {
            draw_border(num);
        }
        display_header(num);
        x = frame[num].startx + frame[num].curx + 1;
        y = frame[num].starty + frame[num].cury + 1;
        goto_xy(x, y);
        frame[num].active = 1;
    }
    return 0;
}

display_header(num)
int num;
{
    register int y, len;

    y = frame[num].starty;
    len = strlen(frame[num].header);
    if (len == 0) return 0;
    len = (frame[num].endy - y - len) / 2;
    if (len <= 0) {
        return -1;
    }
    y = y + len;
    write_string(frame[num].startx, y, frame[num].header, NORM_VID);
    return 0;
}

deactivate(num)
int num;
{
    if (frame[num].active) {
        frame[num].curx = 0;
        frame[num].cury = 0;
        restore_video(num);
        free(frame[num].p);
    }
    return 0;
}
window_xy(num, x, y)
int num, x, y;
{

    if ((x<0)||(x+frame[num].startx >= frame[num].endx - 1)) {
	return 0;
    }
    if ((y<0)||(y+frame[num].starty >= frame[num].endy - 1)) {
	return 0;
    }
    frame[num].curx = x;
    frame[num].cury = y;
    if (!cur_off) {
       goto_xy(frame[num].startx + x + 1,  frame[num].starty + y + 1);
    }
    return 1;
}
unsigned window_getche(int num)
{
    union inkey {
        char ch[2];
	unsigned i;
        } c;

        if (!frame[num].active) {
            return 0;
        }
        window_xy(num, frame[num].curx, frame[num].cury);
	c.i = _bios_keybrd( _KEYBRD_READ );
        if (c.ch[0]) {
            switch (c.ch[0]) {
                case '\r' :
                             break;
                case BKSP :
                             break;
                case 0:      return c.i;
                default:
			     if (frame[num].cury+frame[num].starty < frame[num].endy-1) {
                                write_char(frame[num].startx+frame[num].curx+1,
                                frame[num].starty+frame[num].cury+1,
                                c.ch[0], frame[num].attrib);
                                frame[num].cury++;
                             }
             }
             if (frame[num].curx < 0) {
                frame[num].curx = 0;
             }
             if (frame[num].curx+frame[num].startx > frame[num].endx-2) {
		frame[num].curx--;
             }
             window_xy(num, frame[num].curx, frame[num].cury);
        }
        return c.i;
}

unsigned window_gets(int num, char *s)
{
    char *temp;
    union inkey {
        char ch[2];
	unsigned i;
        } c;

    temp = s;
    for (;;) {
        c.i = window_getche(num);
	switch (c.ch[0]) {
	    case ESC :
			 if (s == temp) {
			     s++;
			     clear_back(temp, s, num);
                             return 1;
                         }
			 else  {
				  s++;
				  while (s != temp) {
				     clear_back(temp, s, num);
				     s--;
				  }
				}
                         break;
            case '\r' :
                         *s = '\0';
                         return 0;
            case BKSP :
			 clear_back(temp, s, num);
			 s--;
			 break;
            case 0:      return c.i;
	    default :	 *s = c.ch[0];
			 s++;
	 }
    }
    return 0;
}
clear_back(temp, s, num)
char *temp;
char *s;
int num;
{
        if (s > temp) {
           s--;
           frame[num].cury--;
           if (frame[num].cury < 0) {
               frame[num].cury = 0;
           }
           window_xy(num, frame[num].curx, frame[num].cury);
           write_char(frame[num].startx + frame[num].curx + 1,
                   frame[num].starty + frame[num].cury + 1, ' ',frame[num].attrib);
        }
}
window_putchar(num, ch)
int num;
char ch;
{
    register int x, y;
    char far *v;

    if (!frame[num].active) {
        return 0;
    }
    x = frame[num].curx + frame[num].startx + 1;
    y = frame[num].cury + frame[num].starty + 1;
    v = vid_mem;
    v += (x*160) + y*2;
    if (y > frame[num].endy) {
        return 1;
    }
    if (x > frame[num].endx) {
	return 1;
    }
    if (ch == '\n') {
        x++;
        y = frame[num].startx + 1;
        v = vid_mem;
        v += (x*160) + y*2;
        frame[num].curx++;
        frame[num].cury = 0;
    }
    else
            {
                frame[num].cury++;
                *v++ = ch;
                *v++ = frame[num].attrib;
            }
    window_xy(num, frame[num].curx, frame[num].cury);
    return 1;
}

window_puts(num, str)
int num;
char *str;
{
    if (!frame[num].active) {
        return 0;
    }
    for (; *str; str++) {
        window_putchar(num, *str);
    }
    return 1;
}

window_cls(num)
int num;
{
    register int i, j;
    char far *v, far *t;

    v = vid_mem;
    t = v;
    for (i = frame[num].startx+1; i < frame[num].endy; i++) {
        for (j = frame[num].starty+1; j < frame[num].endx; j++) {
            v = t;
            v += (j*160) + i*2;
            *v++ = ' ';
            *v = NORM_VID;
        }
    }
    frame[num].curx = 0;
    frame[num].cury = 0;
}

window_cleol(num)
int num;
{
    register int i, x, y;

    x = frame[num].curx;
    y = frame[num].cury;
    window_xy(num, frame[num].curx, frame[num].cury);
    for (i = frame[num].cury; i < frame[num].endy - 1; i++) {
        window_putchar(num, ' ');
    }
    window_xy(num, x, y);
}

window_upline(num)
int num;
{
    if (frame[num].curx > 0) {
        frame[num].curx--;
        window_xy(num, frame[num].curx, frame[num].cury);
        return 1;
    }
    return 0;
}

window_downline(num)
int num;
{
    if (frame[num].curx < (frame[num].endx - frame[num].startx - 1)) {
        frame[num].curx++;
        window_xy(num, frame[num].curx, frame[num].cury);
        return 1;
    }
    return 1;
}

window_bksp(num)
int num;
{
    if (frame[num].cury > 0) {
        frame[num].cury--;
        window_xy(num, frame[num].curx, frame[num].cury);
        window_putchar(num, ' ');
        frame[num].cury--;
        window_xy(num, frame[num].curx, frame[num].cury);
    }
    return 0;
}

make_window(num, header, startx, starty, endx, endy, border, attrib, shi)
int num;
char *header;
int startx, starty, endx, endy;
int border;
unsigned char attrib, shi;

{
    unsigned char *p;
    int dl;

    if (num > MAX_FRAME) {
        return -1;
    }
    if ((startx>24)||(startx<0)||(starty>78)||(starty<0)) {
        return -1;
    }
    if ((endx>24)||(endy>79)) {
        return -1;
    }
    if (shi) {
        dl = 1;
    }
    else
        dl = 0;
    frame[num].startx = startx;
    frame[num].endx = endx;
    frame[num].starty = starty;
    frame[num].endy = endy;
    frame[num].p = p;
    frame[num].header = header;
    frame[num].border = border;
    frame[num].active = 0;
    frame[num].attrib = attrib;
    frame[num].curx = 0;
    frame[num].cury = 0;
    frame[num].shd = shi;

    return 0;
}
