v20i029: Command-line editor with predictions, Part01/04
Rich Salz
rsalz at uunet.uu.net
Wed Oct 18 07:12:42 AEST 1989
Submitted-by: Mark James <jamesm at cpsc.UCalgary.CA>
Posting-number: Volume 20, Issue 29
Archive-name: reactivekbd/part01
[ This is one of the wildest concepts I've seen; not unlike DWIM in
the Interlisp world, I guess. It uses pty's and BSD-style ioctl's.
The package also has the FSF getopt(3) bundled in. /r$ ]
The Reactive Keyboard is a general purpose command line editor with the
addition of predictive text generation. It interfaces with a standard
shell and allows simple editing of input lines. It will also predict new
input lines based on previous input. Typing "make" will create the
program in the current directory.
#! /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 <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 4)."
# Contents: MANIFEST Makefile README command_line.c dt_complete.c
# file+rk.h freq.c functions.h myabspath.c myabspath.h rk_button.c
# rk_button.h rk_file.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(654 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X File Name Archive # Description
X-----------------------------------------------------------
X MANIFEST 1
X Makefile 1
X README 1
X command_line.c 1
X dt_complete.c 1
X file+rk.c 3
X file+rk.h 1
X freq.c 1
X functions.c 4
X functions.h 1
X getopt.c 2
X myabspath.c 1
X myabspath.h 1
X parse_keys.c 2
X rk.1 2
X rk_button.c 1
X rk_button.h 1
X rk_file.c 1
END_OF_FILE
if test 654 -ne `wc -c <'MANIFEST'`; then
echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(314+ characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCFLAGS = -g
X
XOBJS = file+rk.o rk_file.o rk_button.o parse_keys.o getopt.o \
X dt_complete.o functions.o myabspath.o command_line.o
X
X.c.o:
X cc $(CFLAGS) -c $<
X
Xall: rk rk.man freq
X
Xrk: $(OBJS)
X cc $(CFLAGS) -o rk $(OBJS) -ltermcap
X
Xrk.man : rk.1
X tbl rk.1|nroff -man > rk.man
X
Xfreq: freq.c
X cc $(CFLAGS) -o freq freq.c
END_OF_FILE
echo 'shar: Size check ignored; edited by moderator for long lines.'
#if test 314 -ne `wc -c <'Makefile'`; then
# echo shar: \"'Makefile'\" unpacked with wrong size!
#fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(454 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThe Reactive Keyboard is a general purpose command line editor with the
Xaddition of predictive text generation. It interfaces with a standard shell
Xand allows simple editing of input lines. It will also predict new input
Xlines based on previous input. Typing "make"
Xwill create the program in the current directory.
X
XPermission is granted for any individual or institution to use, copy or
Xdistribute this program so long as it is not sold for profit.
END_OF_FILE
if test 454 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'command_line.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'command_line.c'\"
else
echo shar: Extracting \"'command_line.c'\" \(5852 characters\)
sed "s/^X//" >'command_line.c' <<'END_OF_FILE'
X#define ZERO_FREQ_FILE "/.rk.zero_freq"
X#define PRIME_FILE "/.rk.log_file"
X#define KEY_FILE "/.rk.keys"
X
X#include "file+rk.h"
X#include "rk_button.h"
X#include "sys/file.h"
X#include <stdio.h>
X
Xprint_help()
X{
X printf("RK command line arguments:\n");
X
X printf(" -b <buffers> The number of buffers used by rk to save previous\n");
X printf(" commands used by 'previous_line'. Default: 60.\n\n");
X
X printf(" -e <length> The maximum length of predictions at the end of the\n");
X printf(" line. Default: 40.\n\n");
X
X
X printf(" -f <count> The maximum frequency count for any given context\n");
X printf(" Default: 128\n\n");
X
X printf(" -i <length> The maximum length of predictions in the middle of\n");
X printf(" the line. Default: 8.\n\n");
X
X printf(" -k <keys file> The file to read key bindings from.\n");
X printf(" Default:$HOME/.rk.keys\n\n");
X
X printf(" -n <nodes> The amount of memory to allocate initially to speed\n");
X printf(" up creation of nodes. After this memory is used up,\n");
X printf(" more will be allocated, but this will be slower.\n");
X printf(" Default: 64*1024 nodes.\n\n");
X
X printf(" -o <order> This argument controls how deep a tree will be built\n");
X printf(" by rk inorder to make predictions. As order\n");
X printf(" increases, the accuracy of predictions increases,\n");
X printf(" but the speed decreases. Default: 8.\n\n");
X printf(" -p <prime file> The file used to prime the Reactive Keyboard.\n");
X printf(" Default:$HOME/.rk.log_file.\n\n");
X
X
X printf(" -s <startup> The maximum number of characters to be read from the\n");
X printf(" prime file at startup. Default: 16*1024.\n\n");
X
X printf(" -z <zero freq> The zero frequency file name.\n");
X printf(" Default:$HOME/.rk.zero_freq\n\n");
X
X printf(" -A Toggle add_space_mode\n");
X printf(" -E Toggle eol_only mode.\n");
X printf(" -L Toggle eol_longer mode.\n");
X printf(" -N Toggle truncate at newline mode.\n");
X printf(" -P Toggle predictions on/off.\n");
X printf(" -S Toggle show_eol_mode.\n");
X printf(" -g Make this not a login shell.\n");
X printf(" -h Print this help.\n");
X printf(" -l Toggle lisp mode.\n");
X printf(" -m Start up silently.\n");
X printf(" -v Print Version.\n");
X
X}
X
Xprint_version()
X{
X char tbuf[128];
X printf("RK_Button Version:%s.\n", RK_VERSION);
X}
X
Xextern ED_STRUCT editor_data;
X
X
Xget_command_line_arguments(argc,argv)
Xint argc;
Xchar *argv[];
X{
X extern int optind;
X extern char *optarg;
X int i;
X
X extern num_buffers;
X extern char *zero_freq_file;
X static char z_freq_buf[256];
X extern char *prime_file;
X static char prime_buf[256];
X extern char *key_file;
X static char key_buf[256];
X extern max_len;
X extern max_eol;
X extern maxk;
X extern maxprime;
X extern max_freq;
X extern max_nodes;
X extern char silent;
X extern char login;
X extern char pred_mode,
X pred_on_display,
X lisp_mode,
X nl_truncate_mode,
X eol_only_mode,
X eol_longer_mode,
X add_space_mode,
X show_eol_mode;
X
X zero_freq_file=prime_file=key_file=NULL;
X
X while ((i = getopt(argc, argv,"b:e:f:i:k:n:o:p:s:z:AELNPSghlmv"))
X != EOF) {
X switch( i ) {
X case 'b': num_buffers=atoi(optarg)+1;
X if(num_buffers<1)
X abortit("-b:Buffers must be larger than 1.\n",-1);
X break;
X /* 1.. MAXINT*/
X case 'e': max_eol=atoi(optarg);
X if((max_eol<1)||(max_eol>132))
X abortit("-e:End of line length must be between 1 and 132.\n",-1);
X break;
X /* 1..132 */
X case 'f': max_freq=atoi(optarg);
X if((max_freq<3)||(max_freq>255))
X abortit("-f:Maximum Frequency must be between 3 and 255.\n",-1);
X break;
X case 'i': max_len=atoi(optarg);
X if((max_len<1)||(max_len>132))
X abortit("-i:Inline Length must be between 1 and 132.\n",-1);
X break;
X /* 1..132 */
X case 'k':
X if( key_file ) {
X fprintf(stderr,"%s: Too many -k options\n",argv[0]);
X abortit("",1);
X }
X key_file=optarg;
X /* check for existance */
X if(access(key_file,R_OK)){
X perror(key_file);
X abortit("",-1);
X }
X break;
X case 'n': max_nodes=atoi(optarg);
X if(max_nodes<0)
X abortit("-n:Number of nodes must be positive.\n",-1);
X break;
X case 'o': maxk=atoi(optarg);
X if((maxk<3)||(maxk>TOP_K)){
X fprintf(stderr,"-o: Order must be between 3 and %d.\n",TOP_K);
X abortit("",-1);
X }
X break;
X case 'p':
X if( prime_file ) {
X fprintf(stderr, "%s: Too many -p options\n",argv[0]);
X abortit("",1);
X }
X prime_file=optarg;
X /* check for existance */
X if(access(prime_file,(R_OK|W_OK))){
X perror(prime_file);
X abortit("",-1);
X }
X break;
X case 's': maxprime=atoi(optarg); break;
X
X case 'z':
X if( zero_freq_file ) {
X fprintf(stderr, "%s: Too many -z options\n",argv[0]);
X abortit("",1);
X }
X zero_freq_file=optarg;
X /* check for existance */
X if(access(zero_freq_file,(R_OK|W_OK))){
X perror(zero_freq_file);
X abortit("",-1);
X }
X break;
X case 'A': add_space_mode=!add_space_mode; break;
X case 'E': eol_only_mode=!eol_only_mode; break;
X case 'L': eol_longer_mode=!eol_longer_mode; break;
X case 'N': nl_truncate_mode=!nl_truncate_mode; break;
X case 'P': pred_mode=!pred_mode; break;
X case 'S': show_eol_mode=!show_eol_mode; break;
X case 'g': login=!login; break;
X case 'h': print_help(); abortit("",0); break;
X case 'l': lisp_mode=!lisp_mode; break;
X case 'm': silent=1; break;
X case 'v': print_version();abortit("",0); break;
X
X
X default:
X fprintf(stderr,"\r%s: Use -h for help\r\n", argv[0]);
X abortit("",-1);
X }
X
X }
X
X if(zero_freq_file==NULL){
X strcpy(z_freq_buf, getenv("HOME"));
X strcat(z_freq_buf, ZERO_FREQ_FILE );
X zero_freq_file=z_freq_buf;
X }
X if(prime_file==NULL){
X strcpy(prime_buf, getenv("HOME"));
X strcat(prime_buf, PRIME_FILE );
X prime_file=prime_buf;
X }
X if(key_file==NULL){
X strcpy(key_buf, getenv("HOME"));
X strcat(key_buf, KEY_FILE );
X key_file=key_buf;
X }
X
X}
END_OF_FILE
if test 5852 -ne `wc -c <'command_line.c'`; then
echo shar: \"'command_line.c'\" unpacked with wrong size!
fi
# end of 'command_line.c'
fi
if test -f 'dt_complete.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dt_complete.c'\"
else
echo shar: Extracting \"'dt_complete.c'\" \(13902 characters\)
sed "s/^X//" >'dt_complete.c' <<'END_OF_FILE'
X#include <alloca.h> /* JJD: some other alloc may be better to use */
X#include <stdio.h>
X#include <sys/file.h>
X#include <sys/types.h>
X#include <sys/dir.h>
X#include <sys/stat.h>
X#include <sys/param.h> /* JJD 3-89 added to get MAXPATHLEN and CANBSIZ*/
X#include "file+rk.h"
X#include "functions.h"
X
X
X#define FILECOMPLETION 3 /* change if you need to change the binding of
X filecompletion */
X
X/* MAX_FILENAME_LENGTH must be less than MAX_CMD_LINE_LENGTH (CANBSIZ, 256)*/
X/* */
X/* dir.h MAXNAMLEN is 255 (+1 for char []) JJD 3-89 #define */
X
X#define MAX_DIR_TO_SEARCH 16 /* WARNING: just a guess! */
X#define MAX_FILES_TO_SAVE 1024 /* WARNING: just a guess! */
X#define MAX_FILENAME_LENGTH MAXNAMLEN /* store bounds */
X#define MAX_PATHNAME_LENGTH MAXPATHLEN
X
Xextern num_buffers;
Xextern char *cursor_left;
Xextern char output_string[];
Xextern output_string_length;
Xextern char pred_mode,pred_on_display;
Xextern char pred_buff[];
Xextern (*keymap[128][MAXEXTENSIONS]) ();
X
Xint run_ruptime (e) ED_STRUCT *e; {
X
X write (1, "\015\n", 2); /* JJD 3-89*/
X quietly_run_program_connected_to_standard_tty ("uptime"); /* JJD 3-89*/
X write (1, "Continue: ", 10);
X draw_current_edit_line (e);
X return OK;
X}
X
X/* AN IDEA: a better way would look ahead a next char, if not this, put */
X/* in the read buffer and return, else stay here - write (un)getc. */
X
Xint file_completion (e) ED_STRUCT *e; {
X char *cwd,
X *getcwd(),
X *tdot,
X *tchar,chr,
X *f_name[MAX_FILES_TO_SAVE], /* JJD 3-89 to ptrs, defines*/
X tstring[MAX_CMD_LINE_LENGTH + 1],
X de_name[MAX_FILENAME_LENGTH + 1], /* JJD 3-89 dir entry name */
X full_path[MAXPATHLEN];
X
X DIR *opendir(),
X *dir_pointer;
X
X struct direct *readdir(),
X *d_entry;
X int match=0,
X length,
X past_first=0,
X strncmp(),
X ful_path=0,
X count,
X cmatch,
X return_this = OK; /* JJD 2-89 added */
X /* now look for start of filename to match */
X for (tdot=e->dot;((*tdot != ' ') && (tdot != e->current_buffer));tdot--);
X
X /* if we aren't at the start of the whole buffer
X then move ahead a char (to skip the space) */
X if (tdot != e->current_buffer) tdot++;
X /* and save the string to look for */
X strcpy(tstring, tdot);
X for (tchar=tstring;((*tchar != '\/')&&(*tchar!='\0'));tchar++);
X if (*tchar == '\/') {
X ful_path = 1;
X strcpy(full_path,tstring);
X tchar=full_path;
X while (*tchar!='\0') tchar++;
X while ((*tchar!='\/') && (tchar != full_path)) tchar--;
X if (tchar != full_path) {
X *tchar = '\0';
X tchar++;strcpy(tstring,tchar);
X }
X }
X if (ful_path){
X cwd = full_path;
X }
X else {
X void (*sig)();
X sig=signal(SIGCHLD,SIG_DFL);
X getcwd(full_path);cwd=full_path; /* get working directory */
X signal(SIGCHLD,sig);
X }
X if ((dir_pointer = opendir(cwd)) == NULL){ /* and open it to look */
X write(1, "\07",1);
X return OK;
X } /* now look for any matching filenames and
X increment match if we find one */
X d_entry=readdir(dir_pointer);
X for (; d_entry != NULL; d_entry = readdir(dir_pointer)){
X strcpy (de_name, d_entry->d_name);
X if (strncmp(tstring, de_name, strlen(tstring)) == 0){
X if ((strcmp(".", de_name) != 0) &&
X (strcmp("..", de_name) != 0)){ /* JJD 3-89 del . .. */
X f_name[match] = (char *) alloca (strlen(de_name) + 1);
X strcpy(f_name[match],de_name);
X if (++match >= MAX_FILES_TO_SAVE) {
X goto tomany; /* JJD 3-89 forget about the rest of them */
X }
X }
X }
X }
Xtomany:
X if (match == 0) {
X write(1,"\07",1);
X if (dir_pointer != NULL) closedir(dir_pointer); /* JJD 3-89 added if*/
X return OK;
X }
X /* else we found at least 1 match */
X else {
X ssort (f_name, match); /* JJD 3-89, alpha */
X cmatch = 0;
Xagain: output_string_length = 0;
X if (!past_first) length=strlen(tstring);
X else {
X if (cmatch == 0) length=strlen(f_name[match-1]);
X else length=strlen(f_name[cmatch-1]);
X }
X if (ful_path) length = length + strlen(full_path)+1;
X /* so move the cursor to the beginning
X of the file name */
X for (; length; --length)
X tputs (cursor_left, ONE_LINE,append_to_output_string);
X /* set current dot to beginning of the
X file name and copy in the filename*/
X e->dot = tdot;
X if (ful_path){
X strcpy(e->dot,full_path);
X strcat(e->dot,"\/");
X strcat(e->dot,f_name[cmatch]);
X }
X
X/* JJD: WARNING: prev and next str ops could overflow ed_buff, should test */
X
X else strcpy(e->dot,f_name[cmatch]);
X /* reset dot to the end of the line */
X if (e->mark > e->dot) e->mark += strlen (f_name[cmatch]);/*JJD 3-89*/
X e->dot += strlen(f_name[cmatch]);
X
X/* JJD: WARNING: prev and next dot resets could overflow ed_buff, as above */
X
X if (ful_path) {
X if (e->mark > e->dot) e->mark += strlen(full_path)+1;
X e->dot += strlen(full_path)+1;
X }
X /* and concatenate onto output string the
X filename, write it to screen */
X if (ful_path) {
X display_string_into_output_string(full_path);
X display_string_into_output_string("\/");
X }
X display_string_into_output_string (f_name[cmatch]);
X if (cmatch == 0)length=strlen(f_name[match-1])-strlen(f_name[cmatch]);
X else length=strlen(f_name[cmatch-1])-strlen(f_name[cmatch]);
X for (count=0;count<length;count++){
X display_string_into_output_string(" ");
X }
X for (count=0;count<length;count++){
X tputs (cursor_left, ONE_LINE,append_to_output_string);
X }
X write (1, output_string, output_string_length);
X if (pred_mode) { /* JJD 2-89 added */
X make_a_prediction (pred_buff);
X if (pred_buff[0]) display_pred_buffer (e);
X }
X
X READ(0,&chr,1);
X chr &= 127; /* JJD 2-89 added */
X if (pred_on_display) erase_pred_buffer (e); /* JJD 2-89 added */
X if (chr == FILECOMPLETION) {
X past_first = 1;
X if (cmatch < match-1) {
X cmatch++;
X goto again;
X }
X else {cmatch=0;goto again;}
X }
X else {
X/* JJD: it would be better to ungetc and return */
X return_this = OK; /* JJD 2-89 added */
X e->current_input_char = chr;
X return_this = keymap[(int)chr][0](e); /* JJD 2-89 add return_this */
X if (dir_pointer != NULL) closedir(dir_pointer); /* JJD 3-89 add if*/
X return (return_this); /* JJD 2-89 add return_this */
X }
X }
X }
X
X
Xint command_completion (e) ED_STRUCT *e;{
X char *path_var, /* points to the environment variable PATH */
X *tdot,
X *tchar,
X chr,
X *paths[MAX_DIR_TO_SEARCH], /* JJD 3-89 changed to ptrs */
X *f_name[MAX_FILES_TO_SAVE],
X tstring[MAX_CMD_LINE_LENGTH + 1],
X d_name[MAX_PATHNAME_LENGTH + 1],
X de_name[MAX_FILENAME_LENGTH + 1],
X t_name[MAX_PATHNAME_LENGTH + MAX_FILENAME_LENGTH + 1],
X *getenv();
X int count,
X num_dirs=0, /* number of directories to look in */
X current_search_directory,/* the current directory to look at */
X cmatch,
X match=0,
X length,
X past_first=0,
X return_this = OK; /* JJD 2-89 added */
X
XDIR *opendir(),
X *dir_pointer;
X
Xstruct direct *readdir(),
X *d_entry;
Xstruct stat buf; /* JJD 3-89 added */
X
X /* get the file name to match */
X for (tdot=e->dot;((*tdot != ' ') && (tdot != e->current_buffer));tdot--);
X if (tdot != e->current_buffer) tdot++;
X strcpy(tstring, tdot);
X
X path_var = getenv("PATH");
X if (path_var == NULL) { /* JJD 3-89 added test */
X write(1,"\07",1);
X return OK;
X }
X else {
X tchar = path_var; /* skip the first : */
X/* JJD: this assumes a "normal" PATH, which it is 99.99% likely to be */
X if (path_var[0] == ':') tchar++; /* JJD 3-89 added if */
X while(*tchar != '\0'){
X count=0; /* JJD 3-89 stay in bounds*/
X while ((*tchar != ':') && (*tchar != '\0')) d_name[count++] = *tchar++;
X if (*tchar == ':') tchar++;
X d_name[count] = '\0';
X paths[num_dirs] = (char *) alloca (strlen(d_name) + 1);
X strcpy (paths[num_dirs], d_name);
X if (++num_dirs >= MAX_DIR_TO_SEARCH) {
X goto tomanydirs; /* JJD 3-89 forget the rest*/
X }
X }
Xtomanydirs:
X/* now have num_dirs directories to search for the command in */
X/* JJD 3-89 NOW CHECKS FOR EXECUTE PERMISSION and NOT A DIRECTORY, */
X/* THEN SORTS IN ALPHA ORDER, LEAVING IN DUPLICATED (are rare) */
X
X current_search_directory = 0; /* JJD 3-89 changed <= to < */
X for (;current_search_directory<num_dirs;current_search_directory++){
X strcpy (d_name, paths[current_search_directory]); strcat (d_name, "/");
X if ((dir_pointer = opendir(&paths[current_search_directory][0])) != NULL){
X d_entry=readdir(dir_pointer);
X for (;d_entry != NULL;d_entry = readdir(dir_pointer)){
X strcpy (de_name, d_entry->d_name);
X if (strncmp(tstring, de_name, strlen(tstring)) == 0){
X if ((strcmp(".", de_name) != 0) &&
X (strcmp("..", de_name) != 0)) { /* JJD 3-89 del . .. */
X strcpy (t_name, d_name); strcat (t_name, de_name);
X if (access (t_name, X_OK) == 0) { /* executable */
X if (stat(t_name,&buf) == 0){
X if ((buf.st_mode & S_IFMT) != S_IFDIR){ /* not a dir */
X f_name[match] = (char *) alloca (strlen(de_name) + 1);
X strcpy(f_name[match],de_name);
X if (++match >= MAX_FILES_TO_SAVE) {
X goto tomanyfiles; /* JJD 3-89 above */
X }
X }
X }
X }
X }
X }
X }
X }
Xtomanyfiles:
X if (dir_pointer != NULL) closedir(dir_pointer);
X }
X if (match == 0) {
X write(1,"\07",1);
X return OK;
X }
X /* else we found at least 1 match */
X else {
X ssort (f_name, match); /* JJD 3-89, alpha */
X cmatch = 0;
Xagain: output_string_length = 0;
X if (!past_first) length=strlen(tstring);
X else {
X if (cmatch == 0) length=strlen(f_name[match-1]);
X else length=strlen(f_name[cmatch-1]);
X }
X for (; length; --length)
X tputs (cursor_left, ONE_LINE,append_to_output_string);
X/* set current dot to beginning of the file name and copy in the filename*/
X e->dot = tdot;
X strcpy(e->dot,f_name[cmatch]);
X
X/* JJD: WARNING: prev strcpy could overflow ed_buff, should test */
X/* JJD: WARNING: next dot reset could overflow ed_buff, as above */
X /* reset dot to the end of the line */
X
X if (e->mark > e->dot) e->mark += strlen (f_name[cmatch]); /* JJD 3-89 */
X e->dot += strlen(f_name[cmatch]);
X display_string_into_output_string (f_name[cmatch]);
X if (cmatch == 0) length=strlen(f_name[match-1])-strlen(f_name[cmatch]);
X else length=strlen(f_name[cmatch-1])-strlen(f_name[cmatch]);
X for (count=0;count<length;count++){
X display_string_into_output_string(" ");
X }
X for (count=0;count<length;count++){
X tputs (cursor_left, ONE_LINE,append_to_output_string);
X }
X write (1, output_string, output_string_length);
X if (pred_mode) { /* JJD 2-89 added */
X make_a_prediction (pred_buff);
X if (pred_buff[0]) display_pred_buffer (e);
X }
X
X READ(0,&chr,1);
X chr &= 127; /* JJD 2-89 added */
X if (pred_on_display) erase_pred_buffer (e); /* JJD 2-89 added */
X if (chr == (char)28) { /* JJD 2-89 made ^\*/
X past_first = 1;
X if (cmatch < match-1) {
X cmatch++;
X goto again;
X }
X else {cmatch=0;goto again;}
X }
X else {
X/* JJD: it would be better to ungetc and return */
X return_this = OK; /* JJD 2-89 added */
X e->current_input_char = chr;
X return_this = keymap[(int)chr][0](e); /* JJD 2-89 add return_this */
X if (dir_pointer != NULL) closedir(dir_pointer); /* JJD 3-89 add if*/
X return (return_this); /* JJD 2-89 add return_this */
X }
X }
X }
X}
X
X
Xset_mark (e) ED_STRUCT *e; {
X e->mark = e->dot; /* JJD 3-89 mark intialized in set_up_buffers()*/
X e->current_ed_buff_ptr->mark = e->dot; /* JJD 3-89 added */
X}
X
Xshow_mark (e) ED_STRUCT *e; {
X int num_to_go;
X if (e->mark > e->dot){
X e->universal_argument = num_to_go = e->mark - e->dot;
X forward_char (e);
X sleep(1); /* JJD 3-89 change */
X e->universal_argument = num_to_go;
X backward_char (e);
X }
X else if (e->mark < e->dot){
X e->universal_argument = num_to_go = e->dot - e->mark;
X backward_char (e);
X sleep(1); /* JJD 3-89 change */
X e->universal_argument = num_to_go;
X forward_char (e);
X }
X}
X
Xdelete_region_to_killbuffer (e) ED_STRUCT *e; {
X
X int length;
X
X if (e->dot > e->mark){
X length = e->dot - e->mark;
X strncpy(e->kill_buffer, e->mark, length);
X e->kill_buffer[length] = '\0';
X e->universal_argument = length;
X backward_char(e);
X e->universal_argument = length;
X e->mark = e->dot;
X return delete_char (e);
X }
X if (e->mark > e->dot){
X length = e->mark - e->dot;
X strncpy(e->kill_buffer, e->dot, length);
X e->kill_buffer[length] = '\0';
X e->universal_argument = length;
X e->mark = e->dot;
X return delete_char (e);
X }
X return OK; /* JJD 3-89 added */
X}
X
X
Xint strstr(look, lookin) char *look, *lookin;{
X int counter = 0;
X for (counter = 0; (counter < (strlen(lookin) - strlen(look))); counter++){
X if (strncmp(look, &lookin[counter], strlen(look)) == 0)
X return(0);
X }
X return(1);
X}
X
X/*
Xsend_message(message)
Xchar *message;
X{
X ioctl (0, TIOCGETP, &new_stdin_sgttyb);
X ioctl (0, TIOCSETP, &old_stdin_sgttyb);
X printf ("recvd message:%s\n", message);
X ioctl (0, TIOCSETP, &new_stdin_sgttyb);
X}
X*/
X
Xssort (v, n) char *v[]; int n; { /* JJD: Shell Sort alla p.108 K&R C book */
X int gap, i, j; char *temp;
X for (gap = n/2; gap > 0; gap /= 2)
X for (i= gap; i < n; i++)
X for (j = i-gap; j >= 0; j -= gap) {
X if (strcmp(v[j], v[j+gap]) <= 0) break;
X temp = v[j];
X v[j] = v[j+gap];
X v[j+gap] = temp;
X }
X}
END_OF_FILE
if test 13902 -ne `wc -c <'dt_complete.c'`; then
echo shar: \"'dt_complete.c'\" unpacked with wrong size!
fi
# end of 'dt_complete.c'
fi
if test -f 'file+rk.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'file+rk.h'\"
else
echo shar: Extracting \"'file+rk.h'\" \(1071 characters\)
sed "s/^X//" >'file+rk.h' <<'END_OF_FILE'
X#include <sys/param.h> /* JJD 3-89 added to get MAXPATHLEN and CANBSIZ */
Xchar *strcpy(), *strcat(); /* JJD 3-89 for lint */
Xchar *gets(), *sprintf(), *malloc(); /* JJD 3-89 for lint */
Xchar *sprintf(); /* JJD 3-89 for lint */
Xchar *index();
X
X#define OK 0
X#define FINISHED_EDITING -1
X#define FINISHED_BUT_DONT_ADD_CTRL_M -2
X#define HAVE_CHAR -3
X#define UNIVERSAL_ARGUMENT_MAXIMUM 256
X#define MAX_CMD_LINE_LENGTH CANBSIZ
X#define VERSION "1.0 August 21st 1989"
X#define RK_VERSION " 1.0 August 21st 1989"
X#define ONE_LINE (int)1 /* JJD 3-89 was int dummy for tputs */
X
X
Xstruct ed_buffs {
X char string[MAX_CMD_LINE_LENGTH + 1];
X char *dot;
X char *mark; /* JJD 3-89 added */
X struct ed_buffs *next_ptr;
X struct ed_buffs *prev_ptr;
X };
X
Xtypedef struct _ed_struct {
X char current_input_char;
X int universal_argument;
X char *current_buffer;
X char *dot;
X char *mark;
X char kill_buffer[MAX_CMD_LINE_LENGTH + 1];
X struct ed_buffs *current_ed_buff_ptr;
X } ED_STRUCT;
X
X#define MAXEXTENSIONS 12
X
END_OF_FILE
if test 1071 -ne `wc -c <'file+rk.h'`; then
echo shar: \"'file+rk.h'\" unpacked with wrong size!
fi
# end of 'file+rk.h'
fi
if test -f 'freq.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'freq.c'\"
else
echo shar: Extracting \"'freq.c'\" \(5223 characters\)
sed "s/^X//" >'freq.c' <<'END_OF_FILE'
X/* Written by John Darragh, Calgary Alberta, revised 3-89.
X *
X * freq.c: tabulates ASCII character frequencies from stdin and outputs
X * freq sorted ASCII chars on the stdout in a number of formats.
X *
X * intended as a utility for rk_button to create its zero_freq
X * startup FREQ_DATA_FILE and/or default zero_freq[] char array.
X *
X * this info is used by rk to predict chars it hasn't yet added
X * to it's model (either by file priming or user command input).
X *
X * it puts any unseen chars in ASCII sequence, and puts any un-
X * represented control codes (including DEL) at the end.
X *
X * defaults: outputs 256 chars as 128 ASCII char/NL pairs.
X * (the NLs are just for readabilities sake, rk ignores them.)
X *
X * options:
X * -c write output as a C array for inclusion in programs.
X * -n don't put a NL after each of the 128 chars output.
X * (intended for future revision to init_reactive() which
X * would halve the freq file size from 256 -- saves space)
X * <filename> read data from file other than stdin.
X */
X
X#include <stdio.h>
X
X#define TRUE 1
X#define FALSE 0
X#define MAXTABLE 128 /* the size of the ASCII character set */
X
XFILE * infile = stdin; /* for <filename> arg */
Xchar no_nls = FALSE; /* -n option above */
Xchar c_array = FALSE; /* -c option above */
Xint ch_table[MAXTABLE][2]; /* [][0] are labels, [][1] are freq counts */
X
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X char chr; register int i, j; int gap, temp[2];
X
X get_args (argc, argv); /* may change infile, no_nls, c_array */
X /* init table labels and do the freq count */
X for (i=0; i<MAXTABLE; i++) {
X ch_table[i][0] = i; /* the ACSII code */
X ch_table[i][1]= -(i+1); /* ensure ASCII order for 0-freqs */
X } /* by intially -ve freq counts */
X while ((chr = getc(infile)) != EOF) {
X chr &= 0177;
X if (ch_table[(int)chr][1] < 0) /* seen, so fix -ve freqs */
X ch_table[(int)chr][1] = 0;
X ch_table[(int)chr][1]++;
X }
X for (i=0; i<32; i++) {
X if (ch_table[i][1] < 0) /* ensure 0-freq control codes */
X ch_table[i][1] -= MAXTABLE; /* end up at the end */
X }
X if (ch_table[MAXTABLE-1][1] < 0) /* ensure same for DEL char */
X ch_table[MAXTABLE-1][1] -= MAXTABLE;
X /* frequency sort the thing (shell sort) */
X for (gap = MAXTABLE/2; gap > 0; gap /= 2)
X for (i= gap; i < MAXTABLE; i++)
X for (j = i-gap; j >= 0; j -= gap) {
X if (ch_table[j][1] <= ch_table[j+gap][1])
X break;
X temp[0] = ch_table[j][0];
X temp[1] = ch_table[j][1];
X ch_table[j][0] = ch_table[j+gap][0];
X ch_table[j][1] = ch_table[j+gap][1];
X ch_table[j+gap][0] = temp[0];
X ch_table[j+gap][1] = temp[1];
X }
X /* output a compilable "C" character array */
X if (c_array) {
Xprintf ("static char zero_freq[128] = { /* by a user supplied $home/file */\n");
X for (i=MAXTABLE-1; i>=0; i--) {
X switch (chr = (char)(ch_table[i][0] & 127)) {
X case '\n': printf (" \'\\n\',"); break;
X case '\t': printf (" \'\\t\',"); break;
X case '\b': printf (" \'\\b\',"); break;
X case '\r': printf (" \'\\r\',"); break;
X case '\f': printf (" \'\\f\',"); break;
X case '\\': printf (" \'\\\\\',"); break;
X case '\'': printf (" \'\\\'\',"); break;
X case 127: printf ("\'\\%03o\',", (int)chr); break;
X default: if (chr < 32) printf (" \'\\%02o\',", (int)chr);
X else printf (" \'%1c\',", chr); break;
X }
X if (((i%8) == 0) && (i != 0)) printf ("\n");
X }
X printf ("};\n");
X /* otherwise just put out sorted chars */
X } else
X for (i=MAXTABLE-1; i>=0; i--)
X if (no_nls) printf ("%c", (char)ch_table[i][0]);
X else printf ("%c\n", (char)ch_table[i][0]);
X
X abortit ("", 0);
X}
X
X
Xstatic char *options = " -n[no_nls] -c[c_array] <input file>\n";
X
Xstatic get_args (argc, argv) /* may change infile */
Xint argc;
Xchar **argv;
X/*
X * Get any command arguments and set any appropriate
X * global flags and variables.
X */
X{
X static char usage[256] = "usage: ";
X
X strcat (usage, &argv[0][0]); /* fill in name of object file */
X strcat (usage, options);
X
X while ((argc > 1) && (argv[1][0] == '-')) {
X switch (argv[1][1]) {
X
X case 'c': case 'C': /* turn on C char array output */
X c_array = TRUE;
X break;
X
X case 'n': case 'N': /* turn on "no NL" output mode */
X no_nls = TRUE;
X break;
X
X default: abortit (usage, -1);
X
X } /*switch*/
X argc--; argv++;
X
X }
X if (argc == 2) { /* file argument present */
X if ((infile = fopen (&argv[1][0], "r")) == NULL) {
X fprintf (stderr, "cannot open: %s\n", &argv[1][0]);
X abortit (usage, -1);
X }
X } else if (argc != 1) abortit (usage, -1);
X}/*get_args*/
X
X
Xstatic abortit (message, status)
Xchar *message;
Xint status;
X/*
X * All program terminations are through this routine.
X * It prints an optional message, then exits with
X * the parameter status.
X */
X{
X fprintf (stderr, "%s", message);
X fflush (stderr);
X exit (status);
X}/*abortit*/
END_OF_FILE
if test 5223 -ne `wc -c <'freq.c'`; then
echo shar: \"'freq.c'\" unpacked with wrong size!
fi
# end of 'freq.c'
fi
if test -f 'functions.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'functions.h'\"
else
echo shar: Extracting \"'functions.h'\" \(1578 characters\)
sed "s/^X//" >'functions.h' <<'END_OF_FILE'
Xint append_to_output_string();
Xint accept_forward_char();
Xint accept_forward_word();
Xint accept_to_end_of_line();
Xint backspace_char();
Xint backspace_word();
Xint backward_char();
Xint backward_paren();
Xint backward_word();
Xint beginning_of_line();
Xint BOGUS();
Xint capitalize_word();
Xint clear_display();
Xint close_paren();
Xint command_completion();
Xint dash_to_ul_word();
Xint delete_char();
Xint delete_region_to_killbuffer();
Xint delete_word();
Xint describe_bindings();
Xint describe_arguments();
Xint discard_current_edit_line();
Xint discard_rest_of_line();
Xint end_of_line();
Xint file_completion();
Xint finish_editing_line();
Xint forward_char();
Xint forward_paren();
Xint forward_word();
Xint increment_universal_argument();
Xint insert_interrupt_char();
Xint insert_quit_char();
Xint insert_start_char();
Xint insert_stop_char();
Xint insert_suspend_char();
Xint lowercase_word();
Xint meta_prefix();
Xint next_line();
Xint next_pred();
Xint open_paren();
Xint previous_line();
Xint previous_pred();
Xint prime_from_file();
Xint quote_char();
Xint run_mesg();
Xint run_pp();
Xint run_ruptime();
Xint run_talk();
Xint run_tty_program();
Xint run_write();
Xint self_insert();
Xint set_mark();
Xint show_free_nodes();
Xint show_mark();
Xint show_version();
Xint toggle_add_space_mode();
Xint toggle_show_eol_mode();
Xint toggle_eol_longer_mode();
Xint toggle_eol_only_mode();
Xint toggle_lisp_mode();
Xint toggle_nl_truncate_mode();
Xint toggle_pred_mode();
Xint twiddle_chars();
Xint ul_to_dash_word();
Xint uppercase_word();
Xint yank_from_kill_buffer();
END_OF_FILE
if test 1578 -ne `wc -c <'functions.h'`; then
echo shar: \"'functions.h'\" unpacked with wrong size!
fi
# end of 'functions.h'
fi
if test -f 'myabspath.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'myabspath.c'\"
else
echo shar: Extracting \"'myabspath.c'\" \(869 characters\)
sed "s/^X//" >'myabspath.c' <<'END_OF_FILE'
X/* Mark James 89/5/24*/
X
X
X#include "myabspath.h"
X#include <pwd.h>
X#include <stdio.h>
X#include <ctype.h>
X#include <strings.h>
X
X
X/* returns 0 on success, NO_HOME if getenv("HOME") fails, NO_USER if ~user does not exist */
X
Xmyabspath(path,buff)
Xchar *path;
Xchar *buff;
X{
X char *homedir;
X char *getenv();
X char username[MAX_USER_NAME];
X int i;
X struct passwd *pwd;
X
X while (isspace(path[0])&&path[0])
X path++;
X if(path[0]=='~'){
X path++;
X if((path[0]=='/') || (path[0]==0)){
X if((homedir=getenv("HOME"))==0)
X return(NO_HOME);
X strcpy(buff,homedir);
X strcat(buff,path);
X return(0);
X }
X else
X {
X for(i=0;(path[0]!='/')&&(path[0]!=0);i++,path++)
X username[i]=path[0];
X username[i]=0;
X if((pwd=getpwnam(username))==0)
X return(NO_USER);
X strcpy(buff,pwd->pw_dir);
X strcat(buff,path);
X }
X }
X else
X {
X strcpy(buff,path);
X return(0);
X }
X}
X
X
X
X
END_OF_FILE
if test 869 -ne `wc -c <'myabspath.c'`; then
echo shar: \"'myabspath.c'\" unpacked with wrong size!
fi
# end of 'myabspath.c'
fi
if test -f 'myabspath.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'myabspath.h'\"
else
echo shar: Extracting \"'myabspath.h'\" \(64 characters\)
sed "s/^X//" >'myabspath.h' <<'END_OF_FILE'
X#define NO_HOME -1
X#define NO_USER -2
X
X#define MAX_USER_NAME 40
END_OF_FILE
if test 64 -ne `wc -c <'myabspath.h'`; then
echo shar: \"'myabspath.h'\" unpacked with wrong size!
fi
# end of 'myabspath.h'
fi
if test -f 'rk_button.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rk_button.c'\"
else
echo shar: Extracting \"'rk_button.c'\" \(7389 characters\)
sed "s/^X//" >'rk_button.c' <<'END_OF_FILE'
X#include "rk_button.h"
X#include "file+rk.h"
X
Xextern maxk;
Xextern max_nodes;
Xextern max_freq;
Xint maxprime=16*1024;
X
X /** shared with rk_file/file+rk **/
Xchar first[MAX_SET], /* the first letter of each pred */
X context[MAX_CMD_LINE_LENGTH] = "\07", /* last chars entered */
X old_context[MAX_CMD_LINE_LENGTH] = "\07";
XBuffer Buf, CBuf; /* ptrs into the model k levels */
Xchar *prime_file; /* file to prime from and log to */
Xint next_free = 0; /* index of next free node avail */
Xlong psize; /* # chars to prime from prime_file*/
X /* zero freqs, maybe overwritten */
Xstatic char zero_freq[128] = { /* by a user supplied $home/file */
X '\n', ' ', 'e', 's', 't', 'r', 'a', 'l',
X 'n', '.', 'c', 'i', 'm', 'o', 'd', 'h',
X 'p', 'u', 'f', 'b', 'w', 'g', '-', 'y',
X '/', 'v', 'k', '*', 'x', '5', '1', '2',
X '4', '>', 'q', '\07', '3', 'z', '0', 'j',
X 'M', 'I', '6', '\'', 'E', '~', 'A', ',',
X 'S', 'D', 'R', '?', 'C', '|', 'B', 'T',
X 'P', 'U', '!', '_', '<', 'N', '8', '@',
X '&', '7', '\\', '"', 'J', ')', '(', '[',
X ']', 'F', 'L', ':', 'O', 'K', '9', 'H',
X '+', '$', 'W', 'Y', '=', 'G', ';', '^',
X '{', 'X', 'Q', '#', '}', 'V', '%', 'Z',
X '`', '\b', '\t', '\26', '\00', '\01', '\02', '\03',
X '\04', '\05', '\06', '\13', '\f', '\r', '\16', '\17',
X '\20', '\21', '\22', '\23', '\24', '\25', '\27', '\30',
X '\31', '\32', '\33', '\34', '\35', '\36', '\37','\177',};
X
Xchar *zero_freq_file;
X
Xstatic char pred_set[MAX_SET]; /* flags chars already in first[]*/
X
Xstatic NodePtr free_nodes; /* now use malloc to get at init */
Xstatic NodePtr root; /* the root of the k model trie */
X
XNodePtr create_node() { /* return ptr to a new node or abort */
X if (next_free >= max_nodes) {
X char *malloc(); NodePtr nptr;
X nptr = (NodePtr) malloc((unsigned) sizeof(Node));
X if (nptr == nil) /* SHOULD FORGET AND CONTINUE ON */
X abortit ("Out of memory in create_node.\n",-1);
X next_free++; /* just for show_free_nodes */
X return(nptr); /* if more are needed */
X } else return(&free_nodes[next_free++]); /* first nodes upto MAX */
X}
X
XNodePtr move_up(nptr, c) NodePtr nptr; char c; {
X
X NodePtr xptr, fxptr, last_ptr, last_fptr; int state;
X
X if (nptr == nil) xptr = nil;
X else {
X if (nptr->up == nil) state = START;
X else {
X fxptr = xptr = nptr->up; last_fptr = last_ptr = nil;
X state = SCANNING;
X do {
X if (xptr == nil) state = END;
X else {
X if (fxptr->count > xptr->count) {
X last_fptr = last_ptr; fxptr = xptr; }
X if (xptr->value == c) {
X state = FOUND;
X if (fxptr != xptr) {
X if (last_fptr == nil) nptr->up = xptr;
X else last_fptr->next = xptr;
X last_ptr->next = xptr->next; xptr->next = fxptr;
X } } else { last_ptr = xptr; xptr = xptr->next; }
X } } while (state == SCANNING);
X }
X switch (state) {
X case FOUND:
X if (++(xptr->count) == max_freq) { /* Forgets on halving 1 */
X /*last_fptr =*/ fxptr = nptr->up;
X while (fxptr != nil) { /* JJD 9-86 */
X fxptr->count++;
X fxptr->count >>= 1;
X/* DOESN'T FORGET A NODES SUBTREE NODES YET SO DON'T DO IT */
X/* MAY HAcE TO INCREASE max_freq TO REDUCE HALcING & OcERHEAD */
X/* if (fxptr->count == 0) {
X last_fptr->next = fxptr->next;
Xwrite(1,"1/2 free\n",9);
X Free(fxptr);
X fxptr = last_fptr->next;
X } else {
X last_fptr = fxptr; */
X fxptr = fxptr->next;
X
X }
X }
X break;
X case START: case END:
X xptr = create_node();
X xptr->value = c; xptr->count = 1;
X xptr->up = xptr->next = nil;
X if (state == START) nptr->up = xptr;
X else last_ptr->next = xptr;
X break;
X }}
X return (xptr);
X}
X
Xfind_first(buf) Buffer buf; { /* find 1st char of all pred in context */
X
X int i, order = 0; NodePtr xptr; char *p;
X
X for (p= &pred_set[0]; p< &pred_set[MAX_SET]; p++) *p = '\0';
X for (i=maxk-1; i>=0; i--) {
X if (buf[i] != nil)
X if (buf[i]->up != nil) {
X xptr = buf[i]->up;
X while (xptr != nil) {
X if (!pred_set[(int)xptr->value]) {
X pred_set[(int)xptr->value]++;
X first[order++] = xptr->value;
X }
X xptr = xptr->next;
X } } }
X for (p= &zero_freq[0]; p< &zero_freq[MAX_SET]; p++)
X if (!pred_set[(int)*p]) first[order++] = *p;
X}
X
Xchar first_pred(buf) Buffer buf; {
X int i = maxk-1;
X for (;;) {
X if (buf[i] != nil)
X if (buf[i]->up != nil) return (buf[i]->up->value);
X if (i == 0) return((char)1);
X i--;
X }
X}
X
XNodePtr scan_up(nptr,c) NodePtr nptr; char c; {
X
X NodePtr xptr;
X if (nptr == nil) return(nil);
X else {
X xptr = nptr->up;
X for (;;) {
X if (xptr == nil) return (nil);
X else if (xptr->value == c) return(xptr);
X else xptr = xptr->next;
X } }
X}
X
Xinit_reactive() {
X double atof(), u;
X register int i; FILE *from, *popen();
X char c, *b, *rindex(), tbuf[256], home[128];
X char cbuf[32+1], *cstart, *cend, *end; int full; long size;
X
X /* get a bunch of nodes for starters */
X free_nodes = (NodePtr) malloc((unsigned) (max_nodes * sizeof(Node)));
X if (free_nodes == nil) {
X sprintf (tbuf, "cannot allocate %d nodes.\n", max_nodes);
X abortit (tbuf, -1);
X }
X /* set up root and pointers into model */
X CBuf[0] = Buf[0] = root = create_node();
X root->up = root->next = nil;
X root->count = 1;
X for (i=1; i<=maxk; i++) Buf[i] = nil;
X if ((from = fopen (zero_freq_file, "r")) != NULL) {
X i = 0;
X while (((int)(c = getc(from))) != EOF) {
X zero_freq[i++] = c;
X if (((int)(c = getc(from))) == EOF) break; /* del NL */
X if (i>127) break; /* test if okay */
X }
X } /* else use built in zero_freq[] */
X /* calc amount to prime, sys load dependent*/
X if ((from = popen ("uptime", "r")) != NULL) {
X fgets (tbuf, 128, from);
X b = rindex (tbuf, ':'); b++;
X u = atof(b);
X pclose (from);
X } else u = 1.0;
X if (u > 1.0) psize = (long) ((double)((double) maxprime) / u);
X else psize = (long) (maxprime);
X /* if user has .rk.log_file, prime from it */
X if ((from = fopen (prime_file, "r")) != NULL) {
X fseek (from, 0L, 2); /* find out how long it is */
X size = ftell (from);
X if (size > psize) { /* prime max chars at end */
X fseek (from, -psize, 2); /* start after ^G mark */
X/* on second thought, if not "logged" by rk, may be no ^Gs in the file */
X/* while ((((int)(c = getc(from))) != EOF) && (c != '\07')) ;*/
X } else rewind (from);
X cstart = cend = cbuf; end = &cbuf[maxk]; full = 0;
X while (((int)(c = getc(from))) != EOF) {
X *cstart = c;
X if (full) { ++cstart; if (cstart > end) cstart = cbuf; }
X if (++cend > end) { cend = cbuf; full = 1; }
X *cend = '\0';
X for (i=maxk; i>0; i--) Buf[i] = move_up(Buf[i-1],c);
X }
X i = 0; /* align the context */
X while (cstart != cend) {
X context[i] = old_context[i] = *cstart++; i++;
X if (cstart > end) cstart = cbuf;
X }
X fclose (from);
X }
X}
X
END_OF_FILE
if test 7389 -ne `wc -c <'rk_button.c'`; then
echo shar: \"'rk_button.c'\" unpacked with wrong size!
fi
# end of 'rk_button.c'
fi
if test -f 'rk_button.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rk_button.h'\"
else
echo shar: Extracting \"'rk_button.h'\" \(987 characters\)
sed "s/^X//" >'rk_button.h' <<'END_OF_FILE'
X/* definitions for rk_button, written by John Darragh, Calgary, revised 3-89
X */
X#include <ctype.h>
X#include <stdio.h>
X
X#define false 0
X#define true 1
X#define nil ((NodePtr)0)
X#define MAX_SET 128 /* max # of different symbols (ASCII) */
X#define TOP_K 10
X
X#define START 0 /* values for state variables */
X#define SCANNING 1
X#define FOUND 2
X#define END 3
X
Xtypedef struct node { /** variable length Markov tree node **/
X char value; /* ASCII symbol value (to MAX_SET-1) */
X char count; /* frequency count (to max_freq) */
X struct node *next; /* alternative predictions at this k */
X struct node *up; /* next k level up, eg 3 points to 4 */
X} Node;
Xtypedef Node *NodePtr; /** a pointer to a tree node **/
Xtypedef NodePtr Buffer[TOP_K+1]; /* k ptrs into the tree k contexts */
X
XNodePtr scan_up(), move_up();
Xchar first_pred();
END_OF_FILE
if test 987 -ne `wc -c <'rk_button.h'`; then
echo shar: \"'rk_button.h'\" unpacked with wrong size!
fi
# end of 'rk_button.h'
fi
if test -f 'rk_file.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rk_file.c'\"
else
echo shar: Extracting \"'rk_file.c'\" \(3279 characters\)
sed "s/^X//" >'rk_file.c' <<'END_OF_FILE'
X/* "FILE's" link to rk_button, written by John Darragh, Calgary, revised 3-89
X *
X * these are the main function used by file+rk.c to generate predictions
X */
X#include "rk_button.h"
X#include "file+rk.h"
X
Xextern int pred_number; /* Defined in file+rk.c */
Xextern char nl_truncate_mode,
X eol_only_mode,
X eol_longer_mode;
X show_eol_mode;
Xextern ED_STRUCT editor_data;
X
Xextern char first[MAX_SET], /* Defined in rk_button.c */
X context[MAX_CMD_LINE_LENGTH],
X old_context[MAX_CMD_LINE_LENGTH];
Xextern Buffer Buf, CBuf;
Xextern char *prime_file;
Xextern char pred_on_display;
Xint max_len=8;
Xint max_eol=30;
Xint maxk=8;
Xint max_freq=127;
Xint max_nodes=256*1024; /* 256K */
X
X
Xstatic char temp[1024]; /* scratch string buf */
X
X
Xmake_a_prediction (s) char *s; { /* sets s to the current prediction */
X
X char *a = temp; int length, i;
X
X if (eol_only_mode && *(editor_data.dot)) { *s = '\0'; return; }
X strcpy (temp, context);
X strcat (temp, editor_data.current_buffer);
X length = strlen (temp) - strlen (editor_data.dot);
X temp[length] = '\0';
X if (length > maxk) a = &temp[length - maxk];
X
X if (strcmp (old_context, a)) pred_number = 0;
X strcpy (old_context, a);
X
X for (i=1; i<=maxk; i++) CBuf[i] = nil;
X while (*a) {
X for (i=maxk; i>0; i--) CBuf[i] = scan_up(CBuf[i-1],*a);
X a++;
X }
X find_first(CBuf);
X build_menu(CBuf, s);
X }
X
Xupdate_the_model (s) char *s; { /* adds s into the model & updates log */
X
X char *a = s, *c = s; int length, i; FILE *to;
X
X if (strlen(s) < maxk) {
X strcpy (temp, context);
X strcat (temp, s);
X length = strlen (temp);
X if (length > maxk) a = &temp[length - maxk];
X else a = temp;
X }
X strcpy (context, a);
X while (*c) {
X for (i=maxk; i>0; i--) Buf[i] = move_up(Buf[i-1],*c);
X c++;
X } /* do not save "empty" lines in the log file */
X /* reopen to append log, otherwise create it */
X if (s[0] != '\n') { /* now log can be manipulated and still used */
X if ((to = fopen (prime_file, "a")) == NULL) {
X sprintf (temp, "cannot reopen or create: %s\n", prime_file);
X abortit (temp, -1);
X }
X fputs (s, to); fflush (to);
X fclose(to);
X }
X}
X
Xbuild_menu(buf,s) Buffer buf; char *s; { /* fill out prediction in s */
X
X int i,j,length; Buffer tbuf; char *bptr = s, c;
X
X if (eol_longer_mode && !(*(editor_data.dot))) {
X length = max_eol
X - get_display_length(editor_data.current_buffer);
X if (length < max_len) length = max_len;
X } else length = max_len;
X
X c = first[pred_number];
X for (i=0; i<=maxk; i++) tbuf[i] = buf[i];
X for (i=1; i<=length; i++) {
X if (show_eol_mode)
X *bptr++ = c;
X else if((c != '\n') || (i==1))
X *bptr++ = c;
X if (nl_truncate_mode && (c == '\n')) goto bp;
X for (j=maxk; j>=1; j--) tbuf[j] = scan_up (tbuf[j-1],c);
X c = first_pred(tbuf);
X }
Xbp: *bptr = '\0';
X}
X
X
Xshutdown_() {
X FILE *to;
X if ((to = fopen (prime_file, "a")) != NULL) {
X fputs ("\07", to); fflush (to); fclose(to);
X }
X}
X
Xabortit (message, status)
Xchar *message;
Xint status;
X{
X if(pred_on_display)
X erase_pred_buffer(&editor_data);
X shutdown_pty_and_tty();
X shutdown_();
X fprintf (stderr, "%s", message);
X fflush (stdout); fflush (stderr);
X exit (status);
X}
END_OF_FILE
if test 3279 -ne `wc -c <'rk_file.c'`; then
echo shar: \"'rk_file.c'\" unpacked with wrong size!
fi
# end of 'rk_file.c'
fi
echo shar: End of archive 1 \(of 4\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 4 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
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.
More information about the Comp.sources.unix
mailing list