/********************************************************************
 * $Author: lindner $
 * $Revision: 1.8 $
 * $Date: 1993/01/11 20:25:31 $
 * $Source: /home/mudhoney/GopherSrc/gopher1.11b/gopher/RCS/CURcurses.c,v $
 * $State: Rel $
 *
 * Paul Lindner, University of Minnesota CIS.
 *
 * Copyright 1991, 1992 by the Regents of the University of Minnesota
 * see the file "Copyright" in the distribution for conditions of use.
 *********************************************************************
 * MODULE: CURcurses.c
 * Abstraction of all Curses Functions
 *********************************************************************
 * Revision History:
 * $Log: CURcurses.c,v $
 * Revision 1.8  1993/01/11  20:25:31  lindner
 * Fixed weird wprintw error on EP/IX.
 *
 * Revision 1.7  1993/01/09  02:16:21  lindner
 * Changed (void*)-1 constructs to SIG_ERR
 *
 * Revision 1.6  1993/01/09  01:28:11  lindner
 * Replaced hosed Log messages (Ooops!)
 *
 * Revision 1.5  1993/01/09  01:24:42  lindner
 * Added CURchoice(), let's you choose one option from [2-9] items.
 *
 * Revision 1.4  1993/01/09  00:49:16  lindner
 * More mods for VMS from jqj.  Looks like better ctrl-y and ctrl-c
 * processing.
 *
 * Revision 1.3  1993/01/06  17:05:46  lindner
 * Added nl() to CURexit() for EP/IX machines.
 *
 * Revision 1.2  1992/12/31  05:55:44  lindner
 * Mods for VMS
 *
 * Revision 1.1  1992/12/10  06:16:51  lindner
 * Initial revision
 *
 *
 *********************************************************************/

#include "CURcurses.h"
#include "Malloc.h"
#include <signal.h>
#include "Stdlib.h"
#include "compatible.h"

#ifdef VMS
void setterm_pas();
void resetterm();
static int w_getch();
#define wgetch w_getch
#endif
 

/*
 * Initialize data space for various screen information
 */

CursesObj *
CURnew()
{
     CursesObj *cur;

     cur = (CursesObj *) malloc(sizeof(CursesObj));

     cur->Screen       = NULL;
     cur->Termtype     = STRnew();
     cur->Clearscreen  = STRnew();
     cur->AudibleBell  = STRnew();
     cur->Highlighton  = STRnew();
     cur->Highlightoff = STRnew();

     cur->inCurses     = FALSE;
     cur->sigtstp      = (void*)-1;
     cur->sigwinch     = (void*)-1;

     CURinit(cur);
     
     return(cur);

}


/*
 * Initialize various strings and such. 
 */

void
CURinit(cur)
  CursesObj *cur;
{
     int err;
     static char terminal[1024];
     static char capabilities[1024];   /* String for cursor motion */
     static char *ptr = capabilities;  /* for buffering         */
     char *cp;


#ifdef VMS
     CURsetTerm(cur, "VMS");
     CURsetBell(cur, "\007");
     CURsetCLS(cur, "");
     CURsetHighon(cur, "");
     CURsetHighoff(cur, "");
#else
     /*** Set the terminal type ***/
     if (getenv("TERM") != NULL)
	  CURsetTerm(cur, getenv("TERM"));
     else 
	  CURsetTerm(cur, "unknown");

     err = tgetent(terminal, CURgetTerm(cur));
     
     if (err !=1)
	  CURsetTerm(cur, "unknown");

     /*** Get the clearscreen code ***/
     if ((cp = (char *)tgetstr("cl", &ptr)) != NULL)
	  CURsetCLS(cur, cp);
     else
	  CURsetCLS(cur, "");

     /*** Set the bell ***/
     if ((cp = (char *) tgetstr("bl", &ptr)) != NULL)
	  CURsetBell(cur, cp);
     else
	  CURsetBell(cur, "\007");

     /*** Set the highlight codes ***/
     if ((cp = (char *) tgetstr("so", &ptr)) != NULL) {
	  CURsetHighon(cur, cp);
	  if ((cp = (char *) tgetstr("se", &ptr)) != NULL)
	       CURsetHighoff(cur, cp);
     } else {
	  CURsetHighon(cur, "");
	  CURsetHighoff(cur, "");
     }
     CURsetScreen(cur,initscr());
#endif
     cur->inCurses = FALSE;
     
}


/* 
 * Given a properly "CURnew" cursesobj, initialize the screen..
 */

void
CURenter(cur)
  CursesObj *cur;
{
     /* for safety */
     if (cur->inCurses == TRUE)
	  return;

#ifdef VMS
     (void)setterm_pas();
     CURsetScreen(cur,initscr());
#else
     tputs(CURgetCLS(cur),1,CURoutchar);
     fflush(stdout); 
#endif

     cur->inCurses = TRUE;

     CURwenter(cur,stdscr);

#ifdef SIGWINCH
     if (cur->sigwinch != SIG_ERR)
	  signal(SIGWINCH, cur->sigwinch);
#endif
#ifndef VMS
     if (cur->sigtstp != SIG_ERR)
	  signal(SIGTSTP, cur->sigtstp);
#endif
}

/*
 * Set up processing for the window (especially for system V curses!
 */

void
CURwenter(cur, win)
  CursesObj *cur;
  WINDOW *win;
{
     cbreak();
     noecho();
     nonl();
#ifdef SYSVCURSES
     intrflush(win, FALSE);
     nodelay(win, FALSE);
#ifndef ultrix			/** Causes wgetch to dump core in ultrix **/
     keypad(win, TRUE);
#endif
#endif
}     
/*
 * Exit curses system.
 */

void
CURexit(cur)
  CursesObj *cur;
{
     
     if (!cur->inCurses)
	return;
     cur->inCurses = FALSE;
     echo();
     nl();
     endwin();

#ifdef SYSVCURSES
     keypad(stdscr, FALSE);
#endif

#ifdef VMS
     (void)resetterm();
#else
     tputs(CURgetCLS(cur),1,CURoutchar);
     fflush(stdout);
 
     cur->sigtstp = signal(SIGTSTP, SIG_DFL);
#endif

#ifdef SIGWINCH
     cur->sigwinch = signal(SIGWINCH, SIG_DFL);
#endif

}



/*
 * send a character to stdout, not really curses, but we do use it...
 */

int
CURoutchar(c)
  char c;
{
     /** output the given character.  From tputs... **/
     /** Note: this CANNOT be a macro!              **/
     
     putc(c, stdout);
     return(c);
}


/*
 * Centerline, uses curses routines to center a line.
 */
void CURcenterline(cur, theline, yval)
  CursesObj *cur;
  char      *theline;
  int       yval;
{
     mvaddstr(yval, (COLS - strlen(theline))/2, theline);
}


/*
 * CURwgetstr is a replacement of getstr that allows editing of the string
 *
 * if the user types control codes we don't recognize, it's returned instead
 *
 * We assume that the incoming string is shorter than the max..
 *
 */


int
CURwgetstr(cur, win, inputline, maxlength)
  CursesObj *cur;
  WINDOW    *win;
  char      *inputline;
  int       maxlength;
{
     int pointer = 0;
     int curpointer = 0;
     int ch;
     int y,x;

     CURwenter(cur, win);
     cbreak();
     noecho();

     wstandout(win);

     /*** Check to see if there's something in the inputline already ***/
     
     while (inputline[pointer] != '\0') {
	  waddch(win, inputline[pointer]);
	  pointer ++;
	  curpointer ++;
     }

     wrefresh(win);

     for (;;) {
	  ch = CURwgetch(cur,win);

	  switch (ch) {

	  case '\n':
	       inputline[pointer] = '\0';
	       return(ch);
	       break;

	  /**  Backspace and delete **/

	  case '\b':
	       if (curpointer > 0) {
		    char *cp;

		    getyx(win, y,x);
		    wmove(win, y, x-1);
		    
		    /** Update the string **/

		    for (cp = inputline +curpointer-1; *cp != '\0'; cp++) {
			 *cp = *(cp+1);
			 if (*cp != '\0') waddch(win, *cp);
		    }
		    *cp = '\0';
		    waddch(win, ' ');
		    waddch(win, ' ');

		    pointer--;
		    curpointer--;

		    wmove(win, y, x-1);
	       
		    wrefresh(win);
	       } else
		    CURBeep(cur);
	       break;

	  case '\007':  /*** ^G cancel... ***/
	       CURBeep(cur);
	       wstandend(win);
	       return(-1);
	       break;
	       
	  /*** Kill character (ctrl-u) ***/
	  case '\025':
	       while (pointer!=0) {
		    waddch(win,'\010');
		    waddch(win, ' ');
		    waddch(win, '\010');
	       
		    inputline[--pointer] = '\0';
		    curpointer = 0;
	       }
	       wrefresh(win);
	       break;

	  case KEY_LEFT:
	       if (curpointer > 0) {

		    curpointer--;
		    getyx(win, y, x);
		    wmove(win, y, x-1);
		    wrefresh(win);
	       }
	       break;

	  case KEY_RIGHT:
	       if (curpointer<pointer) {
		    int y,x;

		    curpointer++;
		    getyx(win, y, x);
		    wmove(win, y, x+1);
		    wrefresh(win);
	       }
	       break;

	  default:
	       if (isprint(ch) && curpointer == maxlength) {
		    CURBeep(cur);
	       }
	       else if (isprint(ch)) {

		    inputline[curpointer++] = ch;

		    if (curpointer > pointer) {
			 pointer = curpointer;
			 inputline[curpointer+1] = '\0';
		    }
		    waddch(win, ch);
		    wrefresh(win);
	       }
	       else {
		    wstandend(win);
		    return(ch);
	       }
	  }
     }
}


/*
 * This stuff is stolen and modified from hytelnet  Thanks Earl!
 */

int
CURwgetch(cur, window)
  CursesObj *cur;
  WINDOW *window;
{
     int a, b, c;
     
     c = wgetch(window);
     
     if (c == 27) {      /* handle escape sequence */
	  b = wgetch(window);
	  if (b == '[' || b == 'O')
	       a = wgetch(window);
	  else
	       a = b;
	  
	  switch (a) {
	  case 'A': c = KEY_UP; break;
	  case 'B': c = KEY_DOWN; break;
	  case 'C': c = KEY_RIGHT; break;
	  case 'D': c = KEY_LEFT; break;
	  case '5':                       /* vt 300 prev. screen */
	       if (b == '[' && wgetch(window) == '~')
		    c = KEY_PPAGE;
	       break;
	  case '6':                       /* vt 300 next screen */
	       if (b == '[' && wgetch(window) == '~')
		    c = KEY_NPAGE;
	       break;
	  }
     }
     
     /* The many forms of the return key... */
     if ((c == KEY_ENTER)|| (c=='\r')) 
	  c = '\n'; /** SYSV curses Gack! **/
     
     /* The many forms of backspace */
     if (c == '\010' || c == '\177' || c == KEY_BACKSPACE)
	  return('\b');

     return(c);
}

int
CURgetch(cur)
  CursesObj *cur;
{
   return(CURwgetch(cur, stdscr));
}  

/*
 * Resets the screen when a size change has happened
 */

void
CURresize(cur)
  CursesObj *cur;
{
     if (cur->inCurses) {
	  CURexit(cur);
	  CURsetScreen(cur, initscr());
	  CURenter(cur);
     }
}

/*
 * Get one option displays a message, and gets a response
 *
 * If the Response has something in it, it is displayed and editable
 * 
 * If the user wants to abort, GetOneOption returns a -1, otherwise it
 * returns a 0
 */

int
CURGetOneOption(cur, OptionName, Response)
  CursesObj *cur;
  char *OptionName, *Response;
{
     int i;
     char *message[2];
     char *response[2];

     message[0] = OptionName;
     message[1] = NULL;
     
     response[0] = Response;
     response[1] = NULL;

     i = CURRequest(cur, NULL, message, response);
     
     refresh();
     return(i);
}

/*
 * This is the old version of GetOneOption, for those times when the
 * garsh darn terminal is just too gadblam slow :-)
 */
int
CUROldGetOneOption(cur, OptionName, Response)
  CursesObj *cur;
  char *OptionName, *Response;
{
     int i;
     
     mvaddstr(LINES-1, 0, OptionName);
     standout();
     addstr("    ");
     standend();
     clrtoeol();
     move(LINES-1, strlen(OptionName));
     
     refresh();
     echo();
     i = CURwgetstr(cur, stdscr, Response, 4);
     noecho();
     
     return(i);
}



/*
 * Fills in the Response with either a lowercase 'y' or 'n'
 */

void
CURgetYesorNo(cur, OptionName, Response)
  CursesObj *cur;
  char *OptionName, *Response;
{
     int c;
     int posx, posy;

     mvaddstr(LINES-1, 0, OptionName);
     clrtoeol();
     noecho();
     getyx(cur->Screen, posy, posx);
     addch(' ');

     if (*Response == 'y')
	  mvaddstr(posy, posx+1, "y");
     else {
	  *Response = 'n';
	  mvaddstr(posy, posx+1, "n ");
     }
     move(posy, posx+1);

     refresh();

     while (1) {
	  c = CURgetch(cur);

	  if (c == 'y') {
	       mvaddstr(posy, posx+1, "Yes");
	       move(posy, posx+1);
	       refresh();
	       *Response = 'y';
	       *(Response +1) = '\0';
	       return;
	  }
	  else if (c == 'n') {
	       mvaddstr(posy, posx+1, "No ");
	       move(posy, posx+1);
	       refresh();
	       *Response = 'n';
	       *(Response +1) = '\0';
	       return;
	  }
	  
	  else if ((c == '\n')||(c=='\r')) {
	       return;
	  }
#ifdef VMS
	  else if ( c == '\032' ) {	/* control-Z */
		return;
	  }
#endif
	  else {
	       CURBeep(cur);
	  }
     }
}
	  
void 
CURBeep(cur)
  CursesObj *cur;
{
#ifdef SYSVCURSES
     beep();
#else
     CURcenterline(cur,CURgetBell(cur),1);
     /* tputs(CURgetBell(cur),1,CURoutchar); */
     /* fflush(stdout); */
#endif
}


void
CURbox(cur, win, height,width)
  CursesObj *cur;
  WINDOW *win;
  int width, height;
{
     int i;

     wmove(win,0,0);
#ifdef SYSVCURSES
     wattron(win, A_ALTCHARSET);
#endif
     waddch(win, BOX_UL);
     for (i=0; i<width-2; i++)
	  waddch(win, BOX_HLINE);
     waddch(win, BOX_UR);
     for (i=1; i<height-1; i++) {
	  wmove(win, i,0);
	  waddch(win, BOX_VLINE);
	  wmove(win, i,width-1);
	  waddch(win, BOX_VLINE);
     }

     wmove(win, height-1,0);
     waddch(win, BOX_LL);
     for (i=0; i<width-2; i++)
	  waddch(win, BOX_HLINE);
     waddch(win, BOX_LR);
#ifdef SYSVCURSES
     wattroff(win, A_ALTCHARSET);
#endif
}


void
CURbutton(cur, win, Label, bright)
  CursesObj *cur;
  WINDOW *win;
  char *Label;
  boolean bright;
{
#ifdef SYSVCURSES
     wattron(win, A_BOLD);
#endif

     if (bright)
	  wstandout(win);

     waddstr(win, "[");
     waddstr(win, Label);
     waddstr(win, "]");

     if (bright)
	  wstandend(win);
#ifdef SYSVCURSES
     wattroff(win, A_BOLD);
#endif
}     

int
CURDialog(cur, Wintitle, Message)
  CursesObj *cur;
  char **Message;
  char *Wintitle;
{
     WINDOW *tempwin;
     int i,messlength=25, winwidth;
     int messheight=0;

     while (Message[messheight] != NULL) {
	  if (strlen(Message[messheight]) > messlength)
	      messlength = strlen(Message[messheight]);
	  messheight++;
     }

     if (messlength > COLS)
	  messlength = COLS -4;
     if (strlen(Wintitle) > messlength)
	  winwidth = strlen(Wintitle) + 2;
     winwidth = messlength + 6;

     if (winwidth < 30)
	  winwidth = 30;
     
     tempwin = newwin(6+messheight, winwidth, (LINES-(6+messheight))/2, (COLS-winwidth) /2);
     CURwenter(cur,tempwin);
     CURbox(cur, tempwin, 6+messheight, winwidth);

     /** Add the message **/
     for (i=0; i<messheight; i++) {
          wmove(tempwin, 2+i,(winwidth - messlength)/2);
          waddstr(tempwin, Message[i]);
     }



     /** Add the window title **/
     if (Wintitle != NULL) {
	  wmove(tempwin, 0,(winwidth - strlen(Wintitle))/2);
	  wstandout(tempwin);
	  waddstr(tempwin, Wintitle);
	  wstandend(tempwin);
     }

     /** Add the keyboard labels **/
     wmove(tempwin, 3+messheight, winwidth - 29);
     CURbutton(cur, tempwin, "Cancel - ^G", FALSE);
     waddch(tempwin, ' ');
     CURbutton(cur, tempwin, "OK - Enter", FALSE);

     wrefresh(tempwin);

     switch(CURwgetch(cur, tempwin)) {
     case -1:
     case '\007':
	  delwin(tempwin);
	  return(-1);
     default:
	  delwin(tempwin);
	  return(0);
     }
}



int
CURRequest(cur,Wintitle,Prompts,Stowages)
  CursesObj *cur;
  char *Wintitle;
  char **Prompts;
  char **Stowages;
{
     WINDOW *tempwin;
     int i,j;
     int numprompts=0;
     int maxpromptwidth =0;
     int currentfield = 0;

     /** Find the number of prompts... and the max width***/
     while (Prompts[numprompts++] != NULL)
	  if (strlen(Prompts[numprompts-1]) > maxpromptwidth)
	       maxpromptwidth = strlen(Prompts[numprompts-1]);
     
     numprompts --;

     if (numprompts == 0) {
	  return(-1);
     }
     
     tempwin = newwin(6 + numprompts, COLS-2, (LINES-(6+numprompts))/2,1);
     CURwenter(cur,tempwin);
     CURbox(cur,tempwin, 6+numprompts, COLS-2);
     
     /*** Add the window title ***/
     if (Wintitle != NULL) {
	  wmove(tempwin, 0,(COLS -2  - strlen(Wintitle))/2);
	  wstandout(tempwin);
	  waddstr(tempwin, Wintitle);
	  wstandend(tempwin);
     }
     
     /** Add the prompts and typing area **/
     for (i=0; i <numprompts; i++) {
	  wmove(tempwin, 2+i, 2);
	  waddstr(tempwin, Prompts[i]);
	  
	  /** Add the black space for the stowage, and the stowage, if it
	    exists **/
	  wmove(tempwin, 2+i, maxpromptwidth +4);
	  wstandout(tempwin);
	  waddstr(tempwin, Stowages[i]);
	  for (j=strlen(Stowages[i])+maxpromptwidth+4; j< COLS-6; j++) {
	       waddch(tempwin, ' ');
	  }
	  wstandend(tempwin);
     }

     /** Add the labels **/
     if (numprompts > 1) {
	  wmove(tempwin, 3+numprompts, 3);
	  CURbutton(cur, tempwin, "Switch Fields - TAB", FALSE);
     }

     wmove(tempwin, 3+numprompts, COLS/2);
     CURbutton(cur, tempwin, "Cancel ^G", FALSE);
     waddch(tempwin, ' ');
     CURbutton(cur, tempwin, "Accept - Enter", FALSE);


     while (1) {
	  wmove(tempwin, 2+currentfield, maxpromptwidth +4);
	  wrefresh(tempwin);
	  switch (CURwgetstr(cur,tempwin,Stowages[currentfield],80)) {

	  case '\t':
	  case KEY_DOWN:
	       /*** Move to another field ***/
	       currentfield = (currentfield +1) % numprompts;
	       break;

	  case KEY_UP:
	       currentfield--;
	       if (currentfield <0)
		    currentfield = numprompts-1;
	       break;
	       
	  case '\007':
	  case -1:
	       /*** Cancel ***/
	       delwin(tempwin);
	       return(-1);
	       
	  case '\n':
	       delwin(tempwin);
	       return(0);
	  }
	  
     }

}


/* 
 * CURChoice takes a bunch of titles, throws them on the screen,
 * and asks the user to choose one.
 *
 * Returns the number chosen, or -1 if the user cancels.
 */

int
CURChoice(cur, Wintitle, choices, prompt)
  CursesObj *cur;
  char *Wintitle;
  char **choices;
  char *prompt;
{
     int numchoices=0, i, maxchoicewidth=0;
     WINDOW *tempwin;
     
     while (choices[numchoices++] != NULL)
	  if ((i=strlen(choices[numchoices-1])) > maxchoicewidth)
	       maxchoicewidth = i;
     
     numchoices--;

     if (numchoices == 0)
	  return(-1);

     if ((i=strlen(prompt)) > maxchoicewidth)
	  maxchoicewidth = i;

     if ((i=strlen(Wintitle)) > maxchoicewidth)
	  maxchoicewidth = i;


     tempwin = newwin(8+numchoices, maxchoicewidth + 10, (LINES-(6+numchoices))/2, (COLS-(maxchoicewidth+10))/2);
     CURbox(cur, tempwin, 8+numchoices, 10 + maxchoicewidth);

     /*** Add the window title ***/
     if (Wintitle != NULL) {
	  wmove(tempwin, 0,(maxchoicewidth+10 -2  - strlen(Wintitle))/2);
	  wstandout(tempwin);
	  waddstr(tempwin, Wintitle);
	  wstandend(tempwin);
     }

     /*** Add the choices to the screen ***/


     for (i=0; i<numchoices; i++) {
	  wmove(tempwin, 2+i,3);
	  wprintw(tempwin, "%d", i+1);
	  wprintw(tempwin, ". %s", choices[i]);
	  ;
	  
     }

     /** Add the keystroke methods **/
     wmove(tempwin, 5+numchoices, 3);
     wprintw(tempwin, "[Cancel ^G]  [Choose 1-%d]", numchoices);


     /** Add the prompt **/

     wmove(tempwin, 3+numchoices, 3);
     wprintw(tempwin, "%s: ", prompt);


     wrefresh(tempwin);

     while (1) {
	  i = CURwgetch(cur, tempwin);
	  wrefresh(tempwin);
	  if (i == '\007') {
	       delwin(tempwin);
	       return(-1);
	  }	  

	  if (i < '1' || i > ('0'+numchoices))
	       CURBeep(cur);
	  else {
	       delwin(tempwin);
	       return(i-'1');
	  }
     }	  

}

/********************** Cruft for VMS follows ****************************/

#ifdef VMS
#include descrip
#include iodef
#include ssdef
#include ttdef
#include tt2def

static $DESCRIPTOR (term_name, "SYS$INPUT:");
static $DESCRIPTOR (ctrlc_message, "{control-C}");
struct char_buffer_type { unsigned short int dummy;
			  unsigned short int size;
			  unsigned long int tchars;
			  unsigned long int tchars2; } oldbuf, newbuf;
short term_chan;
static int first = 1;
static int in_pos, in_len;
static volatile int interrupt_flag;
static long outband_mask[2] = { 0, 16 };
static unsigned char buffer[20];

int CURinterrupt ( clear_flag )
    int clear_flag;
{
    if ( interrupt_flag ) {
	int temp = interrupt_flag;
	if ( clear_flag ) interrupt_flag = 0;
	return temp;
    }
    return 0;
}

static int control_c_ast ( )
{
    int status;
    short iosb[4];
    interrupt_flag = 1;
    status = sys$qiow ( 0, term_chan, IO$_SETMODE|IO$M_CTRLCAST, 
	&iosb, 0, 0,
	&control_c_ast, &outband_mask, 0, 0, 0, 0 );
}

/*
 * Define local replacement for wgetch that returns the characters without
 * having to set the terminal /pasthru, which screws up control-Y processing.
 */
static int w_getch ( win )
   int win;
{
   int status;
   unsigned short iosb[4];
   if ( in_pos < in_len ) { return (buffer[in_pos++]); }
   status = sys$qiow ( 0, term_chan, IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR,
	&iosb, 0, 0, &buffer, 1, 0, 0, 0, 0 );
   if ( (status&1) == 1 ) status = iosb[0];
   if ( status == SS$_PARTESCAPE ) {
	/* escape sequence in progress, fake a successful read */
	status = 1;
   }
   if ( (status&1) != 1 ) exit ( status );
   in_pos = 1;
   in_len = iosb[1] + iosb[3];
   return ( buffer[0] );
}
void
setterm_pas()
{
  int status;
  short iosb[4];
  sys$assign(&term_name,&term_chan,0,0);

  if(first==1) sys$qiow(0,term_chan,IO$_SENSEMODE,0,0,0,&oldbuf,12,0,0,0,0);
  first = 0;
  newbuf = oldbuf;

  /* set initial control-C AST on channel */
  in_pos = 0; in_len = 0;
   interrupt_flag = 0;
   status = sys$qiow ( 0, term_chan, IO$_SETMODE|IO$M_CTRLCAST, 
	&iosb, 0, 0,
	&control_c_ast, &outband_mask, 0, 0, 0, 0 );
}

void
resetterm()
{
  sys$qiow(0,term_chan,IO$_SETMODE,0,0,0,&oldbuf,12,0,0,0,0);
  sys$dassgn(term_chan);
}


/* VMS doesn't have termcap.  Unfortunately, the code in this */
/* module uses termcap just a little bit (it really shouldn't) */
/* rather than doing everything through curses */
 
/* The following simulates tputs, but does not support padding */
tputs(cp, affcnt, outc)
     register char *cp;
     int affcnt;
     int (*outc)();
{
      while (*cp)
        outc(*(cp++));
}
#endif /* VMS */
 
