//  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.
//  Windowing class.
//  ------------------------------------------------------------------

#ifndef __gwindow_h
#define __gwindow_h


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

#include <string>
#include <gwinall.h>

#undef getc
#undef putc


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

inline void wgetc(int wrow, int wcol, vattr* atr, vchar* chr) {

  vgetc(wrow+gwin.active->srow+gwin.active->border, wcol+gwin.active->scol+gwin.active->border, atr, chr);
}


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

struct gscrollbar_data {
  long minpos;    // Minimum range position
  long maxpos;    // Maximum range position
  long pos;       // Position of the thumb button
  long page;      // Size of the visible part
};


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

class gwindow {

protected:

  _wrec_t* wrec;

  int owner;

  int window_style;

  vattr window_color;

  vattr border_hi_color;
  vattr border_lo_color;

  vattr scrollbar_color;

  vattr title_color;
  int   title_position;

  vattr message_color;

  vattr shadow_color;

public:

  int start_row;
  int start_column;

  int end_row;
  int end_column;

  enum {
    title_top            = TTOP,
    title_left           = TLEFT,
    title_center         = TCENTER,
    title_right          = TRIGHT,
    title_bottom         = TBOTTOM,
    border_top           = TP_BORD,
    border_bottom        = BT_BORD,
    border_left          = LT_BORD,
    border_right         = RT_BORD,
    scrollbar_horizontal = W_HORZ,
    scrollbar_vertical   = W_VERT,
    direction_down       = D_DOWN,
    direction_up         = D_UP,
    direction_left       = D_LEFT,
    direction_right      = D_RIGHT,
    bordertype_single    = BT_SINGLE,
    bordertype_double    = BT_DOUBLE,
    bordertype_singletop = BT_SINGLETOP,
    bordertype_doubletop = BT_DOUBLETOP,
    bordertype_blanks    = BT_BLANKS,
    bordertype_none      = BT_NONE,
    bordertype_blocks    = BT_BLOCKS,
    bordertype_ascii     = BT_ASCII,
    bordertypes          = 7
  };

  gwindow();
  gwindow(int old_handle);
  virtual ~gwindow();

  void init();

  int height() { return 1 + end_row - start_row; }
  int width() { return 1 + end_column - start_column; }

  int border_type() { return window_style & bordertypes; }
  bool has_border() { return border_type() != BT_NONE; }

  vchar boxchar_upper_left_corner()         { return _box_table(border_type(), 0); }
  vchar boxchar_upper_horizontal_line()     { return _box_table(border_type(), 1); }
  vchar boxchar_upper_right_corner()        { return _box_table(border_type(), 2); }
  vchar boxchar_left_vertical_line()        { return _box_table(border_type(), 3); }
  vchar boxchar_right_vertical_line()       { return _box_table(border_type(), 4); }
  vchar boxchar_lower_left_corner()         { return _box_table(border_type(), 5); }
  vchar boxchar_lower_horizontal_line()     { return _box_table(border_type(), 6); }
  vchar boxchar_lower_right_corner()        { return _box_table(border_type(), 7); }
  vchar boxchar_middle_junction()           { return _box_table(border_type(), 8); }
  vchar boxchar_left_vertical_junction()    { return _box_table(border_type(), 9); }
  vchar boxchar_right_vertical_junction()   { return _box_table(border_type(), 10); }
  vchar boxchar_upper_horizontal_junction() { return _box_table(border_type(), 11); }
  vchar boxchar_lower_horizontal_junction() { return _box_table(border_type(), 12); }

  void set_window_at(int srow, int scol);
  void set_window_size(int vlen, int hlen);

  void open(int srow, int scol, int erow, int ecol, int style, vattr bcolor, vattr wcolor, vattr sbcolor = DEFATTR, vattr locolor = DEFATTR);
  void openxy(int srow, int scol, int vlen, int hlen, int style, vattr bcolor, vattr wcolor, vattr sbcolor = DEFATTR, vattr locolor = DEFATTR);
  void open();
  void close();
  void unlink();

  void hide();
  void unhide();

  int active();
  void activate();
  void activate_quick();

  int cursor_row();
  int cursor_column();

  void text_color(vattr color);

  void move_cursor(int row, int column);

  void title(const char* title, vattr color = DEFATTR, int position=-1);
  void no_title();

  void message(const char* text, int border, int leftofs, vattr color = DEFATTR);

  void shadow(vattr color = DEFATTR);
  void no_shadow();

  void set_vscrollbar_range(int minpos, int maxpos, int visible, int total, int redraw);
  void set_hscrollbar_range(int minpos, int maxpos, int visible, int total, int redraw);

  void set_vscrollbar_pos(int pos, int redraw);
  void set_hscrollbar_pos(int pos, int redraw);

  void set_scrollbar_color(vattr color);

  void vscrollbar(uint total, uint maxpos, uint pos, int sadd=0);
  void hscrollbar(uint total, uint maxpos, uint pos, int sadd=0);

  void scroll_down(int count=1);
  void scroll_up(int count=1);

  void scroll_box_down(int scol, int srow, int ecol, int erow, int count=1);
  void scroll_box_up(int scol, int srow, int ecol, int erow, int count=1);

  void getc(int row, int col, vattr* atr, vchar* chr);

  void putc(vchar ch);
  void puts(const char* text);
  void printc(int row, int col, vattr color, vchar ch);
  void prints(int row, int col, vattr color, const char* text);
  void printvs(int row, int col, vattr color, const vchar* text);
  void prints(int row, int col, vattr color, const std::string& text);
  void printns(int row, int col, vattr color, const char* text, int len, vchar fill=' ', vattr fill_color = DEFATTR);

  int printf(const char* format, ...) __attribute__ ((format (printf, 2, 3)));
  int printf(vattr color, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
  int printf(int row, int col, const char* format, ...) __attribute__ ((format (printf, 4, 5)));
  int printf(int row, int col, vattr color, const char* format, ...) __attribute__ ((format (printf, 5, 6)));

  void fill_char(vchar ch);
  void fill(int wsrow, int wscol, int werow, int wecol, vchar ch, vattr color);
  void vertical_line(int wsrow, int wscol, int count, int btype, vattr color);
  void horizontal_line(int wsrow, int wscol, int count, int btype, vattr color);
  void clear(vattr color = DEFATTR);
  void clear_eol();
  void drag(int direction, int howmuch=1);
  void slide(int row, int col);
  void putx(int wrow, int wcol, vattr color, char chr, uint len);
  void print_center(int row, vattr color, const char* text);
};


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

inline void gwindow::init() {

  wrec = NULL;
  start_row = start_column = 0;
  end_row = gvid->curr.screen.rows - 1;
  end_column = gvid->curr.screen.columns - 1;
  window_style = 0;
  window_color = BLACK_|_LGREY;
  border_hi_color = BLUE_|_LGREY;
  border_lo_color = DEFATTR;
  scrollbar_color = DEFATTR;
  title_color = BLUE_|_LGREY;
  title_position = title_center;
  message_color = BLUE_|_LGREY;
  shadow_color = DGREY_|_BLACK;
}


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

inline void gwindow::set_window_at(int srow, int scol) {

  start_row = srow;
  start_column = scol;
}


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

inline void gwindow::set_window_size(int vlen, int hlen) {

  end_row = start_row + vlen - 1;
  end_column = start_column + hlen - 1;
}


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

inline void gwindow::open(int srow, int scol, int erow, int ecol, int style, vattr bcolor, vattr wcolor, vattr sbcolor, vattr locolor) {

  start_row = srow;
  start_column = scol;
  end_row = erow;
  end_column = ecol;
  window_color = wcolor;
  window_style = style;
  border_hi_color = bcolor;
  border_lo_color = locolor;
  scrollbar_color = sbcolor;

  wopen(srow, scol, erow, ecol, style, bcolor, wcolor, sbcolor, locolor);
  wrec = gwin.active;
}


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

inline void gwindow::openxy(int srow, int scol, int vlen, int hlen, int style, vattr bcolor, vattr wcolor, vattr sbcolor, vattr locolor) {

  open(srow, scol, srow+vlen-1, scol+hlen-1, style, bcolor, wcolor, sbcolor, locolor);
}


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

inline void gwindow::open() {

  open(start_row, start_column, end_row, end_column, window_style, border_hi_color, window_color, scrollbar_color, border_lo_color);
}


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

inline int gwindow::active() {

  return wrec == gwin.active;
}


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

inline void gwindow::activate_quick() {

  if(!active())
    wactiv_(wrec->whandle);
}


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

inline void gwindow::close() {

  if(wrec) {
    activate_quick();
    wclose();
    wrec = NULL;
  }
}


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

inline void gwindow::unlink() {

  wunlink(wrec->whandle);
  wrec = NULL;
}


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

inline void gwindow::hide() {

  activate_quick();
  whide();
}


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

inline void gwindow::unhide() {

  wunhide(wrec->whandle);
}


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

inline void gwindow::activate() {

  if(!active())
    wactiv(wrec->whandle);
}


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

inline int gwindow::cursor_row() {

  return wrec->row;
}


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

inline int gwindow::cursor_column() {

  return wrec->column;
}


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

inline void gwindow::text_color(vattr color) {

  window_color = color;
  activate_quick();
  wtextattr(color);
}


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

inline void gwindow::set_scrollbar_color(vattr color) {

  wrec->sbattr = color;
  scrollbar_color = color;
}


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

inline void gwindow::move_cursor(int row, int column) {

  activate_quick();
  wgotoxy(row, column);
}


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

inline void gwindow::title(const char* title, vattr color, int position) {

  if(color != DEFATTR)
    title_color = color;
  if(position != -1)
    title_position = position;
  activate_quick();
  wtitle(title, title_position, title_color);
}


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

inline void gwindow::no_title() {

  title(NULL);
}


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

inline void gwindow::message(const char* text, int border, int leftofs, vattr color) {

  if(color != DEFATTR)
    message_color = color;
  activate_quick();
  wmessage(text, border, leftofs, message_color);
}


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

inline void gwindow::shadow(vattr color) {

  if(color != DEFATTR)
    shadow_color = color;
  activate_quick();
  wshadow(shadow_color);
}


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

inline void gwindow::no_shadow() {

  activate_quick();
  wshadoff();
}


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

inline void gwindow::vscrollbar(uint total, uint maxpos, uint pos, int sadd) {

  activate_quick();
  wscrollbar(scrollbar_vertical, total, maxpos, pos, sadd);
}


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

inline void gwindow::hscrollbar(uint total, uint maxpos, uint pos, int sadd) {

  activate_quick();
  wscrollbar(scrollbar_horizontal, total, maxpos, pos, sadd);
}


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

inline void gwindow::scroll_down(int count) {

  activate_quick();
  wscroll(count, direction_down);
}


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

inline void gwindow::scroll_up(int count) {

  activate_quick();
  wscroll(count, direction_up);
}


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

inline void gwindow::scroll_box_down(int scol, int srow, int ecol, int erow, int count) {

  activate_quick();
  wscrollbox(scol, srow, ecol, erow, count, direction_down);
}


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

inline void gwindow::scroll_box_up(int scol, int srow, int ecol, int erow, int count) {

  activate_quick();
  wscrollbox(scol, srow, ecol, erow, count, direction_up);
}


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

inline void gwindow::getc(int row, int col, vattr* atr, vchar* chr) {

  activate_quick();
  wgetc(row, col, atr, chr);
}


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

inline void gwindow::putc(vchar ch) {

  activate_quick();
  wputc(ch);
}


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

inline void gwindow::puts(const char* text) {

  activate_quick();
  wputs(text);
}


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

inline void gwindow::printc(int row, int col, vattr color, vchar ch) {

  activate_quick();
  wprintc(row, col, color, ch);
}


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

inline void gwindow::prints(int row, int col, vattr color, const char* text) {

  activate_quick();
  wprints(row, col, color == DEFATTR ? window_color : color, text);
}


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

inline void gwindow::printvs(int row, int col, vattr color, const vchar* text) {

  activate_quick();
  wprintvs(row, col, color == DEFATTR ? window_color : color, text);
}


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

inline void gwindow::prints(int row, int col, vattr color, const std::string& text) {

  prints(row, col, color, text.c_str());
}


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

inline void gwindow::printns(int row, int col, vattr color, const char* text, int len, vchar fill, vattr fill_color) {

  activate_quick();
  wprintns(row, col, color, text, len, fill, fill_color);
}


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

inline void gwindow::fill_char(vchar ch) {

  activate_quick();
  wfillch(ch);
}


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

inline void gwindow::fill(int wsrow, int wscol, int werow, int wecol, vchar ch, vattr color) {

  activate_quick();
  wfill(wsrow, wscol, werow, wecol, ch, color);
}


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

inline void gwindow::vertical_line(int wsrow, int wscol, int count, int btype, vattr color) {

  activate_quick();
  wvline(wsrow, wscol, count, btype, color);
}


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

inline void gwindow::horizontal_line(int wsrow, int wscol, int count, int btype, vattr color) {

  activate_quick();
  whline(wsrow, wscol, count, btype, color);
}


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

inline void gwindow::clear(vattr color) {

  activate_quick();
  wcclear(color == DEFATTR ? window_color : color);
}


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

inline gwindow::gwindow() {

  init();
  owner = true;
}


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

inline gwindow::gwindow(int old_handle) {

  init();
  owner = false;

  wrec = wfindrec(old_handle);

  start_row = wrec->srow;
  start_column = wrec->scol;
  end_row = wrec->erow;
  end_column = wrec->ecol;
  window_color = wrec->wattr;
  window_style = wrec->btype;
  border_hi_color = wrec->battr;
  border_lo_color = wrec->loattr;
  scrollbar_color = wrec->sbattr;
}


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

inline gwindow::~gwindow() {

  if(owner)
    close();
}


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

inline void gwindow::slide(int row, int col) {

  activate_quick();
  wslide(row, col);
}


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

inline void gwindow::print_center(int row, vattr color, const char* text) {

  activate_quick();
  wcenters(row, color, text);
}


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

#endif

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