home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
ytalk-3.0
/
part01
/
curses.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-20
|
7KB
|
396 lines
/* curses.c -- curses interface */
/* NOTICE
*
* Copyright (c) 1990,1992,1993 Britt Yenne. All rights reserved.
*
* This software is provided AS-IS. The author gives no warranty,
* real or assumed, and takes no responsibility whatsoever for any
* use or misuse of this software, or any damage created by its use
* or misuse.
*
* This software may be freely copied and distributed provided that
* no part of this NOTICE is deleted or edited in any manner.
*
*/
/* Mail comments or questions to ytalk@austin.eds.com */
#include "header.h"
#include <curses.h>
#include <sys/signal.h>
#include "curses.h"
typedef struct _ywin {
struct _ywin *next; /* next ywin in linked list */
yuser *user; /* user pointer */
WINDOW *win; /* window pointer */
int height, width; /* height and width in characters */
int row, col; /* row and column position on screen */
char *title; /* window title string */
} ywin;
static ywin *head; /* head of linked list */
/* ---- local functions ---- */
/* Take input from the user.
*/
static void
curses_input(fd)
int fd;
{
register int rc;
static ychar buf[MAXBUF];
if((rc = read(fd, buf, MAXBUF)) <= 0)
{
if(rc == 0)
bail(YTE_SUCCESS);
bail(YTE_ERROR);
}
my_input(buf, rc);
}
static ywin *
new_ywin(user, title)
yuser *user;
char *title;
{
register ywin *out;
register int len;
len = strlen(title);
out = (ywin *)get_mem(sizeof(ywin) + len + 1);
(void)memset(out, 0, sizeof(ywin));
out->user = user;
out->title = ((char *)out) + sizeof(ywin);
strcpy(out->title, title);
return out;
}
static void
make_win(w, height, width, row, col)
ywin *w;
int height, width, row, col;
{
if((w->win = newwin(height, width, row, col)) == NULL)
{
register ywin *w;
w = (ywin *)(me->term);
if(w->win != NULL)
show_error("make_win: newwin() failed");
bail(YTE_ERROR);
}
w->height = height;
w->width = width;
w->row = row;
w->col = col;
scrollok(w->win, FALSE);
wmove(w->win, 0, 0);
}
static void
draw_title(w)
ywin *w;
{
register int pad, x;
register char *t;
pad = (w->width - strlen(w->title)) / 2;
move(w->row - 1, w->col);
x = 0;
for(; x < pad - 2; x++)
addch('-');
if(pad >= 2)
{
addch('=');
addch(' ');
x += 2;
}
for(t = w->title; *t && x < w->width; x++, t++)
addch(*t);
if(pad >= 2)
{
addch(' ');
addch('=');
x += 2;
}
for(; x < w->width; x++)
addch('-');
}
/* Return number of lines per window, given "wins" windows.
*/
static int
win_size(wins)
int wins;
{
return (LINES - 1) / wins;
}
/* Break down and redraw all user windows.
*/
static void
curses_redraw()
{
register ywin *w;
register int row, wins, wsize;
/* kill old windows */
wins = 0;
for(w = head; w; w = w->next)
{
if(w->win)
{
delwin(w->win);
w->win = NULL;
}
wins++;
}
if((wsize = win_size(wins)) < 3)
{
end_term();
errno = 0;
show_error("curses_redraw: window size too small");
bail(YTE_ERROR);
}
/* make new windows */
clear();
refresh();
row = 0;
for(w = head; w; w = w->next)
{
if(w->next)
{
make_win(w, wsize-1, COLS, row+1, 0);
resize_win(w->user, wsize-1, COLS);
}
else
{
make_win(w, LINES-row-2, COLS, row+1, 0);
resize_win(w->user, LINES-row-2, COLS);
}
draw_title(w);
row += wsize;
refresh();
wrefresh(w->win);
}
}
/* Start curses and set all options.
*/
static void
curses_start()
{
LINES = COLS = 0; /* so resizes will work */
initscr();
raw();
crmode();
noecho();
clear();
}
/* Restart curses... window size has changed.
*/
static void
curses_restart()
{
register ywin *w;
/* kill old windows */
for(w = head; w; w = w->next)
if(w->win)
{
delwin(w->win);
w->win = NULL;
}
/* restart curses */
endwin();
curses_start();
curses_redraw();
refresh();
/* some systems require we do this again */
#ifdef SIGWINCH
signal(SIGWINCH, curses_restart);
#endif
}
/* ---- global functions ---- */
void
init_curses()
{
curses_start();
refresh();
head = NULL;
add_fd(0, curses_input); /* set up user's input function */
/* set up SIGWINCH signal handler */
#ifdef SIGWINCH
signal(SIGWINCH, curses_restart);
#endif
}
void
end_curses()
{
move(LINES-1, 0);
clrtoeol();
refresh();
endwin();
}
/* Open a new window.
*/
int
open_curses(user, title)
yuser *user;
char *title;
{
register ywin *w;
register int wins;
/* count the open windows. We want to ensure at least
* three lines per window.
*/
wins = 0;
for(w = head; w; w = w->next)
wins++;
if(win_size(wins+1) < 3)
return -1;
/* add the new user */
if(head == NULL)
w = head = new_ywin(user, title);
else
for(w = head; w; w = w->next)
if(w->next == NULL)
{
w->next = new_ywin(user, title);
w = w->next;
break;
}
user->term = w;
/* redraw */
curses_redraw();
return 0;
}
/* Close a window.
*/
void
close_curses(user)
yuser *user;
{
register ywin *w, *p;
/* zap the old user */
w = (ywin *)(user->term);
if(w == head)
head = w->next;
else
{
for(p = head; p; p = p->next)
if(w == p->next)
{
p->next = w->next;
break;
}
if(p == NULL)
{
show_error("close_curses: user not found");
return;
}
}
delwin(w->win);
free(w);
curses_redraw();
}
void
addch_curses(user, c)
yuser *user;
register ychar c;
{
register ywin *w;
register int x, y;
w = (ywin *)(user->term);
getyx(w->win, y, x);
waddch(w->win, c);
if(x >= COLS-1)
wmove(w->win, y, x);
}
void
move_curses(user, y, x)
yuser *user;
register int y, x;
{
register ywin *w;
w = (ywin *)(user->term);
wmove(w->win, y, x);
}
void
clreol_curses(user)
register yuser *user;
{
register ywin *w;
w = (ywin *)(user->term);
wclrtoeol(w->win);
}
void
clreos_curses(user)
register yuser *user;
{
register ywin *w;
w = (ywin *)(user->term);
wclrtobot(w->win);
}
void
scroll_curses(user)
register yuser *user;
{
register ywin *w;
/* Curses has uses busted scrolling. In order to call scroll()
* effectively, scrollok() must be TRUE. However, if scrollok()
* is TRUE, then placing a character in the lower right corner
* will cause an auto-scroll. *sigh*
*/
w = (ywin *)(user->term);
scrollok(w->win, TRUE);
scroll(w->win);
scrollok(w->win, FALSE);
}
void
flush_curses(user)
register yuser *user;
{
register ywin *w;
w = (ywin *)(user->term);
wrefresh(w->win);
}