/* ourutils.c
 * 
 * Part of the Internet Gopher program, copyright (C) 1991
 * University of Minnesota Microcomputer Workstation and Networks Center
 *
 */

#include "gopher.h"

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

        putc(c, stdout);
	return(c);
}

display_mime(Filename, Realname)
  char *Filename, *Realname;
{
     char metamailcmd[512];
     FILE *Metamail;
     
     strcpy(metamailcmd, STRget(MIMECommand));
     strcat(metamailcmd, " ");
     strcat(metamailcmd, Filename);

     CURexit(CursesScreen);
     system(metamailcmd);
     CURenter(CursesScreen);

     printf("Press any key to return to gopher: ");
     getchar();

}     

/*
** This procedure sends a file through the mail.
*/

void
mail_file(Filename, Realname)
  char *Filename, *Realname;
{
     static char *SaveName = NULL;
     char command[512];
     
     if (SaveName==NULL) {
	  if (SaveName = malloc(sizeof(char)*256))
	       perror("Out of memory!");
	  *SaveName = '\0';
     }

     if (CURGetOneOption(CursesScreen, "Mail document to:", SaveName)<0)
	  return;
     
     if (*SaveName == '\0')
	  return;
     
#define ACHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%.@!-_"
		    
     if (SecureMode)
	  if ( strspn(SaveName, ACHARS) != strlen(SaveName)) {
	       puts(CURgetBell(CursesScreen));
	       fflush(stdout);
	       Draw_Status("Address syntax rejected...");
	       refresh();
	       return;
	  }
     
     Draw_Status("Mailing File...");
     refresh();
     
     sprintf(command, "%s -s \"%s\" %s < %s", 
	     STRget(MailCommand), Realname, SaveName, Filename);
     system(command);

}

/*
** 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, Realname)
  char *Filename, *Realname;
{
     FILE *tmpfile, *fNew;
     static char command[MAXSTR];
     static char SaveName[MAXSTR];
     int ch;
     int c;

     strcpy(command, STRget(PagerCommand));

     CURexit(CursesScreen);

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

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

     printf("Press <RETURN> to continue");

     if (!SecureMode)
	  printf(", <m> to mail, <s> to save, or <p> to print:");
     else
	  printf(", <m> to mail:");

     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. ***/

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

	  if (SecureMode) {
	       switch (ch) {
	       case '\n':
	       case '\r':
	       case KEY_ENTER:
	       case ' ':
		    break;
	       case 'm':
		    mail_file(Filename, Realname);
		    break;

	       default:
		    puts(CURgetBell(CursesScreen));
		    fflush(stdout);
		    ch=0;
		    break;
	       }
	  }
	  else {

	       switch(ch) {
	       case '\n':
	       case '\r':
	       case ' ' :
		    break;
	       case 's':
		    Draw_Status("Saving File...");
		    refresh();

		    sprintf(command, "Enter save file name: ");
		    c = CURGetOneOption(CursesScreen, command, SaveName);
		    if (*SaveName == '\0' || c == -1)
			 break;
		    while ((fNew = fopen(SaveName, "wt")) == NULL) {
			 bzero(SaveName, MAXSTR);
			 sprintf(command, "Error opening %s:  Enter new name or <Enter> to cancel: ", SaveName);
			 c = CURGetOneOption(CursesScreen, command, SaveName);
			 if (*SaveName == '\0' || c == -1)
			      break;
		    }
              
		    if (fNew == NULL)
			 break;
		    
		    if ((tmpfile = fopen(Filename, "rt")) == NULL) {
			 CursesErrorMsg("File cannot be opened!");
			 fclose(fNew);
			 break;
		    }

		    while ((c=getc(tmpfile)) != EOF) {
			 putc(c, fNew);
		    }
		    
		    fclose(tmpfile);
		    fclose(fNew);
		    
		    break;

	       case 'p':
		    sprintf(command, "%s %s\n", STRget(PrinterCommand),
			    Filename);
		    system(command);
		    break;
		    
	       case 'm':
		    mail_file(Filename, Realname);
		    break;
		    
	       default:
		    puts(CURgetBell(CursesScreen));
		    fflush(stdout);
		    ch=0;
		    break;
	       }
	  }
     }
     
     
     tputs(CURgetCLS(CursesScreen),1,outchar);
     fflush(stdout);
}


/*
** 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(CURgetCLS(CursesScreen),1,outchar);

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

	  printf("----Press <ENTER> for next page, q to exit------");
	  
	  cbreak();
	  ZeTypedChar = getchar();
	  
	  if ((ZeTypedChar == 'q') || (cp == NULL)) {
	       printf("\n");
	       Done = TRUE;
	  }
     }

     cbreak();
     fclose(InFile);
}
*/


/*
** 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.
**
*/

void
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[WHOLELINE];
     static char inputline[WHOLELINE];
     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");
	  CURcenterline(CursesScreen, Title, 3);
	  CURcenterline(CursesScreen, 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]);
	  }

	  sprintf(printstring, "Press 1-%d to change a field, Return to accept fields and continue", numOptions);

	  CURcenterline(CursesScreen, printstring, LINES-3);

	  refresh();

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

	  ch = CURgetch(CursesScreen);
	  
	  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';
	       CURgetstr(CursesScreen, Responses[i]);
	       noecho();
	  }
	  else
	       CURBeep(CursesScreen);
     }
}

/*
 * This allows the user to add or change data in a form.
 *
 * It returns true if the user wants to keep the changes
 * It returns false if the user wants to abort
 *
 */

BOOLEAN
NewForm(ZeForm)
  Form *ZeForm;
{
     static char printstring[WHOLELINE];
     int         i;          /** Acme Buggy whips and integers **/
     char        ch;

     while (1) {

	  DisplayForm(ZeForm);

	  sprintf(printstring, "Press <ESC> to accept fields and continue");

	  CURcenterline(CursesScreen,"Press <ESC> to accept fields and continue", LINES-3);
	  CURcenterline(CursesScreen,"or press <CTRL-A> to abort", LINES-2);

	  refresh();

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

	  for (i=0; i< ZeForm->numfields; i++) {

	       move(ZeForm->yloc[i],ZeForm->xloc[i] + strlen(ZeForm->tags[i])+2);
	       refresh();
	       echo();

	       ch = CURgetstr(CursesScreen, ZeForm->values[i]);

	       /*** ESC key ***/
	       if (ch == '\033') {
		    noecho();
		    return(TRUE);
	       }

	       /*** CTRL-A ***/
	       else if (ch == '\001') {
		    noecho();
		    return(FALSE);
	       }

	       noecho();
	  }
	  
     }

}




/*
 * This Displays a form and a "menu".  It displays the Form
 * and then it waits for a keypress.  It returns the value of the
 * key that is pressed.
 */

void
DisplayForm(ZeForm)
  Form *ZeForm;
{
     int         availlines;
     int         optionlen;
     int         i;          /** Acme Buggy whips and integers **/


     clear();
     Draw_Banner();
     CURcenterline(CursesScreen, ZeForm->Title, 2);
     
     availlines = LINES - 6;
     
     /*** Print out the options according to the Form structure ***/
     
     for (i=0; i<ZeForm->numfields; i++) {
	  optionlen = strlen((ZeForm->tags)[i]);
	  mvaddstr(ZeForm->yloc[i],ZeForm->xloc[i], 
		   ZeForm->tags[i]);
	  addch(':');
	  addch(' ');
	  
	  /*** Now add the current value ***/
	  addstr((ZeForm->values)[i]);
     }
     
}


void
CursesErrorMsg(Message)
  char *Message;
{
     char ch;
     int i;

     CURBeep(CursesScreen);

     move(LINES-1, 0);
     /*** addstr(Message) doesn't seem to work.... ***/

     for (i=0; (i<60&&Message[i]!='\0'&&Message[i] !='\r' && Message[i]!='\n'); i++)
	  addch(Message[i]);
     

     refresh();

     addstr(" <press RETURN> ");
     clrtoeol();
     refresh();
     ch = CURgetch(CursesScreen);
     while (ch != '\n') {
	  CURBeep(CursesScreen);
	  ch = CURgetch(CursesScreen);
     }
}
     

