/*===========================================================================*\
| WNDWMGR.C - Multi-level virtual window demo              ver 2.0a, 03-22-89 |
|             to demonstrate powerful window management.                      |
|                                                                             |
|   This program shows you how the window management utilities allow you to   |
| access any window at any time.  You can even hide the top level window for  |
| displaying later.                                                           |
|   The demo places a very heavy load on screen processing by doing full      |
| screen scrolling on the virtual screens and then updating them on the CRT.  |
| Notice that the full windows are updated even if covered.  The constantly   |
| scrolling screens are there just to make it more apparent where and how     |
| fast the windows are being updated.                                         |
|   Run program.  Instructions are on the screen.                             |
|                                                                             |
| Be sure that you fully exit the program so that the keyboard interrupt      |
| handler can be fully restored.  If you do not wish to use the keyboard      |
| handler during debugging, change the value passed to setkbdhandler in main  |
| to 0 rather than 1.                                                         |
|   Copyright (c) 1989 by James H. LeMay,  All rights reserved.               |
\*===========================================================================*/

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <process.h>

#include "qwikc20.h"
#include "wndwc20.h"
#include "keybc20.h"

/* ASCII key codes: */
#define ALT1 120
#define ALT2 121
#define ALT3 122
#define ALT4 123
#define LEFTARROW 75
#define RIGHTARROW 77
#define UPARROW 72
#define DOWNARROW 80
#define HOMEKEY 71
#define ENDKEY 79
#define PGUP 73
#define PGDN 81
#define ESCKEY 27
#define RETKEY 13
#define F5KEY 63
#define F10KEY 68

#define SCROLLLOCK 0x10
#define MOVEMODE 0x01
#define RESIZEMODE 0x02
#define SCROLLMODE 0x04

unsigned char rowstep;
unsigned char colstep;
unsigned char i;
unsigned char line;
unsigned char fastrowstep;
unsigned char fastcolstep;
char altermode=MOVEMODE;
int numofrows;
int numofcols;
int name;
int key;
char extkey;
char typematic;

char stra[25][80]=
{ "ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ·",
  "ÓÄÒÄÄÄÄÄÄÄÄÄÄ E A G L E  Performance Software ÄÄÄÄÄÄÄÄÄÄÄÒÄ½",
  "  ÓÄÒÄÄÄÄÄ P.O. Box 292786, Lewisville, TX  75029 ÄÄÄÄÄÒÄ½",
  "    ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½",
  "WNDWC20   gives  you  unparalleled  performance  in   window",
  "software  for Turbo C 2.0.  It features fixed,  hidden,  and",
  "true  virtual  windows with true  random-access.   Now  your",
  "windows can be dynamically updated even if they are covered!",
  "The  speed  of hidden and virtual screens is  phenomenal  as",
  "they use the direct writing routines of QWIKC20.",
  "",
  "RANDOM  ACCESS  is the power to pull any window to  the  top",
  "even if they are covered without shuffling!  This means your",
  "windows can be in any order and not just stacked or tiled.",
  "",
  "VIRTUAL WINDOWS - The screens for virtual windows can be  of",
  "any  row  and  column size in a 64k buffer.   The  rows  and",
  "columns  can  range  from 1 to 255.  These  windows  can  be",
  "resized, zoomed, or scrolled right on the screen!",
  "",
  "Programmers will find the code very easy to use and  simple.",
  "All  the  hard working code is  kept  transparent.   Several",
  "window-relative and window management routines are included.",
  "",
  "" };


/*==============================| scrollon |================================*\
Returns the Scroll Lock status (0=off, nonzero=on).
\*==========================================================================*/
int scrollon(void)
{
    return((*keystatus & SCROLLLOCK) != 0);
}


/*==========================| updatekeystatus |=============================*\
\*==========================================================================*/
void updatekeystatus(void)
{
    char s[20];

    if(scrollon()) {
        if(!virtualflag) altermode=MOVEMODE;
        qwrite( crt_rows, 61, WHITE+GREEN_BG,
                (sprintf( s, "%c%c%c%c", 24, 25, 27, 26 ), s) );
        switch(altermode) {
            case MOVEMODE:   strcpy( s, "-Move   " ); break;
            case RESIZEMODE: strcpy( s, "-Resize " ); break;
            case SCROLLMODE: strcpy( s, "-Scroll " ); break;
        }
        qwriteeos( BLACK+GREEN_BG, s );
        qwriteeos( YELLOW+GREEN_BG, " SCROLL" );
    } else {
        qfill( crt_rows, 61, 1, 20, GREEN_BG, ' ' );
    }
}


/*===========================| updatewindows |==============================*\
For this demo, the windows are not only being scrolled on the screen,
but also in RAM, whether they are seen or not!  So, let's give it a
heavy CPU and video load, and see how fast it still can go.
\*==========================================================================*/
void updatewindows(void)
{
    writetovirtual(name);
    wscrollup();          /* for the heaviest load, scroll up entire screen */
    wwrite( 25, 2, stra[line] );   /* wrap a new line at the bottom */
    vupdatewindow();

    if(++name==WINDOW4) {
        name = WINDOW1;
        if(line==24) line=0;
        else ++line;
    }
}


/*==============================| kbdidle |=================================*\
Here's where the windows are updated!  When the keyboard is idle, the
following function is run.  You may change the contents of course.
\*==========================================================================*/
void kbdidle(void)
{
    updatewindows();
    writetocrt();
    updatekeystatus();
}


/*===========================| initsteprates |==============================*\
\*==========================================================================*/
void initsteprates(void)
{
    if(crt_rows>40) fastrowstep=4;
    else fastrowstep=2;
    fastcolstep=crt_cols/20;
}


/*==========================| adjuststeprates |=============================*\
\*==========================================================================*/
void adjuststeprates(void)
{
    if(typematic) {
        colstep=fastcolstep;
        rowstep=fastrowstep;
    } else {
        colstep=1;
        rowstep=1;
    }
}


/*==============================| getsteps |================================*\
\*==========================================================================*/
void getsteps( int *numofrows, int *numofcols )
{
    int rows=0;
    int cols=0;

    adjuststeprates();
    switch(key) {
        case UPARROW:    rows = -rowstep; break;
        case DOWNARROW:  rows =  rowstep; break;
        case LEFTARROW:  cols = -colstep; break;
        case RIGHTARROW: cols =  colstep; break;
        case PGUP:       rows = -255;     break;
        case PGDN:       rows =  255;     break;
        case HOMEKEY:    cols = -255;     break;
        case ENDKEY:     cols =  255;     break;
    }
    *numofrows = rows;
    *numofcols = cols;
}


/*============================| alterwindow |===============================*\
Handles the move/resize/scroll window commands.
\*==========================================================================*/
void alterwindow(void)
{
    int rows, cols;

    if(!virtualflag) altermode=MOVEMODE;

    if(extkey) {
        getsteps( &rows, &cols );
        switch(altermode) {
            case MOVEMODE:   movewindow    (rows, cols ); break;
            case RESIZEMODE: vresizewindow (rows, cols ); break;
            case SCROLLMODE: vscrollview   (rows, cols ); break;
        }
    } else
    if(virtualflag) {
        switch(toupper(key)) {
            case 'M': altermode=MOVEMODE; break;
            case 'R': altermode=RESIZEMODE; break;
            case 'S': altermode=SCROLLMODE; break;
        }
    }
}


/*============================| createscreen |==============================*\
\*==========================================================================*/
void createscreen(void)
{
    prefer_multitask=1;
    initwindow( YELLOW+BLACK_BG, 1, 0 );
    setvirtualsize( 25, 80 );     /* to keep heap limited */
    titleofs = 0;            /* place titles at extreme LEFT or RIGHT */
    /* margins.top_margin=2; */
    margins.bottom_margin=crt_rows-1;
    /* margins.right_margin=79;
    margins.left_margin=2; */
    qfill( crt_rows, 1, 1, crt_cols, GREEN_BG, ' ' );
    qwrite( crt_rows, 2, WHITE+GREEN_BG, "Alt:1-4" );
    qwriteeos( BLACK+GREEN_BG, "-Window Num  " );
    qwriteeos( WHITE+GREEN_BG, "ESC" );
    qwriteeos( BLACK+GREEN_BG, "-Hide  " );
    qwriteeos( WHITE+GREEN_BG, "F5" );
    qwriteeos( BLACK+GREEN_BG, "-Zoom  " );
    qwriteeos( WHITE+GREEN_BG, "F10" );
    qwriteeos( BLACK+GREEN_BG, "-Quit  " );
    initsteprates();
    setwindowmodes( /* ZOOMMODE | */ CURSOROFFMODE | VIRTUALMODE );

    /* -- virtual window 1 -- */
    makewindow( 1, 1, 20, 60, BLACK+BROWN_BG, BLACK+BROWN_BG, SINGLE_BORDER,
                WINDOW1 );
    writetovirtual( tws.wsname );
    titlewindow( TOP, LEFT, WHITE+BROWN_BG, "1 Virtual Window " );
    for(i=0; i<25; i++) wwrite( i+1, 2, stra[i] );
    vupdatewindow();

    /* -- virtual window 2 -- */
    writetocrt();
    makewindow( 6, 10, 16, 60, WHITE+GREEN_BG, WHITE+GREEN_BG, SINGLE_BORDER,
                WINDOW2 );
    writetovirtual( tws.wsname );
    titlewindow( TOP, LEFT, YELLOW+GREEN_BG, "2 Virtual Window  " );
    for(i=0; i<25; i++) wwrite( i+1, 2, stra[i] );
    vupdatewindow();

    /* -- virtual window 3 -- */
    writetocrt();
    makewindow( 11, 20, 14, 59, WHITE+BLUE_BG, WHITE+BLUE_BG, SINGLE_BORDER,
                WINDOW3 );
    writetovirtual( tws.wsname );
    titlewindow( TOP, LEFT, YELLOW+BLUE_BG, "3 Virtual Window  " );
    for(i=0; i<25; i++) wwrite( i+1, 2, stra[i] );
    vupdatewindow();

    /* -- fixed window 4 -- */
    writetocrt();
    setwindowmodes( CURSOROFFMODE );
    makewindow( 7, 42, 17, 32, BLACK+LIGHTGRAY_BG, BLACK+LIGHTGRAY_BG,
                HDOUBLE_BORDER, WINDOW4 );
    titlewindow( TOP, LEFT, SAMEATTR, "4" );
    titlewindow( TOP, CENTER, SAMEATTR, " Fixed Window " );
    wwritec( 1, "DYNAMIC UPDATING!!" );
    wbrdrh( 2 );
    wwritec( 3, "Instructions:" );
    tws.wsline = SINGLE_BORDER;
    wlineh( 4, 3, tws.wcols-4 );
    wwrite( 5, 3, "ESC - Hide top window" );
    wwrite( 6, 3, "F5  - Zoom virtual window" );
    wwrite( 7, 3, "F10 - Quit" );
    wwrite( 8, 3, "Alt:1-4 - Access window" );
    wwrite( 9, 3, "With ScrollLock on:" );
    wwrite(10, 5,   "R - Resize mode" );
    wwrite(11, 5,   "S - Scroll mode" );
    wwrite(12, 5,   "M - Move   mode" );
    wwrite(13, 5,   "Then arrow keys." );
    wwrite(14, 3, "Ctrl-NumLock to freeze." );
    wwrite(15, 3, "Any other key to pause." );
    wgotorc( tws.wrows, 1 );
    changeborder( DOUBLE_BORDER );
}


void main(void)
{
/*  qsnow=0; */

    kbdidlefunc = kbdidle;          /* set hook for kbdidle routine! */
    useint9handler( 1 );            /* set to 1 for solid keyboard action. */
                                    /* use 0 for debugging. */
    createscreen();
    name=WINDOW1;

    do {
        readkbd( &key, &extkey, &typematic );
        if(scrollon()) alterwindow();
        if(extkey) {
            switch(key) {
                case ALT1:
                case ALT2:
                case ALT3:
                case ALT4:
                    restoreborder();
                    accesswindow( key-ALT1+1 );
                    changeborder( DOUBLE_BORDER ); break;
                case F5KEY: vzoomwindow(); break;
            }
        } else {
            switch(key) {
                case ESCKEY:
                    hidewindow();
                    changeborder( DOUBLE_BORDER ); break;
            }
        }
    } while(!(extkey && (key==F10KEY)));

    accesswindow( WINDOW0 );
    wclrscr();
    setcursor( cursor_initial );
    exit(0);
}
