Example #1
0
File: mark.c Project: meh/screen
void MarkRoutine()
{
	int x, y;

	if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1))
		return;
	flayer->l_encoding = fore->w_encoding;
	flayer->l_mode = 1;
	markdata = (struct markdata *)flayer->l_data;
	markdata->md_user = D_user;	/* XXX: Correct? */
	markdata->md_window = fore;
	markdata->second = 0;
	markdata->rep_cnt = 0;
	markdata->append_mode = 0;
	markdata->write_buffer = 0;
	markdata->nonl = 0;
	markdata->left_mar = 0;
	markdata->right_mar = fore->w_width - 1;
	markdata->hist_offset = fore->w_histheight;
	x = fore->w_x;
	y = D2W(fore->w_y);
	if (x >= fore->w_width)
		x = fore->w_width - 1;

	LGotoPos(flayer, x, W2D(y));
	LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
	     x + 1, W2D(y + 1), fore->w_histheight, fore->w_width, fore->w_height);
	markdata->cx = markdata->x1 = x;
	markdata->cy = markdata->y1 = y;
	flayer->l_x = x;
	flayer->l_y = W2D(y);
}
Example #2
0
static void
erase_chars(struct inpdata *inpdata, char *from, char *to, int x, int mv)
{
  int chng;
  ASSERT(from < to);
  if (inpdata->inp.len > to - inpdata->inp.buf)
    memmove(from, to, inpdata->inp.len - (to - inpdata->inp.buf));
  chng = to - from;
  if (mv)
    {
      x -= chng;
      inpdata->inp.pos -= chng;
    }
  inpdata->inp.len -= chng;
  if (!(inpdata->inpmode & INP_NOECHO))
    {
      struct mchar mc;
      char *s = from < to ? from : to;
      mc = mchar_so;
      while (s < inpdata->inp.buf+inpdata->inp.len)
	{
	  mc.image = *s++;
	  LPutChar(flayer, &mc, x++, INPUTLINE);
	}
      while (chng--)
	LPutChar(flayer, &mchar_blank, x++, INPUTLINE);
      x = inpdata->inpstringlen + inpdata->inp.pos;
      LGotoPos(flayer, x, INPUTLINE);
    }
}
Example #3
0
File: mark.c Project: meh/screen
/* tx, ty: WINDOW,  line: DISPLAY */
void revto_line(int tx, int ty, int line)
{
	int fx, fy;
	int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0;
	int ystart = 0, yend = fore->w_height - 1;
	int i, ry;
	uint32_t *wi;
	struct mline *ml;
	struct mchar mc;

	if (tx < 0)
		tx = 0;
	else if (tx > fore->w_width - 1)
		tx = fore->w_width - 1;
	if (ty < 0)
		ty = 0;
	else if (ty > fore->w_histheight + fore->w_height - 1)
		ty = fore->w_histheight + fore->w_height - 1;

	fx = markdata->cx;
	fy = markdata->cy;

	/* don't just move inside of a kanji, the user wants to see something */
	ml = WIN(ty);
	if (ty == fy && fx + 1 == tx && dw_right(ml, tx, fore->w_encoding) && tx < D_width - 1)
		tx++;
	if (ty == fy && fx - 1 == tx && dw_right(ml, fx, fore->w_encoding) && tx)
		tx--;

	markdata->cx = tx;
	markdata->cy = ty;

	/*
	 * if we go to a position that is currently offscreen
	 * then scroll the screen
	 */
	i = 0;
	if (line >= 0 && line < fore->w_height)
		i = W2D(ty) - line;
	else if (ty < markdata->hist_offset)
		i = ty - markdata->hist_offset;
	else if (ty > markdata->hist_offset + (fore->w_height - 1))
		i = ty - markdata->hist_offset - (fore->w_height - 1);
	if (i > 0)
		yend -= MarkScrollUpDisplay(i);
	else if (i < 0)
		ystart += MarkScrollDownDisplay(-i);

	if (markdata->second == 0) {
		flayer->l_x = tx;
		flayer->l_y = W2D(ty);
		LGotoPos(flayer, tx, W2D(ty));
		return;
	}

	qq = markdata->x1 + markdata->y1 * fore->w_width;
	ff = fx + fy * fore->w_width;	/* "from" offset in WIN coords */
	tt = tx + ty * fore->w_width;	/* "to" offset  in WIN coords */

	if (ff > tt) {
		st = tt;
		en = ff;
		x = tx;
		y = ty;
	} else {
		st = ff;
		en = tt;
		x = fx;
		y = fy;
	}
	if (st > qq) {
		st++;
		x++;
	}
	if (en < qq)
		en--;
	if (tt > qq) {
		revst = qq;
		reven = tt;
	} else {
		revst = tt;
		reven = qq;
	}
	ry = y - markdata->hist_offset;
	if (ry < ystart) {
		y += (ystart - ry);
		x = 0;
		st = y * fore->w_width;
		ry = ystart;
	}
	ml = WIN(y);
	for (t = st; t <= en; t++, x++) {
		if (x >= fore->w_width) {
			x = 0;
			y++, ry++;
			ml = WIN(y);
		}
		if (ry > yend)
			break;
		if (t == st || x == 0) {
			wi = ml->image + fore->w_width;
			for (ce = fore->w_width; ce >= 0; ce--, wi--)
				if (*wi != ' ')
					break;
		}
		if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar) {
			if (dw_right(ml, x, fore->w_encoding)) {
				if (t == revst)
					revst--;
				t--;
				x--;
			}
			if (t >= revst && t <= reven) {
				mc = mchar_so;
				if (pastefont) {
					mc.font = ml->font[x];
					mc.fontx = ml->fontx[x];
				}
				mc.image = ml->image[x];
			} else
				copy_mline2mchar(&mc, ml, x);
			if (dw_left(ml, x, fore->w_encoding)) {
				mc.mbcs = ml->image[x + 1];
				LPutChar(flayer, &mc, x, W2D(y));
				t++;
			}
			LPutChar(flayer, &mc, x, W2D(y));
			if (dw_left(ml, x, fore->w_encoding))
				x++;
		}
	}
	flayer->l_x = tx;
	flayer->l_y = W2D(ty);
	LGotoPos(flayer, tx, W2D(ty));
}
Example #4
0
File: mark.c Project: meh/screen
static void MarkProcess(char **inbufp, size_t *inlenp)
{
	char *inbuf, *pt;
	int inlen;
	int cx, cy, x2, y2, j, yend;
	int newcopylen = 0, od;
	int in_mark;
	int rep_cnt;
	struct acluser *md_user;

/*
  char *extrap = 0, extrabuf[100];
*/

	markdata = (struct markdata *)flayer->l_data;
	fore = markdata->md_window;
	md_user = markdata->md_user;
	if (inbufp == 0) {
		MarkAbort();
		return;
	}

	LGotoPos(flayer, markdata->cx, W2D(markdata->cy));
	inbuf = *inbufp;
	inlen = *inlenp;
	pt = inbuf;
	in_mark = 1;
	while (in_mark && (inlen /* || extrap */ )) {
		unsigned char ch = (unsigned char)*pt++;
		inlen--;
		if (flayer->l_mouseevent.start) {
			int r = LayProcessMouse(flayer, ch);
			if (r == -1)
				LayProcessMouseSwitch(flayer, 0);
			else {
				if (r)
					ch = 0222;
				else
					continue;
			}
		}
		od = mark_key_tab[(int)ch];
		rep_cnt = markdata->rep_cnt;
		if (isdigit(od) && !markdata->f_cmd.flag) {
			if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) {
				markdata->rep_cnt = 10 * rep_cnt + od - '0';
				continue;
				/*
				 * Now what is that 1001 here? Well, we have a screen with
				 * 25 * 80 = 2000 characters. Movement is at most across the full
				 * screen. This we do with word by word movement, as character by
				 * character movement never steps over line boundaries. The most words
				 * we can place on the screen are 1000 single letter words. Thus 1001
				 * is sufficient. Users with bigger screens never write in single letter
				 * words, as they should be more advanced. jw.
				 * Oh, wrong. We still give even the experienced user a factor of ten.
				 */
			}
		}
		cx = markdata->cx;
		cy = markdata->cy;

		if (markdata->f_cmd.flag) {
			markdata->f_cmd.flag = 0;
			markdata->rep_cnt = 0;

			if (isgraph(od)) {
				markdata->f_cmd.target = od;
				rep_cnt = (rep_cnt) ? rep_cnt : 1;
				nextchar(&cx, &cy, markdata->f_cmd.direction, od, rep_cnt);
				revto(cx, cy);
				continue;
			}
		}

 processchar:
		switch (od) {
		case 'f':	/* fall through */
		case 'F':	/* fall through */
		case 't':	/* fall through */
		case 'T':	/* fall through */
			/*
			 * Set f_cmd to do a search on the next key stroke.
			 * If we break, rep_cnt will be reset, so we
			 * continue instead. It might be cleaner to
			 * store the rep_count in f_cmd and
			 * break here so later followon code will be
			 * hit.
			 */
			markdata->f_cmd.flag = 1;
			markdata->f_cmd.direction = od;
			continue;
		case ';':
		case ',':
			if (!markdata->f_cmd.target)
				break;
			if (!rep_cnt)
				rep_cnt = 1;
			nextchar(&cx, &cy,
				 od == ';' ? markdata->f_cmd.direction : (markdata->f_cmd.direction ^ 0x20),
				 markdata->f_cmd.target, rep_cnt);
			revto(cx, cy);
			break;
		case 'o':
		case 'x':
			if (!markdata->second)
				break;
			markdata->cx = markdata->x1;
			markdata->cy = markdata->y1;
			markdata->x1 = cx;
			markdata->y1 = cy;
			revto(markdata->cx, markdata->cy);
			break;
		case '\014':	/* CTRL-L Redisplay */
			Redisplay(0);
			LGotoPos(flayer, cx, W2D(cy));
			break;
		case 0202:	/* M-C-b */
		case '\010':	/* CTRL-H Backspace */
		case 'h':
			if (rep_cnt == 0)
				rep_cnt = 1;
			revto(cx - rep_cnt, cy);
			break;
		case 0216:	/* M-C-p */
		case '\016':	/* CTRL-N */
		case 'j':
			if (rep_cnt == 0)
				rep_cnt = 1;
			revto(cx, cy + rep_cnt);
			break;
		case '+':
			if (rep_cnt == 0)
				rep_cnt = 1;
			j = cy + rep_cnt;
			if (j > fore->w_histheight + fore->w_height - 1)
				j = fore->w_histheight + fore->w_height - 1;
			revto(linestart(j), j);
			break;
		case '-':
			if (rep_cnt == 0)
				rep_cnt = 1;
			cy -= rep_cnt;
			if (cy < 0)
				cy = 0;
			revto(linestart(cy), cy);
			break;
		case '^':
			revto(linestart(cy), cy);
			break;
		case '\n':
			revto(markdata->left_mar, cy + 1);
			break;
		case 0220:	/* M-C-p */
		case '\020':	/* CTRL-P */
		case 'k':
			if (rep_cnt == 0)
				rep_cnt = 1;
			revto(cx, cy - rep_cnt);
			break;
		case 0206:	/* M-C-f */
		case 'l':
			if (rep_cnt == 0)
				rep_cnt = 1;
			revto(cx + rep_cnt, cy);
			break;
		case '\001':	/* CTRL-A from tcsh/emacs */
		case '0':
			revto(markdata->left_mar, cy);
			break;
		case '\004':	/* CTRL-D down half screen */
			if (rep_cnt == 0)
				rep_cnt = (fore->w_height + 1) >> 1;
			revto_line(cx, cy + rep_cnt, W2D(cy));
			break;
		case '$':
			revto(lineend(cy), cy);
			break;
		case '\022':	/* CTRL-R emacs style backwards search */
			ISearch(-1);
			in_mark = 0;
			break;
		case '\023':	/* CTRL-S emacs style search */
			ISearch(1);
			in_mark = 0;
			break;
		case '\025':	/* CTRL-U up half screen */
			if (rep_cnt == 0)
				rep_cnt = (fore->w_height + 1) >> 1;
			revto_line(cx, cy - rep_cnt, W2D(cy));
			break;
		case '\007':	/* CTRL-G show cursorpos */
			if (markdata->left_mar == 0 && markdata->right_mar == fore->w_width - 1)
				LMsg(0, "Column %d Line %d(+%d)", cx + 1, W2D(cy) + 1, markdata->hist_offset);
			else
				LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx + 1,
				     markdata->left_mar + 1, markdata->right_mar + 1, W2D(cy) + 1,
				     markdata->hist_offset);
			break;
		case '\002':	/* CTRL-B  back one page */
			if (rep_cnt == 0)
				rep_cnt = 1;
			rep_cnt *= fore->w_height;
			revto(cx, cy - rep_cnt);
			break;
		case '\006':	/* CTRL-F  forward one page */
			if (rep_cnt == 0)
				rep_cnt = 1;
			rep_cnt *= fore->w_height;
			revto(cx, cy + rep_cnt);
			break;
		case '\005':	/* CTRL-E  scroll up */
			if (rep_cnt == 0)
				rep_cnt = 1;
			MarkScrollUpDisplay(rep_cnt);
			if (cy < D2W(0))
				revto(cx, D2W(0));
			else
				LGotoPos(flayer, cx, W2D(cy));
			break;
		case '\031':	/* CTRL-Y  scroll down */
			if (rep_cnt == 0)
				rep_cnt = 1;
			MarkScrollDownDisplay(rep_cnt);
			if (cy > D2W(fore->w_height - 1))
				revto(cx, D2W(fore->w_height - 1));
			else
				LGotoPos(flayer, cx, W2D(cy));
			break;
		case '@':
			/* it may be useful to have a key that does nothing */
			break;
		case '%':
			rep_cnt--;
			/* rep_cnt is a percentage for the history buffer */
			if (rep_cnt < 0)
				rep_cnt = 0;
			if (rep_cnt > 100)
				rep_cnt = 100;
			revto_line(markdata->left_mar, (rep_cnt * (fore->w_histheight + fore->w_height)) / 100,
				   (fore->w_height - 1) / 2);
			break;
		case 0201:
		case 'g':
			rep_cnt = 1;
			/* FALLTHROUGH */
		case 0205:
		case 'G':
			/* rep_cnt is here the WIN line number */
			if (rep_cnt == 0)
				rep_cnt = fore->w_histheight + fore->w_height;
			revto_line(markdata->left_mar, --rep_cnt, (fore->w_height - 1) / 2);
			break;
		case 'H':
			revto(markdata->left_mar, D2W(0));
			break;
		case 'M':
			revto(markdata->left_mar, D2W((fore->w_height - 1) / 2));
			break;
		case 'L':
			revto(markdata->left_mar, D2W(fore->w_height - 1));
			break;
		case '|':
			revto(--rep_cnt, cy);
			break;
		case 'w':
			if (rep_cnt == 0)
				rep_cnt = 1;
			nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt);
			revto(cx, cy);
			break;
		case 'e':
		case 'E':
			if (rep_cnt == 0)
				rep_cnt = 1;
			nextword(&cx, &cy, NW_ENDOFWORD | NW_MUSTMOVE | (od == 'E' ? NW_BIG : 0), rep_cnt);
			revto(cx, cy);
			break;
		case 'b':
		case 'B':
			if (rep_cnt == 0)
				rep_cnt = 1;
			nextword(&cx, &cy, NW_BACK | NW_ENDOFWORD | NW_MUSTMOVE | (od == 'B' ? NW_BIG : 0), rep_cnt);
			revto(cx, cy);
			break;
		case 'a':
			markdata->append_mode = 1 - markdata->append_mode;
			LMsg(0, (markdata->append_mode) ? ":set append" : ":set noappend");
			break;
		case 'v':
		case 'V':
			/* this sets start column to column 9 for VI :set nu users */
			if (markdata->left_mar == 8)
				rep_cnt = 1;
			else
				rep_cnt = 9;
			/* FALLTHROUGH */
		case 'c':
		case 'C':
			/* set start column (c) and end column (C) */
			if (markdata->second) {
				rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, fore->w_height - 1);	/* Hack */
				markdata->second = 1;	/* rem turns off second */
			}
			rep_cnt--;
			if (rep_cnt < 0)
				rep_cnt = cx;
			if (od != 'C') {
				markdata->left_mar = rep_cnt;
				if (markdata->left_mar > markdata->right_mar)
					markdata->left_mar = markdata->right_mar;
			} else {
				markdata->right_mar = rep_cnt;
				if (markdata->left_mar > markdata->right_mar)
					markdata->right_mar = markdata->left_mar;
			}
			if (markdata->second) {
				markdata->cx = markdata->x1;
				markdata->cy = markdata->y1;
				revto(cx, cy);
			}
			if (od == 'v' || od == 'V')
				LMsg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu");
			break;
		case 'J':
			/* how do you join lines in VI ? */
			markdata->nonl = (markdata->nonl + 1) % 4;
			switch (markdata->nonl) {
			case 0:
				if (join_with_cr)
					LMsg(0, "Multiple lines (CR/LF)");
				else
					LMsg(0, "Multiple lines (LF)");
				break;
			case 1:
				LMsg(0, "Lines joined");
				break;
			case 2:
				LMsg(0, "Lines joined with blanks");
				break;
			case 3:
				LMsg(0, "Lines joined with comma");
				break;
			}
			break;
		case '/':
			Search(1);
			in_mark = 0;
			break;
		case '?':
			Search(-1);
			in_mark = 0;
			break;
		case 'n':
			Search(0);
			break;
		case 'N':
			markdata->isdir = -markdata->isdir;
			Search(0);
			markdata->isdir = -markdata->isdir;
			break;
		case 'y':
		case 'Y':
			if (markdata->second == 0) {
				revto(linestart(cy), cy);
				markdata->second++;
				cx = markdata->x1 = markdata->cx;
				cy = markdata->y1 = markdata->cy;
			}
			if (--rep_cnt > 0)
				revto(cx, cy + rep_cnt);
			revto(lineend(markdata->cy), markdata->cy);
			if (od == 'y')
				break;
			/* FALLTHROUGH */
		case 'W':
			if (od == 'W') {
				if (rep_cnt == 0)
					rep_cnt = 1;
				if (!markdata->second) {
					nextword(&cx, &cy, NW_BACK | NW_ENDOFWORD, 1);
					revto(cx, cy);
					markdata->second++;
					cx = markdata->x1 = markdata->cx;
					cy = markdata->y1 = markdata->cy;
				}
				nextword(&cx, &cy, NW_ENDOFWORD, rep_cnt);
				revto(cx, cy);
			}
			cx = markdata->cx;
			cy = markdata->cy;
			/* FALLTHROUGH */
		case 'A':
			if (od == 'A')
				markdata->append_mode = 1;
			/* FALLTHROUGH */
		case '>':
			if (od == '>')
				markdata->write_buffer = 1;
			/* FALLTHROUGH */
		case ' ':
		case '\r':
			if (!markdata->second) {
				markdata->second++;
				markdata->x1 = cx;
				markdata->y1 = cy;
				revto(cx, cy);
				LMsg(0, "First mark set - Column %d Line %d", cx + 1, W2D(cy) + 1);
				break;
			} else {
				int append_mode = markdata->append_mode;
				int write_buffer = markdata->write_buffer;

				x2 = cx;
				y2 = cy;
				newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char *)0, 0);	/* count */
				if (md_user->u_plop.buf && !append_mode)
					UserFreeCopyBuffer(md_user);
				yend = fore->w_height - 1;
				if (fore->w_histheight - markdata->hist_offset < fore->w_height) {
					markdata->second = 0;
					yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset);
				}
				if (newcopylen > 0) {
					/* the +3 below is for : cr + lf + \0 */
					if (md_user->u_plop.buf)
						md_user->u_plop.buf = realloc(md_user->u_plop.buf,
									      (unsigned)(md_user->u_plop.len +
											 newcopylen + 3));
					else {
						md_user->u_plop.len = 0;
						md_user->u_plop.buf = malloc((unsigned)(newcopylen + 3));
					}
					if (!md_user->u_plop.buf) {
						MarkAbort();
						in_mark = 0;
						LMsg(0, "Not enough memory... Sorry.");
						md_user->u_plop.len = 0;
						md_user->u_plop.buf = 0;
						break;
					}
					if (append_mode) {
						switch (markdata->nonl) {
							/*
							 * this code defines, what glues lines together
							 */
						case 0:
							if (join_with_cr) {
								md_user->u_plop.buf[md_user->u_plop.len] = '\r';
								md_user->u_plop.len++;
							}
							md_user->u_plop.buf[md_user->u_plop.len] = '\n';
							md_user->u_plop.len++;
							break;
						case 1:
							break;
						case 2:
							md_user->u_plop.buf[md_user->u_plop.len] = ' ';
							md_user->u_plop.len++;
							break;
						case 3:
							md_user->u_plop.buf[md_user->u_plop.len] = ',';
							md_user->u_plop.len++;
							break;
						}
					}
					md_user->u_plop.len += rem(markdata->x1, markdata->y1, x2, y2,
								   markdata->hist_offset == fore->w_histheight,
								   md_user->u_plop.buf + md_user->u_plop.len, yend);
					md_user->u_plop.enc = fore->w_encoding;
				}
				if (markdata->hist_offset != fore->w_histheight) {
					LAY_CALL_UP(LRefreshAll(flayer, 0));
				}
				ExitOverlayPage();
				WindowChanged(fore, 'P');
				if (append_mode)
					LMsg(0, "Appended %d characters to buffer", newcopylen);
				else
					LMsg(0, "Copied %d characters into buffer", md_user->u_plop.len);
				if (write_buffer)
					WriteFile(md_user, (char *)0, DUMP_EXCHANGE);
				in_mark = 0;
				break;
			}

		case 0222:
			if (flayer->l_mouseevent.start) {
				int button = flayer->l_mouseevent.buffer[0];
				if (button == 'a') {
					/* Scroll down */
					od = 'j';
				} else if (button == '`') {
					/* Scroll up */
					od = 'k';
				} else if (button == ' ') {
					/* Left click */
					cx = flayer->l_mouseevent.buffer[1];
					cy = D2W(flayer->l_mouseevent.buffer[2]);
					revto(cx, cy);
					od = ' ';
				} else
					od = 0;
				LayProcessMouseSwitch(flayer, 0);
				if (od)
					goto processchar;
			} else
				LayProcessMouseSwitch(flayer, 1);
			break;

		default:
			MarkAbort();
			LMsg(0, "Copy mode aborted");
			in_mark = 0;
			break;
		}
		if (in_mark)	/* markdata may be freed */
			markdata->rep_cnt = 0;
	}
	if (in_mark) {
		flayer->l_x = markdata->cx;
		flayer->l_y = W2D(markdata->cy);
	}
	*inbufp = pt;
	*inlenp = inlen;
}
Example #5
0
static void
InpProcess(char **ppbuf, int *plen)
{
  int len, x;
  char *pbuf;
  char ch;
  struct inpdata *inpdata;
  struct display *inpdisplay;
  int prev, next, search = 0;

  inpdata = (struct inpdata *)flayer->l_data;
  inpdisplay = display;

#define RESET_SEARCH { if (inpdata->search) Free(inpdata->search); }

  LGotoPos(flayer, inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), INPUTLINE);
  if (ppbuf == 0)
    {
      InpAbort();
      return;
    }
  x = inpdata->inpstringlen + inpdata->inp.pos;
  len = *plen;
  pbuf = *ppbuf;
  while (len)
    {
      char *p = inpdata->inp.buf + inpdata->inp.pos;

      ch = *pbuf++;
      len--;
      if (inpdata->inpmode & INP_EVERY)
	{
	  inpdata->inp.buf[inpdata->inp.len] = ch;
	  if (ch)
	    {
	      display = inpdisplay;
	      (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
	      ch = inpdata->inp.buf[inpdata->inp.len];
	    }
	}
      else if (inpdata->inpmode & INP_RAW)
	{
	  display = inpdisplay;
          (*inpdata->inpfinfunc)(&ch, 1, inpdata->priv);	/* raw */
	  if (ch)
	    continue;
	}
      if (((unsigned char)ch & 0177) >= ' ' && ch != 0177 && inpdata->inp.len < inpdata->inpmaxlen)
	{
	  if (inpdata->inp.len > inpdata->inp.pos)
	    memmove(p+1, p, inpdata->inp.len - inpdata->inp.pos);
	  inpdata->inp.buf[inpdata->inp.pos++] = ch;
	  inpdata->inp.len++;

	  if (!(inpdata->inpmode & INP_NOECHO))
	    {
	      struct mchar mc;
	      mc = mchar_so;
	      mc.image = *p++;
	      LPutChar(flayer, &mc, x, INPUTLINE);
	      x++;
	      if (p < inpdata->inp.buf+inpdata->inp.len)
		{
		  while (p < inpdata->inp.buf+inpdata->inp.len)
		    {
		      mc.image = *p++;
		      LPutChar(flayer, &mc, x++, INPUTLINE);
		    }
		  x = inpdata->inpstringlen + inpdata->inp.pos;
		  LGotoPos(flayer, x, INPUTLINE);
		}
	    }
	  RESET_SEARCH;
	}
      else if ((ch == '\b' || ch == 0177) && inpdata->inp.pos > 0)
	{
	  erase_chars(inpdata, p-1, p, x, 1);
	  RESET_SEARCH;
	}
      else if (ch == '\025')			/* CTRL-U */
	{
	  x = inpdata->inpstringlen;
	  if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
	    {
	      LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - 1, INPUTLINE, 0, 0);
	      LGotoPos(flayer, x, INPUTLINE);
	    }
	  inpdata->inp.len = inpdata->inp.pos = 0;
	}
      else if (ch == '\013')			/* CTRL-K */
	{
	  x = inpdata->inpstringlen + inpdata->inp.pos;
	  if (inpdata->inp.len > inpdata->inp.pos && !(inpdata->inpmode & INP_NOECHO))
	    {
	      LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - inpdata->inp.pos - 1, INPUTLINE, 0, 0);
	      LGotoPos(flayer, x, INPUTLINE);
	    }
	  inpdata->inp.len = inpdata->inp.pos;
	}
      else if (ch == '\027' && inpdata->inp.pos > 0)		/* CTRL-W */
	{
	  char *oldp = p--;
	  while (p > inpdata->inp.buf && *p == ' ')
	    p--;
	  while (p > inpdata->inp.buf && *(p - 1) != ' ')
	    p--;
	  erase_chars(inpdata, p, oldp, x, 1);
	  RESET_SEARCH;
	}
      else if (ch == '\004' && inpdata->inp.pos < inpdata->inp.len)	/* CTRL-D */
	{
	  erase_chars(inpdata, p, p+1, x, 0);
	  RESET_SEARCH;
	}
      else if (ch == '\001' || (unsigned char)ch == 0201)	/* CTRL-A */
	{
	  LGotoPos(flayer, x -= inpdata->inp.pos, INPUTLINE);
	  inpdata->inp.pos = 0;
	}
      else if ((ch == '\002' || (unsigned char)ch == 0202) && inpdata->inp.pos > 0)	/* CTRL-B */
	{
	  LGotoPos(flayer, --x, INPUTLINE);
	  inpdata->inp.pos--;
	}
      else if (ch == '\005' || (unsigned char)ch == 0205)	/* CTRL-E */
	{
	  LGotoPos(flayer, x += inpdata->inp.len - inpdata->inp.pos, INPUTLINE);
	  inpdata->inp.pos = inpdata->inp.len;
	}
      else if ((ch == '\006' || (unsigned char)ch == 0206) && inpdata->inp.pos < inpdata->inp.len)	/* CTRL-F */
	{
	  LGotoPos(flayer, ++x, INPUTLINE);
	  inpdata->inp.pos++;
	}
      else if ((prev = ((ch == '\020' || (unsigned char)ch == 0220) &&	/* CTRL-P */
	      inpdata->inp.prev)) ||
	  (next = ((ch == '\016' || (unsigned char)ch == 0216) &&  /* CTRL-N */
		   inpdata->inp.next)) ||
	  (search = ((ch == '\022' || (unsigned char)ch == 0222) && inpdata->inp.prev)))
	{
	  struct mchar mc;
	  struct inpline *sel;
	  int pos = -1;

	  mc = mchar_so;

	  if (prev)
	    sel = inpdata->inp.prev;
	  else if (next)
	    sel = inpdata->inp.next;
	  else
	    {
	      /* search */
	      inpdata->inp.buf[inpdata->inp.len] = 0;	/* Remove the ctrl-r from the end */
	      if (!inpdata->search)
		inpdata->search = SaveStr(inpdata->inp.buf);
	      for (sel = inpdata->inp.prev; sel; sel = sel->prev)
		{
		  char *f;
		  if ((f = strstr(sel->buf, inpdata->search)))
		    {
		      pos = f - sel->buf;
		      break;
		    }
		}
	      if (!sel)
		continue;	/* Did not find a match. Process the next input. */
	    }

	  if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
	    LClearArea(flayer, inpdata->inpstringlen, INPUTLINE, inpdata->inpstringlen + inpdata->inp.len - 1, INPUTLINE, 0, 0);

	  if ((prev || search) && !inpdata->inp.next)
	    inphist = inpdata->inp;
	  memcpy(&inpdata->inp, sel, sizeof(struct inpline));
	  if (pos != -1)
	    inpdata->inp.pos = pos;
	  if (inpdata->inp.len > inpdata->inpmaxlen)
	    inpdata->inp.len = inpdata->inpmaxlen;
	  if (inpdata->inp.pos > inpdata->inp.len)
	    inpdata->inp.pos = inpdata->inp.len;

	  x = inpdata->inpstringlen;
	  p = inpdata->inp.buf;

	  if (!(inpdata->inpmode & INP_NOECHO))
	    {
	      while (p < inpdata->inp.buf+inpdata->inp.len)
		{
		  mc.image = *p++;
		  LPutChar(flayer, &mc, x++, INPUTLINE);
		}
	    }
	  x = inpdata->inpstringlen + inpdata->inp.pos;
	  LGotoPos(flayer, x, INPUTLINE);
	}

      else if (ch == '\003' || ch == '\007' || ch == '\033' ||
	       ch == '\000' || ch == '\n' || ch == '\r')
	{
          if (ch != '\n' && ch != '\r')
	    inpdata->inp.len = 0;
	  inpdata->inp.buf[inpdata->inp.len] = 0;

	  if (inpdata->inp.len && !(inpdata->inpmode & (INP_NOECHO | INP_RAW)))
	    {
	      struct inpline *store;

	      /* Look for a duplicate first */
	      for (store = inphist.prev; store; store = store->prev)
		{
		  if (strcmp(store->buf, inpdata->inp.buf) == 0)
		    {
		      if (store->next)
			store->next->prev = store->prev;
		      if (store->prev)
			store->prev->next = store->next;
		      store->pos = inpdata->inp.pos;
		      break;
		    }
		}

	      if (!store)
		{
		  store = malloc(sizeof(struct inpline));
		  memcpy(store, &inpdata->inp, sizeof(struct inpline));
		}
	      store->next = &inphist;
	      store->prev = inphist.prev;
	      if (inphist.prev)
		inphist.prev->next = store;
	      inphist.prev = store;
	    }

	  flayer->l_data = 0;	/* so inpdata does not get freed */
          InpAbort();		/* redisplays... */
	  *ppbuf = pbuf;
	  *plen = len;
	  display = inpdisplay;
	  if ((inpdata->inpmode & INP_RAW) == 0)
            (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
	  else
            (*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv);
	  if (inpdata->search)
	    free(inpdata->search);
	  free(inpdata);
	  return;
	}
      else
	{
	  /* The user was searching, and then pressed some non-control input. So reset
	   * the search string. */
	  RESET_SEARCH;
	}
    }
  if (!(inpdata->inpmode & INP_RAW))
    {
      flayer->l_x = inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos);
      flayer->l_y = INPUTLINE;
    }
  *ppbuf = pbuf;
  *plen = len;
}