This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/goldlib/gcui/gwininit.cpp

329 lines
8.5 KiB
C++

// 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 kernel.
// Based on CXL by Mike Smedley.
// ------------------------------------------------------------------
#include <cstdio>
#include <cstdarg>
#include <cstdlib>
#include <cstring>
#include <gmemdbg.h>
#include <gutlmisc.h>
#include <gwinall.h>
#include <gkbdcode.h>
// ------------------------------------------------------------------
#define GOLD_INLINE inline
#define GOLD_WCHK
// ------------------------------------------------------------------
// Global window data
GWin gwin;
// ------------------------------------------------------------------
// Window Class constructor
GWin::GWin() {
active = NULL; // pointer to active window
hidden = NULL; // pointer to last hidden window
menu = NULL; // pointer to head menu record
cmenu = NULL; // pointer to current menu record
helptr = NULL; // pointer to help info record
handle = 0; // last handle given to a window
help = 0; // pointer to current help category
werrno = W_NOERROR; // error num from last window func
total = 0; // total number of open windows
mlevel = 0; // system variable used in menus
ilevel = 0; // system variable used in menus
esc = true; // check for Esc in input funcions?
tabwidth = 8; // window TTY output tab width
fillch = ' '; // character to fill windows with
style = STYLE_NORMAL; // window opening style
}
// ------------------------------------------------------------------
// Window Class destructor
GWin::~GWin() {
// No action defined yet
}
// ------------------------------------------------------------------
// Displays a string in centered in active window
int wcenters(int wrow, vattr attr, const char* str) {
register int window_width, string_length;
int start_column, border;
// check for active window
if(!gwin.total)
return gwin.werrno=W_NOACTIVE;
// check for valid row
if(wchkcoord(wrow,0))
return gwin.werrno=W_INVCOORD;
// check for window border
border=gwin.active->border;
// calculate start column & window width
start_column = gwin.active->scol+border;
window_width = (gwin.active->ecol-border)-start_column+1;
// check length of input string
string_length=strlen(str);
if(string_length>window_width)
return gwin.werrno=W_STRLONG;
// display the string
vputs(
gwin.active->srow+wrow+border,
((window_width/2)+start_column)-(string_length/2),
attr,
str
);
// return normally
return gwin.werrno=W_NOERROR;
}
// ------------------------------------------------------------------
// Smoothly drag a window 1 position in given direction
int wdrag(int direction) {
int srow, scol, erow, ecol, fill_row, fill_col, i;
int nsrow, nscol, nerow, necol;
vattr shad_attr = DEFATTR;
int chars_per_line, lines_per_win;
int vert_movement, horz_movement;
vsavebuf* win_image;
vsavebuf* wp;
vatch* p;
register vatch* src;
register vatch* dest;
// check for active window
if(!gwin.total)
return(gwin.werrno=W_NOACTIVE);
// get window coordinates
srow = gwin.active->srow;
scol = gwin.active->scol;
erow = gwin.active->erow;
ecol = gwin.active->ecol;
// calculate lines-per-window and characters-per-line
lines_per_win = erow - srow + 1;
chars_per_line = ecol - scol + 1;
// determine facts about direction of move
vert_movement=horz_movement=0;
switch(direction) {
case D_DOWN:
vert_movement=1;
lines_per_win--;
break;
case D_UP:
vert_movement=-1;
lines_per_win--;
break;
case D_LEFT:
horz_movement=-1;
chars_per_line--;
break;
case D_RIGHT:
default:
horz_movement=1;
chars_per_line--;
}
// calculate new window coordinates
nsrow = srow + vert_movement;
nscol = scol + horz_movement;
nerow = erow + vert_movement;
necol = ecol + horz_movement;
// if window has shadow, close it before the move
if(gwin.active->wsbuf!=NULL) {
shad_attr = gwin.active->wsattr;
wshadoff();
}
// save the current window image
win_image = vsave(srow,scol,erow,ecol);
if(win_image==NULL)
return(gwin.werrno=W_ALLOCERR);
// save the area where the window will relocate to
wp = vsave(nsrow,nscol,nerow,necol);
if(wp==NULL) {
throw_xfree(win_image);
return(gwin.werrno=W_ALLOCERR);
}
// restore window to new coordinates
vrestore(win_image, nsrow, nscol, nerow, necol);
throw_xfree(win_image);
// start buffer positions past coordinates
src = gwin.active->wbuf->data;
dest = wp->data;
if(direction==D_DOWN)
src += chars_per_line;
if(direction==D_UP)
dest += chars_per_line;
// do the transfer of buffer contents
for(i=0; i < lines_per_win; i++) {
if(direction==D_LEFT)
dest++;
if(direction==D_RIGHT)
src++;
// move 1 line
memmove(dest, src, chars_per_line*sizeof(vatch));
src += chars_per_line;
dest += chars_per_line;
if(direction==D_LEFT)
src++;
if(direction==D_RIGHT)
dest++;
}
// erase the trail that was left-over
p = gwin.active->wbuf->data;
if(vert_movement) {
if(direction==D_DOWN)
fill_row=srow;
else {
p += (lines_per_win * chars_per_line);
fill_row=erow;
}
vputx(fill_row, scol, vgattr(*p), vgchar(*p), ecol-scol+1);
}
else {
if(direction==D_RIGHT)
fill_col=scol;
else {
p += chars_per_line;
fill_col=ecol;
}
for(i=srow;i<=erow;i++,p+=chars_per_line+1)
vputc(i, fill_col, vgattr(*p), vgchar(*p));
}
// free old window buffer
throw_xfree(gwin.active->wbuf);
// update window record
gwin.active->wbuf = wp;
gwin.active->row = gwin.active->row - gwin.active->srow + nsrow;
gwin.active->column = gwin.active->column - gwin.active->scol + nscol;
gwin.active->srow = nsrow;
gwin.active->scol = nscol;
gwin.active->erow = nerow;
gwin.active->ecol = necol;
// if window has shadow, redraw it
if(shad_attr != DEFATTR)
wshadow(shad_attr);
// reset cursor position
vposset(gwin.active->row,gwin.active->column);
// return normally
return(gwin.werrno=W_NOERROR);
}
// ------------------------------------------------------------------
// Slides active window to a new location
int wslide(int nsrow, int nscol) {
vattr shattr = DEFATTR;
int err = 0;
// check for active windows
if(!gwin.total)
return gwin.werrno=W_NOACTIVE;
// check for valid coordinates
if(nsrow<0 or nscol<0)
return gwin.werrno=W_INVCOORD;
// if window has shadow, close it before the move
if(gwin.active->wsbuf!=NULL) {
shattr = gwin.active->wsattr;
wshadoff();
}
// slide it on over
while(gwin.active->scol>nscol and !err) err = wdrag(D_LEFT);
while(gwin.active->scol<nscol and !err) err = wdrag(D_RIGHT);
while(gwin.active->srow>nsrow and !err) err = wdrag(D_UP);
while(gwin.active->srow<nsrow and !err) err = wdrag(D_DOWN);
// test for error
if(gwin.werrno)
return gwin.werrno;
// if window has shadow, redraw it
if(shattr != DEFATTR)
wshadow(shattr);
// return normally
return gwin.werrno=W_NOERROR;
}
// ------------------------------------------------------------------