/*{{{  #includes*/
#ifdef CONFIG_H
#   include "config.h"
#endif

#include <sys/types.h>
#include <unistd.h>
#include <termcap.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <strings.h>

#include <local/bool.h>

#define SCREEN_C
#define I_DISPLAY_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_KEYBOARD_C
#define I_MESSAGES_C
#define I_SIGNALS_C

#include "exit.h"
#include "origami.h"
#include "../h/envvar_str.h"
/*}}}  */

/*{{{  variable declarations*/
private char termcap_area[512];
private char *cm,*ce,*cl,*al,*dl,*ti,*te,*bl,*vb,*ks,*ke;
private bool am;
public bool xs;
public char *se,*so;
public int sg;
public FILE *scrout;
public int screen_lines;
public int *sx_ptr;
public int *sy_ptr;
public int *cy_ptr;
/*}}}  */

/*{{{  outchar*/
private void outchar(int ch)
{
  if (!scr_off) putchar(ch);
}
/*}}}  */
/*{{{  gotoxy*/
public void gotoxy(int x,int y)
{
  tputs (tgoto(cm,x-1,y-1),1,outchar);
}
/*}}}  */
/*{{{  insLine:  if al known, do and return FALSE, else do nothing and return TRUE*/
public bool insLine(void)
{
  if (al) tputs(al,1,outchar);
  return(!al);
}
/*}}}  */
/*{{{  DelLine:  if dl known, do and return FALSE, else do nothing and return TRUE*/
public bool DelLine(void)
{
  if (dl) tputs(dl,1,outchar);
  return(!dl);
}
/*}}}  */
/*{{{  init_terminal*/
public void init_terminal()
{
  if (ti) tputs(ti,1,outchar);
}
/*}}}  */
/*{{{  reset_terminal*/
public void reset_terminal()
{
  gotoxy(1, screen_lines);
  oputc('\n');
  if (te) tputs(te,1,outchar);
  oflush;
}
/*}}}  */
/*{{{  standout*/
public void standout(void)
{
  if (so) tputs(so,1,outchar);
}
/*}}}  */
/*{{{  standend*/
public void standend(void)
{
  if (se) tputs(se,1,outchar);
}
/*}}}  */
/*{{{  goclreol: go to xy and do clreol*/
public void goclreol(int x,int y)
{ gotoxy(x,y);
  if (ce)
     tputs(ce,1,outchar);
  else
   { if (am && (y==screen_lines)) x++;
     if (xs) standend();
     while (x++<=W_dx) outchar(' ');
   }
}
/*}}}  */
/*{{{  clrscr:   clear screen, cursor position is undefined afterwards*/
public void ClrScr(void)
{
  if (cl)
     tputs(cl,1,outchar);
  else
   /*{{{  clear line by line*/
   { int i;

     for (i=1;i<screen_lines;goclreol(1,i++));
     if (am) outchar(' ');
   }
   /*}}}  */
}
/*}}}  */
/*{{{  apl_on*/
public void apl_on(void)
{
  if (ks)
   { tputs(ks,1,outchar);
     fflush(scrout);
   }
}
/*}}}  */
/*{{{  num_on*/
public void num_on(void)
{
  if (ke)
   { tputs(ke,1,outchar);
     fflush(scrout);
   }
}
/*}}}  */
/*{{{  bell*/
public void bell(void)
{
  if (bl)
   { tputs(bl,1,outchar);
     fflush(scrout);
   }
}
/*}}}  */
/*{{{  bell_visible*/
public void bell_visible(void)
{
  if (vb)
   { tputs(vb,1,outchar);
     fflush(scrout);
   }
}
/*}}}  */
/*{{{  screen_off*/
public void screen_off(void)
{ if (stdout==scrout && !(scrout=fopen(OS_NULL_DEVICE,WRITE))) scrout=stdout;
}
/*}}}  */
/*{{{  screen_on*/
public void screen_on(void)
{ if (scrout!=stdout) {fclose(scrout);scrout=stdout;}
}
/*}}}  */
/*{{{  get_terminal_capability*/
#if (defined(MOUSY) && defined(XTERM))
   /*{{{  xterm_size*/
   private bool xterm_size(char *t)
   {
     if (!strcmp(t,"xterm") && isatty(fileno(stdout)))
      /*{{{  try to get from xterm*/
        for (;;)
         { char b[32];
           char *d,*s;

           /*{{{  activate the sending*/
           fputs(XTERM_GET_SIZE,stdout);
           fflush(stdout);
           /*}}}  */
           /*{{{  read the header*/
           s=XTERM_SIZE_HEAD;
           while (*s && (read_err(kbd_file,b,1),b[0]==*s)) s++;
           if (*s) break;
           /*}}}  */
           /*{{{  get lines*/
           d=b;
           while (isdigit((read_err(kbd_file,d,1),*d++)));
           if (*--d!=XTERM_SIZE_MID[0]) break;
           *d=0;
           screen_lines=atoi(b);
           /*}}}  */
           /*{{{  get rest of mid text*/
           s=XTERM_SIZE_MID+1;
           while (*s && (read_err(kbd_file,b,1),b[0]==*s)) s++;
           /*}}}  */
           /*{{{  get columns*/
           d=b;
           while (isdigit((read_err(kbd_file,d,1),*d++)));
           if (*--d!=XTERM_SIZE_END[0]) break;
           *d=0;
           W_dx=atoi(b);
           /*}}}  */
           /*{{{  get rest of end text*/
           s=XTERM_SIZE_END+1;
           while (*s && (read_err(kbd_file,b,1),b[0]==*s)) s++;
           /*}}}  */
           return(FALSE);
         }
      /*}}}  */
     return(TRUE);
   }
   /*}}}  */
#   define no_xterm_size xterm_size(terminal)
#else
#   define no_xterm_size 1
#endif

public int get_terminal_capability(void)
{
  char bp[1024];
  static char *terminal=0;
  char *pointer;

  if (!terminal)
   /*{{{  first call => get terminal dependent strings*/
   {
     /*{{{  init reading the data*/
     if (!(terminal=getenv(TERM)))
        /*{{{  define terminal name*/
#        ifdef DEFAULT_TERM
            terminal=DEFAULT_TERM;
#        else
         { oputs((char *)get_msg(M_NO_TERM));return (1); }
#        endif
        /*}}}  */
     /*{{{  read termcap data*/
     switch (tgetent(bp,terminal))
      { case -1: { oputs((char *)get_msg(M_NO_TERMCAP));return (1); }
        case  0: { oputs((char *)get_msg(F_TERMB,terminal));return (1); }
      }
     /*}}}  */
     pointer = termcap_area;
     /*}}}  */
     /*{{{  get needed features*/
     if (!(cm=tgetstr("cm",&pointer)))
      { oputs((char *)get_msg(F_TERMA,"cursor motion (cm)"));exit(r_init_err); }
     if (((screen_lines=tgetnum("li"))==-1)||((W_dx=tgetnum("co"))==-1))
      { oputs((char *)get_msg(F_TERMA,"window size (li/co)"));exit(r_init_err); }
     /*}}}  */
     /*{{{  get optional features*/
     ti=tgetstr("ti",&pointer);
     te=tgetstr("te",&pointer);
     ce=tgetstr("ce",&pointer);
     cl=tgetstr("cl",&pointer);
     al=tgetstr("al",&pointer);
     dl=tgetstr("dl",&pointer);
     bl=tgetstr("bl",&pointer);
     vb=tgetstr("vb",&pointer);
     ks=tgetstr("ks",&pointer);
     ke=tgetstr("ke",&pointer);
     so=tgetstr("so",&pointer);
     sg=tgetnum("sg"); if (sg == -1) sg=0;
     se=tgetstr("se",&pointer);
     /*}}}  */
     /*{{{  check some strange features*/
     am=tgetflag("am");
     xs=tgetflag("xs");
     /*}}}  */
   }
   /*}}}  */
  else
   /*{{{  get window-size*/
     if
      (    no_xterm_size
        && (   tgetent(bp,terminal)!=1
            || ((screen_lines=tgetnum("li"))==-1)
            || ((W_dx=tgetnum("co"))==-1)
           )
      )
        exit_origami(r_init_err,get_msg(F_TERMA,"window size (li/co)"));
   /*}}}  */
  return (0);
}
/*}}}  */
