From bacchus.pa.dec.com!decwrl!uunet!ogicse!zephyr.ens.tek.com!tekred!saab!billr Tue Jul 31 16:53:36 PDT 1990 Article 1054 of comp.sources.games: Path: bacchus.pa.dec.com!decwrl!uunet!ogicse!zephyr.ens.tek.com!tekred!saab!billr From: billr@saab.CNA.TEK.COM (Bill Randle) Newsgroups: comp.sources.games Subject: v11i017: tinyclients - three clients for tinyMUD, Part03/03 Message-ID: <6066@tekred.CNA.TEK.COM> Date: 31 Jul 90 20:31:37 GMT Sender: news@tekred.CNA.TEK.COM Lines: 1990 Approved: billr@saab.CNA.TEK.COM Submitted-by: James Aspnes Posting-number: Volume 11, Issue 17 Archive-name: tinyclients/Part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'tinytalk/CHANGES' <<'END_OF_FILE' XChanges since TinyTalk 1.0. X--------------------------- X XVersion 1.1.2 release 6/25/90. X X * Bug in /logme corrected. X X * Bug in /recall corrected. X XVersion 1.1.1 release 2/16/90. X X * Support for HP-UX 7.0 and System V integrated. X XVersion 1.1 final release 2/7/90. X X * Portals are quieter when not in auto-login mode. X X * A failed portal connection causes the connection to be ignored, X rather than exiting TinyTalk. X X * Added a word-delete character (default ^W). X X * Added a refresh character (default ^R). X X * Added /QUIT, /INTR, and /NOINTR. These allow ^C to be ignored, X instead of causing TinyTalk to exit, and provide a new command to X exit. The default is to exit on ^C. X X * Added /BEEP and /NOBEEP. These allow pages to be indicated with X an audible beep. The default is to use three beeps. X X * Added /STTY and /NOSTTY. These allow the system's terminal X information to be read for keyboard processing, rather than using X the default characters. The default is to use the old characters. X X * Added /GAG, /NOGAG, /SAVEGAG, /LOADGAG, and /LISTGAG. These allow X the actions of specific characters to be ignored (useful for X silencing noisy robots). X X * Added /HILITE, /NOHILITE, /LOADHILITE, /SAVEHILITE, and /LISTHILITE. X These allow specific characters to be hilited; also, whispers and X pages can be hilited. X X * Added /WHISPER and /NOWHISPER. /NOWHISPER simulates silent whisper. X X * Added /RECALL, to retrieve the last line typed. X X * Added /LISTWORLDS and /WORLD, for moving between worlds. END_OF_FILE if test 1557 -ne `wc -c <'tinytalk/CHANGES'`; then echo shar: \"'tinytalk/CHANGES'\" unpacked with wrong size! fi # end of 'tinytalk/CHANGES' fi if test -f 'tinytalk/Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/Makefile'\" else echo shar: Extracting \"'tinytalk/Makefile'\" \(288 characters\) sed "s/^X//" >'tinytalk/Makefile' <<'END_OF_FILE' XCC = cc XCFLAGS = -DTERMCAP XLIBRARIES = -ltermcap X XOBJECTS = fred.o config.o util.o stuff.o keyboard.o wrap.o log.o macro.o \ X command.o special.o gag.o X Xall: tinytalk X Xtinytalk: $(OBJECTS) X $(CC) $(CFLAGS) -o tinytalk $(OBJECTS) $(LIBRARIES) X Xclean: X rm -f $(OBJECTS) X X$(OBJECTS): tl.h END_OF_FILE if test 288 -ne `wc -c <'tinytalk/Makefile'`; then echo shar: \"'tinytalk/Makefile'\" unpacked with wrong size! fi # end of 'tinytalk/Makefile' fi if test -f 'tinytalk/README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/README'\" else echo shar: Extracting \"'tinytalk/README'\" \(926 characters\) sed "s/^X//" >'tinytalk/README' <<'END_OF_FILE' XHow to install TinyTalk. X------------------------ X X TinyTalk should run on any BSD 4.2 or 4.3-derived system. It should Xcompile without modifications on all of these systems. To build XTinyTalk, just type 'make' in the tinytalk directory. X X Some systems may not have the termcap library available, or may have Xa buggy one. On these systems, you must edit the Makefile first. XRemove the '-DTERMCAP' and '-ltermcap' from the CFLAGS and LIBRARIES Xlines, respectively. X X If all goes well, typing 'make' will leave the executable in the Xfile 'tinytalk'. If you have very limited disk space, typing 'strip Xtinytalk' afterward will remove the symbol table, freeing up some Xspace. X X On HP-UX 7.0 systems, edit the Makefile to add -DHPUX to the CFLAGS Xline, then build as usual. X X On System V systems, edit the Makefile to add -DSYSVTTY to the XCFLAGS line, then build as usual. You may also need to remove the X-DTERMCAP line. END_OF_FILE if test 926 -ne `wc -c <'tinytalk/README'`; then echo shar: \"'tinytalk/README'\" unpacked with wrong size! fi # end of 'tinytalk/README' fi if test -f 'tinytalk/config.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/config.c'\" else echo shar: Extracting \"'tinytalk/config.c'\" \(3729 characters\) sed "s/^X//" >'tinytalk/config.c' <<'END_OF_FILE' X/************************************************************************/ X/* TinyTalk configuration file support. */ X/* */ X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */ X/* 1.1 [ 1/25/90] : Added comments. */ X/* */ X/************************************************************************/ X X#include "tl.h" X#include X Xextern char *malloc(), *getenv(); X Xstatic world_rec *the_worlds, *default_world; X Xint read_configuration() X{ X string config_name; X register FILE *config_file; X X get_file_name(config_name); X config_file = fopen(config_name, "r"); X if (config_file == NULL) { X/* fprintf(stderr, "Couldn't open configuration file %s .\n", config_name); */ X return (1); /* Succeed even so. */ X } X X parse_configuration(config_file); /* Ignore any errors. */ X X fclose(config_file); /* Hope it works.... */ X X return (1); /* Always succeed, this is optional. */ X} X Xget_file_name(s) X register char *s; X{ X register char *env; X X env = getenv("TINYTALK"); /* Check TINYTALK first. */ X if (env != NULL) X strcpy(s, env); X else X strcpy(s, "~/.tinytalk"); X expand_filename(s); X} X Xparse_configuration(f) X FILE *f; X{ X if (parse_worlds(f)) /* Returns 0 at EOF or error */ X parse_commands(f); X} X Xint parse_worlds(f) X FILE *f; X{ X string line; X int done, eof_flag; X X the_worlds = NULL; X default_world = NULL; X done = FALSE; X eof_flag = FALSE; X X while (!done) { X if (fgets(line, MAXSTRLEN, f) == NULL) { X done = TRUE; X eof_flag = TRUE; X continue; X } X X if (line[0] == ';') /* Comment */ X continue; X X line[strlen(line)-1] = '\0'; /* Strip newline */ X X if (line[0] == '\0') { /* Blank line? */ X done = TRUE; X continue; X } X X if (!add_world(line)) X done = TRUE; X } X X return (!eof_flag); X} X Xint add_world(line) /* *** WARNING, LENGTH LIMITED *** */ X char *line; X{ X register world_rec *new; X int count; X X new = (world_rec *) malloc(sizeof(world_rec)); X count = sscanf(line, "%31s %31s %31s %31s %31s", new->world, new->character, X new->pass, new->address, new->port); X if (count == 3) { /* No address info */ X *(new->address) = '\0'; X *(new->port) = '\0'; X goto done; X } X else if (count == 5) { /* All info specified */ X if (!strcmp(new->world, "default")) X fprintf(stderr,"Warning: address for default world ignored"); X goto done; X } X else { X fprintf(stderr,"Could not parse: %s .\n", line); X return (0); X } X Xdone: X X if ((the_worlds == NULL) && (count == 5)) /* Set up default world, */ X default_world = new; /* if first one and all info. */ X X new->next = the_worlds; X the_worlds = new; X X return (1); X} X Xparse_commands(f) X FILE *f; X{ X /* All commands ought to be the same as from the keyboard. */ X /* We hand them over there for processing. */ X X string line; X int done; X X done = FALSE; X X while (!done) { X if (fgets(line, MAXSTRLEN, f) == NULL) { X done = TRUE; X break; X } X X line[strlen(line)-1] = '\0'; /* Strip newline */ X X if ((line[0] == '\0') || (line[0] == ';')) /* Blank line or comment. */ X continue; /* Ignore it. */ X X if (*line != '/') { /* Not a command! */ X fprintf(stderr,"Not a command: %s .\n", line); X continue; X } X X handle_command(line, TRUE); /* Special-case errors since we */ X /* aren't started up yet. */ X } /* Actually, doesn't do anything now. */ X X} X Xworld_rec *get_default_world() X{ X return (default_world); X} X Xworld_rec *find_world(name) X register char *name; X{ X register world_rec *p; X X p = the_worlds; X while ((p != NULL) && !(equalstr(p->world, name))) X p = p->next; X X return(p); X} X Xworld_rec *get_world_header() X{ X return (the_worlds); X} END_OF_FILE if test 3729 -ne `wc -c <'tinytalk/config.c'`; then echo shar: \"'tinytalk/config.c'\" unpacked with wrong size! fi # end of 'tinytalk/config.c' fi if test -f 'tinytalk/gag.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/gag.c'\" else echo shar: Extracting \"'tinytalk/gag.c'\" \(6980 characters\) sed "s/^X//" >'tinytalk/gag.c' <<'END_OF_FILE' X/************************************************************************/ X/* TinyTalk output special processing: gags and hiliting. */ X/* */ X/* Version 1.0 [ 2/ 2/90] : Created by ABR. */ X/* 1.1 [ 2/ 5/90] : Added whisper gagging. */ X/* 1.2 [ 2/ 5/90] : Minor changes to fix file problems. */ X/* */ X/************************************************************************/ X X#include "tl.h" X#include X Xextern char *index(), *malloc(); X Xtypedef struct gag_hilite_entry { X struct gag_hilite_entry *next, *prev; X smallstr person; X} gag_hilite_entry; X Xgag_hilite_entry *find_person(); X Xstatic int hilite_pages, hilite_whispers, hilite_other; Xstatic int gag_enabled, gag_whispers; Xstatic gag_hilite_entry *gag_list, *hilite_list; X Xinit_hiliting() X{ X init_hilite_utils(); X hilite_pages = FALSE; X hilite_whispers = FALSE; X hilite_other = TRUE; X hilite_list = NULL; X} X Xinit_gagging() X{ X gag_whispers = FALSE; X gag_enabled = TRUE; X gag_list = NULL; X} X Xint is_gagged(what, name) X char *what, *name; X{ X register char *place; X X if (!gag_enabled) X return (0); X X if (find_person(gag_list, name) != NULL) { /* Are they gagged? */ X /* Don't gag kills, arrivals, or */ X /* departures. */ X X place = index(what, ' '); X if (place != NULL) { X if (!strcmp(place+1, "has arrived.")) X return (0); X if (!strcmp(place+1, "has left.")) X return (0); X if (!strcmp(place+1, "killed you!")) X return (0); X if (!strcmp(place+1, "tried to kill you!")) X return (0); X } X return (1); X } X else X return (0); X} X Xint should_hilite(what, name) X char *what, *name; X{ X if (hilite_whispers && is_my_whisper(what)) X return (1); X X if (!hilite_other) X return (0); X X if (find_person(hilite_list, name) != NULL) /* Are they marked for hilite? */ X return (1); X else X return (0); X} X Xint is_my_whisper(s) /* Check if a string is a whisper. */ X char *s; /* This is a 'whisper-to-me' type. */ X{ X register char *p; X X p = index(s, ' '); X if (p == NULL) /* Whispers always have spaces. */ X return (0); X X if (strncmp(p+1, "whispers", 8)) /* They always have this. */ X return (0); X X if (s[strlen(s)-1] == '"') /* They always end with a quote. */ X return (1); X else X return (0); X} X Xint is_other_whisper(s) /* Check if a string is a whisper. */ X char *s; /* This is a 'whisper-to-other'. */ X{ X register char *p; X X if (!gag_whispers) /* Not gagging whispers, ignore. */ X return (0); X X p = index(s, ' '); X if (p == NULL) /* Whispers always have spaces. */ X return (0); X X if (strncmp(p+1, "whispers something to ", 22)) /* They always have this. */ X return (0); X X if (s[strlen(s)-1] == '.') /* They always end with a quote. */ X return (1); X else X return (0); X} X Xint should_hilite_pages() X{ X return (hilite_pages); X} X Xenable_hiliting() X{ X hilite_other = TRUE; X} X Xdisable_hiliting() X{ X hilite_other = FALSE; X} X Xenable_page_hiliting() X{ X hilite_pages = TRUE; X} X Xdisable_page_hiliting() X{ X hilite_pages = FALSE; X} X Xenable_whisper_hiliting() X{ X hilite_whispers = TRUE; X} X Xdisable_whisper_hiliting() X{ X hilite_whispers = FALSE; X} X Xenable_gagging() X{ X gag_enabled = TRUE; X} X Xdisable_gagging() X{ X gag_enabled = FALSE; X} X Xenable_whisper_gagging() X{ X gag_whispers = TRUE; X} X Xdisable_whisper_gagging() X{ X gag_whispers = FALSE; X} X Xadd_hilite(who) X char *who; X{ X add_person(&hilite_list, who); X} X Xremove_hilite(who) X char *who; X{ X remove_person(&hilite_list, who); X} X Xlist_hilite() X{ X list_people(hilite_list); X if (hilite_other) X puts("% ** Hiliting is enabled."); X else X puts("% ** Hiliting is disabled."); X if (hilite_pages) X puts("% ** Hiliting of pages is enabled."); X else X puts("% ** Hiliting of pages is disabled."); X if (hilite_whispers) X puts("% ** Hiliting of whispers is enabled."); X else X puts("% ** Hiliting of whispers is disabled."); X} X Xsave_hilite(name) X char *name; X{ X save_people("/hilite ", hilite_list, name, "~/tiny.hilite", TRUE); X} X Xadd_gag(who) X char *who; X{ X add_person(&gag_list, who); X} X Xremove_gag(who) X char *who; X{ X remove_person(&gag_list, who); X} X Xlist_gag() X{ X list_people(gag_list); X if (gag_enabled) X puts("% ** Gagging is enabled."); X else X puts("% ** Gagging is disabled."); X} X Xsave_gag(name) X char *name; X{ X save_people("/gag ", gag_list, name, "~/tiny.gag", FALSE); X} X Xadd_person(list, name) X gag_hilite_entry **list; X register char *name; X{ X register gag_hilite_entry *new; X X if (strlen(name) > SMALLSTR) /* Silently truncate long names */ X name[SMALLSTR] = '\0'; X X if (find_person(*list, name) != NULL) /* Already there, just leave 'em. */ X return; X X new = (gag_hilite_entry *) malloc(sizeof(struct gag_hilite_entry)); X new->prev = NULL; /* Add at front of list */ X new->next = *list; X if (new->next != NULL) /* If not at tail of list, */ X new->next->prev = new; /* Set up backlink. */ X *list = new; X X strcpy(new->person, name); X} X Xremove_person(list, name) X gag_hilite_entry **list; X register char *name; X{ X register gag_hilite_entry *where; X X if (strlen(name) > SMALLSTR) /* Silently truncate long names */ X name[SMALLSTR] = '\0'; X X where = find_person(*list, name); X if (where == NULL) { X fprintf(stderr, "%% Person %s was not in the list.\n", name); X return; X } X X if (where->prev == NULL) /* Unlink from head */ X *list = where->next; X else X where->prev->next = where->next; X X if (where->next != NULL) /* If not at end, fix back link */ X where->next->prev = where->prev; X X free(where); /* Free allocated storage. */ X} X Xgag_hilite_entry *find_person(list, name) X gag_hilite_entry *list; X register char *name; X{ X register gag_hilite_entry *where; X X where = list; X while ((where != NULL) && (!equalstr(where->person, name))) X where = where->next; X X return (where); X} X Xlist_people(list) X gag_hilite_entry *list; X{ X register gag_hilite_entry *where; X X where = list; X while (where != NULL) { X printf("%% %s\n", where->person); X where = where->next; X } X} X Xsave_people(cmd, list, name, def, hilite_info) /* Write people to a file. */ X char *cmd; X gag_hilite_entry *list; X char *name, *def; X int hilite_info; X{ X register FILE *the_file; X register gag_hilite_entry *where; X X if (name[0] == '\0') /* Set default name if none given. */ X strcpy(name, def); X X expand_filename(name); X the_file = fopen(name, "w"); /* Open file */ X if (the_file == NULL) { X fprintf(stderr,"%% Could not write to %s .\n", name); X return; X } X X if (hilite_info) { X fputs((hilite_pages ? "/hilite pages\n" : "/hilite nopages\n"), the_file); X fputs((hilite_whispers ? "/hilite whispers\n" : "/hilite nowhispers\n"), X the_file); X fputc('\n', the_file); X }; X X where = list; X while (where != NULL) { /* Scan linked list, outputting */ X fputs(cmd, the_file); /* a command per person. */ X fputs(where->person, the_file); X fputc('\n', the_file); X where = where->next; X } X X fclose(the_file); X} END_OF_FILE if test 6980 -ne `wc -c <'tinytalk/gag.c'`; then echo shar: \"'tinytalk/gag.c'\" unpacked with wrong size! fi # end of 'tinytalk/gag.c' fi if test -f 'tinytalk/log.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/log.c'\" else echo shar: Extracting \"'tinytalk/log.c'\" \(1823 characters\) sed "s/^X//" >'tinytalk/log.c' <<'END_OF_FILE' X/************************************************************************/ X/* TinyTalk logging. */ X/* */ X/* Version 1.0 [ 1/25/90] : Initial implementation by ABR. */ X/* 1.1 [ 2/ 5/90] : Added explicit file flushing. */ X/* */ X/************************************************************************/ X X#include "tl.h" X#include X Xstatic FILE *log_file; Xstatic string log_file_name; Xstatic int log_on, log_me; X Xinit_logging() X{ X strcpy(log_file_name, "~/tiny.log"); /* In home directory. */ X expand_filename(log_file_name); X log_on = 0; /* Don't log output */ X log_me = 0; /* Don't log input either */ X log_file = NULL; /* No log file is open. */ X} X Xenable_logging(name) /* Enable logging. Null name means */ X char *name; /* use current default. */ X{ X if (*name != '\0') { X strcpy(log_file_name, name); X expand_filename(log_file_name); X } X X if (log_file != NULL) /* Close current log file */ X fclose(log_file); X X log_file = fopen(log_file_name, "a"); /* Append to log file */ X log_on = TRUE; X if (log_file == NULL) { X fprintf(stderr,"%% Could not open log file %s.\n", log_file_name); X log_on = FALSE; X } X} X Xdisable_logging() X{ X log_on = FALSE; /* Turn off logging */ X if (log_file != NULL) { /* Close file if open */ X fclose(log_file); X log_file = NULL; X } X} X Xflush_logfile() /* Flush log file to disk. */ X{ X if (log_file != NULL) X fflush(log_file); X} X Xenable_logme() X{ X log_me = TRUE; X} X Xdisable_logme() X{ X log_me = FALSE; X} X Xlog_output(s) /* From server */ X char *s; X{ X if (log_on && (log_file != NULL)) { X fputs(s, log_file); X fputc('\n', log_file); X } X} X Xlog_input(s) /* From keyboard */ X char *s; X{ X if (log_on && log_me && (log_file != NULL)) { X fputs(s, log_file); X fputc('\n', log_file); X } X} END_OF_FILE if test 1823 -ne `wc -c <'tinytalk/log.c'`; then echo shar: \"'tinytalk/log.c'\" unpacked with wrong size! fi # end of 'tinytalk/log.c' fi if test -f 'tinytalk/macro.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/macro.c'\" else echo shar: Extracting \"'tinytalk/macro.c'\" \(5010 characters\) sed "s/^X//" >'tinytalk/macro.c' <<'END_OF_FILE' X/************************************************************************/ X/* TinyTalk macro handling. */ X/* */ X/* Version 1.0 [ 1/25/90] : Initial implementation by ABR. */ X/* 1.1 [ 1/26/90] : Added support for listing macros. */ X/* 1.2 [ 1/27/90] : Fixed bug in add_macro. */ X/* 1.3 [ 2/ 5/90] : Fixed error message in remove_macro. */ X/* */ X/************************************************************************/ X X#include "tl.h" X#include X X#define MAX_ARGS 4 /* Watch out in process_macro */ X /* if you change this. */ X X#define NAME_LEN 31 /* Size of a macro's name */ Xtypedef char namestr[NAME_LEN+1]; /* Also max arg size; if changed, */ X /* look at process_macro. */ X Xtypedef struct macro { X struct macro *next, *prev; /* Linked list of macros */ X namestr the_name; X char *the_body; /* Dynamically allocated */ X} macro; X Xextern char *malloc(); X Xmacro *find_macro(); X Xstatic macro *header; X Xinit_macros() X{ X header = NULL; X} X Xadd_macro(name, body) X register char *name; X char *body; X{ X register macro *new; X X if (strlen(name) > NAME_LEN) /* Silently truncate long names */ X name[NAME_LEN] = '\0'; X X if (find_macro(name) != NULL) { X fprintf(stderr, "%% Macro %s is already defined.\n", name); X return; X } X X new = (macro *) malloc(sizeof(struct macro)); /* Allocate space */ X new->prev = NULL; /* Add at front of list */ X new->next = header; X if (new->next != NULL) /* If not at tail of list, */ X new->next->prev = new; /* Set up backlink. */ X header = new; X X strcpy(new->the_name, name); X new->the_body = malloc(strlen(body) + 1); X strcpy(new->the_body, body); X} X Xremove_macro(name) /* Undefine a macro */ X register char *name; X{ X register macro *where; X X if (strlen(name) > NAME_LEN) /* Silently truncate long names */ X name[NAME_LEN] = '\0'; X X where = find_macro(name); X if (where == NULL) { X fprintf(stderr, "%% Macro %s was not defined.\n", name); X return; X } X X if (where->prev == NULL) /* Unlink from head */ X header = where->next; X else X where->prev->next = where->next; X X if (where->next != NULL) /* If not at end, fix back link */ X where->next->prev = where->prev; X X free(where->the_body); /* Free allocated storage. */ X free(where); X} X Xwrite_macros(name) /* Write macros to a file. */ X char *name; X{ X register FILE *macro_file; X register macro *where; X X expand_filename(name); X macro_file = fopen(name, "w"); /* Open file */ X if (macro_file == NULL) { X fprintf(stderr,"%% Could not write macros to %s .\n", name); X return; X } X X where = header; X while (where != NULL) { /* Scan linked list, outputting */ X fputs("/def ", macro_file); /* the macros. */ X fputs(where->the_name, macro_file); X fputs(" = ", macro_file); X fputs(where->the_body, macro_file); X fputc('\n', macro_file); X where = where->next; X } X X fclose(macro_file); X} X Xprocess_macro(name, args, deststr) /* Process a macro invocation. */ X char *name, *args, *deststr; /* Warning: no length checking! */ X{ X register macro *where; X register char *source, *dest, ch; X namestr arg_ary[MAX_ARGS]; X int i; X X if (strlen(name) > NAME_LEN) /* Silently truncate long names */ X name[NAME_LEN] = '\0'; X X where = find_macro(name); X if (where == NULL) { X fprintf(stderr,"%% Macro %s is not defined.\n", name); X deststr[0] = '\0'; X return; X } X X for (i=0; ithe_body; /* Start copying macro text. */ X dest = deststr; X X while (*source != '\0') { X if (*source != '%') /* If not special char, just copy. */ X *dest++ = *source++; X else { /* Look at next char. */ X source++; X ch = *source; X X if ((ch == '\\') || (ch == ';')) { /* Backslash or ";" ==> newline. */ X *dest++ = '\n'; X source++; X } X else if (ch == '%') { /* Double % ==> single %. */ X *dest++ = '%'; X source++; X } X else if (ch == '*') { /* Entire command line. */ X strcpy(dest, args); X dest += strlen(args); X source++; X } X else if ((ch >= '1') && (ch <= '4')) { /* Argument insertion. */ X strcpy(dest, arg_ary[ch - '1']); X dest += strlen(arg_ary[ch - '1']); X source++; X } X else { /* Don't know what it was. Guess %. */ X *dest++ = '%'; /* Don't advance source here. */ X } X } X } X X *dest++ = '\n'; /* Add a newline. */ X *dest = '\0'; /* Terminate the expansion. */ X} X Xmacro *find_macro(name) X register char *name; X{ X register macro *where; X X where = header; X while ((where != NULL) && (!equalstr(where->the_name, name))) X where = where->next; X X return (where); X} X Xlist_all_macros(full) X int full; X{ X register macro *where; X X where = header; X while (where != NULL) { X if (full) X printf("%% %s = %s\n", where->the_name, where->the_body); X else X printf("%% %s\n", where->the_name); X where = where->next; X } X} END_OF_FILE if test 5010 -ne `wc -c <'tinytalk/macro.c'`; then echo shar: \"'tinytalk/macro.c'\" unpacked with wrong size! fi # end of 'tinytalk/macro.c' fi if test -f 'tinytalk/special.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/special.c'\" else echo shar: Extracting \"'tinytalk/special.c'\" \(4393 characters\) sed "s/^X//" >'tinytalk/special.c' <<'END_OF_FILE' X/************************************************************************/ X/* TinyTalk output special processing. */ X/* */ X/* Version 1.0 [ 2/ 2/90] : Extracted from main loop module; added */ X/* new features for release 1.1. */ X/* */ X/************************************************************************/ X X#include "tl.h" X#include X Xextern char *index(); Xextern world_rec *find_world(); X X#define MAX_QUIET 25 /* Max lines to quiet during login. */ X#define MAX_BEEPS 5 /* Be reasonable! Note--you must */ X /* change do_beep() if this is */ X /* increased. */ X Xstatic int quiet_mode; /* Suppress login messages? */ Xstatic int quiet_waiting; /* Are we in a login process? */ Xstatic int quiet_counter; /* So quietness eventually goes off. */ X Xstatic int beep_count; /* How many times should we beep? */ X Xset_quiet() X{ X quiet_mode = TRUE; X} X Xclear_quiet() X{ X quiet_mode = FALSE; X quiet_waiting = FALSE; /* Need to initialize this, too. */ X} X Xstart_quiet() X{ X if (quiet_mode) { X quiet_waiting = TRUE; X quiet_counter = 0; X } X} X Xstop_quiet() X{ X quiet_waiting = FALSE; X} X Xint keep_quiet(what) /* Returns 1 if should suppress. */ X char *what; X{ X if (!strncmp(what, "Use the WHO command", 19)) { X quiet_waiting = FALSE; /* No longer waiting. */ X return (1); /* Suppress this line. */ X } X X quiet_counter++; /* Don't stay quiet forever, even */ X if (quiet_counter > MAX_QUIET) { /* if we never see the right string. */ X quiet_waiting = FALSE; X return (0); X } X else X return (1); X} X X /* Quiet logins are also handled here. */ X Xint special_hook(what) /* Check for special thingies. */ X register char *what; X{ X smallstr name; X X if (quiet_waiting && keep_quiet(what)) X return (1); X X if (!strncmp(what, "#### Please reconnect to ", 25)) /* Portal? */ X return (handle_portal(what)); X X if (!strncmp(what, "You sense that ", 15)) { /* Handle pages. */ X do_beep(); X if (should_hilite_pages()) X hilite_on(); X print_with_wrap(what); X if (should_hilite_pages()) X hilite_off(); X return (1); X } X X extract_first_word(what, name); /* Get first word (speaker). */ X X if (is_other_whisper(what)) /* Check for whispers to others. */ X return (1); X X if (should_hilite(what, name)) { /* Check for hiliting. */ X hilite_on(); X print_with_wrap(what); X hilite_off(); X return (1); X } X X if (is_gagged(what, name)) /* Check for gagging. */ X return (1); X X return (0); /* Otherwise, just pass it through. */ X} X Xextract_first_word(what, name) X char *what, *name; X{ X register char *place, save; X X place = index(what, ' '); X if (place != NULL) { X save = *place; X *place = '\0'; X } X X strncpy(name, what, SMALLSTR); /* Extract the name. */ X name[SMALLSTR] = '\0'; X X if (place != NULL) /* Restore killed character. */ X *place = save; X} X X /* Handle portals. */ X /* Format is: ... to WORLD@IP-addr (hostname) port ??? #### */ X Xint handle_portal(what) X char *what; X{ X string world, address, port, temp; X int count; X char *place, ch; X register world_rec *where; X X count = sscanf(what, "#### Please reconnect to %s %s port %s ####", X world, address, port); X if (count != 3) X return (0); /* Invalid format. */ X X place = index(world, '@'); /* Strip off IP address. */ X *place = '\0'; X X ch = *(place+1); X if ((ch >= '0') && (ch <= '9')) /* Use IP address if known. */ X strcpy(address, place+1); /* May not have nameservice--use IP. */ X else { X strcpy(temp, address+1); /* Strip parens. */ X strcpy(address, temp); X address[strlen(address)-1] = '\0'; X } X X where = find_world(world); /* See if we know about it. */ X if (where == NULL) { /* Nope, build a new one instead. */ X where = (world_rec *) malloc(sizeof(world_rec)); /* Never reclaimed! */ X where->next = NULL; X strcpy(where->world, world); X *(where->character) = '\0'; X *(where->pass) = '\0'; X strcpy(where->address, address); X strcpy(where->port, port); X } X X if (connect_to(where)) X magic_login(); X else X fprintf(stderr,"%% Connection through portal failed.\n"); X X return (1); /* Yes, it was a portal. */ X} X Xinit_beep() X{ X beep_count = 0; X} X Xdo_beep() X{ X if (beep_count != 0) X write(1, "\007\007\007\007\007", beep_count); X} X Xset_beep(n) X int n; X{ X if (n > MAX_BEEPS) X beep_count = MAX_BEEPS; X else X beep_count = n; X} END_OF_FILE if test 4393 -ne `wc -c <'tinytalk/special.c'`; then echo shar: \"'tinytalk/special.c'\" unpacked with wrong size! fi # end of 'tinytalk/special.c' fi if test -f 'tinytalk/stuff.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/stuff.c'\" else echo shar: Extracting \"'tinytalk/stuff.c'\" \(8094 characters\) sed "s/^X//" >'tinytalk/stuff.c' <<'END_OF_FILE' X/************************************************************************/ X/* TinyTalk: the real good stuff (network connections, main loop). */ X/* */ X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */ X/* 1.1 [ 1/25/90] : Changed for systems without FD_SET. */ X/* 1.2 [ 1/26/90] : Added "quiet" and "nologin" control. */ X/* 1.3 [ 1/27/90] : Increased max number of 'quiet' lines. */ X/* 1.4 [ 2/ 2/90] : Moved out special output handling. */ X/* Changed connection processing. */ X/* 1.5 [ 2/ 5/90] : Modify to handle switching MUDs more */ X/* cleanly. Fix gag problem. */ X/* 1.6 [ 2/16/90] : Integrated support for System V and */ X/* HP-UX, from Andy Norman and Kipp */ X/* Hickman. */ X/* */ X/************************************************************************/ X X#include "tl.h" X#include X#include X#include X#include X#include X#include X#include X#include X X /* For some odd systems, which don't put this in errno.h. */ X Xextern int errno; X X /* For BSD 4.2 systems. */ X X#ifndef FD_ZERO X#define DESCR_MASK int X#define FD_ZERO(p) (*p = 0) X#define FD_SET(n,p) (*p |= (1<<(n))) X#define FD_ISSET(n,p) (*p & (1<<(n))) X#else X#define DESCR_MASK fd_set /* For BSD 4.3 systems. */ X#endif X X /* End of BSD 4.2 systems. */ X X#define REFRESH_TIME 500000 /* Microseconds */ X Xextern char *index(), *malloc(); Xextern struct hostent *gethostbyname(); Xextern unsigned long inet_addr(); Xextern world_rec *find_world(); X Xstatic world_rec *current_world; Xstatic int current_socket; Xstatic int connected; /* Are we connected anywhere? */ Xhugestr current_output; /* Queued as messages arrive. */ Xstatic int need_refresh; /* Does input line need refresh? */ Xstatic int done; /* Are we all done? */ Xstatic int use_magic_login; /* Auto-logins enabled? */ Xstatic int flush_pending_output; /* For portals. */ X Xdo_stuff(initial_world) X world_rec *initial_world; X{ X int count; X DESCR_MASK readers, exceptions; X struct timeval refresh_timeout; X struct timeval *tv; X X flush_pending_output = FALSE; X X connected = FALSE; X if (!connect_to(initial_world)) X die("%% Couldn't connect to initial world.\n"); X X *current_output = '\0'; /* No output yet. */ X X done = FALSE; X X need_refresh = 0; /* No keyboard typing yet. */ X X magic_login(); /* Log us in, if possible. */ X X do { X flush_pending_output = FALSE; /* No output is pending, ignore any */ X /* attempts to flush it. */ X X FD_ZERO(&readers); X FD_ZERO(&exceptions); X FD_SET(0, &readers); /* Check standard input. */ X FD_SET(current_socket, &readers); /* Check socket. */ X X if (need_refresh) { X refresh_timeout.tv_sec = 0; X refresh_timeout.tv_usec = REFRESH_TIME; X tv = &refresh_timeout; X } X else X tv = NULL; X X count = select(current_socket + 1, &readers, NULL, &exceptions, tv); X if (count == -1) { X if (errno != EINTR) /* Control-Z will do this. */ X perror("select"); X } X else if (count == 0) X do_refresh(); X else { X if (FD_ISSET(current_socket, &readers)) X handle_socket_input(); X else if (FD_ISSET(0, &readers)) { X if (need_refresh) X do_refresh(); X handle_keyboard_input(); X } X else X fprintf(stderr,"%% ??select??"); X } X X } while (!done); X X disconnect(); X cleanup_keyboard(); X} X Xint connect_to(w) /* Try to make a connection. */ X register world_rec *w; X{ X struct in_addr host_address; X struct sockaddr_in socket_address; X int err; X X register world_rec *temp_world; /* Use temporaries until we know */ X register int temp_socket; /* that we've succeeded! */ X X temp_world = w; X if (!get_host_address(w->address, &host_address)) { /* Can't do it. */ X return(0); X } X X socket_address.sin_family = AF_INET; X socket_address.sin_port = htons(atoi(w->port)); X bcopy(&host_address, &socket_address.sin_addr, sizeof(struct in_addr)); X X temp_socket = socket(AF_INET, SOCK_STREAM, 0); X if (temp_socket < 0) { X perror("% Couldn't open socket"); X return(0); X } X X err = connect(temp_socket, &socket_address, sizeof(struct sockaddr_in)); X if (err < 0) { X perror("% Couldn't connect to socket"); X return(0); X } X X#ifdef FNDELAY X fcntl(temp_socket, F_SETFL, FNDELAY); /* Do we need this? */ X#endif X X if (connected) /* Disconnect from any open world. */ X disconnect(); X X current_world = temp_world; X current_socket = temp_socket; X X connected = TRUE; X return(1); /* Success! */ X} X Xint get_host_address(name, addr) /* Get a host address. */ X register char *name; X register struct in_addr *addr; X{ X struct hostent *blob; X union { /* %#@!%!@%#!@ idiot who designed */ X long signed_thingy; /* the inetaddr routine.... */ X unsigned long unsigned_thingy; X } thingy; X X if (*name == '\0') { X fprintf(stderr, "%% No host address specified.\n"); X return (0); X } X X if ((*name >= '0') && (*name <= '9')) { /* IP address. */ X addr->s_addr = inet_addr(name); X thingy.unsigned_thingy = addr->s_addr; X if (thingy.signed_thingy == -1) { X fprintf(stderr, "%% Couldn't find host %s .\n", name); X return (0); X } X } X else { /* Host name. */ X blob = gethostbyname(name); X X if (blob == NULL) { X fprintf(stderr, "%% Couldn't find host %s .\n", name); X return (0); X } X X bcopy(blob->h_addr, addr, sizeof(struct in_addr)); X } X X return (1); /* Success. */ X} X Xdisconnect() /* Disconnect from current world. */ X{ X if (connected) { X flush_pending_output = TRUE; /* Flush pending output. This is */ X current_output[0] = '\0'; /* used when switching worlds. */ X close(current_socket); X } X X connected = FALSE; X} X Xtransmit(s, l) /* Send a message over the socket. */ X char *s; X int l; X{ X register int err; X X err = send(current_socket, s, l, 0); X if (err == -1) X perror("send failed"); X} X Xreceive(s) X register char *s; X{ X register int count; X X count = recv(current_socket, s, MAXSTRLEN, 0); X if (count == -1) { X if (errno == EWOULDBLOCK) X s[0] = '\0'; X else { X perror("recv failed"); X } X } X else X s[count] = '\0'; X X if (count <= 0) /* Don't ask me. */ X done = TRUE; X} X Xmagic_login() X{ X string s; X register world_rec *def; X X if (!use_magic_login) /* Check if auto-login is enabled. */ X return; X X if (*(current_world->character) == '\0') { /* Try default world. */ X def = find_world("default"); X if (def == NULL) { /* Just send CR for sync. */ X transmit("\n", 1); X return; X } X else { X sprintf(s,"\nconnect %s %s\n", def->character, def->pass); X transmit(s, strlen(s)); X start_quiet(); /* Suppress login messages? */ X return; X } X } X else { X sprintf(s,"\nconnect %s %s\n", current_world->character, X current_world->pass); X transmit(s, strlen(s)); X start_quiet(); /* Suppress login message? */ X return; X } X} X Xclear_refresh_pending() X{ X need_refresh = 0; X} X Xset_refresh_pending() X{ X need_refresh = 1; X} X Xhandle_socket_input() X{ X string blob; X hugestr bigblob; X register char *place; X X receive(blob); X strcat(current_output, blob); /* Concatenate this bunch of input. */ X X place = index(current_output, '\n'); /* Output any whole lines. */ X if (place != NULL) { X while (place != NULL) { X *place = NULL; X if (!special_hook(current_output)) X print_with_wrap(current_output); X if (flush_pending_output) { /* Flush the buffer. */ X flush_pending_output = FALSE; X *current_output = '\0'; X return; X } X strcpy(bigblob, place + 1); /* Rest of buffer. */ X strcpy(current_output, bigblob); /* Copy it back to buffer. */ X place = index(current_output, '\n'); X } X } X X if (strlen(current_output) > MAXSTRLEN) { /* Too long, flush it. */ X print_with_wrap(current_output); X *current_output = '\0'; /* Flush the buffer. */ X } X} X Xenable_auto_login() X{ X use_magic_login = TRUE; X} X Xdisable_auto_login() X{ X use_magic_login = FALSE; X} X Xset_done() /* Used by /QUIT command to exit */ X{ /* cleanly. */ X done = TRUE; X} END_OF_FILE if test 8094 -ne `wc -c <'tinytalk/stuff.c'`; then echo shar: \"'tinytalk/stuff.c'\" unpacked with wrong size! fi # end of 'tinytalk/stuff.c' fi if test -f 'tinytalk/util.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/util.c'\" else echo shar: Extracting \"'tinytalk/util.c'\" \(6212 characters\) sed "s/^X//" >'tinytalk/util.c' <<'END_OF_FILE' X/************************************************************************/ X/* TinyTalk utilities. */ X/* */ X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */ X/* 1.1 [ 1/25/90] : Moved terminal control here. */ X/* 1.2 [ 1/25/90] : Modified to set termcap var 'ospeed'. */ X/* 1.3 [ 2/ 2/90] : Added comparestr() and hiliting. */ X/* 1.4 [ 2/ 5/90] : Added expand_filename() for $#@! UNIX. */ X/* Disable its fancy stuff because there */ X/* are no shared libraries. */ X/* 1.5 [ 2/16/90] : Integrated support for System V and */ X/* HP-UX, from Andy Norman and Kipp */ X/* Hickman. */ X/* */ X/************************************************************************/ X X#include "tl.h" X X#ifdef HPUX X X#include X#include X X#else /* not HPUX */ X#ifdef SYSVTTY X X#include Xstatic int first_time = 1; Xstatic struct termio old_tty_state; X X#else /* BSD */ X X#include X#include X X#endif /* SYSVTTY */ X#endif /* HPUX */ X X#include X#include X X#undef FANCY X Xextern char *getenv(), *index(); Xextern struct passwd *getpwnam(); X X#ifdef TERMCAP Xextern short ospeed; Xstatic int have_hilite; Xstatic char hilite_on_string[16], hilite_off_string[16]; Xstatic char write_buffer[64]; Xstatic char *write_buffer_ptr; X#endif X Xuppercase(s, t) X register char *s, *t; X{ X while (*s) { X *t = (((*s >= 'a') && (*s <= 'z')) ? *s-32 : *s); X s++; X t++; X } X *t = '\0'; X} X Xint equalstr(s, t) X char *s, *t; X{ X string su, tu; X X uppercase(s,su); X uppercase(t,tu); X return (!strcmp(su,tu)); X} X Xint comparestr(s, t) X char *s, *t; X{ X string su, tu; X X uppercase(s,su); X uppercase(t,tu); X return (strcmp(su,tu)); X} X Xstripstr(s) /* Strip leading & trailing */ X register char *s; /* spaces from a string. */ X{ X string temp; X register char *from; X X if (s[0] == ' ') { /* Remove leading spaces. */ X from = s + 1; X while (*from == ' ') X from++; X strcpy(temp, from); X strcpy(s, temp); X } X X from = s + strlen(s) - 1; X if (*from == ' ') { X --from; X while (*from == ' ') X --from; X *(from+1) = '\0'; X } X} X X#ifdef HPUX X Xcbreak_noecho_mode() X{ X struct termio blob; X X if (ioctl(0, TCGETA, &blob) == -1) X perror("TCGETA ioctl"); X X blob.c_lflag &= ~ECHO; X blob.c_lflag &= ~ECHOE; X blob.c_lflag &= ~ICANON; X blob.c_cc[VMIN] = 0; X blob.c_cc[VTIME] = 0; X X if (ioctl(0, TCSETAF, &blob) == -1) X perror("TCSETAF ioctl"); X X} X Xcooked_echo_mode () X{ X struct termio blob; X X if (ioctl(0, TCGETA, &blob) == -1) X perror("TCGETA ioctl"); X X blob.c_lflag |= ECHO; X blob.c_lflag |= ECHOE; X blob.c_lflag |= ICANON; X X if (ioctl(0, TCSETAF, &blob) == -1) X perror("TCSETAF ioctl"); X X} X X#else /* not HPUX */ X X#ifdef SYSVTTY X Xcbreak_noecho_mode() /* When we're running... */ X{ X struct termio blob; X X if (first_time) { X ioctl(0, TCGETA, &old_tty_state); X first_time = 0; X } X X ioctl(0, TCGETA, &blob); X blob.c_cc[VMIN] = 0; X blob.c_cc[VTIME] = 0; X blob.c_iflag = IGNBRK | IGNPAR | ICRNL; X blob.c_oflag = OPOST | ONLCR; X blob.c_lflag = ISIG; X ioctl(0, TCSETA, &blob); X} X Xcooked_echo_mode() /* When we exit... */ X{ X if (!first_time) { X ioctl(0, TCSETA, &old_tty_state); X } X} X X#else /* BSD */ X Xcbreak_noecho_mode() /* When we're running... */ X{ X struct sgttyb blob; X X if (ioctl(0, TIOCGETP, &blob) == -1) X perror("TIOCGETP ioctl"); X blob.sg_flags |= CBREAK; X blob.sg_flags &= ~ECHO; X if (ioctl(0, TIOCSETP, &blob) == -1) X perror("TIOCSETP ioctl"); X X#ifdef TERMCAP X ospeed = blob.sg_ospeed; X#endif /* TERMCAP */ X} X Xcooked_echo_mode() /* When we exit... */ X{ X struct sgttyb blob; X X if (ioctl(0, TIOCGETP, &blob) == -1) X perror("TIOCGETP ioctl"); X blob.sg_flags &= ~CBREAK; X blob.sg_flags |= ECHO; X if (ioctl(0, TIOCSETP, &blob) == -1) X perror("TIOCSETP ioctl"); X} X X#endif /* SYSVTTY */ X#endif /* HPUX */ X Xdie(why, s1, s2, s3, s4) X char *why, *s1, *s2, *s3, *s4; X{ X cooked_echo_mode(); /* Reset terminal characteristics. */ X disable_logging(); /* Flush and close log file. */ X fprintf(stderr, why, s1, s2, s3, s4); X exit(1); X} X Xinit_hilite_utils() X{ X#ifdef TERMCAP X X char blob[1024]; /* As per termcap man page */ X char *terminal_name, *temp; X X have_hilite = FALSE; X X terminal_name = getenv("TERM"); X if (terminal_name == NULL) X return; X X if (tgetent(blob, terminal_name) != 1) X return; X X temp = hilite_on_string; X X if (tgetstr("md",&temp) != NULL) { X temp = hilite_off_string; X if (tgetstr("me",&temp) != NULL) X have_hilite = TRUE; X } X X if (!have_hilite) { X temp = hilite_on_string; X X if (tgetstr("so",&temp) != NULL) { X temp = hilite_off_string; X if (tgetstr("se",&temp) != NULL) X have_hilite = TRUE; X } X } X X#endif X} X X#ifdef TERMCAP Xoutput_one(c) X char c; X{ X *(write_buffer_ptr++) = c; X} X#endif X Xhilite_on() X{ X#ifdef TERMCAP X X if (have_hilite) { X write_buffer_ptr = write_buffer; X tputs(hilite_on_string, 1, output_one); X write(1, write_buffer, write_buffer_ptr - write_buffer); X } X X#endif X} X Xhilite_off() X{ X#ifdef TERMCAP X X if (have_hilite) { X write_buffer_ptr = write_buffer; X tputs(hilite_off_string, 1, output_one); X write(1, write_buffer, write_buffer_ptr - write_buffer); X } X X#endif X} X Xexpand_filename(s) X string s; X{ X char *env; X string temp; X X if (s[0] != '~') /* Only affect stuff with tildes. */ X return; X X if (s[1] == '/') { /* Current user's home directory. */ X env = getenv("HOME"); X if (env == NULL) X temp[0] = '\0'; X else X strcpy(temp, env); X X strcat(temp, s+1); /* {home}/whatever */ X strcpy(s, temp); X } X X#ifdef FANCY X X else if (s[1] != '\0') { /* Someone else's home directory. */ X struct passwd *tt; X char *loc; X X loc = index(s,'/'); X if (loc != NULL) { /* No slash ==> we don't care. */ X *loc = '\0'; /* Get rid of slash. */ X setpwent(); X tt = getpwnam(s+1); /* Ignore leading tilde. */ X endpwent(); X *loc = '/'; /* Restore slash. */ X if (tt != NULL) { /* Can't find them ==> don't care. */ X strcpy(temp, tt->pw_dir); X strcat(temp, loc); /* {their home}/whatever */ X strcpy(s, temp); X } X } X } X X#endif /* FANCY */ X X} END_OF_FILE if test 6212 -ne `wc -c <'tinytalk/util.c'`; then echo shar: \"'tinytalk/util.c'\" unpacked with wrong size! fi # end of 'tinytalk/util.c' fi if test -f 'tinytalk/wrap.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tinytalk/wrap.c'\" else echo shar: Extracting \"'tinytalk/wrap.c'\" \(1733 characters\) sed "s/^X//" >'tinytalk/wrap.c' <<'END_OF_FILE' X/************************************************************************/ X/* TinyTalk word wrapping. */ X/* */ X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */ X/* 1.1 [ 2/ 5/90] : Move input line erasure into here. */ X/* */ X/************************************************************************/ X X#include "tl.h" X#include X Xextern char *rindex(); X Xstatic int current_wrap_column; Xstatic int default_wrap_column; X Xprint_with_wrap(s) X register char *s; X{ X hugestr temp; X register char *place; X int loc; X X erase_keyboard_input(FALSE); /* Clear current line. */ X X if (current_wrap_column == -1) X current_wrap_column = default_wrap_column; X X if ((current_wrap_column == 0) || strlen(s) < current_wrap_column) { X puts(s); /* No wrap. */ X log_output(s); X return; X } X X strcpy(temp, s); X do { X temp[current_wrap_column] = '\0'; X place = rindex(temp,' '); X if (place == NULL) { /* Can't wrap, give up */ X puts(temp); X log_output(temp); X loc = current_wrap_column; X } X else { X *place = '\0'; /* Terminate string */ X puts(temp); /* and output it. */ X log_output(temp); X loc = place - temp + 1; X } X strcpy(temp, s + loc); /* Rest of string. */ X strcpy(s, temp); /* Should strip double spaces? */ X } while (strlen(s) >= current_wrap_column); X X if (strlen(s) != 0) { X puts(s); X log_output(s); X } X} X Xenable_wrap(column) /* Doesn't just set column, because */ X int column; /* might not have initted keyboard. */ X{ X current_wrap_column = ((column == 0) ? -1 : column); X} X Xdisable_wrap() X{ X current_wrap_column = 0; X} X Xset_default_wrap(column) X int column; X{ X default_wrap_column = column; X} END_OF_FILE if test 1733 -ne `wc -c <'tinytalk/wrap.c'`; then echo shar: \"'tinytalk/wrap.c'\" unpacked with wrong size! fi # end of 'tinytalk/wrap.c' fi echo shar: End of archive 3 \(of 3\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 3 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0