/*Last Modified: 30-APR-1992 08:45:25.44, By: MARK */ /* ourutils.c * * Part of the Internet Gopher program, copyright (C) 1991 * University of Minnesota Microcomputer Workstation and Networks Center * */ #include "gopher.h" int readkey_row, readkey_col; /* ** 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]; char SaveName[MAXSTR]; short int ch; int ret_status; strncpy(command, "\0", MAXSTR ); strcpy(command, PagerCommand); /** Execute the PAGER command **/ strcat(command, " "); strcat(command, Filename); if (strcmp(PagerCommand, "builtin") != 0) system(command); else Ourpager(Filename); printf("Press to continue"); if (!SecureMode) printf(", to save, or

to print:"); else printf(":"); fflush(stdout); ch = 0; while (ch == 0) { ret_status = smg$read_keystroke( &KeyboardId, &ch ); if (SecureMode) { switch (ch) { case SMG$K_TRM_LF: case SMG$K_TRM_CR: case SMG$K_TRM_SPACE: break; default: ret_status = smg$ring_bell( &DisplayId ); fflush(stdout); ch=0; break; } } else { switch(ch) { case SMG$K_TRM_LF: case SMG$K_TRM_CR: case SMG$K_TRM_SPACE : if (strcmp(Filename,GOPHERHELP)!=0) { if (remove(Filename) != 0 ) fprintf(stderr, "Couldn't remove %s!!!\n",Filename); } break; case SMG$K_TRM_LOWERCASE_S: case SMG$K_TRM_UPPERCASE_S: strncpy(command, "\0", MAXSTR ); strncpy(SaveName, "\0", MAXSTR ); sprintf(command, "Enter save file name: "); GetOneOption(command, SaveName); if (strlen(SaveName) == 0) break; while ((fNew = fopen(SaveName, "w")) == NULL) { bzero(SaveName, MAXSTR); strncpy(command, "\0", MAXSTR ); sprintf(command, "Error opening %s: Enter new name or to cancel: ", SaveName); GetOneOption(command, SaveName); if (SaveName[0] == 0) break; } if (fNew == NULL) break; if ((tmpfile = fopen(Filename, "r")) == NULL) fprintf(stderr, "%s cannot be opened.\n", Filename), exit(-1); while (!feof(tmpfile)) fputc(fgetc(tmpfile), fNew); fclose(tmpfile); fclose(fNew); if (strcmp(Filename,GOPHERHELP)!=0) { if( remove(Filename) != 0 ) fprintf(stderr, "Couldn't remove %s!!!\n",Filename); } break; case SMG$K_TRM_LOWERCASE_P: case SMG$K_TRM_UPPERCASE_P: bzero(SaveName, MAXSTR); strncpy(SaveName,"sys$scratch:gopher.print",MAXSTR); while ((fNew = fopen(SaveName, "w")) == NULL) { bzero(SaveName, MAXSTR); strncpy(command, "\0", MAXSTR ); sprintf(command, "Error opening %s: Enter new name or to cancel: ", SaveName); GetOneOption(command, SaveName); if (SaveName[0] == 0) break; } if (fNew == NULL) break; if ((tmpfile = fopen(Filename, "r")) == NULL) fprintf(stderr, "%s cannot be opened.\n", Filename), exit(-1); while (!feof(tmpfile)) fputc(fgetc(tmpfile), fNew); fclose(tmpfile); fclose(fNew); strncpy(command, "\0", MAXSTR ); sprintf(command, "%s %s", PrinterCommand, Filename); system(command); break; default: ret_status = smg$ring_bell( &DisplayId ); fflush(stdout); ch=0; break; } } } ret_status = smg$erase_display( &DisplayId ); 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; int ret_status; if ((InFile = fopen(filename, "r")) == NULL) return; while (Done == FALSE) { ret_status = smg$erase_display( &DisplayId ); for (i=0 ; i < LINES-1; i++) { cp = fgets(inputline, 512, InFile); ZapCRLF(inputline); puts(inputline); } printf("----Press for next page, q to exit------"); ret_status = smg$read_keystroke( &KeyboardId, &ZeTypedChar ); if ((ZeTypedChar == 'q') || (cp == NULL)) { printf("\n"); Done = TRUE; } } 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 user can edit. ** ** Also, if a non-printable character is pressed we stop and return it. ** (tab, esc etc. ) */ char Mygetstr(inputline) char *inputline; { int pointer = 0; short int ch; int ret_status, read_pos; char *typedch, *outch; $DESCRIPTOR( d_outch, outch ); $DESCRIPTOR( d_ch, typedch ); $DESCRIPTOR( d_space, " " ); typedch = ( char * ) malloc( 1 ); outch = ( char * ) malloc( 1 ); d_ch.dsc$a_pointer = typedch; d_ch.dsc$w_length = 1; /*** Check to see if there's something in the inputline already ***/ d_outch.dsc$w_length = 1; while ( inputline[pointer] != '\0' ) { d_outch.dsc$a_pointer = &inputline[pointer]; ret_status = smg$put_chars( &DisplayId, &d_outch, &readkey_row, &readkey_col ); readkey_col = readkey_col + 1; pointer ++; } for (;;) { ret_status = smg$read_keystroke( &KeyboardId, &ch ); *typedch = ch; switch (ch) { case SMG$K_TRM_LF: case SMG$K_TRM_CR: case SMG$K_TRM_HT: inputline[pointer] = '\0'; return; break; /** Backspace and delete **/ case SMG$K_TRM_BS: case SMG$K_TRM_DELETE: if (pointer > 0) { readkey_col = readkey_col - 1; ret_status = smg$set_physical_cursor( &PasteId, &readkey_row, &readkey_col ); ret_status = smg$put_chars( &DisplayId, &d_space, &readkey_row, &readkey_col ); ret_status = smg$set_physical_cursor( &PasteId, &readkey_row, &readkey_col ); inputline[--pointer] = '\0'; } break; default: if (isprint(ch)) { inputline[pointer++]= ch; ret_status = smg$put_chars( &DisplayId, &d_ch, &readkey_row, &readkey_col ); readkey_col = readkey_col + 1; } else return(ch); } } } /* ** 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; char printstring[WHOLELINE]; char inputline[WHOLELINE]; int optionlen, ret_status, row, col; int maxoptionlen; int i,j; /** Acme Buggy whips and integers **/ BOOLEAN Done = FALSE; char ch, fooch; char *outstr; $DESCRIPTOR( d_title, Title ); $DESCRIPTOR( d_err, Err ); $DESCRIPTOR( d_outstr, outstr ); $DESCRIPTOR( d_options, Options ); $DESCRIPTOR( d_colon, ": " ); $DESCRIPTOR( d_resp, Responses ); $DESCRIPTOR( d_prstr, printstring ); outstr = ( char * )malloc( 5 ); while (Done == FALSE) { ret_status = smg$erase_display( &DisplayId ); Draw_Banner(); Draw_Status("Press to exit"); row = 4; col = (80 - strlen( Title )) / 2; d_title.dsc$w_length = strlen( Title ); ret_status = smg$put_chars( &DisplayId, &d_title, &row, &col ); row = 5; col = (80 - strlen( Err )) / 2; d_err.dsc$w_length = strlen( Err ); ret_status = smg$put_chars( &DisplayId, &d_err, &row, &col ); availlines = LINES - 6; /** Find the longest width of the options strings **/ maxoptionlen = 0; for (i=0; i j) ? maxoptionlen:j; } /*** Print out the options in a nice looking fashion ***/ for (i=0; i to accept fields and continue"); /* Centerline("Press to accept fields and continue", LINES-3); Centerline("or press to abort", LINES-2); */ /*** Now get some user input ***/ for (i=0; i< ZeForm->numfields; i++) { move(ZeForm->yloc[i],ZeForm->xloc[i] + strlen(ZeForm->tags[i])+2); echo(); ch = Mygetstr(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; static char printstring[WHOLELINE]; int optionlen; int maxoptionlen; int i,j; /** Acme Buggy whips and integers **/ BOOLEAN Done = FALSE; char ch; Draw_Banner(); /* Centerline( ZeForm->Title, 2); */ availlines = LINES - 6; /*** Print out the options according to the Form structure ***/ for (i=0; inumfields; 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; { short int ch; int i, row, col, ret_status; $DESCRIPTOR( d_message, Message ); $DESCRIPTOR( d_hitcr, " " ); d_message.dsc$w_length = strlen( Message ); row = LINES; col =1; ret_status = smg$erase_line( &DisplayId, &row, &col ); ret_status = smg$put_chars( &DisplayId, &d_message, &row, &col ); col = strlen( Message ) + 2; ret_status = smg$put_chars( &DisplayId, &d_hitcr, &row, &col ); while (ch != SMG$K_TRM_CR ) ret_status = smg$read_keystroke( &KeyboardId, &ch ); } GetOneOption(OptionName, Response) char *OptionName, *Response; { int ret_status, row, col, resp_len, maxlen; char *resp_p1; $DESCRIPTOR( d_option, OptionName ); $DESCRIPTOR( d_resp, Response ); d_resp.dsc$w_length = MAXSTR-1; d_option.dsc$w_length = strlen( OptionName ); maxlen = MAXSTR - 1; row = LINES; readkey_row = LINES; readkey_col = strlen( OptionName ) + 1; col = 1; ret_status = smg$erase_line( &DisplayId, &row, &col ); ret_status = smg$put_chars( &DisplayId, &d_option, &row, &col ); Mygetstr(Response); } /* ** This strips off CR's and LF's leaving us with a nice pure string. */ void ZapCRLF(inputline) char *inputline; { char *cp; cp = strchr(inputline, '\r'); /* Zap CR-LF */ if (cp != NULL) *cp = '\0'; else { cp = strchr(inputline, '\n'); if (cp != NULL) *cp = '\0'; } } /* * This routine allows the user to "find" a specific event. * It doesn't allow them to look at documents, etc. It just lets * them cruise around directories */ GopherStruct* cruise_dirs(ZeGopher, Message) GopherStruct *ZeGopher; char *Message; { int Line; char SavedTitle; short int TypedChar = 0; GopherStruct TmpGopher; process_request(ZeGopher); while (1) { Line = GetMenu(iMenuLines, Gopher, Message, &TypedChar); switch (TypedChar) { case SMG$K_TRM_CR: case SMG$K_TRM_LF: if (Gopher[Line-1].sFileType == '1') process_request(&(Gopher[Line - 1])); else CursesErrorMsg("Cannot select these at this time"); break; case SMG$K_TRM_SPACE: /*** Use this directory/calendar ***/ return(&(Gopher[Line -1])); break; case SMG$K_TRM_LOWERCASE_U: case SMG$K_TRM_UPPERCASE_U: /*** Go up a directory level ***/ popgopher(&TmpGopher); popgopher(&TmpGopher); process_request(&TmpGopher); break; } } } int OpenGopherConn(ZeGopher) GopherStruct *ZeGopher; { int sockfd; static char inputline[MAXLINE]; int length; inputline[0] = '\0'; if ((sockfd = connect_to_gopher(ZeGopher->sHost, ZeGopher->iPort)) <0) { check_sock(sockfd, ZeGopher->sHost); return(-1); } /*** Get rid of that darn Banner line *** length = readline(sockfd, inputline, MAXLINE); */ return(sockfd); /*** TODO check to see if the server version is cool. ***/ } #ifdef UCX int bzero(ptr, len) char *ptr; int len; { long count; for (count = 0; count < len; count++){ *(char*)(ptr + count) = 0; } } char *bcopy(src, dest, len) char *dest, *src; int len; { return((char*)memmove(dest, src, len)); } #endif