Newsgroups: comp.sources.misc
From: Peter Reilley <pvr@wang.com>
Subject:  v22i015:  beav - Binary file editor and viewer, Part06/09
Message-ID: <1991Aug14.200829.5845@sparky.IMD.Sterling.COM>
X-Md4-Signature: 7dc8d4c13b8c2cd934bf216e1c2529c9
Date: Wed, 14 Aug 1991 20:08:29 GMT
Approved: kent@sparky.imd.sterling.com

Submitted-by: Peter Reilley <pvr@wang.com>
Posting-number: Volume 22, Issue 15
Archive-name: beav/part06
Environment: UNIX, AIX, MSDOS

#! /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 6 (of 9)."
# Contents:  random.c search.c
# Wrapped by pvr@elf on Mon Aug 12 13:51:34 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'random.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'random.c'\"
else
echo shar: Extracting \"'random.c'\" \(28638 characters\)
sed "s/^X//" >'random.c' <<'END_OF_FILE'
X/*
X*              Assorted commands.
X* The file contains the command
X* processors for a large assortment of unrelated
X* commands. The only thing they have in common is
X* that they are all command processors.
X*/
X
X#include    "def.h"
X
Xchar    backdel ();
Xbool    fill_out ();
Xvoid    bad_key ();
X
X
X
Xextern    char    MSG_sh_pos[];
Xextern    char    MSG_sh_pos1[];
Xextern    char    MSG_f_str[];
Xextern    char    MSG_3u[];
Xextern    char    MSG_5u[];
Xextern    char    MSG_lu[];
Xextern    char    MSG_03u[];
Xextern    char    MSG_05u[];
Xextern    char    MSG_010lu[];
Xextern    char    MSG_lnk[];
Xextern    char    MSG_unlink[];
Xextern    char    MSG_link[];
Xextern    char    MSG_bad_key[];
Xextern    char    MSG_esc[];
Xextern    char    MSG_ctl_x[];
Xextern    char    MSG_ctl[];
Xextern    char    MSG_key_code[];
Xextern    char    char_str[];
Xextern    char    MSG_w_not_empty[];
Xextern    char    MSG_procing[];
Xextern    char    MSG_ok[];
X#if RUNCHK
Xextern    char    ERR_rnd_1[];
Xextern    char    ERR_rnd_2[];
Xextern    char    ERR_rnd_3[];
Xextern    char    ERR_rnd_4[];
Xextern    char    ERR_rnd_5[];
Xextern    char    ERR_rnd_6[];
Xextern    char    ERR_rnd_7[];
X#endif
X
Xextern  ROW_FMT ascii_fmt;
Xextern  ROW_FMT ebcdic_fmt;
Xextern  ROW_FMT binary_8_fmt;
Xextern  ROW_FMT binary_16_fmt;
Xextern  ROW_FMT binary_32_fmt;
Xextern  ROW_FMT octal_8_fmt;
Xextern  ROW_FMT octal_16_fmt;
Xextern  ROW_FMT octal_32_fmt;
Xextern  ROW_FMT decimal_8_fmt;
Xextern  ROW_FMT decimal_16_fmt;
Xextern  ROW_FMT decimal_32_fmt;
Xextern  ROW_FMT hex_8_fmt;
Xextern  ROW_FMT hex_16_fmt;
Xextern  ROW_FMT hex_32_fmt;
X
Xextern  bool    read_pat_mode;
Xextern  bool    dont_repeat;
Xextern    BUFFER  sav_buf;
X
Xchar    dec_chr_ok ();
Xulong   get_long ();
Xvoid wind_on_dot_all ();
X
X/*
X* Display a bunch of useful information about
X* the current location of dot and mark.
X* The position of the dot and mark and the difference between them.
X* The total buffer size is displayed.
X* This is normally bound to "C-X =".
X*/
Xbool showcpos (f, n, k)
X{
X
X	A32     dotoff,
X	    markoff,
X	    fsize,
X	    bsize;
X	char    buf[180], buf1[180];
X
X	dotoff = curwp -> w_dotp -> l_file_offset;
X	dotoff += curwp -> w_doto;
X
X	if (curwp -> w_markp != NULL)
X	{
X		markoff = curwp -> w_markp -> l_file_offset;
X		markoff += curwp -> w_marko;
X	}
X
X	bsize = curwp -> w_bufp -> b_linep -> l_bp -> l_file_offset;
X	bsize += curwp -> w_bufp -> b_linep -> l_bp -> l_used;
X	fsize = curbp -> b_file_size;
X
X	if (curwp -> w_markp != NULL)
X	{
X		/* build format string */
X		sprintf (buf1, MSG_sh_pos, R_POS_FMT(curwp), R_POS_FMT(curwp), 
X		    R_POS_FMT(curwp), R_POS_FMT(curwp));
X		sprintf (buf, buf1, dotoff, markoff, bsize, fsize);
X	}
X	else
X	{
X		/* build format string */
X		sprintf (buf1, MSG_sh_pos1, R_POS_FMT(curwp), R_POS_FMT(curwp), 
X		    R_POS_FMT(curwp));
X		sprintf (buf, buf1, dotoff, bsize, fsize);
X	}
X
X	sprintf (&buf[strlen(buf)], MSG_f_str, curbp -> b_fname);
X	writ_echo (buf);
X
X	return (TRUE);
X}
X
X
X/*
X* Twiddle the two characters on either side of
X* dot. If dot is at the end of the line twiddle the
X* two characters before it. Return with an error if dot
X* is at the beginning of line; it seems to be a bit
X* pointless to make this work. This fixes up a very
X* common typo with a single stroke. Normally bound
X* to "C-T". This always works within a line, so
X* "WFEDIT" is good enough.
X*/
Xbool twiddle ()
X{
X
X	register    LINE * dotp;
X	register short  doto;
X	register int    cl;
X	register int    cr;
X	char    b_per_u,
X	f_buf[4],
X	s_buf[4],
X	i;
X
X	dotp = curwp -> w_dotp;
X	doto = curwp -> w_doto;
X	b_per_u = curwp -> w_fmt_ptr -> r_b_per_u;
X	/* try to move back one unit */
X	if (!move_ptr (curwp, (long) - b_per_u, TRUE, TRUE, TRUE))
X	{
X		curwp -> w_dotp = dotp; /* if fail then restore dot and quit */
X		curwp -> w_doto = doto;
X		ttbeep ();
X		return (FALSE);
X	}
X	/* pick up first unit byte by byte */
X	for (i = 0; i < b_per_u; i++)
X	{
X		f_buf[i] = DOT_CHAR(curwp);
X		move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
X	}
X	/* move to the end of the second unit */
X	if (!move_ptr (curwp, (long) (b_per_u - 1), TRUE, FALSE, TRUE))
X	{
X		curwp -> w_dotp = dotp; /* if fail then restore dot and quit */
X		curwp -> w_doto = doto;
X		ttbeep ();
X		return (FALSE);
X	}
X	/* pick up second unit (reverse order) and deposit second unit */
X	for (i = 0; i < b_per_u; i++)
X	{
X		s_buf[i] = DOT_CHAR(curwp);
X		DOT_CHAR(curwp) = f_buf[b_per_u - 1 - i];
X		move_ptr (curwp, -1L, TRUE, FALSE, TRUE);
X	}
X	/* deposit first unit */
X	for (i = 0; i < b_per_u; i++)
X	{
X		DOT_CHAR(curwp) = s_buf[i];
X		move_ptr (curwp, -1L, TRUE, FALSE, TRUE);
X	}
X	curwp -> w_dotp = dotp;
X	curwp -> w_doto = doto;
X	lchange (WFHARD);
X	return (TRUE);
X}
X
X/*
X* Quote the next character, and
X* insert it into the buffer. All the characters
X* are taken literally.
X* The character
X* is always read, even if it is inserted 0 times, for
X* regularity.
X*/
Xbool quote (f, n, k)
X{
X
X	register int    s;
X	register int    c;
X
X	if (kbdmop != NULL)
X		c = *kbdmop++;
X	else
X	{
X		c = ttgetc ();
X		if (kbdmip != NULL)
X		{
X			if (kbdmip > &kbdm[NKBDM - 4])
X			{
X				ctrlg (FALSE, 0, KRANDOM);
X				return (ABORT);
X			}
X
X			*kbdmip++ = c;
X		}
X
X	}
X
X	if (n < 0)
X		return (FALSE);
X	if (n == 0)
X		return (TRUE);
X
X	return (linsert (n, c));
X}
X
X/*
X* Toggle the insert mode.  Insert mode is used only in ASCII or EBCDIC modes.
X*/
Xbool insert_toggle ()    /* toggle routine for selfinsert */
X{
X	register    WINDOW * wp;
X
X	if (curbp -> b_flag & BFSLOCK)
X		return (TRUE);
X
X	if (read_pat_mode)
X		dont_repeat = TRUE;
X
X	insert_mode = !insert_mode;
X	for (wp = wheadp; wp; wp = wp -> w_wndp)
X		wp -> w_flag |= WFMODE; /* force mode line update */
X	return (TRUE);
X}
X
X/*
X* Ordinary text characters are bound to this function,
X* which inserts them into the buffer. Characters marked as control
X* characters (using the CTRL flag) may be remapped to their ASCII
X* equivalent. This makes TAB (C-I) work right, and also makes the
X* world look reasonable if a control character is bound to this
X* this routine by hand. Any META or CTLX flags on the character
X* are discarded. 
X* 
X*   Edit the unit under the cursor.
X*   Check that the character is valid for the current display mode.
X*/
X
Xbool selfinsert (f, n, k)
X{
X
X	register int    c;
X	register int    s;
X	char    edt_buf[4],
X	i_chr,
X	b_per_u,
X	u_offs,
X	u_roffs,
X	bit_shf,
X	bit_mask,
X	i;
X	LINE    * l_ptr;
X	short   d_offs;
X	int     bytes,
X	temp_int;
X	long    dot_shf,
X	l_mask,
X	l_val;
X	char    text_buf[12];
X	static char max_dec_8[] = "255";
X	static char max_dec_16[] = "65535";
X	static char max_dec_32[] = "4294967295";
X	int		cur_col;
X
X	bool intel;
X
X	if (n < 0)
X	{
X		ttbeep ();
X		return (FALSE);
X	}
X	if (n == 0)
X	{
X		ttbeep ();
X		return (TRUE);
X	}
X	c = k & KCHAR;
X	if ((k & KCTRL) != 0 && c >= '@' && c <= '_')/* ASCII-ify.           */
X		c -= '@';
X	b_per_u = curwp -> w_fmt_ptr -> r_b_per_u;
X	u_offs = curwp -> w_unit_offset;
X	u_roffs = curwp -> w_fmt_ptr -> r_chr_per_u - u_offs - 1;
X	intel = curwp -> w_intel_mode;
X
X	cur_col = ttcol;
X
X	switch (curwp -> w_fmt_ptr -> r_type)
X	{
X	case EBCDIC:
X		c = to_ebcdic (c);  /* convert ASCII to EBCDIC */
X	case ASCII:
X		if ((insert_mode) || (DOT_POS(curwp) == BUF_SIZE(curwp)))
X		{
X			s = linsert (n, c);
X			if (read_pat_mode)
X				forwchar (0, 1, KRANDOM);/* advance the cursor */
X		}
X		else
X			s = lreplace (n, c);
X		break;
X
X	case HEX:
X		if ((c >= '0') && (c <= '9'))
X		{
X			i_chr = c - '0';/* convert to binary */
X		}
X		else
X			if ((c >= 'A') && (c <= 'F'))
X			{
X				i_chr = c - 'A' + 10;/* convert to binary */
X			}
X			else
X				if ((c >= 'a') && (c <= 'f'))
X				{
X					i_chr = c - 'a' + 10;/* convert to binary */
X				}
X				else
X				{
X					bad_key (k);
X					return (FALSE);
X				}
X		fill_out (); /* expand buffer if necessary */
X
X		/* position dot to byte to be altered */
X		if (intel)
X			dot_shf = u_roffs >> 1;
X		else
X			dot_shf = u_offs >> 1;
X
X		/* save dot position for later */
X		l_ptr = curwp -> w_dotp;
X		d_offs = curwp -> w_doto;
X		move_ptr (curwp, dot_shf, TRUE, FALSE, TRUE);
X
X		if (u_offs & 1)
X		{               /* lower nibble in byte */
X			i_chr &= 0x0f;
X			DOT_CHAR(curwp) &= 0xf0;
X			DOT_CHAR(curwp) |= i_chr;
X		}
X		else
X		{               /* upper nibble in byte */
X			i_chr <<= 4;
X			i_chr &= 0xf0;
X			DOT_CHAR(curwp) &= 0x0f;
X			DOT_CHAR(curwp) |= i_chr;
X		}
X
X		/* restore dot position */
X		curwp -> w_dotp = l_ptr;
X		curwp -> w_doto = d_offs;
X		forwchar (0, 1, KRANDOM);/* advance the cursor */
X		break;
X
X	case BINARY:
X		if ((c != '0') && (c != '1'))
X		{
X			bad_key (k);
X			return (FALSE);
X		}
X
X		/* position dot to byte to be altered */
X		if (intel)
X			dot_shf = u_roffs >> 3;
X		else
X			dot_shf = u_offs >> 3;
X
X		fill_out (); /* expand buffer if necessary */
X
X		/* save dot position for later */
X		l_ptr = curwp -> w_dotp;
X		d_offs = curwp -> w_doto;
X		move_ptr (curwp, dot_shf, TRUE, FALSE, TRUE);
X
X		bit_shf = u_roffs & 0x07;
X
X		if (c == '0')
X		{
X			DOT_CHAR(curwp) &= ~(1 << bit_shf);
X		}
X		else
X		{
X			DOT_CHAR(curwp) |= 1 << bit_shf;
X		}
X
X		/* restore dot position */
X		curwp -> w_dotp = l_ptr;
X		curwp -> w_doto = d_offs;
X		forwchar (0, 1, KRANDOM);/* advance the cursor */
X		break;
X
X	case OCTAL:
X		if (c < '0')
X		{
X			bad_key (k);
X			return (FALSE);
X		}
X		else
X			if ((c > '1') && (u_offs == 0) &&
X			    ((curwp -> w_fmt_ptr -> r_size) == WORDS))
X			{
X				bad_key (k);
X				return (FALSE);
X			}
X			else
X				if ((c > '3') && (u_offs == 0))
X				{
X					bad_key (k);
X					return (FALSE);
X				}
X				else
X					if (c > '7')
X					{
X						bad_key (k);
X						return (FALSE);
X					}
X
X		dot_shf = (c - '0') & 7;/* get binary value */
X		l_mask = 7;         /* create bit mask */
X
X		dot_shf <<= (u_roffs * 3);
X		l_mask <<= (u_roffs * 3);
X
X		fill_out (); /* expand buffer if necessary */
X
X		/* save dot position for later */
X		l_ptr = curwp -> w_dotp;
X		d_offs = curwp -> w_doto;
X
X		/* position dot to the byte to be altered */
X		if (intel)
X		{
X			for (i = 0; i < b_per_u; i++)
X			{
X				DOT_CHAR(curwp) &= ~((D8) l_mask & 0xff);
X				DOT_CHAR(curwp) |= (D8) dot_shf & 0xff;
X				l_mask >>= 8;
X				dot_shf >>= 8;
X				move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
X			}
X		}
X		else
X		{
X			move_ptr (curwp, (long) (b_per_u - 1), TRUE, FALSE, TRUE);
X			/* move to last byte */
X			for (i = 0; i < b_per_u; i++)
X			{
X				DOT_CHAR(curwp) &= ~((D8) l_mask & 0xff);
X				DOT_CHAR(curwp) |= (D8) dot_shf & 0xff;
X				l_mask >>= 8;
X				dot_shf >>= 8;
X				move_ptr (curwp, -1L, TRUE, FALSE, TRUE);/* step back one byte */
X			}
X		}
X
X		/* restore dot position */
X		curwp -> w_dotp = l_ptr;
X		curwp -> w_doto = d_offs;
X		forwchar (0, 1, KRANDOM);/* advance the cursor */
X		break;
X
X	case DECIMAL:
X		fill_out (); /* expand buffer if necessary */
X
X		/* save dot position for later */
X		l_ptr = curwp -> w_dotp;
X		d_offs = curwp -> w_doto;
X
X		bytes = fill_buf (curwp, l_ptr, d_offs, edt_buf, b_per_u);
X		/* if last unit is not full and must be extended */
X		for (; bytes < b_per_u; bytes++)
X		{
X			edt_buf[3] = edt_buf[2];/* shuffle bytes down */
X			edt_buf[2] = edt_buf[1];
X			edt_buf[1] = edt_buf[0];
X			edt_buf[0] = 0;
X		}
X		switch (curwp -> w_fmt_ptr -> r_size)
X		{
X		case BYTES:
X			sprintf (text_buf, MSG_03u, (int) (edt_buf[0] & 0xff));
X			if (!dec_chr_ok (text_buf, max_dec_8, c, u_offs))
X			{
X				bad_key (k);
X				return (TRUE);  /* TRUE so that mask will be same len */
X			}
X			sscanf (text_buf, MSG_3u, &i);/* convert back to binary */
X			l_val = (long) i & 0xff;
X			break;
X
X		case WORDS:
X			l_val = get_int (edt_buf);/* do intel swap */
X			sprintf (text_buf, MSG_05u, (int) (l_val & 0xFFFF));
X			if (!dec_chr_ok (text_buf, max_dec_16, c, u_offs))
X			{
X				bad_key (k);
X				return (TRUE);  /* TRUE so that mask will be same len */
X			}
X			sscanf (text_buf, MSG_5u, &temp_int);
X			/* convert back to binary */
X			l_val = get_int ((char *) & temp_int);/* do intel swap */
X			break;
X
X		case DWORDS:
X			l_val = get_long (edt_buf);/* do intel swap */
X			sprintf (text_buf, MSG_010lu, l_val);
X			if (!dec_chr_ok (text_buf, max_dec_32, c, u_offs))
X			{
X				bad_key (k);
X				return (TRUE);  /* TRUE so that mask will be same len */
X			}
X			sscanf (text_buf, MSG_lu, &l_val);
X			/* convert back to binary */
X			l_val = get_long ((char *) & l_val);/* do intel swap */
X			break;
X#if RUNCHK
X		default:
X			writ_echo (ERR_rnd_2);
X			break;
X#endif
X		}
X		DOT_CHAR(curwp) = (char) l_val & 0xff;
X		for (i = 1; i < b_per_u; i++)
X		{
X			l_val >>= 8;
X			move_ptr (curwp, 1L, TRUE, FALSE, TRUE);/* step forward one byte */
X			DOT_CHAR(curwp) = (char) l_val & 0xff;
X		}
X
X		/* restore dot position */
X		curwp -> w_dotp = l_ptr;
X		curwp -> w_doto = d_offs;
X		forwchar (0, 1, KRANDOM);/* advance the cursor */
X		break;
X
X#if RUNCHK
X	default:
X		writ_echo (ERR_rnd_3);
X		break;
X#endif
X	}
X	/* if cursor has wrapped to the next line then previous line
X		will not be refreshed with WFEDIT so do a WFHARD */
X	if (cur_col > get_curcol(curwp))
X		lchange (WFHARD);
X	else
X		lchange (WFEDIT);
X
X	return (TRUE);
X}
X
X/*
X*   Insert one unit of zeros at the current dot position.
X*/
Xbool    insertunit (f, n, k)
X{
X	lchange (WFEDIT);
X	linsert ((R_B_PER_U(curwp) * n), 0);
X	return (TRUE);
X}
X
X/* 
X*   Increase the size of the buffer if necessary.
X*   If dot is at the byte after the last full unit
X*   then add enough bytes to the buffer to create 
X*   a full unit at the end.
X*/
X
Xbool    fill_out ()
X{
X	long    buf_size, dot_pos, l_val, last_unit;
X	int     b_per_u;
X	char    stat, shift;
X	int     insert_val;
X
X	buf_size = BUF_SIZE(curwp);
X	dot_pos = DOT_POS(curwp);
X	b_per_u = R_B_PER_U(curwp);
X	shift = curwp -> w_disp_shift;
X	stat = TRUE;
X	insert_val = 0;
X	last_unit = buf_size & ~((long)(b_per_u - 1));
X	/* there is an even number of units step back one */
X	if (last_unit == buf_size)
X		last_unit -= b_per_u;
X	last_unit += shift;
X
X	/* if dot is one byte past the end of the buffer */
X	if (dot_pos > last_unit)
X	{
X		insert_val = b_per_u;
X	}
X
X	/* if dot is pointed at the end of the buffer */
X	else if (dot_pos == last_unit)
X	{
X		insert_val = b_per_u - (buf_size - last_unit);
X	}
X
X	/* if insert is necessary then do it */
X	if (insert_val != 0)
X	{
X		lchange (WFHARD);
X		move_ptr (curwp, buf_size, TRUE, FALSE, FALSE); /* move dot to end */
X		stat = linsert (insert_val, 0);
X		move_ptr (curwp, dot_pos, TRUE, TRUE, FALSE); /* put dot back */
X	}
X	return (stat);
X}
X
X/*
X*   This checks that an entered character is ok
X*   for the position given.
X*/
X
Xchar    dec_chr_ok (char_buf, max_str, chr, pos)
X
Xchar    chr,
Xpos,
X*char_buf,
X*max_str;
X
X{
X	char    i;
X
X	if ((chr < '0') || (chr > '9'))
X		return (FALSE);
X
X	char_buf[pos] = chr;        /* insert typed char */
X
X	/* check if number is too big */
X	for (i = 0; max_str[i] != 0; i++)
X	{
X		if (char_buf[i] < max_str[i])
X			break;              /* if char is smaller then must be ok */
X
X		if (char_buf[i] > max_str[i])
X			return (FALSE);     /* val is too large; ERROR */
X	}
X	return (TRUE);
X}
X
X/*
X* Set the rest of the variables for the mode change.
X*/
Xvoid    set_mode_vars ()
X{
X	curwp -> w_disp_shift = 0;  /* shift to 0 when changing mode */
X	curwp -> w_unit_offset = 0; /* go to end of unit */
X	/* if we are in the middle of a search then use the proper format struc */
X	if (read_pat_mode)
X		curwp -> w_fmt_ptr = curwp -> w_fmt_ptr -> r_srch_fmt;
X
X	wind_on_dot (curwp);
X	curwp -> w_flag = WFHARD;
X	update ();
X}
X
X/*
X* Change the display mode to ASCII.
X* The default binding is META C-A.
X*/
Xbool    asciimode ()
X{
X	curwp -> w_fmt_ptr = &ascii_fmt;
X	set_mode_vars ();
X	return (TRUE);
X}
X
X/*
X* Change the display mode to EBCDIC.
X* The default binding is META C-E.
X*/
Xbool    ebcdicmode ()
X{
X	curwp -> w_fmt_ptr = &ebcdic_fmt;
X	set_mode_vars ();
X	return (TRUE);
X}
X
X/*
X* Change the display mode to DECIMAL.
X* The default binding is META C-D.
X*/
Xbool    decimalmode ()
X{
X	switch (curwp -> w_fmt_ptr -> r_size)
X	{
X	case BYTES:
X		curwp -> w_fmt_ptr = &decimal_8_fmt;
X		break;
X	case WORDS:
X		curwp -> w_fmt_ptr = &decimal_16_fmt;
X		break;
X
X	case DWORDS:
X		curwp -> w_fmt_ptr = &decimal_32_fmt;
X		break;
X#if RUNCHK
X	default:
X		writ_echo (ERR_rnd_4);
X		break;
X#endif
X	}
X	set_mode_vars ();
X	return (TRUE);
X}
X
X/*
X* Change the display mode to HEXADECIMAL.
X* The default binding is META C-H.
X*/
Xbool    hexmode ()
X{
X	switch (curwp -> w_fmt_ptr -> r_size)
X	{
X	case BYTES:
X		curwp -> w_fmt_ptr = &hex_8_fmt;
X		break;
X	case WORDS:
X		curwp -> w_fmt_ptr = &hex_16_fmt;
X		break;
X	case DWORDS:
X		curwp -> w_fmt_ptr = &hex_32_fmt;
X		break;
X#if RUNCHK
X	default:
X		writ_echo (ERR_rnd_5);
X		break;
X#endif
X	}
X	set_mode_vars ();
X	return (TRUE);
X}
X
X/*
X* Change the display mode to OCTAL.
X* The default binding is META C-O.
X*/
Xbool    octalmode ()
X{
X	switch (curwp -> w_fmt_ptr -> r_size)
X	{
X	case BYTES:
X		curwp -> w_fmt_ptr = &octal_8_fmt;
X		break;
X
X	case WORDS:
X		curwp -> w_fmt_ptr = &octal_16_fmt;
X		break;
X
X	case DWORDS:
X		curwp -> w_fmt_ptr = &octal_32_fmt;
X		break;
X#if RUNCHK
X	default:
X		writ_echo (ERR_rnd_6);
X		break;
X#endif
X	}
X	set_mode_vars ();
X	return (TRUE);
X}
X
X/*
X* Change the display mode to BINARY.
X* The default binding is META C-B.
X*/
Xbool    binarymode ()
X{
X	switch (curwp -> w_fmt_ptr -> r_size)
X	{
X	case BYTES:
X		curwp -> w_fmt_ptr = &binary_8_fmt;
X		break;
X	case WORDS:
X		curwp -> w_fmt_ptr = &binary_16_fmt;
X		break;
X	case DWORDS:
X		curwp -> w_fmt_ptr = &binary_32_fmt;
X		break;
X#if RUNCHK
X	default:
X		writ_echo (ERR_rnd_7);
X		break;
X#endif
X	}
X	set_mode_vars ();
X	return (TRUE);
X}
X
X/*
X* Change the display shift.
X* Circularly rotate through display shift of 0 through 3.
X* This value is used to shift the display by the designated number of bytes.
X* This is used to cause WORD and DWORD values to be calculated
X* from the correct offset.
X*/
Xbool dispshift (f, n, k)
X{
X	char    mode,
X	size;
X
X	if (read_pat_mode)
X		return (TRUE);  /* no shift is allowed in search mode */
X
X
X	mode = curwp -> w_fmt_ptr -> r_type;
X	size = curwp -> w_fmt_ptr -> r_size;
X
X	if (((mode == HEX) ||
X	    (mode == DECIMAL) ||
X	    (mode == BINARY) ||
X	    (mode == OCTAL)) &&
X	    (size != BYTES))
X	{
X		if ((size == WORDS) &&
X		    (curwp -> w_disp_shift >= 1))
X		{                   /* roll over on words */
X			curwp -> w_disp_shift = 0;
X		}
X		else
X			if ((size == DWORDS) &&
X			    (curwp -> w_disp_shift >= 3))
X			{               /* roll over on double words */
X				curwp -> w_disp_shift = 0;
X			}
X			else
X			{
X				curwp -> w_disp_shift++;/* increment shift */
X			}
X	}
X	else
X	{
X		curwp -> w_disp_shift = 0;/* set to no shift */
X	}
X	move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
X	wind_on_dot (curwp);
X	curwp -> w_flag = WFHARD;   /* force full window refresh */
X	return (TRUE);
X}
X
X/*
X* Delete forward. This is real
X* easy, because the basic delete routine does
X* all of the work. Watches for negative arguments,
X* and does the right thing. If any argument is
X* present, it kills rather than deletes, to prevent
X* loss of text if typed with a big argument.
X* Normally bound to "C-D".
X*/
Xchar    forwdel (f, n, k)
X{
X	char    s;
X
X	if (n < 0)
X		return (backdel (f, -n, KRANDOM));
X
X	s = FALSE;
X	if (R_SIZE(curwp) == BYTES)
X	{
X		if (f != FALSE)
X		{
X			/* Really a kill.       */
X			if ((lastflag & CFKILL) == 0)
X				bclear (&sav_buf);
X			thisflag |= CFKILL;
X		}
X		s = ldelete ((A32)n, f);
X		curwp -> w_unit_offset = 0;
X	}
X	return (s);
X}
X
X
X/*
X* Delete backwards. This is quite easy too,
X* because it's all done with other functions. Just
X* move the cursor back, and delete forwards.
X* Like delete forward, this actually does a kill
X* if presented with an argument.
X*/
Xchar    backdel (f, n, k)
X{
X
X	int     u_off;
X	char    s;
X
X	if (n < 0)
X		return (forwdel (f, -n, KRANDOM));
X
X	s = FALSE;
X	if (R_SIZE(curwp) == BYTES)
X	{
X		u_off = curwp -> w_unit_offset;
X		curwp -> w_unit_offset = 0;
X		if ((s = backchar (f, n * R_CHR_PER_U(curwp), KRANDOM)) == TRUE)
X		{
X			s = ldelete ((A32)n, f);
X			if (f != FALSE)
X			{
X				/* Really a kill.       */
X				if ((lastflag & CFKILL) == 0)
X					bclear (&sav_buf);
X				thisflag |= CFKILL;
X			}
X		}
X		curwp -> w_unit_offset = u_off;
X	}
X	return (s);
X}
X
X
X/*
X* Change the size of the display unit to BYTE.
X* Adjust byte shift to the allowable range.
X* Normally bound to "META-1".
X*/
Xbool dispsize1 ()
X{
X	curwp -> w_disp_shift = 0;  /* shift to 0 when changing size */
X	curwp -> w_unit_offset = 0; /* go to end of unit */
X
X	switch (R_TYPE(curwp))
X	{
X	case OCTAL:
X		curwp -> w_fmt_ptr = &octal_8_fmt;
X		break;
X
X	case DECIMAL:
X		curwp -> w_fmt_ptr = &decimal_8_fmt;
X		break;
X
X	case HEX:
X		curwp -> w_fmt_ptr = &hex_8_fmt;
X		break;
X
X	case BINARY:
X		curwp -> w_fmt_ptr = &binary_8_fmt;
X		break;
X
X	default:
X		return (TRUE);
X		break;
X	}
X
X	/* if we are in the middle of a search then use the proper format struc */
X	if (read_pat_mode)
X		curwp -> w_fmt_ptr = curwp -> w_fmt_ptr -> r_srch_fmt;
X
X	move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
X	wind_on_dot (curwp);
X	curwp -> w_flag = WFHARD;
X	update ();
X	return (TRUE);
X}
X
X/*
X* Change the size of the display unit to WORD.
X* Adjust byte shift to the allowable range.
X* Normally bound to "META-2".
X*/
Xbool dispsize2 ()
X{
X	curwp -> w_disp_shift = 0;  /* shift to 0 when changing size */
X	curwp -> w_unit_offset = 0; /* go to end of unit */
X
X	switch (R_TYPE(curwp))
X	{
X	case OCTAL:
X		curwp -> w_fmt_ptr = &octal_16_fmt;
X		break;
X
X	case DECIMAL:
X		curwp -> w_fmt_ptr = &decimal_16_fmt;
X		break;
X
X	case HEX:
X		curwp -> w_fmt_ptr = &hex_16_fmt;
X		break;
X
X	case BINARY:
X		curwp -> w_fmt_ptr = &binary_16_fmt;
X		break;
X
X	default:
X		return (TRUE);
X		break;
X	}
X
X	/* if we are in the middle of a search then use the proper format struc */
X	if (read_pat_mode)
X		curwp -> w_fmt_ptr = curwp -> w_fmt_ptr -> r_srch_fmt;
X
X	move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
X	wind_on_dot (curwp);
X	curwp -> w_flag = WFHARD;
X	update ();
X	return (TRUE);
X}
X
X/*
X* Change the size of the display unit to DOUBLE WORD.
X* Adjust byte shift to the allowable range.
X* Normally bound to "META-4".
X*/
Xbool dispsize4 ()
X{
X	curwp -> w_disp_shift = 0;  /* shift to 0 when changing size */
X	curwp -> w_unit_offset = 0; /* go to end of unit */
X
X	switch (R_TYPE(curwp))
X	{
X	case OCTAL:
X		curwp -> w_fmt_ptr = &octal_32_fmt;
X		break;
X
X	case DECIMAL:
X		curwp -> w_fmt_ptr = &decimal_32_fmt;
X		break;
X
X	case HEX:
X		curwp -> w_fmt_ptr = &hex_32_fmt;
X		break;
X
X	case BINARY:
X		curwp -> w_fmt_ptr = &binary_32_fmt;
X		break;
X
X	default:
X		return (TRUE);
X		break;
X	}
X
X	/* if we are in the middle of a search then use the proper format struc */
X	if (read_pat_mode)
X		curwp -> w_fmt_ptr = curwp -> w_fmt_ptr -> r_srch_fmt;
X
X	move_ptr (curwp, 0L, TRUE, TRUE, TRUE);
X	wind_on_dot (curwp);
X	curwp -> w_flag = WFHARD;
X	update ();
X	return (TRUE);
X}
X
X/*
X* Display byte swaped.   This command causes the bytes
X* that are displayed in WORD and DWORD mode to be swaped
X* in the way that the INTEL microprocessors do it.
X*/
Xbool dispswapbyte (f, n, k)
X{
X	if ((curwp -> w_fmt_ptr -> r_size) == BYTES)
X		return (TRUE);
X
X	if (curwp -> w_intel_mode)
X		curwp -> w_intel_mode = FALSE;
X	else
X		curwp -> w_intel_mode = TRUE;
X
X	curwp -> w_flag = WFHARD;
X	update ();
X	return (TRUE);
X}
X
X/*
X* Yank text back from the kill buffer. This
X* is really easy. All of the work is done by the
X* standard insert routines. All you do is run the loop,
X* and check for errors. 
X* An attempt has been made to fix the cosmetic bug
X* associated with a yank when dot is on the top line of
X* the window (nothing moves, because all of the new
X* text landed off screen).
X*/
Xbool yank (f, n, k)
X{
X	register D16    c;
X	register A32    i;
X	register    LINE * lp;
X	char        buf[80], buf1[40];
X
X	if (n < 0)
X		return (FALSE);
X	while (n--)
X	{
X		i = 0;
X		save_buf_home ();
X		while ((c = get_save_char ()) != (D16)-1)
X		{
X			if (linsert (1, c) == FALSE)
X				return (FALSE);
X			if ((i & 0x2ff) == 0)
X			{
X				sprintf (buf1, MSG_procing, R_POS_FMT(curwp));
X				sprintf (buf, buf1, (ulong)i);
X				writ_echo (buf);
X				/* check if we should quit */
X				if (ttkeyready ())
X				{
X					wind_on_dot_all();
X					if (ttgetc () == CTL_G)
X						return (FALSE);
X				}
X			}
X			++i;
X		}
X	}
X	/* update buffer display */
X	if ((blistp -> b_nwnd != 0) &&
X	    (blistp -> b_type == BTLIST))
X		listbuffers ();
X
X	curwp -> w_flag |= WFHARD;
X	return (TRUE);
X}
X
X/*
X*   Link windows.   pvr
X*   This function toggles the window linking function.
X*   When linking is enabled all windows that look at 
X*   the same buffer will be forced to have the same 
X*   dot position.   Each window is then moved to be
X*   positioned on the dot.   Thus when a user moves
X*   arround a buffer all other views into that buffer 
X*   will follow.
X*/
X
Xbool linkwind ()
X
X{
X	char    buf[80];
X
X	if (curwp -> w_bufp -> b_flag & BFLINK)
X	{
X		curwp -> w_bufp -> b_flag &= ~(BFLINK & 0xff);
X		sprintf (buf, MSG_lnk, curwp -> w_bufp -> b_bname, MSG_unlink);
X	}
X	else
X	{
X		curwp -> w_bufp -> b_flag |= BFLINK;
X		sprintf (buf, MSG_lnk, curwp -> w_bufp -> b_bname, MSG_link);
X	}
X	writ_echo (buf);
X	return (TRUE);
X}
X/*
X*   Print all bad keys to the screen and beep 
X*/
Xvoid    bad_key (key)
Xint     key;
X{
X	char    buf[80], buf1[40];
X
X	ttbeep ();
X	sprintf (buf, MSG_bad_key);
X	keyname (&buf[strlen (buf)], key);
X	sprintf (&buf[strlen (buf)], ", %X", key);
X	writ_echo (buf);
X}
X
X/*
X *	Combine sequential bytes from the rest of the windows
X *	into this window.   This is useful in combining PROM
X *	image files from odd and even bytes into one file.
X */
Xbool	n_way_combine (f, n, k)
X{
X	WINDOW * dest_wp, *src_wp;
X	BUFFER *src_bp;
X	A32    dotp;
X	D8	byt;
X	int j = 0;
X	char        buf[80], buf1[40];
X
X	/* save the destination window for later restore */
X	dest_wp = curwp;
X
X	if ((BUF_SIZE (curwp)) != (A32)0)
X	{
X		writ_echo (MSG_w_not_empty);
X		return(FALSE);
X	}
X	/* Current window must be empty, modifiable and not the only one. */
X	if ((BUF_SIZE (curwp) != 0) ||
X	    (curwp -> w_wndp == NULL) ||
X	    (curwp -> w_bufp -> b_flag & (BFVIEW | BFSLOCK)))
X	{
X		writ_echo (MSG_w_not_empty);
X		return(FALSE);
X	}
X
X
X
X
X	for (;;)
X	{
X		/* step to the next window after the destination window */
X		nextwind();
X
X		/* as I cycle around the windows skip the destination window */
X		if (curwp == dest_wp)
X		{
X			continue;
X		}
X		byt = DOT_CHAR(curwp) & 0xff;
X		dotp = DOT_POS(curwp);   /* get the current dot position */
X		/* move the dot position ahead in current buffer */
X		if (move_ptr (curwp, 1L, TRUE, FALSE, TRUE) == FALSE)
X		{
X			/* did we advance? */
X			if (DOT_POS(curwp) == dotp)
X			{
X				wind_on_dot_all();
X				writ_echo (MSG_ok);
X				return (TRUE);   /* done all that we could */
X			}
X		}
X
X		src_wp = curwp;
X		src_bp = curwp -> w_bufp;
X		curwp = dest_wp;
X		curbp = dest_wp -> w_bufp;
X		if (linsert (1, byt) == FALSE)
X		{
X			wind_on_dot_all();
X			return (FALSE);	/* insert failed for some reason */
X		}
X		curwp = src_wp;
X		curbp = src_bp;
X		if ((j++ & 0x2ff) == 0)
X		{
X			sprintf (buf1, MSG_procing, R_POS_FMT(curwp));
X			sprintf (buf, buf1, dotp);
X			writ_echo (buf);
X			/* check if we should quit */
X			if (ttkeyready ())
X			{
X				wind_on_dot_all();
X				if (ttgetc () == CTL_G)
X					return (FALSE);
X			}
X		}
X	}
X}
X
X/*
X *	Split the current buffer into the rest of the windows.
X *	This is useful in splitting a binary file into PROM
X *	image files.
X */
Xbool	n_way_split (f, n, k)
X{
X	WINDOW  *src_wp;
X	A32     b_size;
X	D8	byt;
X	int j = 0;
X	char        buf[80], buf1[40];
X
X	/* save the source window and buffer for later restore */
X	src_wp = curwp;
X
X	/* step to the next window after the source window */
X	nextwind();
X
X	/* check that all the destination windows are empty and modifiable */
X	for (;;)
X	{
X		if ((BUF_SIZE (curwp) != 0) ||
X		    (curwp -> w_bufp -> b_flag & (BFVIEW | BFSLOCK)))
X		{
X			writ_echo (MSG_w_not_empty);
X			return(FALSE);
X		}
X
X		/* force all windows to be refreshed */
X		lchange (WFHARD);
X		/* step to the next window */
X		nextwind();
X		/* stop after one pass around the windows */
X		if (curwp == src_wp)
X			break;
X	}
X
X	b_size = BUF_SIZE(src_wp);  /* get the buffer size */
X
X	/* do the split until source is exhausted */
X	for (;;)
X	{
X		/* step to the next window after the source window */
X		nextwind();
X
X		/* current window cannot be the source */
X		if (curwp == src_wp)
X			continue;
X
X		byt = DOT_CHAR(src_wp) & 0xff;   /* get the byte to copy */
X
X		/* are we at the end of the buffer */
X		if (b_size == DOT_POS(src_wp))
X		{
X			wind_on_dot_all();
X			writ_echo (MSG_ok);
X			return (TRUE);
X		}
X		if (linsert (1, byt) == FALSE)
X		{
X			wind_on_dot_all();
X			return (FALSE);
X		}
X		if ((j++ & 0x2ff) == 0)
X		{
X			sprintf (buf1, MSG_procing, R_POS_FMT(src_wp));
X			sprintf (buf, buf1, DOT_POS(src_wp));
X			writ_echo (buf);
X			/* check if we should quit */
X			if (ttkeyready ())
X			{
X				wind_on_dot_all();
X				if (ttgetc () == CTL_G)
X					return (FALSE);
X			}
X		}
X		if (move_ptr (src_wp, 1L, TRUE, FALSE, TRUE) == FALSE)
X		{
X			wind_on_dot_all();
X			writ_echo (MSG_ok);
X			return (TRUE);	/* hit the end of the source buffer */
X		}
X	}
X}
X
Xvoid wind_on_dot_all ()
X{
X	WINDOW  *wp;
X
X	wp = curwp;
X	do
X	{
X		wind_on_dot (curwp);
X		nextwind();
X	}    while (wp != curwp);
X}
END_OF_FILE
if test 28638 -ne `wc -c <'random.c'`; then
    echo shar: \"'random.c'\" unpacked with wrong size!
fi
# end of 'random.c'
fi
if test -f 'search.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'search.c'\"
else
echo shar: Extracting \"'search.c'\" \(24684 characters\)
sed "s/^X//" >'search.c' <<'END_OF_FILE'
X/*
X*       Search commands.
X* The functions in this file implement the
X* search commands (both plain and incremental searches
X* are supported) and the query-replace command.
X*/
X#include    "def.h"
X
Xchar    replaceit ();
Xchar    forwsrch ();
Xchar    backsrch ();
Xchar    readpattern ();
Xvoid    next_pat ();
X
Xextern    char    MSG_sch_str[];
Xextern    char    MSG_bsrc_str[];
Xextern    char    MSG_rpl_str[];
Xextern    char    MSG_pat_fnd[];
Xextern    char    MSG_no_srch[];
Xextern    char    MSG_fnd_at[];
Xextern    char    MSG_no_rpl[];
Xextern    char    MSG_1_rpl[];
Xextern    char    MSG_n_rpl[];
Xextern    char    MSG_srcing[];
Xextern    char    MSG_curs[];
Xextern    char    MSG_cmp_end[];
Xextern    char    MSG_cmp_term[];
Xextern    char    MSG_cmp_dif[];
Xextern    char    MSG_only_2[];
Xextern    char    MSG_cmping[];
Xextern    char    MSG_not_fnd[];
X#if RUNCHK
Xextern    char    ERR_rdpat[];
Xextern    char    ERR_mask[];
Xextern    char    ERR_m_cl[];
X#endif
X
X#define CCHR(x)     ((x)-'@')
X
X#define SRCH_BEGIN  (0)         /* Search sub-codes.    */
X#define SRCH_FORW   (-1)
X#define SRCH_BACK   (-2)
X#define SRCH_PREV   (-3)
X#define SRCH_NEXT   (-4)
X#define SRCH_NOPR   (-5)
X#define SRCH_ACCM   (-6)
X
Xtypedef struct
X{
X	int     s_code;
X	LINE * s_dotp;
X	short   s_doto;
X}SRCHCOM;
X
X#define MAX_PAT 260
X
Xextern  ROW_FMT hex_s_8_fmt;
Xextern  ROW_FMT ascii_s_fmt;
X
Xbool    recall_flag = FALSE;
Xbool    read_pat_mode = FALSE;
Xbool    srch_mode = FALSE;
Xbool    rplc_mode = FALSE;
Xbool    dont_repeat = FALSE;    /* used to prevent toggling commands from */
X/* failing in read_pattern */
Xstatic  char    srch_patb[MAX_PAT];
Xstatic  char    srch_maskb[MAX_PAT];
Xstatic  char    rplc_patb[MAX_PAT];
Xstatic  char    rplc_maskb[MAX_PAT];
X
Xstatic  LINE    *srch_pat = (LINE *)srch_patb;
Xstatic  LINE    *srch_mask = (LINE *)srch_maskb;
Xstatic  LINE    *cur_pat;
Xstatic  LINE    *cur_mask;
Xstatic  LINE    *rplc_pat = (LINE *)rplc_patb;
Xstatic  LINE    *rplc_mask = (LINE *)rplc_maskb;
X
Xstatic  int     old_srch_pat_size = 0;/* for pattern recall */
Xstatic  int     old_rplc_pat_size = 0;
Xstatic  ROW_FMT *old_fmt = &hex_s_8_fmt;
X
Xchar    *cur_prompt;
X
Xstatic  SRCHCOM cmds[NSRCH];
Xstatic int  cip;
X
Xint     srch_lastdir = SRCH_NOPR;/* Last search flags.   */
X
X/*
X* Search forward.
X* Get a search string from the user, and search for it,
X* starting at ".". If found, "." gets moved to the
X* first matched character, and display does all the hard stuff.
X* If not found, it just prints a message.
X*/
Xchar    forwsearch ()
X{
X	register char   s;
X	char    buf[80], buf1[30];
X
X	srch_mode = TRUE;
X	rplc_mode = FALSE;
X	cur_prompt = MSG_sch_str;
X	if ((s = readpattern ()) != TRUE)
X	{
X		srch_mode = FALSE;
X		eerase ();  /* clear message line */
X		return (s);
X	}
X	if (forwsrch () == FALSE)
X	{
X		writ_echo (MSG_not_fnd);
X		srch_mode = FALSE;
X		return (FALSE);
X	}
X	srch_lastdir = SRCH_FORW;
X	curwp -> w_flag |= WFMODE;  /* update mode line */
X	curwp -> w_unit_offset = 0;
X	/* build format */
X	sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
X	sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
X	    curwp -> w_doto);
X	writ_echo (buf);
X	srch_mode = FALSE;
X	return (TRUE);
X}
X
X
X/*
X* Reverse search.
X* Get a search string from the  user, and search, starting at "."
X* and proceeding toward the front of the buffer. If found "." is left
X* pointing at the first character of the pattern [the last character that
X* was matched].
X*/
Xchar    backsearch ()
X{
X	register char   s;
X	char    buf[80], buf1[30];
X
X	srch_mode = TRUE;
X	rplc_mode = FALSE;
X	cur_prompt = MSG_bsrc_str;
X	if ((s = readpattern ()) != TRUE)
X	{
X		srch_mode = FALSE;
X		eerase ();  /* clear message line */
X		return (s);
X	}
X	if (backsrch () == FALSE)
X	{
X		writ_echo (MSG_not_fnd);
X		srch_mode = FALSE;
X		return (FALSE);
X	}
X	srch_lastdir = SRCH_BACK;
X	curwp -> w_flag |= WFMODE;  /* update mode line */
X	curwp -> w_unit_offset = 0;
X	sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
X	sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
X	    curwp -> w_doto);
X	writ_echo (buf);
X	srch_mode = FALSE;
X	return (TRUE);
X}
X
X
X/* 
X* Search again, using the same search string
X* and direction as the last search command. The direction
X* has been saved in "srch_lastdir", so you know which way
X* to go.
X*/
Xchar    searchagain ()
X{
X	char    buf[80], buf1[30];
X	long    dot_pos;
X	srch_mode = TRUE;
X	rplc_mode = FALSE;
X
X	dot_pos = DOT_POS(curwp);
X	if (srch_lastdir == SRCH_FORW)
X	{
X		/* advance one unit so we don't find the same thing again */
X		move_ptr (curwp, dot_pos + 1, TRUE, FALSE, FALSE);
X		if (forwsrch () == FALSE)
X		{    /* go back to orig pt */
X			move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
X			writ_echo (MSG_not_fnd);
X			srch_mode = FALSE;
X			return (FALSE);
X		}
X		curwp -> w_flag |= WFMODE;  /* update mode line */
X		curwp -> w_unit_offset = 0;
X		sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
X		sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
X		    curwp -> w_doto);
X		writ_echo (buf);
X		srch_mode = FALSE;
X		return (TRUE);
X	}
X	if (srch_lastdir == SRCH_BACK)
X	{
X		/* step back one unit so we don't find the same thing again */
X		move_ptr (curwp, dot_pos - 1, TRUE, FALSE, FALSE);
X		if (backsrch () == FALSE)
X		{    /* go back to orig pt */
X			move_ptr (curwp, dot_pos, TRUE, FALSE, FALSE);
X			writ_echo (MSG_not_fnd);
X			srch_mode = FALSE;
X			return (FALSE);
X		}
X		curwp -> w_flag |= WFMODE;  /* update mode line */
X		curwp -> w_unit_offset = 0;
X		sprintf (buf1, MSG_pat_fnd, R_POS_FMT(curwp));
X		sprintf (buf, buf1, curwp -> w_dotp -> l_file_offset +
X		    curwp -> w_doto);
X		writ_echo (buf);
X		srch_mode = FALSE;
X		return (TRUE);
X	}
X	writ_echo (MSG_no_srch);
X	srch_mode = FALSE;
X	return (FALSE);
X}
X
X
X/*
X* Query Replace.
X*   Replace strings selectively.  Does a search and replace operation.
X*   A space or a comma replaces the string, a period replaces and quits,
X*   an n doesn't replace, a C-G quits.
X* (note typical hack to add a function with minimal code) 
X*/
Xchar    queryrepl (f, n, k)
X{
X
X	register char   s;
X
X	srch_mode = FALSE;
X	rplc_mode = TRUE;
X	cur_prompt = MSG_sch_str;
X	if (s = readpattern ())
X	{
X		replaceit ();
X	}
X	srch_mode = FALSE;
X	rplc_mode = FALSE;
X	return (s);
X}
X
X
Xchar    replaceit ()
X{
X	register int    s;
X	int     rcnt = 0;           /* Replacements made so far */
X	int     plen;               /* length of found string   */
X	int     rlen;               /* length of replace string   */
X	long    abs_dot_p;          /* absolute dot position */
X	long    abs_mark_p;         /* absolute mark position */
X	char    buf[80], buf1[80];
X
X	/* 
X  * Search forward repeatedly, checking each time whether to insert
X  * or not.  The "!" case makes the check always true, so it gets put
X  * into a tighter loop for efficiency.
X  *
X  * If we change the line that is the remembered value of dot, then
X  * it is possible for the remembered value to move.  This causes great
X  * pain when trying to return to the non-existant line.
X  *
X  * possible fixes:
X  * 1) put a single, relocated marker in the WINDOW structure, handled
X  *    like mark.  The problem now becomes a what if two are needed...
X  * 2) link markers into a list that gets updated (auto structures for
X  *    the nodes)
X  * 3) Expand the mark into a stack of marks and add pushmark, popmark.
X  */
X
X	plen = srch_pat -> l_used;
X	rlen = rplc_pat -> l_used;
X
X	abs_dot_p = DOT_POS(curwp); /* save current dot position */
X	abs_mark_p = MARK_POS(curwp);
X
X	while (forwsrch () == TRUE)
X	{
Xretry:
X		sprintf (buf1, MSG_fnd_at, R_POS_FMT(curwp));
X		sprintf (buf, buf1, DOT_POS(curwp));
X		writ_echo (buf);
X		curwp -> w_flag |= WFMODE;  /* update mode line */
X		update ();
X		switch (ttgetc ())
X		{
X		case 'r':
X		case 'R':
X		case ' ':
X		case ',':
X			/* update has fixedup the dot position so move to found byte */
X			/* go and do the replace */
X			if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
X				return (FALSE);
X			/* begin searching after replace string */
X			move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
X			rcnt++;
X			break;
X
X		case 'o':
X		case 'O':
X		case '.':
X			if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
X				return (FALSE);
X			/* begin searching after replace string */
X			move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
X			rcnt++;
X			goto stopsearch;
X
X		case 'q':
X		case 'Q':
X		case CCHR ('G'):
X			ctrlg (FALSE, 0, KRANDOM);
X			goto stopsearch;
X
X		case 'a':
X		case 'A':
X		case '!':
X			do
X			{
X				if (lrepl_str (plen, rplc_pat, rplc_mask) == FALSE)
X					return (FALSE);
X				/* begin searching after replace string */
X				move_ptr (curwp, (long)rlen, TRUE, FALSE, TRUE);
X				rcnt++;
X			}                while (forwsrch () == TRUE);
X			goto stopsearch;
X
X		case 's':
X		case 'S':
X		case 'n':
X			/* begin searching after this byte */
X			move_ptr (curwp, 1L, TRUE, FALSE, TRUE);
X			break;
X
X		default:
X			ttbeep ();
X			goto retry;
X		}
X	}
X
Xstopsearch:
X	move_ptr (curwp, abs_dot_p, TRUE, TRUE, FALSE);
X	if (curwp -> w_markp != NULL)
X	{
X		swapmark ();
X		/* insure that the mark points to the same byte as before */
X		if (abs_mark_p > abs_dot_p)
X			move_ptr (curwp, abs_mark_p + rlen - plen, TRUE, FALSE, FALSE);
X		else
X			move_ptr (curwp, abs_mark_p, TRUE, FALSE, FALSE);
X		swapmark ();
X	}
X	curwp -> w_flag |= WFHARD;
X	update ();
X	if (rcnt == 0)
X	{
X		writ_echo (MSG_no_rpl);
X	}
X	else if (rcnt == 1)
X	{
X		writ_echo (MSG_1_rpl);
X	}
X	else
X	{
X		sprintf (buf1, MSG_n_rpl, R_POS_FMT(curwp));
X		sprintf (buf, buf1, (ulong)rcnt);
X		writ_echo (buf);
X	}
X	flush_count += rcnt;        /* jam for auto write buffers */
X	return (TRUE);
X}
X
X
X/*
X* This routine does the real work of a
X* forward search. The pattern is sitting in the external
X* variable "srch_pat" the mask if in "srch_mask".
X* If found, dot is updated, the window system
X* is notified of the change, and TRUE is returned. If the
X* string isn't found, FALSE is returned.
X*/
Xchar    forwsrch ()
X{
X	register    LINE    *save_dotp, *save2_dotp;
X	register    int     save_doto, save2_doto;
X	register    D8      *pat_ptr, *mask_ptr;
X	register    int     i, j, pat_cnt;
X	register    D8      first_pat, first_mask;
X	char        buf[80], buf1[40];
X
X	save_dotp = curwp -> w_dotp;    /* save dot position for later */
X	save_doto = curwp -> w_doto;
X	pat_ptr = srch_pat -> l_text;
X	mask_ptr = srch_mask -> l_text;
X	pat_cnt = srch_pat -> l_used;
X	first_mask = mask_ptr[0];
X	first_pat = pat_ptr[0] | first_mask;
X	j =  (int)DOT_POS(curwp) & 0xffff;
X
X	do 
X	{
X		if ((j++ & 0x2ff) == 0)
X		{
X			sprintf (buf1, MSG_srcing, R_POS_FMT(curwp));
X			sprintf (buf, buf1, DOT_POS(curwp));
X			writ_echo (buf);
X			/* check if we should quit */
X			if (ttkeyready ())
X			{
X				if (ttgetc () == CTL_G)
X					break;
X			}
X		}
X		if (first_pat == 
X		    ((DOT_CHAR(curwp) | first_mask) & 0xff))
X		{
X			save2_dotp = curwp -> w_dotp;    /* save dot position for later */
X			save2_doto = curwp -> w_doto;
X			for (i = 1; i < pat_cnt; i++)
X			{
X				if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
X				    ((pat_ptr[i] & ~mask_ptr[i]) != 
X				    (DOT_CHAR(curwp) & ~mask_ptr[i])))
X				{   /* not found */
X					curwp -> w_dotp = save2_dotp;  /* restore dot position */
X					curwp -> w_doto = save2_doto;
X					break;
X				}
X			}
X			if (i == pat_cnt)   /* found */
X			{   /* move back to the first matching unit */
X				move_ptr (curwp, -(long)pat_cnt + 1, TRUE, FALSE, TRUE);
X				wind_on_dot (curwp);
X				return (TRUE);
X			}
X		}
X	}    while (move_ptr (curwp, 1L, TRUE, FALSE, TRUE));
X
X	curwp -> w_dotp = save_dotp;  /* restore dot position */
X	curwp -> w_doto = save_doto;
X	return (FALSE);
X}
X
X
X/*
X* This routine does the real work of a
X* backward search. The pattern is sitting in the external
X* variable "srch_pat". If found, dot is updated, the window system
X* is notified of the change, and TRUE is returned. If the
X* string isn't found, FALSE is returned.
X*/
Xchar    backsrch ()
X{
X	register    LINE    *save_dotp, *save_p;
X	register    int     save_doto, save_o;
X	register    char    *pat_ptr, *mask_ptr;
X	register    int     i, j, pat_cnt;
X	register    char    first_pat, first_mask;
X	char        buf[80], buf1[40];
X
X	save_dotp = curwp -> w_dotp;    /* save dot position for later */
X	save_doto = curwp -> w_doto;
X	pat_ptr = srch_pat -> l_text;
X	mask_ptr = srch_mask -> l_text;
X	pat_cnt = srch_pat -> l_used;
X	first_mask = mask_ptr[0];
X	first_pat = pat_ptr[0] | first_mask;
X	j =  (int)DOT_POS(curwp) & 0xffff;
X
X	do 
X	{
X		/* check if we should quit */
X		if (ttkeyready ())
X		{
X			if (ttgetc () == CTL_G)
X				break;
X		}
X		if ((j-- & 0x2ff) == 0)
X		{
X			sprintf (buf1, MSG_srcing, R_POS_FMT(curwp));
X			sprintf (buf, buf1, DOT_POS(curwp));
X			writ_echo (buf);
X		}
X		if (first_pat == 
X		    (curwp -> w_dotp -> l_text[curwp -> w_doto] | first_mask))
X		{
X
X			save_p = curwp -> w_dotp;
X			save_o = curwp -> w_doto;
X			for (i = 1; i < pat_cnt; i++)
X			{
X				if (!move_ptr (curwp, 1L, TRUE, FALSE, TRUE) ||
X				    ((pat_ptr[i] & ~mask_ptr[i]) != 
X				    (DOT_CHAR(curwp) & ~mask_ptr[i])))
X				{   /* not found */
X					curwp -> w_dotp = save_p;   /* restore ptr to continue */
X
X					curwp -> w_doto = save_o;
X					break;
X				}
X			}
X			if (i == pat_cnt)   /* found */
X			{   /* move back to the first matching unit */
X				move_ptr (curwp, -(long)pat_cnt + 1, TRUE, FALSE, TRUE);
X				wind_on_dot (curwp);
X				return (TRUE);
X			}
X		}
X	}    while (move_ptr (curwp, -1L, TRUE, FALSE, TRUE));
X
X	curwp -> w_dotp = save_dotp;  /* restore dot position */
X	curwp -> w_doto = save_doto;
X	return (FALSE);
X}
X
X/*
X* Read a pattern.
X* Display and edit in the form of the current window.
X* Slide the displayed line back and forth when the cursor hits a boundary.
X* Manage the mask buffer. When a '*' (wild card) is entered mask all
X* bits in that unit and display all '?'s.
X*/
Xchar    readpattern ()
X{
X	int     cod, mask_cod, curs_pos, curs_pos1, prt_siz, i, doto, loff;
X	WINDOW  srch_wind, *save_wind;
X	BUFFER  srch_buf, *save_buf;
X	LINE    head_line, *line_ptr1, *line_ptr2;
X	char    disp_buf[120],
X	mask_buf[120],
X	buf1[80],
X	siz_prompt2,
X	r_type,
X	first_time,
X	u_off,
X	stat;
X
X
X	save_wind = curwp;          /* save current window for later */
X	save_buf = curbp;       /* save current buffer for later */
X
X	curwp = &srch_wind;         /* search window is current window during
X					                                   search */
X	curbp = &srch_buf;
X	cur_pat = srch_pat;         /* set global variables for LINE finctions */
X	cur_mask = srch_mask;
X
X	recall_flag = FALSE;
X	first_time = TRUE;
X	read_pat_mode = TRUE;
X	curwp -> w_wndp = NULL;
X	curwp -> w_bufp = curbp;
X	curwp -> w_linep = cur_pat;
X	curwp -> w_loff = 0;
X	curwp -> w_dotp = cur_pat;
X	curwp -> w_doto = 0;
X	curwp -> w_unit_offset = 0;
X	curwp -> w_toprow = 24;
X	curwp -> w_ntrows = 1;
X	curwp -> w_intel_mode = save_wind -> w_intel_mode;
X	curwp -> w_disp_shift = 0;
X	if (R_TYPE(save_wind) == TEXT)
X		curwp -> w_fmt_ptr = &ascii_s_fmt;
X	else
X		curwp -> w_fmt_ptr = save_wind -> w_fmt_ptr -> r_srch_fmt;
X
X	srch_buf.b_bufp = NULL;
X	srch_buf.b_linep = &head_line;
X	srch_buf.b_unit_offset = 0;    /* unit offset   pvr */
X	srch_buf.b_markp = NULL;
X	srch_buf.b_marko = 0;
X	srch_buf.b_flag = 0;
X	srch_buf.b_nwnd = 1;
X	srch_buf.b_fname[0] = 0;
X	srch_buf.b_bname[0] = 0;
X
X	head_line.l_fp = cur_pat;
X	head_line.l_bp = cur_pat;
X	head_line.l_file_offset = 0;    /* pvr */
X	head_line.l_used = 0;
X	head_line.l_size = 0;
X
X	cur_pat -> l_fp = &head_line;
X	cur_pat -> l_bp = &head_line;
X	cur_pat -> l_size = 266;    /* leave some extra past 256 */
X	cur_pat -> l_used = 0;
X	cur_pat -> l_file_offset = 0;
X
X	cur_mask -> l_fp = &head_line;
X	cur_mask -> l_bp = &head_line;
X	cur_mask -> l_size = 266;   /* leave some extra past 256 */
X	cur_mask -> l_used = 0;
X	cur_mask -> l_file_offset = 0;
X
X	rplc_pat -> l_fp = &head_line;
X	rplc_pat -> l_bp = &head_line;
X	rplc_pat -> l_size = 266;    /* leave some extra past 256 */
X	rplc_pat -> l_used = 0;
X	rplc_pat -> l_file_offset = 0;
X
X	rplc_mask -> l_fp = &head_line;
X	rplc_mask -> l_bp = &head_line;
X	rplc_mask -> l_size = 266;   /* leave some extra past 256 */
X	rplc_mask -> l_used = 0;
X	rplc_mask -> l_file_offset = 0;
X
X	sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT(curwp),
X	    R_BYTE_FMT(curwp), R_BYTE_FMT(curwp));
X	sprintf (disp_buf, buf1, curwp -> w_doto,
X	    curwp -> w_fmt_ptr -> r_chr_per_u - curwp -> w_unit_offset - 1,
X	    curwp -> w_dotp -> l_used);
X
X	siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
X
X	for (i = siz_prompt2; i < NCOL; i++)    /* clear rest of buffer */
X		disp_buf [i] = ' ';
X
X	writ_echo (disp_buf);
X
X	r_type = R_TYPE(curwp);
X
X	while (TRUE)
X	{
X		/* position cursor */
X		curs_pos = curwp -> w_doto - curwp -> w_loff;
X		if (curwp -> w_fmt_ptr -> r_size == 1)
X		{
X			curs_pos >>= 1;
X		}
X		else if (curwp -> w_fmt_ptr -> r_size == 3)
X		{
X			curs_pos >>= 2;
X		}
X		curs_pos1 = curwp -> w_fmt_ptr -> r_positions[curs_pos] + 
X		    curwp -> w_unit_offset + siz_prompt2;
X		ttmove (nrow - 1, curs_pos1);
X		ttflush ();
X
X		cod = getkey ();
X
X		if (cod == 0x014D)  /* check for return */
X		{
X			if ((rplc_mode == TRUE) && (cur_prompt == MSG_sch_str))
X			{
X				next_pat ();
X				dont_repeat = FALSE;    /* fix up */
X				goto next_loop;
X			}
X			else
X			{
X				old_srch_pat_size = srch_pat -> l_used; /* save for restore */
X				if (rplc_mode == TRUE)
X					old_rplc_pat_size = rplc_pat -> l_used;
X
X				old_fmt = curwp -> w_fmt_ptr;
X				curwp = save_wind;  /* restore current window */
X				curbp = save_buf;  /* restore current buffer */
X				read_pat_mode = FALSE;
X				return (TRUE);
X			}
X		}
X
X		if ((cod >= ' ') && (cod < 0x7f))
X		{
X			if ((r_type == ASCII) || (r_type == EBCDIC))
X			{
X				mask_cod = '9'; /* use 9 as dummy char that will get through */
X			}
X			else if (r_type == DECIMAL)
X			{
X				mask_cod = '0'; /* clear mask byte */
X			}
X			else if (cod == '?')
X			{
X				cod = '0';
X				switch (r_type)
X				{
X				case OCTAL:
X					if (curwp -> w_unit_offset == 0)    /* if first char */
X					{
X						if (R_SIZE(curwp) == WORDS)
X							mask_cod = '1';
X						else
X							mask_cod = '3';
X					}
X					else
X						mask_cod = '7';
X					break;
X
X				case HEX:
X					mask_cod = 'F';
X					break;
X
X				case BINARY:
X					mask_cod = '1';
X					break;
X#if RUNCHK
X				default:
X					printf (ERR_rdpat);
X					break;
X#endif
X				}
X			}
X			else
X			{
X				mask_cod = '0';
X			}
X		}
X		else
X			mask_cod = cod;     /* must be control; do the same to the mask */
X
X		/* save current dot and window positions */
X		doto = curwp -> w_doto;
X		u_off = curwp -> w_unit_offset;
X		loff = curwp -> w_loff;
X		stat = execute (cod, FALSE, 1);
X
X		if (stat == ABORT)
X		{
X			old_srch_pat_size = srch_pat -> l_used; /* save for restore */
X			if (rplc_mode == TRUE)
X				old_rplc_pat_size = rplc_pat -> l_used;
X			old_fmt = curwp -> w_fmt_ptr;
X			curwp = save_wind;  /* restore current window */
X			curbp = save_buf;  /* restore current buffer */
X			read_pat_mode = FALSE;
X			return (FALSE);
X		}
X
X		/* If key is recall then reset the size variables */
X		if (first_time)
X		{
X			first_time = FALSE;
X			if (recall_flag)
X			{
X				srch_pat -> l_used = old_srch_pat_size;
X				srch_mask -> l_used = old_srch_pat_size;
X				rplc_pat -> l_used = old_rplc_pat_size;
X				rplc_mask -> l_used = old_rplc_pat_size;
X				curwp -> w_fmt_ptr = old_fmt;
X				recall_flag = FALSE;
X			}
X		}
X
X		/* if it was a toggling command, don't do it again */
X		if (!dont_repeat &&
X		    (stat == TRUE))
X		{
X			head_line.l_fp = cur_mask;   /* point to mask */
X			head_line.l_bp = cur_mask;
X			curwp -> w_linep = cur_mask;
X			curwp -> w_dotp = cur_mask;
X			curwp -> w_loff = loff;
X			curwp -> w_doto = doto;
X			curwp -> w_unit_offset = u_off;
X			execute (mask_cod, FALSE, 1);
X
X			head_line.l_fp = cur_pat;    /* restore pointers */
X			head_line.l_bp = cur_pat;
X			curwp -> w_linep = cur_pat;
X			curwp -> w_dotp = cur_pat;
X		}
X		else
X			dont_repeat = FALSE;
X
X		/* limit at 256 bytes */
X		if (cur_pat -> l_used >= 256)
X		{
X			cur_mask -> l_used = 255;
X			cur_pat -> l_used = 255;
X			if (curwp -> w_doto >= 256)
X			{
X				move_ptr (curwp, 255L, TRUE, TRUE, FALSE);  /* last position */
X			}
X		}
X
X		/* if buffer is size locked then replace pattern must be the */
X		/* same size as the search pattern */
X		if (rplc_mode && (save_buf -> b_flag & BFSLOCK))
X		{
X			rplc_pat -> l_used = srch_pat -> l_used;
X			rplc_mask -> l_used = srch_pat -> l_used;
X		}
X
X		r_type = R_TYPE(curwp);
X#if RUNCHK
X		/* check that the pattern and the mask are the same size */
X		if (cur_pat -> l_used != cur_mask -> l_used)
X		{
X			printf (ERR_mask, cur_pat -> l_used, cur_mask -> l_used);
X		}
X
X		/* check that in ascii mode the byte that will be set to zero */
X		/* is the dummy char 9 */
X		/*        if (((r_type == ASCII) &&
X            (cur_mask -> l_text[curwp -> w_doto - 1] != '9'))
X            ||
X            ((r_type == EBCDIC) &&
X            (cur_mask -> l_text[curwp -> w_doto - 1] != to_ebcdic('9'))))
X            printf (ERR_m_cl);
X*/
X#endif
X		if (((r_type == ASCII) ||
X		    (r_type == EBCDIC)) &&
X		    ((cod >= ' ') && (cod < 0x7f)))
X			cur_mask -> l_text[doto] = 0; /* clear mask byte */
X
Xnext_loop:
X		sprintf (buf1, MSG_curs, cur_prompt, R_BYTE_FMT(curwp),
X		    R_BYTE_FMT(curwp), R_BYTE_FMT(curwp));
X		sprintf (disp_buf, buf1, curwp -> w_doto,
X		    curwp -> w_fmt_ptr -> r_chr_per_u - curwp -> w_unit_offset - 1,
X		    curwp -> w_dotp -> l_used);
X
X		siz_prompt2 = strlen (disp_buf); /* save prompt length for later */
X
X		for (i = siz_prompt2; i < NCOL; i++)
X		{
X			disp_buf [i] = ' ';
X			mask_buf [i] = ' ';
X		}
X
X		if ((curbp -> b_flag & BFSLOCK) &&
X		    (rplc_pat -> l_used != srch_pat -> l_used))
X		{
X			rplc_pat -> l_used = srch_pat -> l_used;
X			/* if dot is past the end then move it back, replace string only */
X			if (DOT_POS(curwp) > srch_pat -> l_used)
X				move_ptr (curwp, (long)srch_pat -> l_used, TRUE, TRUE, FALSE);
X		}
X
X		wind_on_dot (curwp);
X
X		/* figure number of bytes to convert to text */
X		if ((cur_pat -> l_used - curwp -> w_loff) <
X		    (prt_siz = curwp -> w_fmt_ptr -> r_bytes))
X			prt_siz = cur_pat -> l_used - curwp -> w_loff;
X
X		bin_to_text (&cur_pat -> l_text[curwp -> w_loff],
X		    &disp_buf[siz_prompt2],
X		    prt_siz, curwp -> w_fmt_ptr);
X
X		/* change any char to a ? if any bit is set in the mask buffer */
X		if ((r_type != ASCII) && (r_type != EBCDIC))
X		{
X			/* print the contents of the mask to a invisible buffer */
X			bin_to_text (&cur_mask -> l_text[curwp -> w_loff],
X			    &mask_buf[siz_prompt2],
X			    prt_siz, curwp -> w_fmt_ptr);
X
X			for (i = siz_prompt2; (disp_buf[i] != 0) && (i < NCOL); i++)
X			{
X				if ((mask_buf[i] != '0') &&
X				    (mask_buf[i] != ' '))
X					disp_buf[i] = '?';
X			}
X		}
X		else
X		{
X			for (i = 0; i < prt_siz; i++)
X			{
X				if (cur_mask -> l_text[curwp -> w_loff + i] != 0)
X					disp_buf[i + siz_prompt2] = '?';
X			}
X		}
X		writ_echo (disp_buf);
X	}
X}
X
X/*
X*   Recall the last contents of the search string
X*/
Xbool    recall ()
X{
X	recall_flag = TRUE;
X	return (TRUE);
X}
X
X/*
X*   Switch between search pattern and replace pattern and their 
X*   respective masks 
X*/
Xvoid    next_pat ()
X{
X	if (cur_pat == srch_pat)
X	{
X		cur_prompt = MSG_rpl_str;
X		cur_pat = rplc_pat; /* point to replace pattern */
X		cur_mask = rplc_mask;
X	}
X	else
X	{
X		cur_prompt = MSG_sch_str;
X		cur_pat = srch_pat;     /* point to search pattern */
X		cur_mask = srch_mask;
X	}
X	curwp -> w_dotp = cur_pat;
X	curwp -> w_linep = cur_pat;
X	curbp -> b_linep -> l_fp = cur_pat;
X	curbp -> b_linep -> l_bp = cur_pat;
X
X	if (curwp -> w_doto > cur_pat -> l_used)
X	{
X		curwp -> w_doto = cur_pat -> l_used;
X		curwp -> w_unit_offset = 0;
X	}
X	if (curwp -> w_loff > cur_pat -> l_used)
X		curwp -> w_loff = cur_pat -> l_used;
X	dont_repeat = TRUE;
X}
X
X/*
X* Compare the contents of two windows.
X* There must be exactly two windows displayed.
X* The bytes under the cursor in each window are compared and if 
X* a difference is found then the loop is stopped with the dot
X* position in each window pointing to the difference.
X* The two windows can be pointing at the same or different buffers.
X*/
Xbool    compare ()
X
X{
X	WINDOW  *wp1, *wp2;
X	bool    move1, move2;
X	int     j;
X	char    *term_str = MSG_cmp_dif;
X	char    buf[80], buf1[60];
X
X	if (wheadp -> w_wndp -> w_wndp != NULL)
X	{
X		writ_echo (MSG_only_2);
X		return (FALSE);
X	}
X
X	wp1 = wheadp;
X	wp2 = wheadp -> w_wndp;
X	j =  (int)DOT_POS(curwp) & 0xffff;
X
X	wp1 -> w_flag |= WFMOVE;
X	wp2 -> w_flag |= WFMOVE;
X
X	while (DOT_CHAR(wp1) == DOT_CHAR(wp2))
X	{
X		if ((j++ & 0xff) == 0)
X		{
X			sprintf (buf1, MSG_cmping, R_POS_FMT(curwp));
X			sprintf (buf, buf1, DOT_POS(curwp));
X			writ_echo (buf);
X			/* check if we should quit */
X			if (ttkeyready ())
X			{
X				if (ttgetc () == CTL_G)
X				{
X					term_str = MSG_cmp_term;
X					break;
X				}
X			}
X		}
X		move1 = move_ptr (wp1, 1L, TRUE, FALSE, TRUE);
X		move2 = move_ptr (wp2, 1L, TRUE, FALSE, TRUE);
X
X		if (!(move1 && move2))
X		{
X			term_str = MSG_cmp_end;
X			break;
X		}
X	}
X	writ_echo (term_str);
X	wind_on_dot (wp1);
X	wind_on_dot (wp2);
X	return (TRUE);
X}
END_OF_FILE
if test 24684 -ne `wc -c <'search.c'`; then
    echo shar: \"'search.c'\" unpacked with wrong size!
fi
# end of 'search.c'
fi
echo shar: End of archive 6 \(of 9\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 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

-- 
>>>>>>>>>>>>>>>> Peter Reilley ..... pvr@wang.com <<<<<<<<<<<<<<<<<<<<<<<
                     Well, that about says it.

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.
