/*********************************************************
 ** ReadWindowSize                                      **
 **                                                     **
 ** An example source how to read the window size       **
 ** in characters using CSI sequences (correctly)       **
 ** © 03.07.2000, THOR                                  **
 ** Thomas Richter                                      **
 *********************************************************/

/// Includes
#include <exec/types.h>
#include <dos/dos.h>
#include <dos/dosextens.h>

#include <proto/exec.h>
#include <proto/dos.h>
///
/// Defines
#define COOKED_MODE     0
#define RAW_MODE        1
#define MAX_DELAY       (5*1000*1000)
///
/// Protos
BOOL WindowSize(BPTR file,LONG *width,LONG *height);
///
/// Statics
char version[]="$VER: ReadWindowSize 1.00 (4.7.2000) © THOR";
struct DosLibrary *DOSBase;      /* This is filled in by the startup code */
///

/// Sample main program
int main(int argc,char **argv)
{
LONG width,height;

        if (WindowSize(Output(),&width,&height)) {
                Printf("The window size is %ld x %ld characters.\n",width,height);
                return 0;
        }

        Printf("Could not obtain the window size.\n");
        return 5;
}
///
/// WindowSize
BOOL WindowSize(BPTR file,LONG *width,LONG *height)
{
BOOL success;
BOOL incsi,innum,negative,inesc;
LONG counter;
LONG args[5];
UBYTE in;


        *width = *height = 0;

        if (SetMode(file,RAW_MODE)) {

                success  = TRUE;
                incsi    = FALSE;
                inesc    = FALSE;
                innum    = FALSE;
                negative = FALSE;
                counter  = 0;

                /* Now send a window borders request to the stream */
                Write(file,"\2330 q",4);

                /* Now parse an incomming string */
                for(;;) {
                        if (WaitForChar(file,MAX_DELAY) == FALSE) {
                                success = FALSE;
                                break;
                        }

                        if (Read(file,&in,1) != 1) {
                                success = FALSE;
                                break;
                        }

                        if (incsi) {
                                if ((in<' ') || (in>'~')) {             /* Invalid sequence? */
                                        incsi = FALSE;
                                } else if ((in>='0') && (in<='9')) {
                                        /* Valid number? */
                                        if (innum == FALSE) {
                                                innum = TRUE;
                                                args[counter] = 0;
                                        }
                                        args[counter] = args[counter]*10+in-'0';
                                } else {
                                        /* Abort parsing the number. Install its sign, and let it be. */
                                        if (innum) {
                                                if (negative)
                                                        args[counter] = -args[counter];
                                                innum    = FALSE;
                                                negative = FALSE;
                                        }
                                        if ((in>='@') && (in<='~')) {    /* End of sequence? */
                                                if ((in=='r') && (counter==3)) {        /* Is it a bounds report? */
                                                        *height = args[2]-args[0]+1;
                                                        *width  = args[3]-args[1]+1;
                                                        break;
                                                }
                                                incsi = FALSE;          /* Abort sequence */
                                        } else if (in==';') {                   /* Argument separator? */
                                                counter++;
                                                if (counter>4) counter=4;       /* Do not parse more than 5 arguments, throw everything else away */
                                                innum    = FALSE;
                                                negative = FALSE;
                                        } else if (in=='-') {
                                                if (innum)
                                                        incsi = FALSE;  /* minus sign in the middle is invalid */
                                                negative = ~negative;
                                        } else if (in==' ') {
                                                /* Ignore SPC prefix */
                                        } else {
                                                /* Abort the sequence */
                                                incsi = FALSE;
                                        }
                                }
                        } else if (inesc) {
                                if (in == '[') {
                                        inesc    = FALSE;
                                        incsi    = TRUE;   /* found a CSI sequence */
                                        innum    = FALSE;  /* but not yet a valid number */
                                        negative = FALSE;
                                        counter  = 0;
                                        args[0]  = args[1]=args[2]=args[3]=args[4] = 1;
                                } else if ((in >= ' ') && (in <= '/')) {
                                        /* ignore the ESC sequence contents */
                                } else {
                                        inesc    = FALSE;  /* terminate the ESC sequence */
                                }
                        } else if (in == 0x9B) {
                                        incsi    = TRUE;   /* found a CSI sequence */
                                        innum    = FALSE;  /* but not yet a valid number */
                                        negative = FALSE;
                                        counter  = 0;
                                        args[0]  = args[1]=args[2]=args[3]=args[4] = 1;
                        } else if (in == 0x1B) {
                                        inesc    = TRUE;  /* found an ESC sequence */
                        } /* Everything else is thrown away */
                }

                if (SetMode(file,COOKED_MODE)) {
                        return success;
                }
        }

        return FALSE;
}
///






