#include "gopher.h"

#ifdef SYSVCURSES
#include <termio.h>

#define       STDOUT  1


/* this is some modified elm source  (Raw) */
static int inraw = 0;

struct termio raw_tty,
	       original_tty;

#define OFF 0
#define ON 1
#define	ttgetattr(fd,where)	ioctl((fd),TCGETA,(where))
#define	ttsetattr(fd,where)	ioctl((fd),TCSETAW,(where))


Raw(state)
int state;
{
     /** state is either ON or OFF, as indicated by call **/
     
     if (state == OFF && inraw) {
          (void) ttsetattr(STDOUT,&original_tty);
          inraw = 0;
     }
     else if (state == ON && ! inraw) {
	  
          (void) ttgetattr(STDOUT, &original_tty);
          (void) ttgetattr(STDOUT, &raw_tty);    /** again! **/
	  
          raw_tty.c_lflag &= ~(ICANON | ECHO); /* noecho raw mode        */
	  
          raw_tty.c_cc[VMIN] = '\01';  /* minimum # of chars to queue    */
          raw_tty.c_cc[VTIME] = '\0';  /* minimum time to wait for input */
	  
          (void) ttsetattr(STDOUT, &raw_tty);
          inraw = 1;
     }
}

#endif


outchar(c)
char c;
{
        /** output the given character.  From tputs... **/
        /** Note: this CANNOT be a macro!              **/

        putc(c, stdout);
}



/*
** This procedure exits out of the curses environment and
** displays the file indicated by pathname to the screen
** using a pager command of some sort 
*/

void
display_file(Filename)
  char *Filename;
{
     FILE *tmpfile, *fNew;
     char command[MAXSTR];
     static char SaveName[MAXSTR];
     char ch;

     strcpy(command, PagerCommand);

     exit_curses();

     /** Execute the PAGER command **/
     strcat(command, " ");
     strcat(command, Filename);

     
     if (strcmp(PagerCommand, "builtin") != 0)
	  system(command);
     else
	  Ourpager(Filename);

     printf("Press <SPACE> to continue, <s> to save, or <p> to print:");
     fflush(stdout);
     noecho();
     cbreak();

     /** System V systems don't want to go back into cbreak mode, so we
       force it into cbreak, canonical, etc mode. ***/

#ifdef SYSVCURSES
     Raw(ON);
#endif

     ch = 0;
     while (ch == 0) {
	  ch=getchar();

	  switch(ch) {
	  case '\n':
	  case '\r':
	  case ' ' :
	       break;
	  case 's':
	       sprintf(command, "Enter save file name: ");
	       GetOneOption(command, SaveName);
	       if (strlen(SaveName) == 0)
		    break;
	       while ((fNew = fopen(SaveName, "wt")) == NULL) {
		    bzero(SaveName, MAXSTR);
		    sprintf(command, "Error opening %s:  Enter new name or <Enter> to cancel: ", SaveName);
		    GetOneOption(command, SaveName);
		    if (SaveName[0] == 0)
			 break;
	       }
              
	       if (fNew == NULL)
		    break;

	       if ((tmpfile = fopen(Filename, "rt")) == NULL)
		    fprintf(stderr, "%s cannot be opened.\n", Filename), exit(tmpfile);
	       while (!feof(tmpfile)) fputc(fgetc(tmpfile), fNew);

	       fclose(tmpfile);
	       fclose(fNew);

	       break;
	  case 'p':
	       sprintf(command, "%s %s\n", PRINTER_COMMAND, Filename);
	       system(command);
	       break;
	  default:
	       printf("%s",sGAudibleBell);
	       fflush(stdout);
	       ch=0;
	       break;
	  }
     }
     
     tputs(sGClearscreen,1,outchar);
     fflush(stdout);

#ifdef SYSVCURSES
     Raw(OFF);
#endif
}


/*
** This mini pager is intended for people worried about shell escapes from
** more or less or whatever
*/


Ourpager(filename)
  char *filename;
{
     FILE *InFile;
     int i;
     char inputline[512], *cp;
     int Done = FALSE;
     char ZeTypedChar;
     
     if ((InFile = fopen(filename, "r")) == NULL)
	  return;

     while (Done == FALSE) {
	  tputs(sGClearscreen,1,outchar);

	  for (i=0 ; i < LINES; i++) {
	       cp = fgets(inputline, 512, InFile);
	       ZapCRLF(inputline);
	       puts(inputline);
	  }

	  printf("----Press <SPACE> for next page, q to exit------");
	  
#ifdef SYSVCURSES
	  Raw(ON);
#else
	  cbreak();
#endif

	  ZeTypedChar = getchar();
	  
	  if ((ZeTypedChar == 'q') || (cp == NULL)) {
	       printf("\n");
	       Done = TRUE;
	  }
     }

#ifdef SYSVCURSES
     Raw(OFF);
#else
     cbreak();
#endif

     fclose(InFile);
}
/*
** Non System V getstr's all seem to be broken in some way.  Anyways
** a normal getstr wouldn't do for us.  This one displays a current value
** That the use can edit.
**
*/


Mygetstr(inputline)
  char *inputline;
{
     int pointer = 0;
     char ch;

     cbreak();
     noecho();     

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

     refresh();
	  

     for (;;) {
	  ch = getch();

	  switch (ch) {

	  case '\n':
	  case '\r':
	  case '\t':
	       inputline[pointer] = '\0';
	       return;
	       break;

	  case '\010':
	  case '\177':
	       if (pointer > 0) {
		    addch('\010');
		    delch();
	       
		    inputline[--pointer] = '\0';
		    refresh();
	       }
	       break;
		    
	  default:
	       inputline[pointer++]= ch;
	       addch(ch);
	       refresh();
	  }
     }
}

/*
** This routine will allow the user to change a whole bunch of fields.
** 
** The maximum number of options is hard set at 9 right now.  It may be
** different in the future.
**
** The space for storing stuff is provided by the caller.  This routine
** will present it to the user in this fashion:
**
**           Option1 : responses1
**           Option2 : responses2
**           .....
**
** It would be wise to keep the length of the options and responses
** below 38 characters.
**
*/


Get_Options(Title, Err, numOptions, Options, Responses)
  char *Title;
  char Err[MAXSTR];
  int    numOptions;
  char **Options;
  char Responses[MAXRESP][MAXSTR];
{
     int         availlines;
     static char printstring[80];
     static char inputline[80];
     int         optionlen;
     int         maxoptionlen;
     int         i,j;          /** Acme Buggy whips and integers **/
     BOOLEAN     Done = FALSE;
     char        ch;

     while (Done == FALSE) {

	  clear();
	  Draw_Banner();
	  Draw_Status("Press <RETURN> to exit");
	  Centerline( Title, 3);
	  Centerline( Err, 4);
	  
	  availlines = LINES - 6;
	  
	  /** Find the longest width of the options strings **/
	  
	  maxoptionlen = 0;
	  
	  for (i=0; i<numOptions; i++) {
	       j= strlen(Options[i]);
	       maxoptionlen = (maxoptionlen > j) ? maxoptionlen:j;
	  }
	  
	  
	  /*** Print out the options in a nice looking fashion ***/
	  
	  for (i=0; i<numOptions; i++) {
	       optionlen = strlen(Options[i]);
	       mvaddch(i+5, 2, ('0' + 1 + i));
	       addstr(". ");
	       addstr(Options[i]);
	       mvaddstr(i+5, maxoptionlen + 6, ": ");
	       addstr(Responses[i]);
	  }

	  Centerline("Select an Option to Change:", LINES-3);

	  refresh();

	  /*** Now get some user input ***/

	  ch = getch();


	  if (ch == '\n' || ch == '\r' || ch == 'Q' || ch=='q')
	       Done = TRUE;
	  
	  else if (isdigit(ch)) {
	       i = ch - '1' ;
	       Draw_Status("Press Return when finished");
	       move( i +5, maxoptionlen +8);
	       clrtoeol();
	       refresh();

	       echo();
	       inputline[0] = '\0';
	       Mygetstr(Responses[i]);
	       noecho();

	       /*strcpy(Responses[i], inputline);*/

	  }
	  else
	       addstr(sGAudibleBell);
     }
	       
}


GetOneOption(OptionName, Response)
  char *OptionName, *Response;
{
     mvaddstr(LINES-1, 0, OptionName);
     clrtoeol();
     refresh();
     echo();
     Mygetstr(Response);
     noecho();
}

/*
 ** This strips off  CR's and LF's leaving us with a nice pure string.
 */

void
ZapCRLF(inputline)
char *inputline;
{
     char *cp;
     
     cp = index(inputline, '\r');    /* Zap CR-LF */
     if (cp != NULL)
          *cp = '\0';
     else {
          cp = index(inputline, '\n');
          if (cp != NULL)
               *cp = '\0';
     }
}



