//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  Copyright (C) 1999-2000 Alexander S. Aganichev
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  GCUI: Golded+ Character-oriented User Interface.
//  Screen/video functions.
//  Based on CXL by Mike Smedley.
//  ------------------------------------------------------------------

#ifndef __gvidall_h
#define __gvidall_h


//  ------------------------------------------------------------------

#include <gdefs.h>
#if defined(__USE_NCURSES__)
#include <gcurses.h>
#endif
#if defined(__WIN32__)
#include <windows.h>
#endif

#if defined(_MSC_VER)
#pragma warning(disable: 4200)
#endif


//  ------------------------------------------------------------------

#ifdef BLINK
#undef BLINK
#endif
#define BLINK       128

#ifdef INTENSE
#undef INTENSE
#endif
#define INTENSE     8

#if defined(__UNIX__) && !defined(__USE_NCURSES__)
#define ACSET       BLINK
#else
#define ACSET       0
#endif


//  ------------------------------------------------------------------

#if defined(__USE_NCURSES__)
typedef chtype vchar;     // Type of characters on-screen
typedef int    vattr;     // Type of screen attributes
typedef chtype vatch;     // Type of character-attribute groups
#elif defined(__WIN32__)
typedef char vchar;       // Type of characters on-screen
typedef int  vattr;       // Type of screen attributes
typedef CHAR_INFO vatch;  // Type of character-attribute groups
#else
typedef char vchar;       // Type of characters on-screen
typedef int  vattr;       // Type of screen attributes
typedef word vatch;       // Type of character-attribute groups
#endif


//  ------------------------------------------------------------------
//  Attribute codes for functions that use them

const vattr DEFATTR   = -1;

const vattr BLACK_    = 0;
const vattr BLUE_     = 1;
const vattr GREEN_    = 2;
const vattr CYAN_     = 3;
const vattr RED_      = 4;
const vattr MAGENTA_  = 5;
const vattr BROWN_    = 6;
const vattr LGREY_    = 7;
const vattr DGREY_    = 8;
const vattr LBLUE_    = 9;
const vattr LGREEN_   = 10;
const vattr LCYAN_    = 11;
const vattr LRED_     = 12;
const vattr LMAGENTA_ = 13;
const vattr YELLOW_   = 14;
const vattr WHITE_    = 15;

const vattr _BLACK    = (BLACK_   << 4);
const vattr _BLUE     = (BLUE_    << 4);
const vattr _GREEN    = (GREEN_   << 4);
const vattr _CYAN     = (CYAN_    << 4);
const vattr _RED      = (RED_     << 4);
const vattr _MAGENTA  = (MAGENTA_ << 4);
const vattr _BROWN    = (BROWN_   << 4);
const vattr _LGREY    = (LGREY_   << 4);
const vattr _DGREY    = (DGREY_   << 4);
const vattr _LBLUE    = (LBLUE_   << 4);
const vattr _LGREEN   = (LGREEN_  << 4);
const vattr _LCYAN    = (LCYAN_   << 4);
const vattr _LRED     = (LRED_    << 4);
const vattr _LMAGENTA = (LMAGENTA_<< 4);
const vattr _YELLOW   = (YELLOW_  << 4);
const vattr _WHITE    = (WHITE_   << 4);


//  ------------------------------------------------------------------
//  Additional monochrome color values

const vattr UNDERLINE = 1;
const vattr NORMAL    = 7;
const vattr HIGHLIGHT = 15;
const vattr REVERSE   = 112;


//  ------------------------------------------------------------------
//  Display adapter types returned from vidtype()
//  If bit 0 is set, the adapter was detected in monochrome mode

#define GV_NONE     0x0000
#define V_MONO      0x0001
#define V_MDA       0x0011
#define V_HGC       0x0021
#define V_HGCPLUS   0x0041
#define V_INCOLOR   0x0080
#define V_CGA       0x0100
#define V_EGA       0x0200
#define V_EGAMONO   0x0201
#define V_MCGA      0x0400
#define V_MCGAMONO  0x0401
#define V_VGA       0x0800
#define V_VGAMONO   0x0801


//  ------------------------------------------------------------------
//  Video parameter settings

#define VP_DMA      0   // direct screen writes
#define VP_CGA      1   // direct screen writes, eliminate CGA snow
#define VP_BIOS     2   // BIOS screen writes
#define VP_MONO     3   // monochrome attribute translation on
#define VP_COLOR    4   // monochrome attribute translation off
#define VP_OS2VIO   6   // OS/2 vio screen writes
#define VP_W32CON   7   // WIN32 console screen writes
#define VP_CURSES   8   // Curses screen writes


//  ------------------------------------------------------------------
//  Video devices

#define GVID_DMA  0
#define GVID_CGA  1
#define GVID_BIO  2
#define GVID_OS2  4
#define GVID_W32  5
#define GVID_CUR  6


//  ------------------------------------------------------------------
//  Useful defines for video (0x10) interrupt function numbers

#if defined(__MSDOS__)
#define V_SET_MODE              0x00
#define V_SET_CURSOR_POS        0x02
#define V_GET_CURSOR_POS        0x03
#define V_SCROLL_UP             0x06
#define V_SCROLL_DOWN           0x07
#define V_RD_CHAR_ATTR          0x08
#define V_WR_CHAR_ATTR          0x09
#define V_WR_CHAR               0x0A
#define V_WR_TTY                0x0E
#define V_GET_MODE              0x0F
#define V_GET_FONT_INFO         0x1130
#endif


//  ------------------------------------------------------------------

#if defined(__MSDOS__)
struct __int10_ah1b_statebuf {
                        // Offset  Size    Description
  dword statfunctable;  //  00h    DWORD   address of static funtionality table (see below)
  byte  videomode;      //  04h    BYTE    video mode in effect
  word  columns;        //  05h    WORD    number of columns
  word  regenbuflen;    //  07h    WORD    length of regen buffer in bytes
  word  regenbufstart;  //  09h    WORD    starting address of regen buffer
  word  cursorpos0;     //  0Bh    WORD    cursor position for page 0
  word  cursorpos1;     //  0Dh    WORD    cursor position for page 1
  word  cursorpos2;     //  0Fh    WORD    cursor position for page 2
  word  cursorpos3;     //  11h    WORD    cursor position for page 3
  word  cursorpos4;     //  13h    WORD    cursor position for page 4
  word  cursorpos5;     //  15h    WORD    cursor position for page 5
  word  cursorpos6;     //  17h    WORD    cursor position for page 6
  word  cursorpos7;     //  19h    WORD    cursor position for page 7
  word  cursortype;     //  1Bh    WORD    cursor type
  byte  activepage;     //  1Dh    BYTE    active display page
  word  crctportaddr;   //  1Eh    WORD    CRTC port address
  byte  curr_reg_3x8;   //  20h    BYTE    current setting of register (3?8)
  byte  curr_reg_3x9;   //  21h    BYTE    current setting of register (3?9)
  byte  rows;           //  22h    BYTE    number of rows
  word  bytesperchar;   //  23h    WORD    bytes/character
  byte  dispcombcode;   //  25h    BYTE    display combination code of active display
  byte  dcc;            //  26h    BYTE    DCC of alternate display
  word  numcolors;      //  27h    WORD    number of colors supported in current mode
  byte  numpages;       //  29h    BYTE    number of pages supported in current mode
  byte  numscanlines;   //  2Ah    BYTE    number of scan lines active (0,1,2,3) = (200,350,400,480) Tseng ET3000: (4,5,6 = 512,600,768)
  byte  primcharblock;  //  2Bh    BYTE    primary character block
  byte  seccharblock;   //  2Ch    BYTE    secondary character block
  byte  miscflags;      //  2Dh    BYTE    miscellaneous flags (see below)
  byte  reserved1[3];   //  2Eh  3 BYTEs   reserved (00h)
  byte  videomem;       //  31h    BYTE    video memory available 00h = 64K, 01h = 128K, 02h = 192K, 03h = 256K
  byte  stateflags;     //  32h    BYTE    save pointer state flags (see below)
  byte  reserved2[13];  //  33h 13 BYTEs   reserved (00h)
};
#endif


//  ------------------------------------------------------------------
//  Border types

#define BT_SINGLE     0
#define BT_DOUBLE     1
#define BT_SINGLETOP  2
#define BT_DOUBLETOP  3
#define BT_BLANKS     4
#define BT_NONE       5
#define BT_BLOCKS     6
#define BT_ASCII      7


//  ------------------------------------------------------------------
//  Video information structure

struct GVidInfo {

  // Screen info
  struct _screen
  {
    int  mode;          // Video mode
    int  rows;          // Number of rows
    int  columns;       // Number of columns
    int  cheight;       // Character height
    int  cwidth;        // Character width
  } screen;

  // Cursor info
  struct _cursor
  {
    int  column;        // Cursor column
    int  row;           // Cursor row
    int  start;         // Cursor start line
    int  end;           // Cursor end line
    word attr;          // Cursor attribute. Hidden if attr == 0xFFFF
  } cursor;

  // Colors
  struct _color
  {
    vattr textattr;     // Text attribute
    vattr overscan;     // Overscan color
    int   intensity;    // Background color state (intense or blinking)
    int   palette[16];  // Palette state
  } color;
};


//  ------------------------------------------------------------------

#ifdef __DJGPP__
typedef uint32_t gdma; // Video DMA linear address
#else
typedef word*    gdma; // Video DMA pointer
#endif

//  ------------------------------------------------------------------
//  Video information record

class GVid {

public:

  int      adapter;    // Video adapter type

  GVidInfo orig;       // Original video info
  GVidInfo curr;       // Current video info

  int      device;     // Video device type

  gdma     dmadir;     // Video DMA pointer (direct)
  gdma     dmaptr;     // Video DMA pointer (direct or buffered)

  vchar*   bufchr;     // Video line char buffer (char only)
  vatch*   bufwrd;     // Video line word buffer (char+attr)
  vchar*   bufansi;    // Video line ANSI buffer (11*numcols)

  int      currow;     // Current cursor row
  int      curcol;     // Current cursor column

  size_t   numrows;    // number of displayed rows
  size_t   numcols;    // number of displayed columns

  word     videoseg;   // video buffer segment address

public:

  GVid();
  ~GVid();

public:

  void init();

  int  detectadapter  ();
  void detectinfo     (GVidInfo* _info);
  static
  void setcolorpairs  (bool enabletransparent=false);

  void resetcurr      ();

  void setdevice      (int _device);

  void setmode        (int _mode);
  void setrows        (int _rows);

  void setoverscan    (vattr _overscan);
  void setintensity   (int _intensity);

  void getpalette     (int* _palette);
  void setpalette     (int* _palette);

  bool isdma()  { return device == GVID_DMA; }
  bool iscga()  { return device == GVID_CGA; }
  bool isbios() { return device == GVID_BIO; }

  void restore_cursor();

  void resize_screen(int columns, int rows);

};

extern GVid *gvid;


//  ------------------------------------------------------------------
//  Box characters table

#if !defined(__USE_NCURSES__)

extern char* __box_table[];
#define _box_table(i,j) (__box_table[i][j])

#else

chtype _box_table(int type, int c);

#endif


//  ------------------------------------------------------------------
//  Prototypes

int setvparam  (int setting);

vattr mapattr  (vattr attr);
vattr revsattr (vattr attr);

inline vattr attrib(int f, int b, int i, int bl) { return (int)((b<<4)|(f)|(i<<3)|(bl<<7)); }

void vputw      (int row, int col, vatch chat);
void vputws     (int row, int col, vatch* buf, uint len);
void vputc      (int row, int col, vattr atr, vchar chr);
void vputvs     (int row, int col, vattr atr, const vchar* str);
void vputs      (int row, int col, vattr atr, const char* str);
void vputs_box  (int row, int col, vattr atr, const char* str);
void vputns     (int row, int col, vattr atr, const char* str, uint len);
void vputx      (int row, int col, vattr atr, vchar chr, uint len);
void vputy      (int row, int col, vattr atr, vchar chr, uint len);

vatch vgetw     (int row, int col);
void vgetc      (int row, int col, vattr* atr, vchar* chr);

void vscroll    (int srow, int scol, int erow, int ecol, vattr atr, int lines);

void vposget    (int* row, int* col);
void vposset    (int row, int col);

void vclrscr    ();
void vclrscr    (vattr atr);     // Overloaded

typedef struct _vsavebuf {
  int top, left, right, bottom;
  __extension__ vatch data[0];
} vsavebuf;
vsavebuf* vsave (int srow=-1, int scol=-1, int erow=-1, int ecol=-1);
void vrestore   (vsavebuf* buf, int srow=-1, int scol=-1, int erow=-1, int ecol=-1);

void vcurget    (int* sline, int* eline);
void vcurset    (int sline, int eline);

void vcurhide   ();
void vcurshow   ();
bool vcurhidden ();

void vcurlarge  ();
void vcursmall  ();

void vbox       (int srow, int scol, int erow, int ecol, int box, vattr hiattr, vattr loattr = DEFATTR);
void vfill      (int srow, int scol, int erow, int ecol, vchar chr, vattr atr);


#if defined(__USE_NCURSES__)

int gvid_dosattrcalc (int ourattr);
int gvid_attrcalc (int dosattr);

inline vchar vgchar (vatch chat) { return chat & (A_CHARTEXT | A_ALTCHARSET); }
inline vattr vgattr (vatch chat) { return gvid_dosattrcalc(chat & ~(A_CHARTEXT | A_ALTCHARSET)); }
inline vatch vschar (vatch chat, vchar chr) { return (chr & (A_CHARTEXT | A_ALTCHARSET)) | (chat & ~(A_CHARTEXT | A_ALTCHARSET)); }
inline vatch vsattr (vatch chat, vattr atr) { return (chat & (A_CHARTEXT | A_ALTCHARSET)) | gvid_attrcalc(atr); }
inline vatch vcatch (vchar chr, vattr atr)  { return chr | gvid_attrcalc(atr); }

#elif defined(__WIN32__)

inline vchar vgchar (vatch chat) { return chat.Char.AsciiChar; }
inline vattr vgattr (vatch chat) { return chat.Attributes; }
inline vatch vschar (vatch chat, vchar chr) { chat.Char.UnicodeChar = 0; chat.Char.AsciiChar = chr; return chat; }
inline vatch vsattr (vatch chat, vattr atr) { chat.Attributes = WORD(atr); return chat; }
inline vatch vcatch (vchar chr, vattr atr)  { vatch chat; chat.Char.UnicodeChar = 0; chat.Char.AsciiChar = chr; chat.Attributes = WORD(atr); return chat; }

#else

inline vchar vgchar (vatch chat) { return chat & 0xff; }
inline vattr vgattr (vatch chat) { return (chat >> 8) & 0xff; }
inline vatch vschar (vatch chat, vchar chr) { return (chat & 0xff00) | chr; }
inline vatch vsattr (vatch chat, vattr atr) { return (chat & 0xff) | (atr << 8); }
inline vatch vcatch (vchar chr, vattr atr)  { return (chr & 0xff) | ((atr << 8) & 0xff00); }

#endif

inline vchar vgetc (int row, int col) { return vgchar(vgetw(row, col)); }

typedef void (*VidPutStrCP)(int,int,int,const char*);

void gvid_boxcvt(char* s);


//  ------------------------------------------------------------------

#endif

//  ------------------------------------------------------------------
