~ubuntu-branches/ubuntu/trusty/screen/trusty-backports

1 by Nathaniel McCallum
Import upstream version 4.0.2
1
/* Copyright (c) 1993-2002
2
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4
 * Copyright (c) 1987 Oliver Laumann
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2, or (at your option)
9
 * any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program (see the file COPYING); if not, write to the
18
 * Free Software Foundation, Inc.,
19
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
20
 *
21
 ****************************************************************
22
 */
23
24
#include <sys/types.h>
25
#include "config.h"
26
#include "screen.h"
27
#include "extern.h"
28
29
#define INPUTLINE (flayer->l_height - 1)
30
31
static void InpProcess __P((char **, int *));
32
static void InpAbort __P((void));
33
static void InpRedisplayLine __P((int, int, int, int));
34
35
extern struct layer *flayer;
36
extern struct display *display;
37
extern struct mchar mchar_blank, mchar_so;
38
39
struct inpline
40
{
41
  char  buf[101];	/* text buffer */
42
  int  len;		/* length of the editible string */
43
  int  pos;		/* cursor position in editable string */
44
};
45
46
static struct inpline inphist; /* XXX: should be a dynamic list */
47
48
49
struct inpdata
50
{
51
  struct inpline inp;
52
  int  inpmaxlen;	/* 100, or less, if caller has shorter buffer */
53
  char *inpstring;	/* the prompt */
54
  int  inpstringlen;	/* length of the prompt */
55
  int  inpmode;		/* INP_NOECHO, INP_RAW, INP_EVERY */
56
  void (*inpfinfunc) __P((char *buf, int len, char *priv));
57
  char  *priv;		/* private data for finfunc */
58
};
59
60
static struct LayFuncs InpLf =
61
{
62
  InpProcess,
63
  InpAbort,
64
  InpRedisplayLine,
65
  DefClearLine,
66
  DefRewrite,
67
  DefResize,
68
  DefRestore
69
};
70
71
/*
72
**   Here is the input routine
73
*/
74
75
/* called once, after InitOverlayPage in Input() or Isearch() */
76
void
77
inp_setprompt(p, s)
78
char *p, *s;
79
{
80
  struct inpdata *inpdata;
81
  
82
  inpdata = (struct inpdata *)flayer->l_data;
83
  if (p)
84
    {
85
      inpdata->inpstringlen = strlen(p);
86
      inpdata->inpstring = p;
87
    }
88
  if (s)
89
    {
90
      if (s != inpdata->inp.buf)
91
	strncpy(inpdata->inp.buf, s, sizeof(inpdata->inp.buf) - 1);
92
      inpdata->inp.buf[sizeof(inpdata->inp.buf) - 1] = 0;
93
      inpdata->inp.pos = inpdata->inp.len = strlen(inpdata->inp.buf);
94
    }
95
  InpRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0);
96
}
97
98
/*
99
 * We dont use HS status line with Input().
100
 * If we would use it, then we should check e_tgetflag("es") if
101
 * we are allowed to use esc sequences there.
102
 *
103
 * mode is an OR of
104
 * INP_NOECHO == suppress echoing of characters.
105
 * INP_RAW    == raw mode. call finfunc after each character typed.
106
 * INP_EVERY  == digraph mode.
107
 */
108
void
109
Input(istr, len, mode, finfunc, data)
110
char *istr;
111
int len;
112
int mode;
113
void (*finfunc) __P((char *buf, int len, char *data));
114
char *data;
115
{
116
  int maxlen;
117
  struct inpdata *inpdata;
118
  
119
  if (len > 100)
120
    len = 100;
121
  if (!(mode & INP_NOECHO))
122
    {
123
      maxlen = flayer->l_width - 1 - strlen(istr);
124
      if (len > maxlen)
125
	len = maxlen;
126
    }
127
  if (len < 0)
128
    {
129
      LMsg(0, "Width %d chars too small", -len);
130
      return;
131
    }
132
  if (InitOverlayPage(sizeof(*inpdata), &InpLf, 1))
133
    return;
134
  inpdata = (struct inpdata *)flayer->l_data;
135
  inpdata->inpmaxlen = len;
136
  inpdata->inpfinfunc = finfunc;
137
  inpdata->inp.pos = inpdata->inp.len = 0;
138
  inpdata->inpmode = mode;
139
  inpdata->priv = data;
140
  inp_setprompt(istr, (char *)NULL);
141
  flayer->l_x = inpdata->inpstringlen;
142
  flayer->l_y = INPUTLINE;
143
}
144
145
static void
146
InpProcess(ppbuf, plen)
147
char **ppbuf;
148
int *plen;
149
{
150
  int len, x;
151
  char *pbuf;
152
  char ch;
153
  struct inpdata *inpdata;
154
  struct display *inpdisplay;
155
156
  inpdata = (struct inpdata *)flayer->l_data;
157
  inpdisplay = display;
158
159
  LGotoPos(flayer, inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), INPUTLINE);
160
  if (ppbuf == 0)
161
    {
162
      InpAbort();
163
      return;
164
    }
165
  x = inpdata->inpstringlen + inpdata->inp.pos;
166
  len = *plen;
167
  pbuf = *ppbuf;
168
  while (len)
169
    {
170
      char *p = inpdata->inp.buf + inpdata->inp.pos;
171
172
      ch = *pbuf++;
173
      len--;
174
      if (inpdata->inpmode & INP_EVERY)
175
	{
176
	  inpdata->inp.buf[inpdata->inp.len] = ch;
177
	  inpdata->inp.buf[inpdata->inp.len + 1] = ch;	/* gross */
178
	  display = inpdisplay;
179
	  (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
180
	  ch = inpdata->inp.buf[inpdata->inp.len];
181
	}
182
      else if (inpdata->inpmode & INP_RAW)
183
	{
184
	  display = inpdisplay;
185
          (*inpdata->inpfinfunc)(&ch, 1, inpdata->priv);	/* raw */
186
	  if (ch)
187
	    continue;
188
	}
189
      if (((unsigned char)ch & 0177) >= ' ' && ch != 0177 && inpdata->inp.len < inpdata->inpmaxlen)
190
	{
191
	  if (inpdata->inp.len > inpdata->inp.pos)
192
	    bcopy(p, p+1, inpdata->inp.len - inpdata->inp.pos);
193
	  inpdata->inp.buf[inpdata->inp.pos++] = ch;
194
	  inpdata->inp.len++;
195
196
	  if (!(inpdata->inpmode & INP_NOECHO))
197
	    {
198
	      struct mchar mc;
199
	      mc = mchar_so;
200
	      mc.image = *p++;
201
	      LPutChar(flayer, &mc, x, INPUTLINE);
202
	      x++;
203
	      if (p < inpdata->inp.buf+inpdata->inp.len)
204
		{
205
		  while (p < inpdata->inp.buf+inpdata->inp.len)
206
		    {
207
		      mc.image = *p++;
208
		      LPutChar(flayer, &mc, x++, INPUTLINE);
209
		    }
210
		  x = inpdata->inpstringlen + inpdata->inp.pos;
211
		  LGotoPos(flayer, x, INPUTLINE);
212
		}
213
	    }
214
	}
215
      else if ((ch == '\b' || ch == 0177) && inpdata->inp.pos > 0)
216
	{
217
	  if (inpdata->inp.len > inpdata->inp.pos)
218
	    bcopy(p, p-1, inpdata->inp.len - inpdata->inp.pos);
219
	  inpdata->inp.len--;
220
	  inpdata->inp.pos--;
221
	  p--;
222
223
	  if (!(inpdata->inpmode & INP_NOECHO))
224
	    {
225
	      struct mchar mc;
226
	      mc = mchar_so;
227
	      x--;
228
	      while (p < inpdata->inp.buf+inpdata->inp.len)
229
		{
230
		  mc.image = *p++;
231
		  LPutChar(flayer, &mc, x++, INPUTLINE);
232
		}
233
	      LPutChar(flayer, &mchar_blank, x, INPUTLINE);
234
	      x = inpdata->inpstringlen + inpdata->inp.pos;
235
	      LGotoPos(flayer, x, INPUTLINE);
236
	    }
237
	}
238
      else if (ch == '\025')			/* CTRL-U */
239
	{
240
  	  x = inpdata->inpstringlen;
241
	  if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
242
	    {
243
	      LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - 1, INPUTLINE, 0, 0);
244
	      LGotoPos(flayer, x, INPUTLINE);
245
	    }
246
	  inpdata->inp.len = inpdata->inp.pos = 0;
247
	}
248
      else if (ch == '\013')			/* CTRL-K */
249
	{
250
  	  x = inpdata->inpstringlen + inpdata->inp.pos;
251
	  if (inpdata->inp.len > inpdata->inp.pos && !(inpdata->inpmode & INP_NOECHO))
252
	    {
253
	      LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - inpdata->inp.pos - 1, INPUTLINE, 0, 0);
254
	      LGotoPos(flayer, x, INPUTLINE);
255
	    }
256
	  inpdata->inp.len = inpdata->inp.pos;
257
	}
258
      else if (ch == '\001' || (unsigned char)ch == 0201)	/* CTRL-A */
259
	{
260
	  LGotoPos(flayer, x -= inpdata->inp.pos, INPUTLINE);
261
	  inpdata->inp.pos = 0;
262
	}
263
      else if ((ch == '\002' || (unsigned char)ch == 0202) && inpdata->inp.pos > 0)	/* CTRL-B */
264
	{
265
	  LGotoPos(flayer, --x, INPUTLINE);
266
	  inpdata->inp.pos--;
267
	}
268
      else if (ch == '\005' || (unsigned char)ch == 0205)	/* CTRL-E */
269
	{
270
	  LGotoPos(flayer, x += inpdata->inp.len - inpdata->inp.pos, INPUTLINE);
271
	  inpdata->inp.pos = inpdata->inp.len;
272
	}
273
      else if ((ch == '\006' || (unsigned char)ch == 0206) && inpdata->inp.pos < inpdata->inp.len)	/* CTRL-F */
274
	{
275
	  LGotoPos(flayer, ++x, INPUTLINE);
276
	  inpdata->inp.pos++;
277
	}
278
      else if (ch == '\020' || (unsigned char)ch == 0220)	/* CTRL-P */
279
        {
280
	  struct mchar mc;
281
	  mc = mchar_so;
282
	  if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
283
	    LClearArea(flayer, inpdata->inpstringlen, INPUTLINE, inpdata->inpstringlen + inpdata->inp.len - 1, INPUTLINE, 0, 0);
284
285
	  inpdata->inp = inphist;	/* structure copy */
286
	  if (inpdata->inp.len > inpdata->inpmaxlen)
287
	    inpdata->inp.len = inpdata->inpmaxlen;
288
	  if (inpdata->inp.pos > inpdata->inp.len)
289
	    inpdata->inp.pos = inpdata->inp.len;
290
291
  	  x = inpdata->inpstringlen;
292
	  p = inpdata->inp.buf;
293
	  
294
	  if (!(inpdata->inpmode & INP_NOECHO))
295
	    {
296
	      while (p < inpdata->inp.buf+inpdata->inp.len)
297
		{
298
		  mc.image = *p++;
299
		  LPutChar(flayer, &mc, x++, INPUTLINE);
300
		}
301
	    }
302
  	  x = inpdata->inpstringlen + inpdata->inp.pos;
303
	  LGotoPos(flayer, x, INPUTLINE);
304
	}
305
306
      else if (ch == '\004' || ch == '\003' || ch == '\007' || ch == '\033' ||
307
	       ch == '\000' || ch == '\n' || ch == '\r')
308
	{
309
          if (ch != '\004' && ch != '\n' && ch != '\r')
310
	    inpdata->inp.len = 0;
311
	  inpdata->inp.buf[inpdata->inp.len] = 0;
312
313
	  if (inpdata->inp.len && inpdata->inpmode == 0)
314
	    inphist = inpdata->inp;	/* structure copy */
315
	  
316
  	  flayer->l_data = 0;
317
          InpAbort();		/* redisplays... */
318
	  *ppbuf = pbuf;
319
	  *plen = len;
320
	  display = inpdisplay;
321
	  if ((inpdata->inpmode & INP_RAW) == 0)
322
            (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
323
	  else
324
            (*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv);
325
	  free((char *)inpdata);
326
	  return;
327
	}
328
    }
329
  if (!(inpdata->inpmode & INP_RAW))
330
    {
331
      flayer->l_x = inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos);
332
      flayer->l_y = INPUTLINE;
333
    }
334
  *ppbuf = pbuf;
335
  *plen = len;
336
}
337
338
static void
339
InpAbort()
340
{
341
  LAY_CALL_UP(LayRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0));
342
  ExitOverlayPage();
343
}
344
345
static void
346
InpRedisplayLine(y, xs, xe, isblank)
347
int y, xs, xe, isblank;
348
{
349
  int q, r, s, l, v;
350
  struct inpdata *inpdata;
351
  
352
  inpdata = (struct inpdata *)flayer->l_data;
353
  if (y != INPUTLINE)
354
    {
355
      LAY_CALL_UP(LayRedisplayLine(y, xs, xe, isblank));
356
      return;
357
    }
358
  inpdata->inp.buf[inpdata->inp.len] = 0;
359
  q = xs;
360
  v = xe - xs + 1;
361
  s = 0;
362
  r = inpdata->inpstringlen;
363
  if (v > 0 && q < r)
364
    {
365
      l = v;
366
      if (l > r - q)
367
	l = r - q;
368
      LPutStr(flayer, inpdata->inpstring + q - s, l, &mchar_so, q, y);
369
      q += l;
370
      v -= l;
371
    }
372
  s = r;
373
  r += inpdata->inp.len;
374
  if (!(inpdata->inpmode & INP_NOECHO) && v > 0 && q < r)
375
    {
376
      l = v;
377
      if (l > r - q)
378
	l = r - q;
379
      LPutStr(flayer, inpdata->inp.buf + q - s, l, &mchar_so, q, y);
380
      q += l;
381
      v -= l;
382
    }
383
  s = r;
384
  r = flayer->l_width;
385
  if (!isblank && v > 0 && q < r)
386
    {
387
      l = v;
388
      if (l > r - q)
389
	l = r - q;
390
      LClearArea(flayer, q, y, q + l - 1, y, 0, 0);
391
      q += l;
392
    }
393
}
394
395
int
396
InInput()
397
{
398
  if (flayer && flayer->l_layfn == &InpLf)
399
    return 1;
400
  return 0;
401
}
402