/* Unix screen update functions for regutil
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is regutil.
 *
 * The Initial Developer of the Original Code is Patrick TJ McPhee.
 * Portions created by Patrick McPhee are Copyright © 1998, 2001
 * Patrick TJ McPhee. All Rights Reserved.
 *
 * Contributors:
 *
 * $Header: /netlabs.cvs/osfree/src/REXX/libs/rexxutil/regscreenux.c,v 1.1.1.1 2003/10/04 08:35:12 prokushev Exp $
 */
#include "regutil.h"
#ifdef USE_TERM_H
# include <sys/ioctl.h>
# define addstr cursaddstr
# include <curses.h>
# include <term.h>
#else
# include <termcap.h>
#endif
#include <termios.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>

/* ******************************************************************** */
/* ************************** Screen Update *************************** */
/* ******************************************************************** */

/* using termcap */

static const char notimp[] = "not implemented";
#define what() memcpy(result->strptr, notimp, sizeof(notimp)-1), result->strlength = sizeof(notimp)-1


/* load the termcap info */
void sethandles(void)
{
    static char tcent[1024];

    if (!*tcent)
      tgetent(tcent, getenv("TERM"));
}


/* syscls() */
rxfunc(syscls)
{
   static char clrbuf[100], * clr = clrbuf;

   if (!*clr) {
      sethandles();
      clr = tgetstr("cl", &clr);
   }

   if (clr) {
      fputs(clr, stdout);
      fflush(stdout);
      result_zero();
   }
   else {
       result_one();
   }

   return 0;
} 


/* syscurpos([row],[column]) -- returns current position, but I don't know
 * how to get that */
rxfunc(syscurpos)
{
   static char cposbuf[100], * cpos = cposbuf;

   if (argc != 0 && argc != 2)
       return BADARGS;

   if (!*cpos) {
      sethandles();
      cpos = tgetstr("cm", &cpos);
   }

   if (cpos) {
      int x, y;
      char * ex, *why;

      rxstrdup(ex, argv[1]);
      rxstrdup(why, argv[0]);
      x = atoi(ex)-1;
      y = atoi(why)-1;

      fputs(tgoto(cpos, x, y), stdout);
      fflush(stdout);
      strcpy(result->strptr, "0 0");
      result->strlength = 3;
   }
   else {
      strcpy(result->strptr, "0 0");
      result->strlength = 3;
   }

   return 0;
} 


/* syscurstate(state) */
rxfunc(syscurstate)
{
   static char css[100], *pcsson, *pcssoff;
   char * onoff;

   checkparam(1, 1);

   rxstrdup(onoff, argv[0]);
   strupr(onoff);

   if (!*css) {
      char *pcss = css;
      sethandles();
      pcsson = tgetstr("ve", &pcss);
      pcssoff = tgetstr("vi", &pcss);
   }

   if (pcsson && pcssoff) {
       if (!strcasecmp(onoff, "OFF"))
          onoff = pcssoff;
       else
          onoff = pcsson;
   }

   fputs(onoff, stdout);
   fflush(stdout);

   return 0;
} 


/* sysgetkey([opt],[timeout]) */
rxfunc(sysgetkey)
{
   static struct termios oterm, nterm;
   static int init = 1;
   register rxbool doecho = true;
   fd_set readfds;
   struct timeval select_tv;
   struct timeval *pselect_tv = NULL;

   checkparam(0,2);

   if (argc > 0 && argv[0].strptr && (argv[0].strptr[0] == 'N' || argv[0].strptr[0] == 'n'))
      doecho = false;

   if (argc > 1 && argv[1].strptr) {
      select_tv.tv_sec = rxint(argv+1);
      select_tv.tv_usec = rxuint(argv+1);

      if (select_tv.tv_sec || select_tv.tv_usec) {
         pselect_tv = &select_tv;
      }
   }

   if (init) {
      init = 0;
      tcgetattr(0, &oterm);			/* save oterm state */
      nterm = oterm;				/* get base of nterm state */
      nterm.c_lflag &= ~(ICANON | ISIG | IEXTEN);
      nterm.c_iflag &= ~(ICRNL | INLCR | IXON | IXOFF | IXANY | BRKINT);
      nterm.c_cc[VMIN]  = 1;
      nterm.c_cc[VTIME] = 0;
   }

   if (!doecho)
       nterm.c_lflag &= ~(ECHO|ECHOE|ECHOK);
   else
       nterm.c_lflag |= ECHO|ECHOE|ECHOK;

   tcsetattr(0, TCSANOW, &nterm);			/* set mode */
   /*
    * Wait for specified timeout
    */
   FD_ZERO(&readfds);
   FD_SET(0, &readfds);
   if (select(1,&readfds,NULL,0,pselect_tv) > 0) {
      result->strlength = sprintf(result->strptr, "%c", getchar());
   }
   else
      result->strlength = 0;
   tcsetattr(0, TCSANOW, &oterm);			/* restore mode */

   return 0;
} 

/* systextscreenread(row,column, len) */
rxfunc(systextscreenread)
{
   what();
   return 0;
} 

/* systextscreensize() -- don't use termcap because the termcap
 * result comes from the database, not the screen  */
rxfunc(systextscreensize)
{
   struct winsize ws;

   /* Get the terminal size */
   if (ioctl(0, TIOCGWINSZ, &ws) || 0 == ws.ws_row)
      return 80;

   result->strlength = sprintf(result->strptr, "%d %d", ws.ws_row, ws.ws_col);

   return 0;
} 
