pvr@wang.com (Peter Reilley) (02/28/91)
#! /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 4 (of 11)." # Contents: line.c symbol.c # Wrapped by pvr@elf on Wed Feb 27 14:16:48 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'line.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'line.c'\" else echo shar: Extracting \"'line.c'\" \(18200 characters\) sed "s/^X//" >'line.c' <<'END_OF_FILE' X/* X* Text line handling. X* The functions in this file X* are a general set of line management X* utilities. They are the only routines that X* touch the text. They also touch the buffer X* and window structures, to make sure that the X* necessary updating gets done. There are routines X* in this file that handle the kill buffer too. X* It isn't here for any good reason. X* X* Note that this code only updates the dot and X* mark values in the window list. Since all the code X* acts on the current window, the buffer that we X* are editing must be being displayed, which means X* that "b_nwnd" is non zero, which means that the X* dot and mark values in the buffer headers are X* nonsense. X*/ X X#include "def.h" X Xbool ldelnewline_p (); Xvoid l_fix_up (); Xbool kinsert (); X X Xextern char MSG_cnt_alloc[]; Xextern char MSG_too_m_k[]; X#if RUNCHK Xextern char ERR_no_alloc[]; Xextern char ERR_db_dalloc[]; Xextern char ERR_lock[]; Xextern char ERR_lock_del[]; X#endif X#include "lintfunc.dec" X X#ifndef KBLOCK X#define KBLOCK 256 /* Kill buffer block size. */ X#endif X Xchar *kbufp = NULL; /* Kill buffer data. */ Xint kused = 0; /* # of bytes used in KB. */ Xint ksize = 0; /* # of bytes allocated in KB. */ X Xextern LINE *cur_pat; Xextern LINE *cur_mask; Xextern bool read_pat_mode; X X/* X* This routine allocates a block X* of memory large enough to hold a LINE X* containing "used" characters. The block is X* always rounded up a bit. Return a pointer X* to the new block, or NULL if there isn't X* any memory left. Print a message in the X* message line if no space. X*/ XLINE * lalloc (used) Xregister int used; X{ X register LINE * lp; X char buf[80], buf1[50]; X#if RUNCHK X if (read_pat_mode) X printf (ERR_no_alloc); X#endif X X if ((lp = (LINE *) malloc (sizeof (LINE) + used)) == NULL) X { X sprintf (buf1, MSG_cnt_alloc, R_POS_FMT(curwp)); X sprintf (buf, buf1, (A32)used); X writ_echo (buf); X curbp -> b_flag |= BFBAD;/* may be trashed */ X curwp -> w_flag |= WFMODE; X update (); X return (NULL); X } X lp -> l_size = used; X lp -> l_used = used; X lp -> l_file_offset = 0; /* set resonable initial value */ X return (lp); X} X X X/* X* Delete line "lp". Fix all of the X* links that might point at it (they are X* moved to offset 0 of the next line. X* Unlink the line from whatever buffer it X* might be in. Release the memory. The X* buffers are updated too; the magic conditions X* described in the above comments don't hold X* here. X*/ X Xvoid lfree (lp) Xregister LINE * lp; X{ X register BUFFER * bp; X register WINDOW * wp; X X#if RUNCHK X if (read_pat_mode) X printf (ERR_db_dalloc); X#endif X X wp = wheadp; X while (wp != NULL) X { X if (wp -> w_linep == lp) X { X wp -> w_linep = lp -> l_fp; X wp -> w_loff = 0; X } X X if (wp -> w_dotp == lp) X { X wp -> w_dotp = lp -> l_fp; X wp -> w_doto = 0; X } X X if (wp -> w_markp == lp) X { X wp -> w_markp = lp -> l_fp; X wp -> w_marko = 0; X } X X wp = wp -> w_wndp; X } X X bp = bheadp; X while (bp != NULL) X { X X if (bp -> b_nwnd == 0) X { X if (bp -> b_dotp == lp) X { X bp -> b_dotp = lp -> l_fp; X bp -> b_doto = 0; X } X X if (bp -> b_markp == lp) X { X bp -> b_markp = lp -> l_fp; X bp -> b_marko = 0; X } X } X bp = bp -> b_bufp; X } X X lp -> l_bp -> l_fp = lp -> l_fp; X lp -> l_fp -> l_bp = lp -> l_bp; X free ((char *) lp); X} X X X/* X* This routine gets called when X* a character is changed in place in the X* current buffer. It updates all of the required X* flags in the buffer and window system. The flag X* used is passed as an argument; if the buffer is being X* displayed in more than 1 window we change EDIT to X* HARD. Set MODE if the mode line needs to be X* updated (the "*" has to be set). X*/ Xvoid lchange (flag) Xregister int flag; X{ X register WINDOW * wp; X X if (curbp -> b_nwnd != 1) /* Ensure hard. */ X flag = WFHARD; X if ((curbp -> b_flag & BFCHG) == 0) X { X /* First change, so */ X flag |= WFMODE; /* update mode lines. */ X curbp -> b_flag |= BFCHG; X } X X wp = wheadp; X while (wp != NULL) X { X if (wp -> w_bufp == curbp) X wp -> w_flag |= flag; X wp = wp -> w_wndp; X } X} X X X/* X* Insert "n" copies of the character "c" X* at the current location of dot. In the easy case X* all that happens is the text is stored in the line. X* Always allocate some extra space in line so that edit X* will be faster next time but will save space in the general case. X* In the hard case, the line has to be reallocated. X* When the window list is updated, take special X* care; I screwed it up once. You always update dot X* in the current window. You update mark, and a X* dot in another window, if it is greater than X* the place where you did the insert. Return TRUE X* if all is well, and FALSE on errors. X*/ Xbool linsert (n, c) X{ X register char *cp1; X register char *cp2; X register LINE * lp1; X register LINE * lp2; X register LINE * lp3; X register short doto; X register int i; X register WINDOW * wp; X X#if RUNCHK X /* check that buffer size can be changed */ X if (curbp -> b_flag & BFSLOCK) X { X writ_echo (ERR_lock); X return (FALSE); X } X#endif X X lchange (WFMOVE); X lp1 = curwp -> w_dotp; /* Current line */ X if (lp1 == curbp -> b_linep) X { X /* At the end: special */ X if ((lp2 = lalloc (n + NBLOCK)) == NULL)/* Allocate new line */ X return (FALSE); X lp2 -> l_used = n; /* set to correct size */ X lp3 = lp1 -> l_bp; /* Previous line */ X lp3 -> l_fp = lp2; /* Link in */ X lp2 -> l_fp = lp1; X lp1 -> l_bp = lp2; X lp2 -> l_bp = lp3; X for (i = 0; i < n; ++i) X lp2 -> l_text[i] = c; X curwp -> w_dotp = lp2; X curwp -> w_doto = n; X lp2 -> l_file_offset = lp1 -> l_file_offset + lp1 -> l_used; X l_fix_up (lp2); /* re-adjust file offsets */ X return (TRUE); X } X X doto = curwp -> w_doto; /* Save for later. */ X if (lp1 -> l_used + n > lp1 -> l_size) X { X /* Hard: reallocate */ X if ((lp2 = lalloc (lp1 -> l_used + n + NBLOCK)) == NULL) X return (FALSE); X lp2 -> l_used = lp1 -> l_used + n; /* set to correct size */ X cp1 = &lp1 -> l_text[0]; X cp2 = &lp2 -> l_text[0]; X while (cp1 != &lp1 -> l_text[doto]) X *cp2++ = *cp1++; X cp2 += n; X while (cp1 != &lp1 -> l_text[lp1 -> l_used]) X *cp2++ = *cp1++; X lp1 -> l_bp -> l_fp = lp2; X lp2 -> l_fp = lp1 -> l_fp; X lp1 -> l_fp -> l_bp = lp2; X lp2 -> l_bp = lp1 -> l_bp; X lp2 -> l_file_offset = lp1 -> l_file_offset; X free ((char *) lp1); X } X else X { X /* Easy: in place */ X lp2 = lp1; /* Pretend new line */ X lp2 -> l_used += n; X cp2 = &lp1 -> l_text[lp1 -> l_used]; X cp1 = cp2 - n; X while (cp1 != &lp1 -> l_text[doto]) X *--cp2 = *--cp1; X } X X for (i = 0; i < n; ++i) /* Add the characters */ X lp2 -> l_text[doto + i] = c; X wp = wheadp; /* Update windows */ X while (wp != NULL) X { X if (wp -> w_linep == lp1) X { X wp -> w_linep = lp2; X } X X if (wp -> w_dotp == lp1) X { X wp -> w_dotp = lp2; X if (wp == curwp || wp -> w_doto > doto) X wp -> w_doto += n; X } X X if (wp -> w_markp == lp1) X { X wp -> w_markp = lp2; X if (wp -> w_marko > doto) X wp -> w_marko += n; X } X X wp = wp -> w_wndp; X } X l_fix_up (curwp -> w_dotp); /* re-adjust file offsets */ X return (TRUE); X} X X X/* X* This function deletes "n" bytes, X* starting at dot. It understands how to deal X* with end of lines, etc. It returns TRUE if all X* of the characters were deleted, and FALSE if X* they were not (because dot ran into the end of X* the buffer). The "kflag" is TRUE if the text X* should be put in the kill buffer. X*/ Xbool ldelete (n, kflag) X{ X register char *cp1; X register char *cp2; X register LINE * dotp; X register short doto, l_size, prev_size; X register WINDOW * wp; X X#if RUNCHK X /* check that buffer size can be changed */ X if (curbp -> b_flag & BFSLOCK) X { X writ_echo (ERR_lock_del); X return (FALSE); X } X#endif X X doto = curwp -> w_doto; X X lchange (WFMOVE); X X prev_size = 0; X while (((l_size = curwp -> w_dotp -> l_used) - doto) < n) X { X /* break out when there are no more lines to delete */ X if (l_size == prev_size) X break; X /* Must merge the two lines. */ X if (ldelnewline_p () == FALSE) X return (FALSE); X prev_size = l_size; X } X X dotp = curwp -> w_dotp; X X /* if at the end of the buffer then delete nothing */ X if (doto >= dotp -> l_used) X { X l_fix_up (dotp); /* re-adjust file offsets */ X return (TRUE); X } X cp1 = &dotp -> l_text[doto];/* Scrunch text. */ X cp2 = cp1 + n; X X /* put stuff to delete into the kill buffer */ X if (kflag != FALSE) X { X /* Kill? */ X while (cp1 != cp2) X { X if (kinsert (*cp1) == FALSE) X return (FALSE); X ++cp1; X } X X cp1 = &dotp -> l_text[doto]; X } X /* kill bytes in the current line */ X while (cp2 < &dotp -> l_text[dotp -> l_used]) X *cp1++ = *cp2++; X X dotp -> l_used -= n; X wp = wheadp; /* Fix windows */ X while (wp != NULL) X { X if (wp -> w_dotp == dotp && wp -> w_doto >= doto) X { X wp -> w_doto -= n; X if (wp -> w_doto < doto) X wp -> w_doto = doto; X } X X if (wp -> w_markp == dotp && wp -> w_marko >= doto) X { X wp -> w_marko -= n; X if (wp -> w_marko < doto) X wp -> w_marko = doto; X } X X wp = wp -> w_wndp; X } X l_fix_up (curwp -> w_dotp); /* re-adjust file offsets */ X return (TRUE); X} X X X/* X* Delete a newline. Join the current line X* with the next line. Always allocate some extra space, if this X* line was edited ones then it will probably be again. It will X* go faster the second time. If the next line is the magic X* header line always return TRUE; merging the last line X* with the header line can be thought of as always being a X* successful operation, even if nothing is done, and this makes X* the kill buffer work "right". Easy cases can be done by X* shuffling data around. Hard cases require that lines be moved X* about in memory. Return FALSE on error and TRUE if all X* looks ok. Called by "ldelete" only. X*/ Xbool ldelnewline_p () X{ X X register char *cp1; X register char *cp2; X register LINE * lp1; X register LINE * lp2; X register LINE * lp3; X register WINDOW * wp; X X lp1 = curwp -> w_dotp; X lp2 = lp1 -> l_fp; X if (lp2 == curbp -> b_linep) X { X /* At the buffer end. */ X if (lp1 -> l_used == 0) /* Blank line. */ X lfree (lp1); X return (TRUE); X } X X /* will next line fit in current line? */ X if (lp2 -> l_used <= lp1 -> l_size - lp1 -> l_used) X { X X cp1 = &lp1 -> l_text[lp1 -> l_used]; X cp2 = &lp2 -> l_text[0]; X while (cp2 != &lp2 -> l_text[lp2 -> l_used]) X *cp1++ = *cp2++; X wp = wheadp; X while (wp != NULL) X { X X if (wp -> w_linep == lp2) X { X wp -> w_linep = lp1; X wp -> w_loff += lp1 -> l_used; X } X X if (wp -> w_dotp == lp2) X { X wp -> w_dotp = lp1; X wp -> w_doto += lp1 -> l_used; X } X X if (wp -> w_markp == lp2) X { X wp -> w_markp = lp1; X wp -> w_marko += lp1 -> l_used; X } X X wp = wp -> w_wndp; X } X X lp1 -> l_used += lp2 -> l_used; X lp1 -> l_fp = lp2 -> l_fp; X lp2 -> l_fp -> l_bp = lp1; X free ((char *) lp2); X return (TRUE); X } X X /* lines too big so allocate a new one */ X if ((lp3 = lalloc (lp1 -> l_used + lp2 -> l_used + NBLOCK)) == NULL) X return (FALSE); X lp3 -> l_used = lp1 -> l_used + lp2 -> l_used; /* set to correct size */ X cp1 = &lp1 -> l_text[0]; X cp2 = &lp3 -> l_text[0]; X while (cp1 != &lp1 -> l_text[lp1 -> l_used]) X *cp2++ = *cp1++; X cp1 = &lp2 -> l_text[0]; X while (cp1 != &lp2 -> l_text[lp2 -> l_used]) X *cp2++ = *cp1++; X lp1 -> l_bp -> l_fp = lp3; X lp3 -> l_fp = lp2 -> l_fp; X lp2 -> l_fp -> l_bp = lp3; X lp3 -> l_bp = lp1 -> l_bp; X lp3 -> l_file_offset = lp1 -> l_file_offset; X wp = wheadp; X while (wp != NULL) X { X X if (wp -> w_linep == lp1 || wp -> w_linep == lp2) X { X wp -> w_linep = lp3; X if (wp -> w_linep == lp2) X wp -> w_loff += lp1 -> l_used; X } X X if (wp -> w_dotp == lp1) X wp -> w_dotp = lp3; X else X if (wp -> w_dotp == lp2) X { X wp -> w_dotp = lp3; X wp -> w_doto += lp1 -> l_used; X } X X if (wp -> w_markp == lp1) X wp -> w_markp = lp3; X else X if (wp -> w_markp == lp2) X { X wp -> w_markp = lp3; X wp -> w_marko += lp1 -> l_used; X } X X wp = wp -> w_wndp; X } X X free ((char *) lp1); X free ((char *) lp2); X return (TRUE); X} X X/* X* Replace character at dot position. X*/ Xbool lreplace (n, c) Xint n; Xchar c; X { X lchange (WFEDIT); X while (n--) X { X DOT_CHAR(curwp) = c & 0xff; X move_ptr (curwp, 1L, TRUE, FALSE, TRUE); X } X } X X/* X* Replace plen characters before dot with argument string. X*/ Xbool lrepl_str (plen, rstr, mstr) X Xregister int plen; /* length to remove */ Xregister LINE *rstr; /* replace string */ Xregister LINE *mstr; /* mask string */ X{ X register int i; /* used for random characters */ X register LINE *dotp; /* pointer to line structure */ X register int doto; /* offset into line */ X register int rlen; /* rplace string length */ X register char c; /* temp storage for char */ X register char mask; /* temp storage for mask */ X X /* X * make the string lengths match (either pad the line X * so that it will fit, or scrunch out the excess). X * be careful with dot's offset. X */ X doto = curwp -> w_doto; X rlen = rstr -> l_used; X if (plen > rlen) X { X ldelete (plen - rlen, FALSE); X } X else if (plen < rlen) X { X if (linsert (rlen - plen, ' ') == FALSE) X return (FALSE); X } X curwp -> w_doto = doto; X dotp = curwp -> w_dotp; /* save dot line for later */ X X /* do the replacement. */ X for (i = 0; i < rlen; i++) X { X c = DOT_CHAR(curwp); X mask = mstr -> l_text[i]; X DOT_CHAR(curwp) = (c & mask) | (rstr -> l_text[i] & ~mask); X move_ptr (curwp, 1L, TRUE, FALSE, TRUE); X } X curwp -> w_doto = doto; X curwp -> w_dotp = dotp; X lchange (WFHARD); X return (TRUE); X} X X X/* X* Delete all of the text X* saved in the kill buffer. Called by commands X* when a new kill context is being created. The kill X* buffer array is released, just in case the buffer has X* grown to immense size. No errors. X*/ Xvoid kdelete () X{ X if (kbufp != NULL) X { X free ((char *) kbufp); X kbufp = NULL; X kused = 0; X ksize = 0; X } X} X X/* X* Insert a character to the kill buffer, X* enlarging the buffer if there isn't any room. Always X* grow the buffer in chunks, on the assumption that if you X* put something in the kill buffer you are going to put X* more stuff there too later. Return TRUE if all is X* well, and FALSE on errors. Print a message on X* errors. X*/ Xbool kinsert (c) X{ X register char *nbufp; X register int i; X X if (kused == ksize) X { X if ((nbufp = malloc (ksize + KBLOCK)) == NULL) X { X writ_echo (MSG_too_m_k); X return (FALSE); X } X for (i = 0; i < ksize; ++i) X nbufp[i] = kbufp[i]; X if (kbufp != NULL) X free ((char *) kbufp); X kbufp = nbufp; X ksize += KBLOCK; X } X kbufp[kused++] = c; X return (TRUE); X} X X X/* X* This function gets characters from X* the kill buffer. If the character index "n" is X* off the end, it returns "-1". This lets the caller X* just scan along until it gets a "-1" back. X*/ Xchar kremove (n) X{ X if (n >= kused) X return (-1); X return (kbufp[n] & 0xFF); X} X X/* X* Line fixup. X* This fixes the 'l_file_offset' variable in X* each line structure. X* This is necessary after every change in the size X* of the buffer. X*/ Xvoid l_fix_up (line) X XLINE * line; /* points to buffer header line */ X X{ X long offset; X LINE * end_line; X X end_line = curwp -> w_bufp -> b_linep;/* header line */ X X if (line == NULL) X line = end_line -> l_fp;/* point to first line */ X X offset = line -> l_file_offset;/* starting offset */ X offset += line -> l_used; X while ((line = line -> l_fp) != end_line) X { X line -> l_file_offset = offset; X offset += line -> l_used; X } X} X X X END_OF_FILE if test 18200 -ne `wc -c <'line.c'`; then echo shar: \"'line.c'\" unpacked with wrong size! fi chmod +x 'line.c' # end of 'line.c' fi if test -f 'symbol.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'symbol.c'\" else echo shar: Extracting \"'symbol.c'\" \(18827 characters\) sed "s/^X//" >'symbol.c' <<'END_OF_FILE' X/* X* Symbol table stuff. X* Symbol tables, and keymap setup. X* The terminal specific parts of building the X* keymap has been moved to a better place. X*/ X#define LINT_ARGS 1 /* enable lint type checking */ X#include "def.h" X Xvoid keyadd (); Xvoid keydup (); X X Xextern char MSG_byte_shift[]; Xextern char MSG_back_char[]; Xextern char MSG_quit[]; Xextern char MSG_forw_del_char[]; Xextern char MSG_toggle_swap[]; Xextern char MSG_forw_char[]; Xextern char MSG_abort[]; Xextern char MSG_ins_self[]; Xextern char MSG_back_del_char[]; Xextern char MSG_refresh[]; Xextern char MSG_forw_line[]; Xextern char MSG_back_line[]; Xextern char MSG_quote[]; Xextern char MSG_recall[]; Xextern char MSG_twiddle[]; Xextern char MSG_forw_page[]; Xextern char MSG_kill_region[]; Xextern char MSG_yank[]; Xextern char MSG_down_window[]; Xextern char MSG_ins_toggle[]; Xextern char MSG_display_buffers[]; Xextern char MSG_quit[]; Xextern char MSG_exit_flush_all[]; Xextern char MSG_set_file_name[]; Xextern char MSG_file_insert[]; Xextern char MSG_buf_size_lock[]; Xextern char MSG_flush_all[]; Xextern char MSG_down_window[]; Xextern char MSG_up_window[]; Xextern char MSG_file_read[]; Xextern char MSG_file_save[]; Xextern char MSG_file_visit[]; Xextern char MSG_file_write[]; Xextern char MSG_swap_dot_and_mark[]; Xextern char MSG_shrink_window[]; Xextern char MSG_display_position[]; Xextern char MSG_start_macro[]; Xextern char MSG_end_macro[]; Xextern char MSG_help[]; Xextern char MSG_only_window[]; Xextern char MSG_split_window[]; Xextern char MSG_use_buffer[]; Xextern char MSG_spawn_cli[]; Xextern char MSG_execute_macro[]; Xextern char MSG_goto_line[]; Xextern char MSG_ins_unit[]; Xextern char MSG_kill_buffer[]; Xextern char MSG_load_bindings[]; Xextern char MSG_forw_window[]; Xextern char MSG_back_window[]; Xextern char MSG_view_file[]; Xextern char MSG_enlarge_window[]; Xextern char MSG_ascii_mode[]; Xextern char MSG_binary_mode[]; Xextern char MSG_buffer_name[]; Xextern char MSG_decimal_mode[]; Xextern char MSG_ebcdic_mode[]; Xextern char MSG_hex_mode[]; Xextern char MSG_back_del_unit[]; Xextern char MSG_octal_mode[]; Xextern char MSG_display_version[]; Xextern char MSG_unit_size1[]; Xextern char MSG_unit_size2[]; Xextern char MSG_unit_size4[]; Xextern char MSG_reposition_window[]; Xextern char MSG_set_mark[]; Xextern char MSG_goto_eob[]; Xextern char MSG_goto_bob[]; Xextern char MSG_next_buff[]; Xextern char MSG_prev_buff[]; Xextern char MSG_query_replace[]; Xextern char MSG_display_bindings[]; Xextern char MSG_auto_save[]; Xextern char MSG_back_unit[]; Xextern char MSG_compare[]; Xextern char MSG_forw_del_unit[]; Xextern char MSG_forw_unit[]; Xextern char MSG_link_windows[]; Xextern char MSG_print[]; Xextern char MSG_back_search[]; Xextern char MSG_forw_search[]; Xextern char MSG_back_page[]; Xextern char MSG_copy_region[]; Xextern char MSG_extended_command[]; Xextern char MSG_up_window[]; Xextern char MSG_search_again[]; Xextern char MSG_bind_to_key[]; Xextern char MSG_file_visit_split[]; Xextern char MSG_yank_buffer[]; Xextern char MSG_save_region[]; Xextern char MSG_use_buffer_split[]; Xextern char MSG_no_f_tb[]; X X/* X* Defined by "main.c". X*/ Xextern char ctrlg (); /* Abort out of things */ Xextern char quit (); /* Quit */ Xextern char ctlxlp (); /* Begin macro */ Xextern char ctlxrp (); /* End macro */ Xextern char ctlxe (); /* Execute macro */ Xextern char showversion (); /* Show version numbers, etc. */ Xextern char flushnquit (); /* Flush buffers & exit (fitz) */ Xextern char flush_all (); /* Flush buffers (jam) */ Xextern char autosave (); /* autosave function (jam) */ X X/* X* Defined by "search.c". X*/ Xextern char forwsearch (); /* Search forward */ Xextern char backsearch (); /* Search backwards */ Xextern char searchagain (); /* Repeat last search command */ Xextern char queryrepl (); /* Query replace */ Xextern char compare (); /* Compare two windows */ Xextern char recall (); /* Recall last search string */ X X/* X* Defined by "basic.c". X*/ Xextern char backchar (); /* Move backward by characters */ Xextern char forwchar (); /* Move forward by characters */ Xextern char gotobob (); /* Move to start of buffer */ Xextern char gotoeob (); /* Move to end of buffer */ Xextern char forwline (); /* Move forward by lines */ Xextern char backline (); /* Move backward by lines */ Xextern char forwpage (); /* Move forward by pages */ Xextern char backpage (); /* Move backward by pages */ Xextern char setmark (); /* Set mark */ Xextern char swapmark (); /* Swap "." and mark */ Xextern char gotoline (); /* Go to a specified line. */ X X/* X* Defined by "buffer.c". X*/ Xextern char listbuffers (); /* Display list of buffers */ Xextern char usebuffer (); /* Switch a window to a buffer */ Xextern char use_buffer (); /* ditto, plus window split */ Xextern char killbuffer (); /* Make a buffer go away. */ Xextern char next_buf (); /* goto next buffer */ Xextern char prev_buf (); /* goto prev buffer */ Xextern char yank_buffer (); /* yank buffer by name */ Xextern char buffername (); /* change buffer name */ Xextern char bufsizlock (); /* lock buffer size */ X X/* X* Defined by "file." X*/ Xextern char fileread (); /* Get a file, read only */ Xextern char filevisit (); /* Get a file, read write */ Xextern char file_visit (); /* ditto , plus window split */ Xextern char filewrite (); /* Write a file */ Xextern char filesave (); /* Save current file */ Xextern char filename (); /* Adjust file name */ Xextern char fileinsert (); /* insert file to cursor (jam ) */ Xextern char viewfile (); /* readonly file visit (jam) */ X X/* X* Defined by "random.c". X*/ X Xextern char dispshift (); /* Increment display shift */ Xextern char selfinsert (); /* Insert character */ Xextern char insert_toggle (); /* toggle insert mode (jam) */ Xextern char insertunit (); /* insert unit (pvr) */ Xextern char showcpos (); /* Show the cursor position */ Xextern char twiddle (); /* Twiddle units */ Xextern char forwdel (); /* Forward delete */ Xextern char backdel (); /* Backward delete */ Xextern char quote (); /* Insert literal */ Xextern char asciimode (); /* display ASCII data */ Xextern char ebcdicmode (); /* display EBCDIC data */ Xextern char decimalmode (); /* display DECIMAL data */ Xextern char hexmode (); /* display HEX data */ Xextern char octalmode (); /* display OCTAL data */ Xextern char binarymode (); /* display BINARY data */ Xextern char dispsize1 (); /* display in BYTE format */ Xextern char dispsize2 (); /* display in WORD format */ Xextern char dispsize4 (); /* display in DWORD format*/ Xextern char dispswapbyte (); /* Display swaped bytes pvr */ Xextern char yank (); /* Yank back from killbuffer. */ Xextern char linkwind (); /* Link all windows on one buffer. */ X X/* X* Defined by "region.c". X*/ Xextern char killregion (); /* Kill region. */ Xextern char copyregion (); /* Copy region to kill buffer. */ Xextern char save_region (); /* Save region in named buffer. */ X X/* X* Defined by "spawn.c". X*/ Xextern char spawncli (); /* Run CLI in a subjob. */ Xextern char clock (); /* display time in modeline */ X X/* X* Defined by "window.c". X*/ Xextern char reposition (); /* Reposition window */ Xextern char refresh (); /* Refresh the screen */ Xextern char nextwind (); /* Move to the next window */ Xextern char prevwind (); /* Move to the previous window */ Xextern char mvdnwind (); /* Move window down */ Xextern char mvupwind (); /* Move window up */ Xextern char onlywind (); /* Make current window only one */ Xextern char splitwind (); /* Split current window */ Xextern char enlargewind (); /* Enlarge display window. */ Xextern char shrinkwind (); /* Shrink window. */ X X/* X* Defined by "word.c". X*/ Xextern char backunit (); /* Backup by units */ Xextern char forwunit (); /* Advance by units */ Xextern char delfunit (); /* Delete forward unit. */ Xextern char delbunit (); /* Delete backward unit. */ X X/* X* Defined by "extend.c". X*/ Xextern char extend (); /* Extended commands. */ Xextern char help (); /* Help key. */ Xextern char bindtokey (); /* Modify key bindings. */ Xextern char wallchart (); /* Make wall chart. */ Xextern char check_extend (); /* load extended key file */ Xextern char load_extend (); /* load extended file by name */ X X/* X* Defined by "display.c X*/ Xextern char print (); /* print window from mark to dot */ X Xtypedef struct X{ X X short k_key; /* Key to bind. */ X char (*k_funcp) (); /* Function. */ X char *k_name; /* Function name string. */ X char k_modify; /* modify bit */ X} X KEY; X X/* X* Default key binding table. This contains X* the function names, the symbol table name, and (possibly) X* a key binding for the builtin functions. There are no X* bindings for C-U or C-X. These are done with special X* code, but should be done normally. X*/ XKEY key[] = X{ X KCTRL | 'A', dispshift, MSG_byte_shift, 0, X KCTRL | 'B', backchar, MSG_back_char, SSRCH | SRPLC, X KCTRL | 'C', quit, MSG_quit, 0,/* pvr */ X KCTRL | 'D', forwdel, MSG_forw_del_char, SMOD | SSIZE | SSRCH | SRPLC, X KCTRL | 'E', dispswapbyte, MSG_toggle_swap, SSRCH | SRPLC,/* pvr */ X KCTRL | 'F', forwchar, MSG_forw_char, SSRCH | SRPLC, X KCTRL | 'G', ctrlg, MSG_abort, SSRCH | SRPLC, X KCTRL | 'I', selfinsert, MSG_ins_self, SMOD | SSRCH | SRPLC, X KCTRL | 'H', backdel, MSG_back_del_char, SMOD | SSIZE | SSRCH | SRPLC, X KCTRL | 'L', refresh, MSG_refresh, SSRCH | SRPLC, X KCTRL | 'N', forwline, MSG_forw_line, SSRCH | SRPLC, X KCTRL | 'P', backline, MSG_back_line, SSRCH | SRPLC, X KCTRL | 'Q', quote, MSG_quote, 0, X KCTRL | 'R', recall, MSG_recall, SSRCH | SRPLC, X KCTRL | 'T', twiddle, MSG_twiddle, SMOD | SSRCH | SRPLC, X KCTRL | 'V', forwpage, MSG_forw_page, SRPLC, X KCTRL | 'W', killregion, MSG_kill_region, SMOD | SSIZE, X KCTRL | 'Y', yank, MSG_yank, SMOD | SSIZE, X KCTRL | 'Z', mvdnwind, MSG_down_window, 0,/* fitz */ X KCTLX | KCTRL | 'A', insert_toggle, MSG_ins_toggle, SSRCH | SRPLC, X KCTLX | KCTRL | 'B', listbuffers, MSG_display_buffers, 0, X KCTLX | KCTRL | 'C', quit, MSG_quit, 0, X KCTLX | KCTRL | 'E', flushnquit, MSG_exit_flush_all, 0,/* fitz */ X KCTLX | KCTRL | 'F', filename, MSG_set_file_name, SMOD,/* jam */ X KCTLX | KCTRL | 'I', fileinsert, MSG_file_insert, SMOD | SSIZE, X KCTLX | KCTRL | 'L', bufsizlock, MSG_buf_size_lock, 0, X KCTLX | KCTRL | 'M', flush_all, MSG_flush_all, 0, X KCTLX | KCTRL | 'N', mvdnwind, MSG_down_window, 0, X KCTLX | KCTRL | 'P', mvupwind, MSG_up_window, 0, X KCTLX | KCTRL | 'R', fileread, MSG_file_read, 0, X KCTLX | KCTRL | 'S', filesave, MSG_file_save, 0, X KCTLX | KCTRL | 'V', filevisit, MSG_file_visit, 0, X KCTLX | KCTRL | 'W', filewrite, MSG_file_write, 0, X KCTLX | KCTRL | 'X', swapmark, MSG_swap_dot_and_mark, 0, X KCTLX | KCTRL | 'Z', shrinkwind, MSG_shrink_window, 0, X KCTLX | '=', showcpos, MSG_display_position, 0, X KCTLX | '(', ctlxlp, MSG_start_macro, 0, X KCTLX | ')', ctlxrp, MSG_end_macro, 0, X KCTLX | '?', help, MSG_help, 0, X KCTLX | '1', onlywind, MSG_only_window, 0, X KCTLX | '2', splitwind, MSG_split_window, 0, X KCTLX | 'B', usebuffer, MSG_use_buffer, 0, X KCTLX | 'C', spawncli, MSG_spawn_cli, 0,/* fitz */ X KCTLX | 'E', ctlxe, MSG_execute_macro, 0, X KCTLX | 'G', gotoline, MSG_goto_line, 0, X KCTLX | 'I', insertunit, MSG_ins_unit, SMOD | SSIZE | SSRCH | SRPLC, X KCTLX | 'K', killbuffer, MSG_kill_buffer, 0, X KCTLX | 'L', load_extend, MSG_load_bindings, 0, X KCTLX | 'N', nextwind, MSG_forw_window, 0, X KCTLX | 'P', prevwind, MSG_back_window, 0, X KCTLX | 'V', viewfile, MSG_view_file, 0,/* jam */ X KCTLX | 'Z', enlargewind, MSG_enlarge_window, 0, X KMETA | KCTRL | 'A', asciimode, MSG_ascii_mode, SSRCH | SRPLC, /* pvr */ X KMETA | KCTRL | 'B', binarymode, MSG_binary_mode, SSRCH | SRPLC, /* pvr */ X KMETA | KCTRL | 'N', buffername, MSG_buffer_name, 0, X KMETA | KCTRL | 'D', decimalmode, MSG_decimal_mode, SSRCH | SRPLC, /* pvr */ X KMETA | KCTRL | 'E', ebcdicmode, MSG_ebcdic_mode, SSRCH | SRPLC, /* pvr */ X KMETA | KCTRL | 'H', hexmode, MSG_hex_mode, SSRCH | SRPLC, /* pvr */ X KMETA | KCTRL | 'K', delbunit, MSG_back_del_unit, SMOD | SSIZE | SSRCH | SRPLC, X KMETA | KCTRL | 'O', octalmode, MSG_octal_mode, SSRCH | SRPLC, /* pvr */ X KMETA | KCTRL | 'V', showversion, MSG_display_version, 0, X KMETA | '1', dispsize1, MSG_unit_size1, SSRCH | SRPLC,/* pvr */ X KMETA | '2', dispsize2, MSG_unit_size2, SSRCH | SRPLC,/* pvr */ X KMETA | '4', dispsize4, MSG_unit_size4, SSRCH | SRPLC,/* pvr */ X KMETA | '!', reposition, MSG_reposition_window, 0, X KMETA | '.', setmark, MSG_set_mark, 0, X KMETA | '>', gotoeob, MSG_goto_eob, SSRCH | SRPLC, X KMETA | '<', gotobob, MSG_goto_bob, SSRCH | SRPLC, X KMETA | '+', next_buf, MSG_next_buff, 0, X KMETA | '-', prev_buf, MSG_prev_buff, 0, X KMETA | '%', queryrepl, MSG_query_replace, SMOD, X KMETA | '?', wallchart, MSG_display_bindings, 0, X KMETA | 'A', autosave, MSG_auto_save, 0, X KMETA | 'B', backunit, MSG_back_unit, SSRCH | SRPLC, X KMETA | 'C', compare, MSG_compare, 0, X KMETA | 'D', delfunit, MSG_forw_del_unit, SMOD | SSIZE | SSRCH | SRPLC, X KMETA | 'F', forwunit, MSG_forw_unit, SSRCH | SRPLC, X KMETA | 'G', use_buffer, MSG_use_buffer_split, 0, X KMETA | 'K', bindtokey, MSG_bind_to_key, 0, X KMETA | 'L', linkwind, MSG_link_windows, 0, X KMETA | 'O', save_region, MSG_save_region, 0, X KMETA | 'P', print, MSG_print, 0, X KMETA | 'R', backsearch, MSG_back_search, 0, X KMETA | 'S', forwsearch, MSG_forw_search, 0, X KMETA | 'T', searchagain, MSG_search_again, 0, X KMETA | 'U', file_visit, MSG_file_visit_split, 0, X KMETA | 'V', backpage, MSG_back_page, SRPLC, X KMETA | 'W', copyregion, MSG_copy_region, 0, X KMETA | 'X', extend, MSG_extended_command, 0, X KMETA | 'Y', yank_buffer, MSG_yank_buffer, SMOD | SSIZE, X KMETA | 'Z', mvupwind, MSG_up_window, 0 X}; X X#define NKEY (sizeof(key) / sizeof(key[0])) X X/* X* Symbol table lookup. X* Return a pointer to the SYMBOL node, or NULL if X* the symbol is not found. X*/ XSYMBOL * symlookup (cp) Xregister char *cp; X{ X register SYMBOL * sp; X X sp = symbol[symhash (cp)]; X while (sp != NULL) X { X if (strcmp (cp, sp -> s_name) == 0) X return (sp); X sp = sp -> s_symp; X } X return (NULL); X} X X X/* X* Take a string, and compute the symbol table X* bucket number. This is done by adding all of the characters X* together, and taking the sum mod NSHASH. The string probably X* should not contain any GR characters; if it does the "*cp" X* may get a nagative number on some machines, and the "%" X* will return a negative number! X*/ Xint symhash (cp) Xregister char *cp; X{ X register int c; X register int n; X X n = 0; X while ((c = *cp++) != 0) X n += c; X return (n % NSHASH); X} X X X/* X* Build initial keymap. The funny keys X* (commands, odd control characters) are mapped using X* a big table and calls to "keyadd". The printing characters X* are done with some do-it-yourself handwaving. The terminal X* specific keymap initialization code is called at the X* very end to finish up. All errors are fatal. X*/ Xvoid keymapinit () X{ X register SYMBOL * sp; X register KEY * kp; X register int i; X register int hash; X X for (i = 0; i < NKEYS; ++i) X binding[i] = NULL; X for (kp = &key[0]; kp < &key[NKEY]; ++kp) X keyadd (kp -> k_key, kp -> k_funcp, kp -> k_name, kp -> k_modify); X keydup (KCTLX | KCTRL | 'G', MSG_abort); X keydup (KMETA | KCTRL | 'G', MSG_abort); X keydup (0x7F, MSG_back_del_char); X keydup (KMETA | 'Q', MSG_quote); X keydup (KMETA | 0x7F, MSG_back_del_unit); X /* X * Should be bound by "tab" already. X */ X if ((sp = symlookup (MSG_ins_self)) == NULL) X abort (); X for (i = 0x20; i < 0x7F; ++i) X { X if (binding[i] != NULL) X abort (); X binding[i] = sp; X ++sp -> s_nkey; X } X ttykeymapinit (); X} X X X/* X* Create a new builtin function "name" X* with function "funcp". If the "new" is a real X* key, bind it as a side effect. All errors X* are fatal. X*/ Xvoid keyadd (new, funcp, name, modify) Xint (*funcp) (); Xchar *name; X{ X register SYMBOL * sp; X register int hash; X X if ((sp = (SYMBOL *) malloc (sizeof (SYMBOL))) == NULL) X abort (); X hash = symhash (name); X sp -> s_symp = symbol[hash]; X symbol[hash] = sp; X sp -> s_nkey = 0; X sp -> s_name = name; X sp -> s_funcp = funcp; X sp -> s_modify = modify; X if (new >= 0) X { X /* Bind this key. */ X if (binding[new] != NULL) X abort (); X binding[new] = sp; X ++sp -> s_nkey; X } X} X X/* X* Bind key "new" to the existing X* routine "name". If the name cannot be found, X* or the key is already bound, abort. X*/ Xvoid keydup (new, name) Xregister int new; Xchar *name; X{ X register SYMBOL * sp; X X if (binding[new] != NULL || (sp = symlookup (name)) == NULL) X { X printf (MSG_no_f_tb, name); X abort (); X } X binding[new] = sp; X ++sp -> s_nkey; X} END_OF_FILE if test 18827 -ne `wc -c <'symbol.c'`; then echo shar: \"'symbol.c'\" unpacked with wrong size! fi chmod +x 'symbol.c' # end of 'symbol.c' fi echo shar: End of archive 4 \(of 11\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 11 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0