home *** CD-ROM | disk | FTP | other *** search
- Subject: v09i011: ELM Mail System, Part11/19
- Newsgroups: mod.sources
- Approved: rs@mirror.TMC.COM
-
- Submitted by: Dave Taylor <hplabs!taylor>
- Mod.sources: Volume 9, Issue 11
- Archive-name: elm2/Part11
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If this archive is complete, you will see the message:
- # "End of archive 11 (of 19)."
- # Contents: src/screen.c src/screen3270.q src/showmsg.c src/strings.c
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo shar: Extracting \"src/screen.c\" \(11166 characters\)
- if test -f src/screen.c ; then
- echo shar: Will not over-write existing file \"src/screen.c\"
- else
- sed "s/^X//" >src/screen.c <<'END_OF_src/screen.c'
- X/** screen.c **/
- X
- X/** screen display routines for ELM program
- X
- X (C) Copyright 1985, Dave Taylor
- X**/
- X
- X#include "headers.h"
- X
- X#define minimum(a,b) ((a) < (b) ? (a) : (b))
- X
- Xstatic int last_current = -1;
- X
- Xchar *strcpy(), *strncpy(), *nameof();
- X
- Xshowscreen()
- X{
- X char buffer[SLEN];
- X
- X ClearScreen();
- X
- X if (selected)
- X sprintf(buffer,
- X "Mailbox is '%s' with %d shown out of %d [Elm %s]",
- X nameof(infile), selected, message_count, VERSION);
- X else
- X sprintf(buffer, "Mailbox is '%s' with %d message%s [Elm %s]",
- X nameof(infile), message_count, plural(message_count), VERSION);
- X Centerline(1, buffer);
- X
- X last_header_page = -1; /* force a redraw regardless */
- X show_headers();
- X
- X if (mini_menu)
- X show_menu();
- X
- X show_last_error();
- X
- X if (hp_terminal)
- X define_softkeys(MAIN);
- X}
- X
- Xupdate_title()
- X{
- X /** display a new title line, probably due to new mail arriving **/
- X
- X char buffer[SLEN];
- X
- X if (selected)
- X sprintf(buffer,
- X "Mailbox is '%s' with %d shown out of %d [Elm %s]",
- X nameof(infile), selected, message_count, VERSION);
- X else
- X sprintf(buffer, "Mailbox is '%s' with %d message%s [Elm %s]",
- X nameof(infile), message_count, plural(message_count), VERSION);
- X
- X ClearLine(1);
- X
- X Centerline(1, buffer);
- X}
- X
- Xshow_menu()
- X{
- X /** write main system menu... **/
- X
- X if (user_level == 0) { /* a rank beginner. Give less options */
- X Centerline(LINES-7,
- X "You can use any of the following commands by pressing the first character;");
- X Centerline(LINES-6,
- X"D)elete mail, M)ail a message, R)eply to mail, U)ndelete, or Q)uit");
- X Centerline(LINES-5,
- X "To read a message, press <return>. j = move arrow down, k = move arrow up");
- X } else {
- X Centerline(LINES-7,
- X "|=pipe, !=shell, ?=help, <n>=set current to n, /=search pattern");
- X Centerline(LINES-6,
- X"A)lias, C)hange mailbox, D)elete, E)dit, F)orward, G)roup reply, M)ail,");
- X Centerline(LINES-5,
- X "N)ext, O)ptions, P)rint, R)eply, S)ave, T)ag, Q)uit, U)ndelete, or eX)it");
- X }
- X}
- X
- Xint
- Xshow_headers()
- X{
- X /** Display page of headers (10) if present. First check to
- X ensure that header_page is in bounds, fixing silently if not.
- X If out of bounds, return zero, else return non-zero
- X Modified to only show headers that are "visible" to ze human
- X person using ze program, eh?
- X **/
- X
- X register int this_msg = 0, line = 4, last = 0, last_line,
- X displayed = 0;
- X char newfrom[SLEN], buffer[SLEN];
- X
- X if (fix_header_page()) {
- X dprint0(7, "show_headers returned FALSE 'cause of fix-header-page\n");
- X return(FALSE);
- X }
- X
- X if (selected) {
- X if ((header_page*headers_per_page) > selected) {
- X dprint2(7, "show_headers returned FALSE since selected [%d] < %d\n",
- X selected, header_page*headers_per_page);
- X return(FALSE); /* too far! too far! */
- X }
- X
- X dprint0(6,"** show_headers AND selected...\n");
- X
- X if (header_page == 0) {
- X this_msg = visible_to_index(1);
- X displayed = 0;
- X }
- X else {
- X this_msg = visible_to_index(header_page * headers_per_page + 1);
- X displayed = header_page * headers_per_page;
- X }
- X
- X dprint2(7,"this_msg (index) = %d [header_page = %d]\n", this_msg,
- X header_page);
- X
- X dprint1(7,"we've already displayed %d messages\n", displayed);
- X
- X last = displayed+headers_per_page;
- X
- X dprint1(7,"and the last msg on this page is %d\n", last);
- X }
- X else {
- X if (header_page == last_header_page) /* nothing to do! */
- X return(FALSE);
- X
- X /** compute last header to display **/
- X
- X this_msg = header_page * headers_per_page;
- X last = this_msg + (headers_per_page - 1);
- X }
- X
- X if (last >= message_count) last = message_count-1;
- X
- X /** Okay, now let's show the header page! **/
- X
- X ClearLine(line); /* Clear the top line... */
- X
- X MoveCursor(line, 0); /* and move back to the top of the page... */
- X
- X while ((selected && displayed < last) || this_msg <= last) {
- X tail_of(header_table[this_msg].from, newfrom, TRUE);
- X
- X if (selected) {
- X if (this_msg == current-1)
- X build_header_line(buffer, &header_table[this_msg], ++displayed,
- X TRUE, newfrom);
- X else
- X build_header_line(buffer, &header_table[this_msg],
- X ++displayed, FALSE, newfrom);
- X }
- X else {
- X if (this_msg == current-1)
- X build_header_line(buffer, &header_table[this_msg], this_msg+1,
- X TRUE, newfrom);
- X else
- X build_header_line(buffer, &header_table[this_msg],
- X this_msg+1, FALSE, newfrom);
- X }
- X
- X Write_to_screen("%s\r\n", 1, buffer); /* avoid '%' probs */
- X CleartoEOLN();
- X line++; /* for clearing up in a sec... */
- X
- X if (selected) {
- X if ((this_msg = next_visible(this_msg+1)-1) < 0)
- X break; /* GET OUTTA HERE! */
- X
- X /* the preceeding looks gross because we're using an INDEX
- X variable to pretend to be a "current" counter, and the
- X current counter is always 1 greater than the actual
- X index. Does that make sense??
- X */
- X }
- X else
- X this_msg++; /* even dumber... */
- X }
- X
- X dprint0(1,"** out of redraw loop! **\n");
- X
- X if (mini_menu)
- X last_line = LINES-8;
- X else
- X last_line = LINES-3;
- X
- X while (line < last_line) {
- X CleartoEOLN();
- X Writechar('\r');
- X Writechar('\n');
- X line++;
- X }
- X
- X display_central_message();
- X
- X last_current = current;
- X last_header_page = header_page;
- X
- X return(TRUE);
- X}
- X
- Xshow_current()
- X{
- X /** Show the new header, with all the usual checks **/
- X
- X register int first = 0, last = 0, last_line, new_line, i=0, j=0;
- X char newfrom[SLEN], old_buffer[SLEN], new_buffer[SLEN];
- X
- X (void) fix_header_page(); /* Who cares what it does? ;-) */
- X
- X /** compute last header to display **/
- X
- X first = header_page * headers_per_page;
- X last = first + (headers_per_page - 1);
- X
- X if (last > message_count)
- X last = message_count;
- X
- X /** okay, now let's show the pointers... **/
- X
- X /** have we changed??? **/
- X
- X if (current == last_current)
- X return;
- X
- X if (selected) {
- X dprint2(2,"\nshow_current\n* last_current = %d, current = %d\n",
- X last_current, current);
- X last_line = ((i=compute_visible(last_current-1)-1) %
- X headers_per_page)+4;
- X new_line = ((j=compute_visible(current-1)-1) % headers_per_page)+4;
- X dprint1(2,"* compute_visible(last-1)=%d\n",
- X compute_visible(last_current-1));
- X dprint1(2,"* compute_visible(current-1)=%d\n",
- X compute_visible(current-1));
- X dprint2(2,"* ending up with last_line = %d and new_line = %d\n",
- X last_line, new_line);
- X }
- X else {
- X last_line = ((last_current-1) % headers_per_page)+4;
- X new_line = ((current-1) % headers_per_page)+4;
- X }
- X
- X dprint4(7,
- X "--> show-current: last_current=%d [%d] and current=%d [%d]\n",
- X last_current, i, current, j);
- X
- X dprint2(7," maps to lines %d and %d\n", last_line, new_line);
- X
- X if (has_highlighting && ! arrow_cursor) {
- X /** build the old and new header lines... **/
- X
- X tail_of(header_table[current-1].from, newfrom, TRUE);
- X build_header_line(new_buffer, &header_table[current-1],
- X (selected? compute_visible(current-1) : current),
- X TRUE, newfrom);
- X
- X if (last_current > 0) { /* say we went from no mail to new... */
- X tail_of(header_table[last_current-1].from, newfrom, TRUE);
- X build_header_line(old_buffer, &header_table[last_current-1],
- X (selected? compute_visible(last_current-1) : last_current),
- X FALSE, newfrom);
- X
- X ClearLine(last_line);
- X PutLine0(last_line, 0, old_buffer);
- X }
- X PutLine0(new_line, 0, new_buffer);
- X }
- X else {
- X if (on_page(last_current))
- X PutLine0(last_line,0," "); /* remove old pointer... */
- X if (on_page(current))
- X PutLine0(new_line, 0,"->");
- X }
- X
- X last_current = current;
- X}
- X
- Xbuild_header_line(buffer, entry, message_number, highlight, from)
- Xchar *buffer;
- Xstruct header_rec *entry;
- Xint message_number, highlight;
- Xchar *from;
- X{
- X /** Build in buffer the message header ... entry is the current
- X message entry, 'from' is a modified (displayable) from line,
- X 'highlight' is either TRUE or FALSE, and 'message_number'
- X is the number of the message.
- X **/
- X
- X /** Note: using 'strncpy' allows us to output as much of the
- X subject line as possible given the dimensions of the screen.
- X The key is that 'strncpy' returns a 'char *' to the string
- X that it is handing to the dummy variable! Neat, eh? **/
- X
- X char subj[LONG_SLEN], /* to output subject */
- X buff[NLEN]; /* keep start_highlight value */
- X
- X if (strcmp(start_highlight,"->") != 0 && arrow_cursor) {
- X strcpy(buff, start_highlight);
- X strcpy(start_highlight, "->");
- X }
- X
- X strncpy(subj, entry->subject, COLUMNS-45);
- X
- X subj[COLUMNS-45] = '\0'; /* insurance, eh? */
- X
- X /* now THIS is a frightening format statement!!! */
- X
- X sprintf(buffer, "%s%s%c%c%c%-3d %3.3s %-2d %-18.18s (%d) %s%s%s",
- X highlight? ((has_highlighting && !arrow_cursor) ?
- X start_highlight : "->") : " ",
- X (highlight && has_highlighting && !arrow_cursor)? " " : "",
- X show_status(entry->status),
- X (entry->status & DELETED? 'D' : ' '),
- X (entry->status & TAGGED? '+' : ' '),
- X message_number,
- X entry->month,
- X atoi(entry->day),
- X from,
- X entry->lines,
- X (entry->lines / 1000 > 0? "" : /* spacing the */
- X entry->lines / 100 > 0? " " : /* same for the */
- X entry->lines / 10 > 0? " " : /* lines in () */
- X " "), /* [wierd] */
- X subj,
- X (highlight && has_highlighting && !arrow_cursor) ?
- X end_highlight : "");
- X
- X /** Actually, it's rather an impressive feat that we can
- X do so much in essentially one statement! (Of course,
- X I'll bet the test suite for the printf routine isn't
- X THIS rigorous either!!!) (to be honest, though, just
- X looking at this statement makes me chuckle...)
- X **/
- X
- X if (arrow_cursor) /* restore! */
- X strcpy(start_highlight, buff);
- X
- X}
- X
- Xint
- Xfix_header_page()
- X{
- X /** this routine will check and ensure that the current header
- X page being displayed contains messages! It will silently
- X fix 'header-page' if wrong. Returns TRUE if changed. **/
- X
- X int last_page, old_header;
- X
- X old_header = header_page;
- X
- X last_page = (int) ((message_count-1) / headers_per_page);
- X
- X if (header_page > last_page)
- X header_page = last_page;
- X else if (header_page < 0)
- X header_page = 0;
- X
- X return(old_header != header_page);
- X}
- X
- Xint
- Xon_page(message)
- Xint message;
- X{
- X /** Returns true iff the specified message is on the displayed page. **/
- X
- X dprint1(6,"** on_page(%d) returns...", message);
- X
- X if (selected) message = compute_visible(message-1);
- X
- X if (message >= header_page * headers_per_page)
- X if (message <= ((header_page+1) * headers_per_page)) {
- X dprint0(6,"TRUE\n");
- X return(TRUE);
- X }
- X
- X dprint0(6,"FALSE\n");
- X return(FALSE);
- X}
- X
- Xshow_status(status)
- Xint status;
- X{
- X /** This routine returns a single character indicative of
- X the status of this message. The precedence is;
- X
- X F = form letter
- X E = Expired message
- X P = Priority message
- X A = Action associated with message
- X N = New message
- X _ = (space) default
- X **/
- X
- X if (status & FORM_LETTER) return( 'F' );
- X else if (status & EXPIRED) return( 'E' );
- X else if (status & PRIORITY) return( 'P' );
- X else if (status & ACTION) return( 'A' );
- X else if (status & NEW) return( 'N' );
- X else return( ' ' );
- X}
- END_OF_src/screen.c
- if test 11166 -ne `wc -c <src/screen.c`; then
- echo shar: \"src/screen.c\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"src/screen3270.q\" \(11593 characters\)
- if test -f src/screen3270.q ; then
- echo shar: Will not over-write existing file \"src/screen3270.q\"
- else
- sed "s/^X//" >src/screen3270.q <<'END_OF_src/screen3270.q'
- XFrom hpccc!mcgregor@hplabs.ARPA Thu Jun 5 11:41:49 1986
- XReceived: from hplabs.ARPA by hpldat ; Thu, 5 Jun 86 11:41:32 pdt
- XMessage-Id: <8606051841.AA16872@hpldat>
- XReceived: by hplabs.ARPA ; Thu, 5 Jun 86 11:38:07 pdt
- XTo: hplabs!taylor@hplabs.ARPA
- XDate: Thu, 5 Jun 86 11:36:39 PDT
- XFrom: hpccc!mcgregor@hplabs.ARPA (Scott McGregor)
- XSubject: revised screen3270.q
- XTelephone: (415) 857-5875
- XPostal-Address: Hewlett-Packard, PO Box 10301, Mail stop 20CH, Palo Alto CA 943X03-0890
- XX-Mailer: ELM [version 1.0]
- X
- X
- X/*
- X * screen3270.q
- X *
- X * Created for ELM, 5/86 to work (hopefully) on UTS systems with 3270
- X * type terminals, by Scott L. McGregor, HP Corporate Computing Center.
- X *
- X */
- X
- X#include "headers.h"
- X# include <sys/utsname.h>
- X# include <sys/tubio.h>
- X
- X# include <errno.h>
- X
- X
- X# define TTYIN 0 /* standard input */
- X#include <stdio.h>
- X#define MAXKEYS 101
- X#define OFF 0
- X#define UNKNOWN 0
- X#define ON 1
- X#define FALSE 0
- X#define TRUE 1
- X
- Xchar *error_name();
- X
- Xextern int _line, _col;
- X
- X
- Xpfinitialize()
- X{
- X char cp[80];
- X
- X dprint0(9,"pfinitialize()\n");
- X pfinit();
- X /*
- X * load the system defined pfkeys
- X */
- X pfload("/usr/local/etc/.elmpfrc");
- X /*
- X * load the user's keys if any
- X */
- X strcat(cp,home);
- X strcat(cp,"/.elmpfrc");
- X pfload(cp);
- X pfprint();
- X}
- X
- X/*
- X * note, inputs are limited to 80 characters! Any larger amount
- X * will be truncated without notice!
- X */
- X
- X
- X/*
- X * pfinit() initializes _pftable
- X */
- Xpfinit()
- X{
- X int i,j;
- X
- X dprint0(9,"pfinit()\n");
- X for (i=0;i<MAXKEYS;i++) {
- X for (j=0;j<80;j++) {
- X _pftable[i][j]='\0';
- X }
- X }
- X return(0);
- X}
- X
- X
- X/*
- X * pfset(key) sets _pftable entries.
- X */
- Xpfset(key,return_string)
- Xint key;
- Xchar *return_string;
- X{
- X int i;
- X
- X dprint2(9,"pfset(%d,%s)\n",key,return_string);
- X for (i=0;i<=80;i++) {
- X if (i <= strlen(return_string))
- X _pftable[key][i] = return_string[i];
- X else _pftable[key][i] = '\0';
- X }
- X dprint2(9,"pfset: %d %s\n",key,_pftable[key]);
- X
- X return(0);
- X}
- X
- X/*
- X * pfload(name) reads file "name" and parses the
- X * key definitions in it into a table used by the
- X * pfreturn.
- X */
- Xpfload(name)
- Xchar *name;
- X{
- X FILE *pfdefs;
- X int i,j,k;
- X int key = 0;
- X char defn[80];
- X char newdefn[80];
- X
- X dprint1(9,"pfload(%s)\n",name);
- X if ((pfdefs = fopen(name,"r")) == NULL){
- X dprint2(2,"%s pfrc open failed, %s \n",name,
- X error_name(errno));
- X return(0);
- X }
- X
- X /*
- X * This program reads .elmpfrc files which it currently
- X * expects to be in the form:
- X *
- X * <pfkeynumber> <whitespace> <pfkeyvalue> [<whitespace> <comment>]
- X *
- X * Pfkeynumber is an integer 1-24. Whitespace can be one
- X * or more blanks or tabs. Pfkeyvalue is any string NOT
- X * containing whitespace (however, \b for blank, \t for tab
- X * and \n for newline can be used instead to indicate that
- X * the indicated whitespace character is part of a command.
- X * Note that the EnTER key will NOT be treated as a newline
- X * command, so defining a newline key is a good idea!
- X * Anything else appearing on the line after the pfkey is ignored
- X * and so can be used as a comment.
- X *
- X * This may not be the best form for a file used by
- X * humans to set parms, and if someone comes up with a
- X * better one and a parser to read it, then this can be
- X * replaced.
- X *
- X */
- X
- X dprint1(1,"%s pfrc opened\n",name);
- X k = 0;
- X while ( fscanf(pfdefs,"%d%s",&key,defn) != EOF ) {
- X dprint2(9,"pfkey definition 1: %d %s\n",key,defn);
- X if ((key < 0) || (key > MAXKEYS)) {
- X dprint2(9,"pfkey defn failed: key=%d MAXKEYS=%d\n",key,MAXKEYS);
- X k++;
- X } else {
- X dprint2(9,"pfkey definition 2: %d %s\n",key,defn);
- X for (i=0,j=0;i<strlen(defn);i++) {
- X if (defn[i]=='\\') {
- X if (defn[i+1]=='n') {
- X newdefn[j++]='\n'; i++;
- X }
- X if (defn[i+1]=='t') {
- X newdefn[j++]='\t'; i++;
- X }
- X if (defn[i+1]=='0') {
- X newdefn[j++]='\0'; i++;
- X }
- X if (defn[i+1]=='1') {
- X newdefn[j++]='\001'; i++;
- X }
- X if (defn[i+1]=='b') {
- X newdefn[j++]=' '; i++;
- X }
- X }
- X else {
- X newdefn[j++]=defn[i];
- X }
- X }
- X dprint2(9,"pfkey new definition: %d %s\n",key,newdefn);
- X pfset(key,newdefn);
- X }
- X }
- X dprint1(9,"pfkey definition table: %s\n",_pftable);
- X return(k);
- X}
- X
- X
- X/*
- X * pfreturn(key) returns the stored string for that pfkey.
- X */
- Xpfreturn(key,string)
- Xint key;
- Xchar string[];
- X{
- X int i;
- X
- X dprint2(9,"pfreturn(%d,%s)\n",key,string);
- X for (i=0;i<80;i++) {
- X string[i] = _pftable[key][i];
- X }
- X dprint1(9,"pfreturn string=%s\n",string);
- X return;
- X}
- X
- X
- X/*
- X * pfprint() prints all pfkey definitions
- X */
- Xpfprint()
- X
- X{
- X int i;
- X char string[80];
- X
- X for (i=0;i<MAXKEYS;i++) {
- X if (strlen(_pftable[i]) != 0)
- X dprint2(9,"%d pf table entry=%s\n",i+1,_pftable[i]);
- X }
- X}
- X
- X/*
- X * rowcol2offset(row,col) takes the row and column numbers and
- X * returns the offset into the array.
- X * row and column are assumed to vary from 0 to LINES-1, and COLUMNS-1
- X * respectively.
- X */
- Xrowcol2offset(row,col)
- Xint row, col;
- X{
- X dprint2(9,"rowcol2offset(%d,%d)\n",row,col);
- X
- X if ((row <= LINES) && (row >= 0)) {
- X if ((col <= COLUMNS) && (col >=0)) {
- X return(row*COLUMNS+col);
- X }
- X else return(0);
- X }
- X else return(0);
- X}
- X
- X/*
- X * offset2row(offset) takes the offset returnes the row.
- X * row is assumed to vary from 0 to LINES-1.
- X */
- Xoffset2row(offset)
- Xint offset;
- X{
- X int i;
- X
- X dprint1(9,"offset2row(%d)\n",offset);
- X i = (int) (offset / COLUMNS);
- X dprint1(9,"offset2row returns= %d)\n",i);
- X return(i);
- X}
- X
- X/*
- X * offset2col(offset) takes the offset returnes the col.
- X * col is assumed to vary from 0 to COLUMNS-1.
- X */
- Xoffset2col(offset)
- Xint offset;
- X{
- X int i;
- X
- X dprint1(9,"offset2col(%d)\n",offset);
- X i = (int) (offset % COLUMNS);
- X dprint1(9,"offset2col returns= %d)\n",i);
- X return(i);
- X}
- X
- X/*
- X * Row(row) takes the row in 0 <= row < LINES and returns
- X * row in 0 < row <= LINES.
- X */
- XRow(row)
- Xint row;
- X{
- X dprint1(9,"Row(%d)\n",row);
- X return(row+1);
- X}
- X
- X/*
- X * Col(Col) takes the col in 0 <= col < COLUMNS and returns
- X * col in 0 < col <= COLUMNS.
- X */
- XCol(col)
- Xint col;
- X{
- X dprint1(9,"Col(%d)\n",col);
- X return(col+1);
- X}
- X
- X
- Xgethostname(hostname,size) /* get name of current host */
- Xint size;
- Xchar *hostname;
- X{
- X /** Return the name of the current host machine. UTS only **/
- X
- X /** This routine compliments of Scott McGregor at the HP
- X Corporate Computing Center **/
- X
- X int uname();
- X struct utsname name;
- X
- X dprint2(9,"gethostname(%s,%d)\n",hostname,size);
- X (void) uname(&name);
- X (void) strncpy(hostname,name.nodename,size-1);
- X if (strlen(name.nodename) > SLEN)
- X hostname[size] = '\0';
- X}
- X
- Xint
- Xisa3270()
- X{
- X /** Returns TRUE and sets LINES and COLUMNS to the correct values
- X for an Amdahl (IBM) tube screen, or returns FALSE if on a normal
- X terminal (of course, next to a 3270, ANYTHING is normal!!) **/
- X
- X struct tubiocb tubecb;
- X
- X dprint0(9,"isa3270()\n");
- X if (ioctl(TTYIN, TUBGETMOD, &tubecb) == -1){
- X return(FALSE); /* not a tube! */
- X }
- X LINES = tubecb.line_cnt - 2;
- X COLUMNS = tubecb.col_cnt;
- X if (!check_only && !mail_only) {
- X isatube = TRUE;
- X return(TRUE);
- X }
- X else {
- X isatube = FALSE;
- X return(FALSE);
- X }
- X}
- X
- X/*
- X * ReadCh3270() reads a character from the 3270.
- X */
- Xint ReadCh3270()
- X{
- X /** read a character from the display! **/
- X
- X register int x;
- X char tempstr[80];
- X char ch;
- X
- X dprint0(9,"ReadCh3270()\n");
- X if ((_input_buf_ptr > COLUMNS) ||
- X (_input_buffer[_input_buf_ptr] == '\0')) {
- X WriteScreen3270();
- X for (x=0; x < COLUMNS; x++) _input_buffer[x] = '\0';
- X panel (noerase, read) {
- X #@ LINES+1,1# #INC,_input_buffer,COLUMNS#
- X }
- X dprint1(9,"ReadCh3270 _input_buffer=%s\n",_input_buffer);
- X x=strlen(_input_buffer);
- X pfreturn(qskp,tempstr);
- X if (!strcmp(tempstr,"\001")) {
- X if (strlen(_input_buffer) == 1) {
- X tempstr[0]='\0';
- X }
- X else {
- X tempstr[0]='\n';
- X tempstr[1]='\0';
- X }
- X }
- X dprint1(9,"ReadCh3270 pfkey=%s\n",tempstr);
- X strcat(_input_buffer,tempstr);
- X dprint1(9,"ReadCh3270 _input_buffer+pfkey=%s\n",_input_buffer);
- X ch = _input_buffer[0];
- X dprint1(9,"ReadCh3270 returns(%c)\n",ch);
- X _input_buf_ptr = 1;
- X return(ch);
- X }
- X else {
- X ch = _input_buffer[_input_buf_ptr];
- X dprint1(9,"ReadCh3270 returns(%c)\n",ch);
- X _input_buf_ptr = _input_buf_ptr + 1;
- X return(ch);
- X }
- X}
- X
- X
- X/*
- X * WriteScreen3270() Loads a screen to the buffer.
- X *
- X */
- XWriteScreen3270()
- X{
- X register int x;
- X int currcol;
- X int currrow;
- X int i;
- X int state = OFF;
- X int prevrow = 1;
- X int prevcol = 1;
- X int prevptr = 0;
- X int clear_state = ON;
- X char tempstr[80];
- X char copy_screen[66*132];
- X
- X dprint0(9,"WriteScreen3270()\n");
- X prevrow = 1;
- X prevcol = 1;
- X prevptr = 0;
- X state = OFF;
- X for (x=0; x < LINES*COLUMNS; x++){
- X if ((_internal_screen[x] == '\016')
- X && (state == OFF)) {
- X currrow = (x / COLUMNS ) + 1;
- X currcol = (x % COLUMNS ) + 1 ;
- X i = x - prevptr - 1;
- X strncpy(copy_screen, (char *) (_internal_screen+(prevptr)),i);
- X panel(erase=clear_state,write,noread) {
- X #@ prevrow, prevcol # #ON,copy_screen,i #
- X }
- X clear_state = OFF;
- X state = ON;
- X /* prevrow = currrow; */
- X /* prevcol = currcol; */
- X prevrow = currrow + 1;
- X prevcol = 0;
- X prevptr = x+1;
- X }
- X else if ((_internal_screen[x] == '\017')
- X && (state == ON)) {
- X currrow = (x / COLUMNS ) + 1;
- X currcol = (x % COLUMNS ) + 1;
- X i = x - prevptr - 1;
- X strncpy(copy_screen, (char *) (_internal_screen+(prevptr)),i);
- X panel(erase = clear_state,write,noread) {
- X #@ prevrow,prevcol # #OH,copy_screen,i #
- X }
- X clear_state = OFF;
- X state = OFF;
- X /* prevrow = currrow; */
- X /* prevcol = currcol; */
- X prevrow = currrow + 1;
- X prevcol = 0;
- X }
- X else if (_internal_screen[x] < ' ') {
- X _internal_screen[x] = ' ';
- X prevptr = x + 1;
- X }
- X }
- X /* write remainder of buffer */
- X if (state == OFF) {
- X currrow = (LINES) + 1 ;
- X currcol = (COLUMNS ) + 1;
- X i = x - prevptr ;
- X strncpy(copy_screen, (char *) (_internal_screen+(prevptr)),i);
- X panel(erase=clear_state,write,noread) {
- X #@ prevrow,prevcol # #ON,copy_screen,i #
- X }
- X }
- X else {
- X currrow = (LINES ) + 1 ;
- X currcol = (COLUMNS ) + 1 ;
- X i = x - prevptr ;
- X strncpy(copy_screen, (char *) (_internal_screen+(prevptr)),i);
- X panel(erase=clear_state,write,noread) {
- X #@ prevrow,prevcol # #OH,copy_screen,i #
- X }
- X }
- X}
- X
- X
- X/*
- X * Clear3270
- X */
- XClear3270()
- X{
- X int i,j;
- X
- X dprint0(9,"Clear3270()\n");
- X j = rowcol2offset(LINES,COLUMNS);
- X for (i = 0; i < j; i++) {
- X _internal_screen[i] = ' ';
- X }
- X return(0);
- X}
- X
- X/*
- X * WriteChar3270(row,col) writes a character at the row and column.
- X */
- XWriteChar3270(row,col,ch)
- Xint row, col;
- Xchar ch;
- X{
- X dprint3(9,"WriteChar3270(%d,%d,%c)\n",row,col,ch);
- X _internal_screen[rowcol2offset(row,col)] = ch;
- X}
- X
- X/*
- X * WriteLine3270(row,col) writes a line at the row and column.
- X */
- XWriteLine3270(row,col,line)
- Xint row, col;
- Xchar *line;
- X{
- X int i, j, k;
- X dprint3(9,"WriteLine3270(%d,%d,%s)\n",row,col,line);
- X _line = row;
- X _col = col;
- X k = strlen(line);
- X i=rowcol2offset(row,col);
- X for (j=0; j<k; i++, j++) {
- X if ((line[j] >= ' ') ||
- X (line[j] == '\016') ||
- X (line[j] == '\017'))
- X _internal_screen[i] = line[j];
- X else _internal_screen[i] = ' ';
- X }
- X /* _line = offset2row(i-1); calling program updates location */
- X /* _col = offset2col(i-1); */
- X
- X}
- X
- X
- X/*
- X * ClearEOLN3270() clears the remainder of the current line on a 3270.
- X */
- XClearEOLN3270()
- X{
- X int i,j ;
- X
- X dprint0(9,"ClearEOLN3270()\n");
- X j = rowcol2offset(_line,COLUMNS);
- X for (i=rowcol2offset(_line,_col); i < j; i++) {
- X _internal_screen[i] = ' ';
- X }
- X}
- X
- X/*
- X * ClearEOS3270() clears the remainder of the current screen on a 3270.
- X */
- XClearEOS3270()
- X{
- X int i,j;
- X
- X dprint0(9,"ClearEOS3270()\n");
- X j = rowcol2offset(LINES,COLUMNS);
- X for (i = rowcol2offset(_line,_col); i < j; i++) {
- X _internal_screen[i] = ' ';
- X }
- X}
- X
- END_OF_src/screen3270.q
- if test 11593 -ne `wc -c <src/screen3270.q`; then
- echo shar: \"src/screen3270.q\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"src/showmsg.c\" \(10629 characters\)
- if test -f src/showmsg.c ; then
- echo shar: Will not over-write existing file \"src/showmsg.c\"
- else
- sed "s/^X//" >src/showmsg.c <<'END_OF_src/showmsg.c'
- X/** showmsg.c **/
- X
- X/** This file contains all the routines needed to display the specified
- X message.
- X
- X These routines (C) Copyright 1986 Dave Taylor
- X
- X Modified 6/86 to use pager variable!!! Hurrah!!!!
- X Modified 7/86 to have secure pipes.. *sigh*
- X**/
- X
- X#include "headers.h"
- X#include <ctype.h>
- X#include <errno.h>
- X#include <signal.h>
- X
- X#ifdef BSD
- X# include <sys/wait.h>
- X# undef tolower
- X#endif
- X
- Xextern int errno;
- X
- Xchar *error_name(), *strcat(), *strcpy();
- Xvoid _exit();
- X
- Xint memory_lock = FALSE; /* is it available?? */
- Xint pipe_abort = FALSE; /* did we receive a SIGNAL(SIGPIPE)? */
- X
- Xint
- Xshow_msg(number)
- Xint number;
- X{
- X /*** display number'th message. Get starting and ending lines
- X of message from headers data structure, then fly through
- X the file, displaying only those lines that are between the
- X two!
- X Returns non-zero iff screen was changed
- X ***/
- X
- X dprint0(8, "show_msg called\n");
- X
- X if (number > message_count) {
- X error1("Only %d messages!", message_count);
- X return(0);
- X }
- X else if (number < 1) {
- X error("you can't read THAT message!");
- X return(0);
- X }
- X
- X clearit(header_table[number-1].status, NEW); /* it's been read now! */
- X
- X memory_lock = FALSE;
- X
- X /* some explaination for that last one - We COULD use memory locking
- X to speed up the paging, but the action of "ClearScreen" on a screen
- X with memory lock turned on seems to vary considerably (amazingly so)
- X so it's safer to only allow memory lock to be a viable bit of
- X trickery when dumping text to the screen in scroll mode.
- X Philosophical arguments should be forwarded to Bruce at the
- X University of Walamazoo, Australia, via ACSNet *wry chuckle* */
- X
- X return(show_message(header_table[number-1].lines,
- X header_table[number-1].offset,number));
- X}
- X
- Xint
- Xshow_message(lines, file_loc, msgnumber)
- Xint lines, msgnumber;
- Xlong file_loc;
- X{
- X /*** Show the indicated range of lines from mailfile
- X for message 'msgnumber' by using 'display'
- X Returns non-zero iff screen was altered.
- X ***/
- X
- X dprint3(9,"show_message(%d,%ld,%d)\n", lines, file_loc, msgnumber);
- X
- X if (fseek(mailfile, file_loc, 0) != 0) {
- X dprint2(1,"Error: seek %d bytes into file, errno %s (show_message)\n",
- X file_loc, error_name(errno));
- X error2("ELM failed seeking %d bytes into file (%s)",
- X file_loc, error_name(errno));
- X return(0);
- X }
- X
- X if (feof(mailfile))
- X dprint0(1,"\n*** seek put us at END OF FILE!!! ***\n");
- X
- X /* next read will get 'this' line so must be at end of previous */
- X
- X Raw(OFF);
- X if (strcmp(pager,"builtin") == 0 || strcmp(pager,"internal") == 0)
- X display(lines, msgnumber);
- X else
- X secure_display(lines, msgnumber);
- X Raw(ON);
- X if (memory_lock) EndMemlock(); /* turn it off!! */
- X
- X return(1); /* we did it boss! */
- X}
- X
- X
- X/** This next one is the 'pipe' file descriptor for writing to the
- X pager process... **/
- X
- XFILE *output_pipe, *popen();
- X
- Xint
- Xdisplay(lines, msgnum)
- Xint lines, msgnum;
- X{
- X /** Display specified number of lines from file mailfile.
- X Note: This routine MUST be placed at the first line
- X of the input file!
- X Returns the same as the routine above (namely zero or one)
- X **/
- X
- X char from_buffer[LONG_STRING], buffer[VERY_LONG_STRING], *full_month();
- X
- X int lines_displayed = 0;
- X int crypted = 0, gotten_key = 0; /* encryption */
- X int weed_header, weeding_out = 0; /* weeding */
- X int mail_sent, /* misc use */
- X form_letter = FALSE, /* Form ltr? */
- X form_letter_section = 0, /* section */
- X builtin = FALSE; /* our pager? */
- X
- X dprint3(4,"displaying %d lines from message %d using %s\n",
- X lines, msgnum, pager);
- X
- X ClearScreen();
- X
- X if (cursor_control) transmit_functions(OFF);
- X
- X pipe_abort = FALSE;
- X
- X builtin = (strcmp(pager, "builtin") == 0 ||
- X strcmp(pager,"internal") == 0);
- X
- X if (form_letter = (header_table[msgnum-1].status&FORM_LETTER)) {
- X if (filter)
- X form_letter_section = 1; /* initialize to section 1 */
- X }
- X
- X if (builtin)
- X start_builtin(lines);
- X else {
- X if ((output_pipe = popen(pager,"w")) == NULL) {
- X error2("Can't create pipe to %s [%s]", pager,
- X error_name(errno));
- X dprint2(1,"\n*** Can't create pipe to %s - error %s ***\n\n",
- X pager, error_name(errno));
- X return(0);
- X }
- X dprint1(4,"Opened a write-only pipe to routine %s \n", pager);
- X }
- X
- X if (title_messages) {
- X
- X mail_sent = (strncmp(header_table[msgnum-1].from, "To:", 3) == 0);
- X
- X tail_of(header_table[msgnum-1].from, from_buffer, FALSE);
- X
- X sprintf(buffer, "\r%s #%d %s %s%s\t %s %s %s, %d at %s%s\n\r",
- X form_letter? "Form": "Message",
- X msgnum, mail_sent? "to" : "from", from_buffer,
- X (strlen(from_buffer) > 24? "\n\r":
- X (strlen(from_buffer) > 16 ? "" : "\t")),
- X "Mailed",
- X full_month(header_table[msgnum-1].month),
- X header_table[msgnum-1].day,
- X atoi(header_table[msgnum-1].year) + 1900,
- X header_table[msgnum-1].time,
- X filter? "": "\n\r\n\r");
- X
- X if (builtin)
- X display_line(buffer);
- X else
- X fprintf(output_pipe, "%s", buffer);
- X
- X if (! mail_sent && matches_weedlist("To:") && filter &&
- X strcmp(header_table[current-1].to,username) != 0 &&
- X strlen(header_table[current-1].to) > 0) {
- X sprintf(buffer, "\n\r(message addressed to %s)\n\r",
- X header_table[current-1].to);
- X if (builtin)
- X display_line(buffer);
- X else
- X fprintf(output_pipe, "%s", buffer);
- X }
- X
- X /** The test above is: if we didn't originally send the mail
- X (e.g. we're not reading "mail.sent") AND the user is currently
- X weeding out the "To:" line (otherwise they'll get it twice!)
- X AND the user is actually weeding out headers AND the message
- X wasn't addressed to the user AND the 'to' address is non-zero
- X (consider what happens when the message doesn't HAVE a "To:"
- X line...the value is NULL but it doesn't match the username
- X either. We don't want to display something ugly like
- X "(message addressed to )" which will just clutter up the
- X display!).
- X
- X And you thought programming was EASY!!!!
- X **/
- X }
- X
- X weed_header = filter; /* allow us to change it after header */
- X
- X while (lines > 0 && pipe_abort == FALSE) {
- X
- X if (fgets(buffer, VERY_LONG_STRING, mailfile) == NULL) {
- X if (lines_displayed == 0) {
- X
- X /* AUGH! Why do we get this occasionally??? */
- X
- X dprint0(1,
- X "\n\n** Out of Sync!! EOF with nothing read (display) **\n");
- X dprint0(1,"** closing and reopening mailfile... **\n\n");
- X
- X if (!builtin) pclose(output_pipe); /* close pipe NOW! */
- X
- X if (mailfile != NULL)
- X fclose(mailfile); /* huh? */
- X
- X if ((mailfile = fopen(infile, "r")) == NULL) {
- X error("Sync error: can't re-open mailbox!!");
- X show_mailfile_stats();
- X emergency_exit();
- X }
- X return(show_message(lines,
- X header_table[msgnum-1].offset,
- X msgnum));
- X }
- X if (!builtin)
- X pclose(output_pipe);
- X if (lines == 0 && pipe_abort == FALSE) { /* displayed it all */
- X if (!builtin)
- X PutLine0(LINES,0,"\rPress <return> to return to Elm: ");
- X else
- X printf("\n\r\n\rPress <return> to return to Elm: ");
- X fflush(stdout);
- X Raw(ON);
- X (void) ReadCh();
- X Raw(OFF);
- X }
- X return(TRUE);
- X }
- X
- X if (strlen(buffer) > 0)
- X no_ret(buffer);
- X
- X if (strlen(buffer) == 0) {
- X weed_header = 0; /* past header! */
- X weeding_out = 0;
- X }
- X
- X lines--;
- X lines_displayed++;
- X
- X if (form_letter && weed_header)
- X /* skip it. NEVER display random headers in forms! */;
- X else if (weed_header && matches_weedlist(buffer))
- X weeding_out = 1; /* aha! We don't want to see this! */
- X else if (buffer[0] == '[') {
- X if (strcmp(buffer, START_ENCODE)==0)
- X crypted++;
- X else if (strcmp(buffer, END_ENCODE)==0)
- X crypted--;
- X else if (crypted) {
- X encode(buffer);
- X show_line(buffer, builtin);
- X }
- X else
- X show_line(buffer, builtin);
- X }
- X else if (crypted) {
- X if (! gotten_key++) getkey(OFF);
- X encode(buffer);
- X show_line(buffer, builtin);
- X }
- X else if (weeding_out) {
- X weeding_out = (whitespace(buffer[0])); /* 'n' line weed */
- X if (! weeding_out) /* just turned on! */
- X show_line(buffer, builtin);
- X }
- X else if (form_letter && first_word(buffer,"***") && filter) {
- X strcpy(buffer,
- X"\n------------------------------------------------------------------------------\n");
- X show_line(buffer, builtin); /* hide '***' */
- X form_letter_section++;
- X }
- X else if (form_letter_section == 1 || form_letter_section == 3)
- X /** skip this stuff - we can't deal with it... **/;
- X else
- X show_line(buffer, builtin);
- X }
- X
- X if (cursor_control) transmit_functions(ON);
- X
- X if (! builtin) pclose(output_pipe);
- X
- X if (lines == 0 && pipe_abort == FALSE) { /* displayed it all! */
- X if (! builtin)
- X PutLine0(LINES,0,"\rPress <return> to return to Elm: ");
- X else
- X printf("\n\r\n\rPress <return> to return to Elm: ");
- X fflush(stdout);
- X Raw(ON);
- X (void) ReadCh();
- X Raw(OFF);
- X }
- X return(TRUE);
- X}
- X
- Xshow_line(buffer, builtin)
- Xchar *buffer;
- Xint builtin;
- X{
- X /** Hands the given line to the output pipe. 'builtin' is true if
- X we're using the builtin pager. **/
- X
- X if (builtin) {
- X strcat(buffer, "\n\r");
- X pipe_abort = display_line(buffer);
- X }
- X else {
- X errno = 0;
- X fprintf(output_pipe, "%s\n", buffer);
- X
- X if (errno != 0)
- X dprint1(1,"\terror %s hit!\n", error_name(errno));
- X }
- X}
- X
- Xint
- Xsecure_display(lines, msgnumber)
- Xint lines, msgnumber;
- X{
- X /** This is the cheap way to implement secure pipes - spawn a
- X child process running under the old userid, then open the
- X pager and feed the message to it. When the subprocess ends
- X (the routine returns) simply return. Simple and effective.
- X (too bad it's this much of a hassle to implement secure
- X pipes, though - I can imagine it being a constant problem!)
- X **/
- X
- X int pid, w;
- X#ifdef BSD
- X union wait status;
- X#else
- X int status;
- X#endif
- X register int (*istat)(), (*qstat)();
- X
- X#ifdef NO_VM /* machine without virtual memory! */
- X if ((pid = fork()) == 0) {
- X#else
- X if ((pid = vfork()) == 0) {
- X#endif
- X
- X setgid(groupid); /* and group id */
- X setuid(userid); /* back to the normal user! */
- X
- X _exit(display(lines, msgnumber));
- X }
- X
- X istat = signal(SIGINT, SIG_IGN);
- X qstat = signal(SIGQUIT, SIG_IGN);
- X
- X while ((w = wait(&status)) != pid && w != -1)
- X ;
- X
- X signal(SIGINT, istat);
- X signal(SIGQUIT, qstat);
- X
- X#ifdef BSD
- X return(status.w_retcode);
- X#else
- X return(status);
- X#endif
- X}
- END_OF_src/showmsg.c
- if test 10629 -ne `wc -c <src/showmsg.c`; then
- echo shar: \"src/showmsg.c\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"src/strings.c\" \(11005 characters\)
- if test -f src/strings.c ; then
- echo shar: Will not over-write existing file \"src/strings.c\"
- else
- sed "s/^X//" >src/strings.c <<'END_OF_src/strings.c'
- X/** strings.c **/
- X
- X/** This file contains all the string oriented functions for the
- X ELM Mailer, and lots of other generally useful string functions!
- X
- X For BSD systems, this file also includes the function "tolower"
- X to translate the given character from upper case to lower case.
- X
- X (C) Copyright 1985, Dave Taylor
- X**/
- X
- X#include <stdio.h>
- X#include "headers.h"
- X#include <ctype.h>
- X
- X#ifdef BSD
- X#undef tolower
- X#undef toupper
- X#endif
- X
- X/** forward declarations **/
- X
- Xchar *format_long(), *strip_commas(), *tail_of_string(), *shift_lower(),
- X *get_token(), *strip_parens(), *argv_zero(), *strcpy(), *strncpy();
- X
- X#ifdef BSD
- X
- Xint
- Xtolower(ch)
- Xchar ch;
- X{
- X /** This should be a macro call, but if you use this as a macro
- X calls to 'tolower' where the argument is a function call will
- X cause the function to be called TWICE which is obviously the
- X wrong behaviour. On the other hand, to just blindly translate
- X assuming the character is always uppercase can cause BIG
- X problems, so...
- X **/
- X
- X return ( isupper(ch) ? ch - 'A' + 'a' : ch );
- X}
- X
- Xint
- Xtoupper(ch)
- Xchar ch;
- X{
- X /** see comment for above routine - tolower() **/
- X
- X return ( islower(ch) ? ch - 'a' + 'A' : ch );
- X}
- X
- X#endif
- X
- Xint
- Xprintable_chars(string)
- Xchar *string;
- X{
- X /** Returns the number of "printable" (ie non-control) characters
- X in the given string... Modified 4/86 to know about TAB
- X characters being every eight characters... **/
- X
- X register int count = 0, index;
- X
- X for (index = 0; index < strlen(string); index++)
- X if (string[index] >= ' ')
- X if (string[index] == '\t')
- X count += (7-(count % 8));
- X else
- X count++;
- X
- X return(count);
- X}
- X
- Xtail_of(from, buffer, header_line)
- Xchar *from, *buffer;
- Xint header_line;
- X{
- X /** Return last two words of 'from'. This is to allow
- X painless display of long return addresses as simply the
- X machine!username. Alternatively, if the first three
- X characters of the 'from' address are 'To:' and 'header_line'
- X is TRUE, then return the buffer value prepended with 'To '.
- X
- X Mangled to know about the PREFER_UUCP hack. 6/86
- X **/
- X
- X /** Note: '!' delimits Usenet nodes, '@' delimits ARPA nodes,
- X ':' delimits CSNet & Bitnet nodes, and '%' delimits
- X multiple stage ARPA hops... **/
- X
- X register int loc, i = 0, cnt = 0;
- X char tempbuffer[SLEN];
- X
- X#ifdef PREFER_UUCP
- X
- X /** let's see if we have an address appropriate for hacking **/
- X
- X if (chloc(from,'!') != -1 && in_string(from, BOGUS_INTERNET))
- X from[strlen(from)-strlen(BOGUS_INTERNET)] = '\0';
- X
- X#endif
- X
- X for (loc = strlen(from)-1; loc >= 0 && cnt < 2; loc--) {
- X if (from[loc] == BANG || from[loc] == AT_SIGN ||
- X from[loc] == COLON) cnt++;
- X if (cnt < 2) buffer[i++] = from[loc];
- X }
- X
- X buffer[i] = '\0';
- X
- X reverse(buffer);
- X
- X if ((strncmp(buffer,"To:", 3) == 0) && header_line)
- X buffer[2] = ' ';
- X else if ((strncmp(from, "To:", 3) == 0) && header_line) {
- X sprintf(tempbuffer,"To %s", buffer);
- X strcpy(buffer, tempbuffer);
- X }
- X else if (strncmp(buffer, "To:", 3) == 0) {
- X for (i=3; i < strlen(buffer); i++)
- X tempbuffer[i-3] = buffer[i];
- X tempbuffer[i-3] = '\0';
- X strcpy(buffer, tempbuffer);
- X }
- X}
- X
- Xchar *format_long(inbuff, init_len)
- Xchar *inbuff;
- Xint init_len;
- X{
- X /** Return buffer with \n\t sequences added at each point where it
- X would be more than 80 chars long. It only allows the breaks at
- X legal points (ie commas followed by white spaces). init-len is
- X the characters already on the first line... Changed so that if
- X this is called while mailing without the overhead of "elm", it'll
- X include "\r\n\t" instead.
- X Changed to use ',' as a separator and to REPLACE it after it's
- X found in the output stream...
- X **/
- X
- X static char ret_buffer[VERY_LONG_STRING];
- X register int index = 0, current_length = 0, depth=15, i;
- X char buffer[VERY_LONG_STRING];
- X char *word, *bufptr;
- X
- X strcpy(buffer, inbuff);
- X
- X bufptr = (char *) buffer;
- X
- X current_length = init_len + 2; /* for luck */
- X
- X while ((word = get_token(bufptr,",", depth)) != NULL) {
- X
- X /* first, decide what sort of separator we need, if any... */
- X
- X if (strlen(word) + current_length > 80) {
- X if (index > 0) {
- X ret_buffer[index++] = ','; /* close 'er up, doctor! */
- X if (mail_only)
- X ret_buffer[index++] = '\r';
- X ret_buffer[index++] = '\n';
- X ret_buffer[index++] = '\t';
- X }
- X
- X /* now add this pup! */
- X
- X for (i=(word[0] == ' '? 1:0); i<strlen(word); i++)
- X ret_buffer[index++] = word[i];
- X current_length = strlen(word) + 8; /* 8 = TAB */
- X }
- X
- X else { /* just add this address to the list.. */
- X
- X if (index > 0) {
- X ret_buffer[index++] = ','; /* comma added! */
- X ret_buffer[index++] = ' ';
- X current_length += 2;
- X }
- X for (i=(word[0] == ' '? 1:0); i<strlen(word); i++)
- X ret_buffer[index++] = word[i];
- X current_length += strlen(word);
- X }
- X
- X bufptr = NULL;
- X }
- X
- X ret_buffer[index] = '\0';
- X
- X return( (char *) ret_buffer);
- X}
- X
- Xchar *strip_commas(string)
- Xchar *string;
- X{
- X /** return string with all commas changed to spaces. This IS
- X destructive and will permanently change the input string.. **/
- X
- X register int i;
- X
- X for (i=0; i < strlen(string); i++)
- X if (string[i] == COMMA)
- X string[i] = SPACE;
- X
- X return( (char *) string);
- X}
- X
- Xchar *strip_parens(string)
- Xchar *string;
- X{
- X /** Return string with all parenthesized information removed.
- X This is a non-destructive algorithm... **/
- X
- X static char buffer[VERY_LONG_STRING];
- X register int i, depth = 0, buffer_index = 0;
- X
- X for (i=0; i < strlen(string); i++) {
- X if (string[i] == '(')
- X depth++;
- X else if (string[i] == ')')
- X depth--;
- X else if (depth == 0)
- X buffer[buffer_index++] = string[i];
- X }
- X
- X buffer[buffer_index] = '\0';
- X
- X return( (char *) buffer);
- X}
- X
- Xmove_left(string, chars)
- Xchar string[];
- Xint chars;
- X{
- X /** moves string chars characters to the left DESTRUCTIVELY **/
- X
- X register int i;
- X
- X chars--; /* index starting at zero! */
- X
- X for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
- X string[i-chars] = string[i];
- X
- X string[i-chars] = '\0';
- X}
- X
- Xremove_first_word(string)
- Xchar *string;
- X{ /** removes first word of string, ie up to first non-white space
- X following a white space! **/
- X
- X register int loc;
- X
- X for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++)
- X ;
- X
- X while (string[loc] == ' ' || string[loc] == '\t')
- X loc++;
- X
- X move_left(string, ++loc);
- X}
- X
- Xsplit_word(buffer, first, rest)
- Xchar *buffer, *first, *rest;
- X{
- X /** Rip the buffer into first word and rest of word, translating it
- X all to lower case as we go along..
- X **/
- X
- X register int i, j = 0;
- X
- X /** skip leading white space, just in case.. **/
- X
- X for (i=0; whitespace(buffer[i]); i++) ;
- X
- X /** now copy into 'first' until we hit white space or EOLN **/
- X
- X for (j=0; i < strlen(buffer) && ! whitespace(buffer[i]); )
- X first[j++] = tolower(buffer[i++]);
- X
- X first[j] = '\0';
- X
- X while (whitespace(buffer[i])) i++;
- X
- X for (j=0; i < strlen(buffer); i++)
- X rest[j++] = tolower(buffer[i]);
- X
- X rest[j] = '\0';
- X
- X return;
- X}
- X
- Xchar *tail_of_string(string, maxchars)
- Xchar *string;
- Xint maxchars;
- X{
- X /** Return a string that is the last 'maxchars' characters of the
- X given string. This is only used if the first word of the string
- X is longer than maxchars, else it will return what is given to
- X it...
- X **/
- X
- X static char buffer[SLEN];
- X register int index, i;
- X
- X for (index=0;! whitespace(string[index]) && index < strlen(string);
- X index++)
- X ;
- X
- X if (index < maxchars) {
- X strncpy(buffer, string, maxchars-2); /* word too short */
- X buffer[maxchars-2] = '.';
- X buffer[maxchars-1] = '.';
- X buffer[maxchars] = '.';
- X buffer[maxchars+1] = '\0';
- X }
- X else {
- X i = maxchars;
- X buffer[i--] = '\0';
- X while (i > 1)
- X buffer[i--] = string[index--];
- X buffer[2] = '.';
- X buffer[1] = '.';
- X buffer[0] = '.';
- X }
- X
- X return( (char *) buffer);
- X}
- X
- Xreverse(string)
- Xchar *string;
- X{
- X /** reverse string... pretty trivial routine, actually! **/
- X
- X char buffer[SLEN];
- X register int i, j = 0;
- X
- X for (i = strlen(string)-1; i >= 0; i--)
- X buffer[j++] = string[i];
- X
- X buffer[j] = '\0';
- X
- X strcpy(string, buffer);
- X}
- X
- Xint
- Xget_word(buffer, start, word)
- Xchar *buffer, *word;
- Xint start;
- X{
- X /** return next word in buffer, starting at 'start'.
- X delimiter is space or end-of-line. Returns the
- X location of the next word, or -1 if returning
- X the last word in the buffer. -2 indicates empty
- X buffer! **/
- X
- X register int loc = 0;
- X
- X while (buffer[start] == ' ' && buffer[start] != '\0')
- X start++;
- X
- X if (buffer[start] == '\0') return(-2); /* nothing IN buffer! */
- X
- X while (buffer[start] != ' ' && buffer[start] != '\0')
- X word[loc++] = buffer[start++];
- X
- X word[loc] = '\0';
- X return(start);
- X}
- X
- Xchar *shift_lower(string)
- Xchar *string;
- X{
- X /** return 'string' shifted to lower case. Do NOT touch the
- X actual string handed to us! **/
- X
- X static char buffer[LONG_SLEN];
- X register int i;
- X
- X for (i=0; i < strlen(string); i++)
- X if (isupper(string[i]))
- X buffer[i] = tolower(string[i]);
- X else
- X buffer[i] = string[i];
- X
- X buffer[strlen(string)] = 0;
- X
- X return( (char *) buffer);
- X}
- X
- XCenterline(line, string)
- Xint line;
- Xchar *string;
- X{
- X /** Output 'string' on the given line, centered. **/
- X
- X register int length, col;
- X
- X length = strlen(string);
- X
- X if (length > COLUMNS)
- X col = 0;
- X else
- X col = (COLUMNS - length) / 2;
- X
- X PutLine0(line, col, string);
- X}
- X
- Xchar *argv_zero(string)
- Xchar *string;
- X{
- X /** given a string of the form "/something/name" return a
- X string of the form "name"... **/
- X
- X static char buffer[NLEN];
- X register int i, j=0;
- X
- X for (i=strlen(string)-1; string[i] != '/'; i--)
- X buffer[j++] = string[i];
- X buffer[j] = '\0';
- X
- X reverse(buffer);
- X
- X return( (char *) buffer);
- X}
- X
- X#define MAX_RECURSION 20 /* up to 20 deep recursion */
- X
- Xchar *get_token(source, keys, depth)
- Xchar *source, *keys;
- Xint depth;
- X{
- X /** This function is similar to strtok() (see "opt_utils")
- X but allows nesting of calls via pointers...
- X **/
- X
- X register int last_ch;
- X static char *buffers[MAX_RECURSION];
- X char *return_value, *sourceptr;
- X
- X if (depth > MAX_RECURSION) {
- X error1("get_token calls nested greater than %d deep!",
- X MAX_RECURSION);
- X emergency_exit();
- X }
- X
- X if (source != NULL)
- X buffers[depth] = source;
- X
- X sourceptr = buffers[depth];
- X
- X if (*sourceptr == '\0')
- X return(NULL); /* we hit end-of-string last time!? */
- X
- X sourceptr += strspn(sourceptr, keys); /* skip the bad.. */
- X
- X if (*sourceptr == '\0') {
- X buffers[depth] = sourceptr;
- X return(NULL); /* we've hit end-of-string */
- X }
- X
- X last_ch = strcspn(sourceptr, keys); /* end of good stuff */
- X
- X return_value = sourceptr; /* and get the ret */
- X
- X sourceptr += last_ch; /* ...value */
- X
- X if (*sourceptr != '\0') /** don't forget if we're at end! **/
- X sourceptr++;
- X
- X return_value[last_ch] = '\0'; /* ..ending right */
- X
- X buffers[depth] = sourceptr; /* save this, mate! */
- X
- X return((char *) return_value); /* and we're outta here! */
- X}
- END_OF_src/strings.c
- if test 11005 -ne `wc -c <src/strings.c`; then
- echo shar: \"src/strings.c\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 11 \(of 19\).
- cp /dev/null ark11isdone
- DONE=true
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
- if test ! -f ark${I}isdone ; then
- echo shar: You still need to run archive ${I}.
- DONE=false
- fi
- done
- if test "$DONE" = "true" ; then
- echo You have unpacked all 19 archives.
- echo "See the Instructions file"
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- fi
- ## End of shell archive.
- exit 0
-