/*$Header: /p/tcsh/cvsroot/tcsh/win32/nt.screen.c,v 1.14 2006/03/14 01:22:57 mitr Exp $*/
/*
* ed.screen.c: Editor/termcap-curses interface
*/
/*-
* Copyright (c) 1980, 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "sh.h"
#include "ed.h"
#include "tc.h"
#include "ed.defns.h"
/* #define DEBUG_LITERAL */
/*
* IMPORTANT NOTE: these routines are allowed to look at the current screen
* and the current possition assuming that it is correct. If this is not
* true, then the update will be WRONG! This is (should be) a valid
* assumption...
*/
extern int nt_getsize(int*,int*,int*);
extern int nt_ClearEOL( void) ;
extern void NT_ClearEOD( void) ;
extern void NT_ClearScreen(void) ;
extern void NT_VisibleBell(void);
extern void NT_WrapHorizontal(void);
static int GetSize(int *lins, int *cols);
int DisplayWindowHSize;
void
terminit(void)
{
return;
}
int T_ActualWindowSize;
static void ReBufferDisplay (void);
/*ARGSUSED*/
void
TellTC(void)
{
xprintf(CGETS(7, 1, "\n\tYou're using a Windows console.\n"));
}
static void
ReBufferDisplay(void)
{
register int i;
Char **b;
Char **bufp;
int lins,cols;
nt_getsize(&lins,&cols,&DisplayWindowHSize);
b = Display;
Display = NULL;
if (b != NULL) {
for (bufp = b; *bufp != NULL; bufp++)
xfree((ptr_t) * bufp);
xfree((ptr_t) b);
}
b = Vdisplay;
Vdisplay = NULL;
if (b != NULL) {
for (bufp = b; *bufp != NULL; bufp++)
xfree((ptr_t) * bufp);
xfree((ptr_t) b);
}
TermH = cols;
TermV = (INBUFSIZE * 4) / TermH + 1;/*FIXBUF*/
b = (Char **) xmalloc((size_t) (sizeof(*b) * (TermV + 1)));
for (i = 0; i < TermV; i++)
b[i] = (Char *) xmalloc((size_t) (sizeof(*b[i]) * (TermH + 1)));
b[TermV] = NULL;
Display = b;
b = (Char **) xmalloc((size_t) (sizeof(*b) * (TermV + 1)));
for (i = 0; i < TermV; i++)
b[i] = (Char *) xmalloc((size_t) (sizeof(*b[i]) * (TermH + 1)));
b[TermV] = NULL;
Vdisplay = b;
}
void
SetTC(char *what, char *how)
{
int li,win,co;
nt_getsize(&li,&co,&win);
if (!lstrcmp(what,"li")) {
li = atoi(how);
}else if(!lstrcmp(what,"co")) { //set window, not buffer size
win = atoi(how);
}
else
stderror(ERR_SYSTEM, "SetTC","Sorry, this function is not supported");
ChangeSize(li,win);
return;
}
/*
* Print the termcap string out with variable substitution
*/
void
EchoTC(Char **v)
{
Char **globbed;
char cv[BUFSIZE];/*FIXBUF*/
int verbose = 0, silent = 0;
static char *fmts = "%s\n", *fmtd = "%d\n";
int li,co;
setname("echotc");
v = glob_all_or_error(v);
globbed = v;
cleanup_push(globbed, blk_cleanup);
if (!v || !*v || *v[0] == '\0')
goto end;
if (v[0][0] == '-') {
switch (v[0][1]) {
case 'v':
verbose = 1;
break;
case 's':
silent = 1;
break;
default:
stderror(ERR_NAME | ERR_TCUSAGE);
break;
}
v++;
}
if (!*v || *v[0] == '\0')
goto end;
(void) StringCbCopy(cv,sizeof(cv), short2str(*v));
GetSize(&li,&co);
if(!lstrcmp(cv,"rows") || !lstrcmp(cv,"lines") ) {
xprintf(fmtd,T_Lines);
goto end;
}
else if(!lstrcmp(cv,"cols") ) {
xprintf(fmtd,T_ActualWindowSize);
goto end;
}
else if(!lstrcmp(cv,"buffer") ) {
xprintf(fmtd,T_Cols);
goto end;
}
else
stderror(ERR_SYSTEM, "EchoTC","Sorry, this function is not supported");
end:
cleanup_until(globbed);
}
int GotTermCaps = 0;
void
ResetArrowKeys(void)
{
}
void
DefaultArrowKeys(void)
{
}
int
SetArrowKeys(const CStr *name, XmapVal *fun, int type)
{
UNREFERENCED_PARAMETER(name);
UNREFERENCED_PARAMETER(fun);
UNREFERENCED_PARAMETER(type);
return -1;
}
int
IsArrowKey(Char *name)
{
UNREFERENCED_PARAMETER(name);
return 0;
}
int
ClearArrowKeys(const CStr *name)
{
UNREFERENCED_PARAMETER(name);
return -1;
}
void
PrintArrowKeys(const CStr *name)
{
UNREFERENCED_PARAMETER(name);
return;
}
void
BindArrowKeys(void)
{
return;
}
#define GoodStr(ignore) 1
void
SetAttributes(Char atr)
{
atr &= ATTRIBUTES;
}
/* PWP 6-27-88 -- if the tty driver thinks that we can tab, we ask termcap */
int
CanWeTab(void)
{
return 1;
}
/* move to line <where> (first line == 0) as efficiently as possible; */
void
MoveToLine(int where)
{
int del;
if (where == CursorV)
return;
if (where > TermV) {
#ifdef DEBUG_SCREEN
xprintf("MoveToLine: where is ridiculous: %d\r\n", where);
flush();
#endif /* DEBUG_SCREEN */
return;
}
del = where - CursorV;
NT_MoveToLineOrChar(del, 1);
CursorV = where; /* now where is here */
}
/* move to character position (where) as efficiently as possible */
void
MoveToChar(int where)
{
if (where == CursorH)
return;
if (where >= TermH) {
#ifdef DEBUG_SCREEN
xprintf("MoveToChar: where is riduculous: %d\r\n", where);
flush();
#endif /* DEBUG_SCREEN */
return;
}
if (!where) { /* if where is first column */
//(void) putraw('\r'); /* do a CR */
NT_MoveToLineOrChar(where, 0);
flush();
CursorH = 0;
return;
}
NT_MoveToLineOrChar(where, 0);
CursorH = where; /* now where is here */
}
void
so_write(register Char *cp, register int n)
{
if (n <= 0)
return; /* catch bugs */
if (n > TermH) {
return;
}
do {
if (*cp & LITERAL) {
Char *d;
for (d = litptr + (*cp++ & ~LITERAL) * LIT_FACTOR; *d;
d++)
(void) putraw(*d);
}
else
(void) putraw(*cp++);
CursorH++;
} while (--n);
if (CursorH >= TermH) { /* wrap? */
CursorH = 0;
CursorV++;
NT_WrapHorizontal();
}
else if(CursorH >= DisplayWindowHSize) {
flush();
NT_MoveToLineOrChar(CursorH,0);
}
}
void
DeleteChars(int num) /* deletes <num> characters */
{
if (num <= 0)
return;
if (!T_CanDel) {
#ifdef DEBUG_EDIT
xprintf(CGETS(7, 16, "ERROR: cannot delete\r\n"));
#endif /* DEBUG_EDIT */
flush();
return;
}
if (num > TermH) {
#ifdef DEBUG_SCREEN
xprintf(CGETS(7, 17, "DeletChars: num is riduculous: %d\r\n"), num);
flush();
#endif /* DEBUG_SCREEN */
return;
}
}
/* Puts terminal in insert character mode, or inserts num characters in the
line */
void
Insert_write(register Char *cp, register int num)
{
UNREFERENCED_PARAMETER(cp);
if (num <= 0)
return;
if (!T_CanIns) {
#ifdef DEBUG_EDIT
xprintf(CGETS(7, 18, "ERROR: cannot insert\r\n"));
#endif /* DEBUG_EDIT */
flush();
return;
}
if (num > TermH) {
#ifdef DEBUG_SCREEN
xprintf(CGETS(7, 19, "StartInsert: num is riduculous: %d\r\n"), num);
flush();
#endif /* DEBUG_SCREEN */
return;
}
}
/* clear to end of line. There are num characters to clear */
void
ClearEOL(int num)
{
if (num <= 0)
return;
nt_ClearEOL();
}
void
ClearScreen(void)
{ /* clear the whole screen and home */
NT_ClearScreen();
}
void
SoundBeep(void)
{ /* produce a sound */
beep_cmd ();
if (adrof(STRnobeep))
return;
if (adrof(STRvisiblebell))
NT_VisibleBell(); /* visible bell */
else
MessageBeep(MB_ICONQUESTION);
}
void
ClearToBottom(void)
{ /* clear to the bottom of the screen */
NT_ClearEOD();
}
void
GetTermCaps(void)
{
int lins,cols;
nt_getsize(&lins,&cols,&DisplayWindowHSize);
GotTermCaps = 1;
T_Cols = cols;
T_Lines = lins;
T_ActualWindowSize = DisplayWindowHSize;
T_Margin = MARGIN_AUTO;
T_CanCEOL = 1;
T_CanDel = 0;
T_CanIns = 0;
T_CanUP = 1;
ReBufferDisplay();
ClearDisp();
return;
}
/* GetSize():
* Return the new window size in lines and cols, and
* true if the size was changed.
*/
int
GetSize(int *lins, int *cols)
{
int ret = 0;
*lins = T_Lines;
*cols = T_Cols;
nt_getsize(lins,cols,&DisplayWindowHSize);
// compare the actual visible window size,but return the console buffer size
// this is seriously demented.
ret = (T_Lines != *lins || T_ActualWindowSize != DisplayWindowHSize);
T_Lines = *lins;
T_Cols = *cols;
T_ActualWindowSize = DisplayWindowHSize;
return ret;
}
void
ChangeSize(int lins, int cols)
{
int rc = 0;
// here we're setting the window size, not the buffer size.
//
nt_set_size(lins,cols);
rc = GetSize(&lins,&cols);
ReBufferDisplay(); /* re-make display buffers */
ClearDisp();
}
void
PutPlusOne(Char c, int width)
{
extern int OldvcV;
while (width > 1 && CursorH + width > DisplayWindowHSize)
PutPlusOne(' ', 1);
if ((c & LITERAL) != 0) {
Char *d;
for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++)
(void) putwraw(*d);
} else {
(void) putwraw(c);
}
Display[CursorV][CursorH++] = (Char) c;
while (--width > 0)
Display[CursorV][CursorH++] = CHAR_DBWIDTH;
if (CursorH >= TermH) { /* if we must overflow */
CursorH = 0;
CursorV++;
OldvcV++;
NT_WrapHorizontal();
}
else if(CursorH >= DisplayWindowHSize) {
NT_MoveToLineOrChar(CursorH,0);
}
}