OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [readline/] [display.c] - Blame information for rev 1767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* display.c -- readline redisplay facility. */
2
 
3
/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
4
 
5
   This file is part of the GNU Readline Library, a library for
6
   reading lines of text with interactive input and history editing.
7
 
8
   The GNU Readline Library is free software; you can redistribute it
9
   and/or modify it under the terms of the GNU General Public License
10
   as published by the Free Software Foundation; either version 2, or
11
   (at your option) any later version.
12
 
13
   The GNU Readline Library is distributed in the hope that it will be
14
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15
   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   The GNU General Public License is often shipped with GNU software, and
19
   is generally kept in a file called COPYING or LICENSE.  If you do not
20
   have a copy of the license, write to the Free Software Foundation,
21
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22
#define READLINE_LIBRARY
23
 
24
#if defined (HAVE_CONFIG_H)
25
#  include <config.h>
26
#endif
27
 
28
#include <sys/types.h>
29
 
30
#if defined (HAVE_UNISTD_H)
31
#  include <unistd.h>
32
#endif /* HAVE_UNISTD_H */
33
 
34
#include "posixstat.h"
35
 
36
#if defined (HAVE_STDLIB_H)
37
#  include <stdlib.h>
38
#else
39
#  include "ansi_stdlib.h"
40
#endif /* HAVE_STDLIB_H */
41
 
42
#include <stdio.h>
43
 
44
#ifdef __MSDOS__
45
# include <pc.h>
46
#endif
47
 
48
/* System-specific feature definitions and include files. */
49
#include "rldefs.h"
50
 
51
/* Termcap library stuff. */
52
#include "tcap.h"
53
 
54
/* Some standard library routines. */
55
#include "readline.h"
56
#include "history.h"
57
 
58
#include "rlprivate.h"
59
#include "xmalloc.h"
60
 
61
#if !defined (strchr) && !defined (__STDC__)
62
extern char *strchr (), *strrchr ();
63
#endif /* !strchr && !__STDC__ */
64
 
65
#if defined (HACK_TERMCAP_MOTION)
66
extern char *term_forward_char;
67
#endif
68
 
69
static void update_line __P((char *, char *, int, int, int, int));
70
static void space_to_eol __P((int));
71
static void delete_chars __P((int));
72
static void insert_some_chars __P((char *, int));
73
static void cr __P((void));
74
 
75
static int *inv_lbreaks, *vis_lbreaks;
76
static int inv_lbsize, vis_lbsize;
77
 
78
/* Heuristic used to decide whether it is faster to move from CUR to NEW
79
   by backing up or outputting a carriage return and moving forward. */
80
#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
81
 
82
/* **************************************************************** */
83
/*                                                                  */
84
/*                      Display stuff                               */
85
/*                                                                  */
86
/* **************************************************************** */
87
 
88
/* This is the stuff that is hard for me.  I never seem to write good
89
   display routines in C.  Let's see how I do this time. */
90
 
91
/* (PWP) Well... Good for a simple line updater, but totally ignores
92
   the problems of input lines longer than the screen width.
93
 
94
   update_line and the code that calls it makes a multiple line,
95
   automatically wrapping line update.  Careful attention needs
96
   to be paid to the vertical position variables. */
97
 
98
/* Keep two buffers; one which reflects the current contents of the
99
   screen, and the other to draw what we think the new contents should
100
   be.  Then compare the buffers, and make whatever changes to the
101
   screen itself that we should.  Finally, make the buffer that we
102
   just drew into be the one which reflects the current contents of the
103
   screen, and place the cursor where it belongs.
104
 
105
   Commands that want to can fix the display themselves, and then let
106
   this function know that the display has been fixed by setting the
107
   RL_DISPLAY_FIXED variable.  This is good for efficiency. */
108
 
109
/* Application-specific redisplay function. */
110
VFunction *rl_redisplay_function = rl_redisplay;
111
 
112
/* Global variables declared here. */
113
/* What YOU turn on when you have handled all redisplay yourself. */
114
int rl_display_fixed = 0;
115
 
116
int _rl_suppress_redisplay = 0;
117
 
118
/* The stuff that gets printed out before the actual text of the line.
119
   This is usually pointing to rl_prompt. */
120
char *rl_display_prompt = (char *)NULL;
121
 
122
/* Pseudo-global variables declared here. */
123
/* The visible cursor position.  If you print some text, adjust this. */
124
int _rl_last_c_pos = 0;
125
int _rl_last_v_pos = 0;
126
 
127
/* Number of lines currently on screen minus 1. */
128
int _rl_vis_botlin = 0;
129
 
130
/* Variables used only in this file. */
131
/* The last left edge of text that was displayed.  This is used when
132
   doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
133
static int last_lmargin;
134
 
135
/* The line display buffers.  One is the line currently displayed on
136
   the screen.  The other is the line about to be displayed. */
137
static char *visible_line = (char *)NULL;
138
static char *invisible_line = (char *)NULL;
139
 
140
/* A buffer for `modeline' messages. */
141
static char msg_buf[128];
142
 
143
/* Non-zero forces the redisplay even if we thought it was unnecessary. */
144
static int forced_display;
145
 
146
/* Default and initial buffer size.  Can grow. */
147
static int line_size = 1024;
148
 
149
static char *local_prompt, *local_prompt_prefix;
150
static int visible_length, prefix_length;
151
 
152
/* The number of invisible characters in the line currently being
153
   displayed on the screen. */
154
static int visible_wrap_offset;
155
 
156
/* static so it can be shared between rl_redisplay and update_line */
157
static int wrap_offset;
158
 
159
/* The index of the last invisible_character in the prompt string. */
160
static int last_invisible;
161
 
162
/* The length (buffer offset) of the first line of the last (possibly
163
   multi-line) buffer displayed on the screen. */
164
static int visible_first_line_len;
165
 
166
/* Expand the prompt string S and return the number of visible
167
   characters in *LP, if LP is not null.  This is currently more-or-less
168
   a placeholder for expansion.  LIP, if non-null is a place to store the
169
   index of the last invisible character in the returned string. */
170
 
171
/* Current implementation:
172
        \001 (^A) start non-visible characters
173
        \002 (^B) end non-visible characters
174
   all characters except \001 and \002 (following a \001) are copied to
175
   the returned string; all characters except those between \001 and
176
   \002 are assumed to be `visible'. */
177
 
178
static char *
179
expand_prompt (pmt, lp, lip)
180
     char *pmt;
181
     int *lp, *lip;
182
{
183
  char *r, *ret, *p;
184
  int l, rl, last, ignoring;
185
 
186
  /* Short-circuit if we can. */
187
  if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
188
    {
189
      r = savestring (pmt);
190
      if (lp)
191
        *lp = strlen (r);
192
      return r;
193
    }
194
 
195
  l = strlen (pmt);
196
  r = ret = xmalloc (l + 1);
197
 
198
  for (rl = ignoring = last = 0, p = pmt; p && *p; p++)
199
    {
200
      /* This code strips the invisible character string markers
201
         RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
202
      if (*p == RL_PROMPT_START_IGNORE)
203
        {
204
          ignoring++;
205
          continue;
206
        }
207
      else if (ignoring && *p == RL_PROMPT_END_IGNORE)
208
        {
209
          ignoring = 0;
210
          last = r - ret - 1;
211
          continue;
212
        }
213
      else
214
        {
215
          *r++ = *p;
216
          if (!ignoring)
217
            rl++;
218
        }
219
    }
220
 
221
  *r = '\0';
222
  if (lp)
223
    *lp = rl;
224
  if (lip)
225
    *lip = last;
226
  return ret;
227
}
228
 
229
/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
230
   PMT and return the rest of PMT. */
231
char *
232
_rl_strip_prompt (pmt)
233
     char *pmt;
234
{
235
  char *ret;
236
 
237
  ret = expand_prompt (pmt, (int *)NULL, (int *)NULL);
238
  return ret;
239
}
240
 
241
/*
242
 * Expand the prompt string into the various display components, if
243
 * necessary.
244
 *
245
 * local_prompt = expanded last line of string in rl_display_prompt
246
 *                (portion after the final newline)
247
 * local_prompt_prefix = portion before last newline of rl_display_prompt,
248
 *                       expanded via expand_prompt
249
 * visible_length = number of visible characters in local_prompt
250
 * prefix_length = number of visible characters in local_prompt_prefix
251
 *
252
 * This function is called once per call to readline().  It may also be
253
 * called arbitrarily to expand the primary prompt.
254
 *
255
 * The return value is the number of visible characters on the last line
256
 * of the (possibly multi-line) prompt.
257
 */
258
int
259
rl_expand_prompt (prompt)
260
     char *prompt;
261
{
262
  char *p, *t;
263
  int c;
264
 
265
  /* Clear out any saved values. */
266
  if (local_prompt)
267
    free (local_prompt);
268
  if (local_prompt_prefix)
269
    free (local_prompt_prefix);
270
  local_prompt = local_prompt_prefix = (char *)0;
271
  last_invisible = visible_length = 0;
272
 
273
  if (prompt == 0 || *prompt == 0)
274
    return (0);
275
 
276
  p = strrchr (prompt, '\n');
277
  if (!p)
278
    {
279
      /* The prompt is only one line. */
280
      local_prompt = expand_prompt (prompt, &visible_length, &last_invisible);
281
      local_prompt_prefix = (char *)0;
282
      return (visible_length);
283
    }
284
  else
285
    {
286
      /* The prompt spans multiple lines. */
287
      t = ++p;
288
      local_prompt = expand_prompt (p, &visible_length, &last_invisible);
289
      c = *t; *t = '\0';
290
      /* The portion of the prompt string up to and including the
291
         final newline is now null-terminated. */
292
      local_prompt_prefix = expand_prompt (prompt, &prefix_length, (int *)NULL);
293
      *t = c;
294
      return (prefix_length);
295
    }
296
}
297
 
298
/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
299
   arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
300
   and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
301
   increased.  If the lines have already been allocated, this ensures that
302
   they can hold at least MINSIZE characters. */
303
static void
304
init_line_structures (minsize)
305
      int minsize;
306
{
307
  register int n;
308
 
309
  if (invisible_line == 0)       /* initialize it */
310
    {
311
      if (line_size < minsize)
312
        line_size = minsize;
313
      visible_line = xmalloc (line_size);
314
      invisible_line = xmalloc (line_size);
315
    }
316
  else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
317
    {
318
      line_size *= 2;
319
      if (line_size < minsize)
320
        line_size = minsize;
321
      visible_line = xrealloc (visible_line, line_size);
322
      invisible_line = xrealloc (invisible_line, line_size);
323
    }
324
 
325
  for (n = minsize; n < line_size; n++)
326
    {
327
      visible_line[n] = 0;
328
      invisible_line[n] = 1;
329
    }
330
 
331
  if (vis_lbreaks == 0)
332
    {
333
      /* should be enough. */
334
      inv_lbsize = vis_lbsize = 256;
335
      inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
336
      vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
337
      inv_lbreaks[0] = vis_lbreaks[0] = 0;
338
    }
339
}
340
 
341
/* Basic redisplay algorithm. */
342
void
343
rl_redisplay ()
344
{
345
  register int in, out, c, linenum, cursor_linenum;
346
  register char *line;
347
  int c_pos, inv_botlin, lb_botlin, lb_linenum;
348
  int newlines, lpos, temp;
349
  char *prompt_this_line;
350
 
351
  if (!readline_echoing_p)
352
    return;
353
 
354
  if (!rl_display_prompt)
355
    rl_display_prompt = "";
356
 
357
  if (invisible_line == 0)
358
    {
359
      init_line_structures (0);
360
      rl_on_new_line ();
361
    }
362
 
363
  /* Draw the line into the buffer. */
364
  c_pos = -1;
365
 
366
  line = invisible_line;
367
  out = inv_botlin = 0;
368
 
369
  /* Mark the line as modified or not.  We only do this for history
370
     lines. */
371
  if (_rl_mark_modified_lines && current_history () && rl_undo_list)
372
    {
373
      line[out++] = '*';
374
      line[out] = '\0';
375
    }
376
 
377
  /* If someone thought that the redisplay was handled, but the currently
378
     visible line has a different modification state than the one about
379
     to become visible, then correct the caller's misconception. */
380
  if (visible_line[0] != invisible_line[0])
381
    rl_display_fixed = 0;
382
 
383
  /* If the prompt to be displayed is the `primary' readline prompt (the
384
     one passed to readline()), use the values we have already expanded.
385
     If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
386
     number of non-visible characters in the prompt string. */
387
  if (rl_display_prompt == rl_prompt || local_prompt)
388
    {
389
      int local_len = local_prompt ? strlen (local_prompt) : 0;
390
      if (local_prompt_prefix && forced_display)
391
        _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
392
 
393
      if (local_len > 0)
394
        {
395
          temp = local_len + out + 2;
396
          if (temp >= line_size)
397
            {
398
              line_size = (temp + 1024) - (temp % 1024);
399
              visible_line = xrealloc (visible_line, line_size);
400
              line = invisible_line = xrealloc (invisible_line, line_size);
401
            }
402
          strncpy (line + out, local_prompt, local_len);
403
          out += local_len;
404
        }
405
      line[out] = '\0';
406
      wrap_offset = local_len - visible_length;
407
    }
408
  else
409
    {
410
      int pmtlen;
411
      prompt_this_line = strrchr (rl_display_prompt, '\n');
412
      if (!prompt_this_line)
413
        prompt_this_line = rl_display_prompt;
414
      else
415
        {
416
          prompt_this_line++;
417
          pmtlen = prompt_this_line - rl_display_prompt;        /* temp var */
418
          if (forced_display)
419
            {
420
              _rl_output_some_chars (rl_display_prompt, pmtlen);
421
              /* Make sure we are at column zero even after a newline,
422
                 regardless of the state of terminal output processing. */
423
              if (pmtlen < 2 || prompt_this_line[-2] != '\r')
424
                cr ();
425
            }
426
        }
427
 
428
      pmtlen = strlen (prompt_this_line);
429
      temp = pmtlen + out + 2;
430
      if (temp >= line_size)
431
        {
432
          line_size = (temp + 1024) - (temp % 1024);
433
          visible_line = xrealloc (visible_line, line_size);
434
          line = invisible_line = xrealloc (invisible_line, line_size);
435
        }
436
      strncpy (line + out,  prompt_this_line, pmtlen);
437
      out += pmtlen;
438
      line[out] = '\0';
439
      wrap_offset = 0;
440
    }
441
 
442
#define CHECK_INV_LBREAKS() \
443
      do { \
444
        if (newlines >= (inv_lbsize - 2)) \
445
          { \
446
            inv_lbsize *= 2; \
447
            inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
448
          } \
449
      } while (0)
450
 
451
#define CHECK_LPOS() \
452
      do { \
453
        lpos++; \
454
        if (lpos >= screenwidth) \
455
          { \
456
            if (newlines >= (inv_lbsize - 2)) \
457
              { \
458
                inv_lbsize *= 2; \
459
                inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
460
              } \
461
            inv_lbreaks[++newlines] = out; \
462
            lpos = 0; \
463
          } \
464
      } while (0)
465
 
466
  /* inv_lbreaks[i] is where line i starts in the buffer. */
467
  inv_lbreaks[newlines = 0] = 0;
468
  lpos = out - wrap_offset;
469
 
470
  /* XXX - what if lpos is already >= screenwidth before we start drawing the
471
     contents of the command line? */
472
  while (lpos >= screenwidth)
473
    {
474
      /* XXX - possible fix from Darin Johnson <darin@acuson.com> for prompt
475
         string with invisible characters that is longer than the screen
476
         width.  XXX - this doesn't work right if invisible characters have
477
         to be put on the second screen line -- it adds too much (the number
478
         of invisible chars after the screenwidth). */
479
      temp = ((newlines + 1) * screenwidth) + ((newlines == 0) ? wrap_offset : 0);
480
 
481
      inv_lbreaks[++newlines] = temp;
482
      lpos -= screenwidth;
483
    }
484
 
485
  lb_linenum = 0;
486
  for (in = 0; in < rl_end; in++)
487
    {
488
      c = (unsigned char)rl_line_buffer[in];
489
 
490
      if (out + 8 >= line_size)         /* XXX - 8 for \t */
491
        {
492
          line_size *= 2;
493
          visible_line = xrealloc (visible_line, line_size);
494
          invisible_line = xrealloc (invisible_line, line_size);
495
          line = invisible_line;
496
        }
497
 
498
      if (in == rl_point)
499
        {
500
          c_pos = out;
501
          lb_linenum = newlines;
502
        }
503
 
504
      if (META_CHAR (c))
505
        {
506
          if (_rl_output_meta_chars == 0)
507
            {
508
              sprintf (line + out, "\\%o", c);
509
 
510
              if (lpos + 4 >= screenwidth)
511
                {
512
                  temp = screenwidth - lpos;
513
                  CHECK_INV_LBREAKS ();
514
                  inv_lbreaks[++newlines] = out + temp;
515
                  lpos = 4 - temp;
516
                }
517
              else
518
                lpos += 4;
519
 
520
              out += 4;
521
            }
522
          else
523
            {
524
              line[out++] = c;
525
              CHECK_LPOS();
526
            }
527
        }
528
#if defined (DISPLAY_TABS)
529
      else if (c == '\t')
530
        {
531
          register int temp, newout;
532
 
533
#if 0
534
          newout = (out | (int)7) + 1;
535
#else
536
          newout = out + 8 - lpos % 8;
537
#endif
538
          temp = newout - out;
539
          if (lpos + temp >= screenwidth)
540
            {
541
              register int temp2;
542
              temp2 = screenwidth - lpos;
543
              CHECK_INV_LBREAKS ();
544
              inv_lbreaks[++newlines] = out + temp2;
545
              lpos = temp - temp2;
546
              while (out < newout)
547
                line[out++] = ' ';
548
            }
549
          else
550
            {
551
              while (out < newout)
552
                line[out++] = ' ';
553
              lpos += temp;
554
            }
555
        }
556
#endif
557
      else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && term_up && *term_up)
558
        {
559
          line[out++] = '\0';   /* XXX - sentinel */
560
          CHECK_INV_LBREAKS ();
561
          inv_lbreaks[++newlines] = out;
562
          lpos = 0;
563
        }
564
      else if (CTRL_CHAR (c) || c == RUBOUT)
565
        {
566
          line[out++] = '^';
567
          CHECK_LPOS();
568
          line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
569
          CHECK_LPOS();
570
        }
571
      else
572
        {
573
          line[out++] = c;
574
          CHECK_LPOS();
575
        }
576
    }
577
  line[out] = '\0';
578
  if (c_pos < 0)
579
    {
580
      c_pos = out;
581
      lb_linenum = newlines;
582
    }
583
 
584
  inv_botlin = lb_botlin = newlines;
585
  CHECK_INV_LBREAKS ();
586
  inv_lbreaks[newlines+1] = out;
587
  cursor_linenum = lb_linenum;
588
 
589
  /* C_POS == position in buffer where cursor should be placed. */
590
 
591
  /* PWP: now is when things get a bit hairy.  The visible and invisible
592
     line buffers are really multiple lines, which would wrap every
593
     (screenwidth - 1) characters.  Go through each in turn, finding
594
     the changed region and updating it.  The line order is top to bottom. */
595
 
596
  /* If we can move the cursor up and down, then use multiple lines,
597
     otherwise, let long lines display in a single terminal line, and
598
     horizontally scroll it. */
599
 
600
  if (_rl_horizontal_scroll_mode == 0 && term_up && *term_up)
601
    {
602
      int nleft, pos, changed_screen_line;
603
 
604
      if (!rl_display_fixed || forced_display)
605
        {
606
          forced_display = 0;
607
 
608
          /* If we have more than a screenful of material to display, then
609
             only display a screenful.  We should display the last screen,
610
             not the first.  */
611
          if (out >= screenchars)
612
            out = screenchars - 1;
613
 
614
          /* The first line is at character position 0 in the buffer.  The
615
             second and subsequent lines start at inv_lbreaks[N], offset by
616
             OFFSET (which has already been calculated above).  */
617
 
618
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
619
#define VIS_LLEN(l)     ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
620
#define INV_LLEN(l)     (inv_lbreaks[l+1] - inv_lbreaks[l])
621
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
622
#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
623
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
624
 
625
          /* For each line in the buffer, do the updating display. */
626
          for (linenum = 0; linenum <= inv_botlin; linenum++)
627
            {
628
              update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
629
                           VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
630
 
631
              /* If this is the line with the prompt, we might need to
632
                 compensate for invisible characters in the new line. Do
633
                 this only if there is not more than one new line (which
634
                 implies that we completely overwrite the old visible line)
635
                 and the new line is shorter than the old.  Make sure we are
636
                 at the end of the new line before clearing. */
637
              if (linenum == 0 &&
638
                  inv_botlin == 0 && _rl_last_c_pos == out &&
639
                  (wrap_offset > visible_wrap_offset) &&
640
                  (_rl_last_c_pos < visible_first_line_len))
641
                {
642
                  nleft = screenwidth + wrap_offset - _rl_last_c_pos;
643
                  if (nleft)
644
                    _rl_clear_to_eol (nleft);
645
                }
646
 
647
              /* Since the new first line is now visible, save its length. */
648
              if (linenum == 0)
649
                visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
650
            }
651
 
652
          /* We may have deleted some lines.  If so, clear the left over
653
             blank ones at the bottom out. */
654
          if (_rl_vis_botlin > inv_botlin)
655
            {
656
              char *tt;
657
              for (; linenum <= _rl_vis_botlin; linenum++)
658
                {
659
                  tt = VIS_CHARS (linenum);
660
                  _rl_move_vert (linenum);
661
                  _rl_move_cursor_relative (0, tt);
662
                  _rl_clear_to_eol
663
                    ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth);
664
                }
665
            }
666
          _rl_vis_botlin = inv_botlin;
667
 
668
          /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
669
             different screen line during this redisplay. */
670
          changed_screen_line = _rl_last_v_pos != cursor_linenum;
671
          if (changed_screen_line)
672
            {
673
              _rl_move_vert (cursor_linenum);
674
              /* If we moved up to the line with the prompt using term_up,
675
                 the physical cursor position on the screen stays the same,
676
                 but the buffer position needs to be adjusted to account
677
                 for invisible characters. */
678
              if (cursor_linenum == 0 && wrap_offset)
679
                _rl_last_c_pos += wrap_offset;
680
            }
681
 
682
          /* We have to reprint the prompt if it contains invisible
683
             characters, since it's not generally OK to just reprint
684
             the characters from the current cursor position.  But we
685
             only need to reprint it if the cursor is before the last
686
             invisible character in the prompt string. */
687
          nleft = visible_length + wrap_offset;
688
          if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
689
              _rl_last_c_pos <= last_invisible && local_prompt)
690
            {
691
#if defined (__MSDOS__)
692
              putc ('\r', rl_outstream);
693
#else
694
              if (term_cr)
695
                tputs (term_cr, 1, _rl_output_character_function);
696
#endif
697
              _rl_output_some_chars (local_prompt, nleft);
698
              _rl_last_c_pos = nleft;
699
            }
700
 
701
          /* Where on that line?  And where does that line start
702
             in the buffer? */
703
          pos = inv_lbreaks[cursor_linenum];
704
          /* nleft == number of characters in the line buffer between the
705
             start of the line and the cursor position. */
706
          nleft = c_pos - pos;
707
 
708
          /* Since _rl_backspace() doesn't know about invisible characters in the
709
             prompt, and there's no good way to tell it, we compensate for
710
             those characters here and call _rl_backspace() directly. */
711
          if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
712
            {
713
              _rl_backspace (_rl_last_c_pos - nleft);
714
              _rl_last_c_pos = nleft;
715
            }
716
 
717
          if (nleft != _rl_last_c_pos)
718
            _rl_move_cursor_relative (nleft, &invisible_line[pos]);
719
        }
720
    }
721
  else                          /* Do horizontal scrolling. */
722
    {
723
#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
724
      int lmargin, ndisp, nleft, phys_c_pos, t;
725
 
726
      /* Always at top line. */
727
      _rl_last_v_pos = 0;
728
 
729
      /* Compute where in the buffer the displayed line should start.  This
730
         will be LMARGIN. */
731
 
732
      /* The number of characters that will be displayed before the cursor. */
733
      ndisp = c_pos - wrap_offset;
734
      nleft  = visible_length + wrap_offset;
735
      /* Where the new cursor position will be on the screen.  This can be
736
         longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
737
      phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
738
      t = screenwidth / 3;
739
 
740
      /* If the number of characters had already exceeded the screenwidth,
741
         last_lmargin will be > 0. */
742
 
743
      /* If the number of characters to be displayed is more than the screen
744
         width, compute the starting offset so that the cursor is about
745
         two-thirds of the way across the screen. */
746
      if (phys_c_pos > screenwidth - 2)
747
        {
748
          lmargin = c_pos - (2 * t);
749
          if (lmargin < 0)
750
            lmargin = 0;
751
          /* If the left margin would be in the middle of a prompt with
752
             invisible characters, don't display the prompt at all. */
753
          if (wrap_offset && lmargin > 0 && lmargin < nleft)
754
            lmargin = nleft;
755
        }
756
      else if (ndisp < screenwidth - 2)         /* XXX - was -1 */
757
        lmargin = 0;
758
      else if (phys_c_pos < 1)
759
        {
760
          /* If we are moving back towards the beginning of the line and
761
             the last margin is no longer correct, compute a new one. */
762
          lmargin = ((c_pos - 1) / t) * t;      /* XXX */
763
          if (wrap_offset && lmargin > 0 && lmargin < nleft)
764
            lmargin = nleft;
765
        }
766
      else
767
        lmargin = last_lmargin;
768
 
769
      /* If the first character on the screen isn't the first character
770
         in the display line, indicate this with a special character. */
771
      if (lmargin > 0)
772
        line[lmargin] = '<';
773
 
774
      /* If SCREENWIDTH characters starting at LMARGIN do not encompass
775
         the whole line, indicate that with a special character at the
776
         right edge of the screen.  If LMARGIN is 0, we need to take the
777
         wrap offset into account. */
778
      t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
779
      if (t < out)
780
        line[t - 1] = '>';
781
 
782
      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
783
        {
784
          forced_display = 0;
785
          update_line (&visible_line[last_lmargin],
786
                       &invisible_line[lmargin],
787
                       0,
788
                       screenwidth + visible_wrap_offset,
789
                       screenwidth + (lmargin ? 0 : wrap_offset),
790
                       0);
791
 
792
          /* If the visible new line is shorter than the old, but the number
793
             of invisible characters is greater, and we are at the end of
794
             the new line, we need to clear to eol. */
795
          t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
796
          if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
797
              (_rl_last_c_pos == out) &&
798
              t < visible_first_line_len)
799
            {
800
              nleft = screenwidth - t;
801
              _rl_clear_to_eol (nleft);
802
            }
803
          visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
804
          if (visible_first_line_len > screenwidth)
805
            visible_first_line_len = screenwidth;
806
 
807
          _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
808
          last_lmargin = lmargin;
809
        }
810
    }
811
  fflush (rl_outstream);
812
 
813
  /* Swap visible and non-visible lines. */
814
  {
815
    char *temp = visible_line;
816
    int *itemp = vis_lbreaks, ntemp = vis_lbsize;
817
 
818
    visible_line = invisible_line;
819
    invisible_line = temp;
820
 
821
    vis_lbreaks = inv_lbreaks;
822
    inv_lbreaks = itemp;
823
 
824
    vis_lbsize = inv_lbsize;
825
    inv_lbsize = ntemp;
826
 
827
    rl_display_fixed = 0;
828
    /* If we are displaying on a single line, and last_lmargin is > 0, we
829
       are not displaying any invisible characters, so set visible_wrap_offset
830
       to 0. */
831
    if (_rl_horizontal_scroll_mode && last_lmargin)
832
      visible_wrap_offset = 0;
833
    else
834
      visible_wrap_offset = wrap_offset;
835
  }
836
}
837
 
838
/* PWP: update_line() is based on finding the middle difference of each
839
   line on the screen; vis:
840
 
841
                             /old first difference
842
        /beginning of line   |        /old last same       /old EOL
843
        v                    v        v             v
844
old:    eddie> Oh, my little gruntle-buggy is to me, as lurgid as
845
new:    eddie> Oh, my little buggy says to me, as lurgid as
846
        ^                    ^  ^                          ^
847
        \beginning of line   |  \new last same     \new end of line
848
                             \new first difference
849
 
850
   All are character pointers for the sake of speed.  Special cases for
851
   no differences, as well as for end of line additions must be handled.
852
 
853
   Could be made even smarter, but this works well enough */
854
static void
855
update_line (old, new, current_line, omax, nmax, inv_botlin)
856
     register char *old, *new;
857
     int current_line, omax, nmax, inv_botlin;
858
{
859
  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
860
  int temp, lendiff, wsatend, od, nd;
861
  int current_invis_chars;
862
 
863
  /* If we're at the right edge of a terminal that supports xn, we're
864
     ready to wrap around, so do so.  This fixes problems with knowing
865
     the exact cursor position and cut-and-paste with certain terminal
866
     emulators.  In this calculation, TEMP is the physical screen
867
     position of the cursor. */
868
  temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
869
  if (temp == screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
870
      && _rl_last_v_pos == current_line - 1)
871
    {
872
      if (new[0])
873
        putc (new[0], rl_outstream);
874
      else
875
        putc (' ', rl_outstream);
876
      _rl_last_c_pos = 1;               /* XXX */
877
      _rl_last_v_pos++;
878
      if (old[0] && new[0])
879
        old[0] = new[0];
880
    }
881
 
882
  /* Find first difference. */
883
  for (ofd = old, nfd = new;
884
       (ofd - old < omax) && *ofd && (*ofd == *nfd);
885
       ofd++, nfd++)
886
    ;
887
 
888
  /* Move to the end of the screen line.  ND and OD are used to keep track
889
     of the distance between ne and new and oe and old, respectively, to
890
     move a subtraction out of each loop. */
891
  for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
892
  for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
893
 
894
  /* If no difference, continue to next line. */
895
  if (ofd == oe && nfd == ne)
896
    return;
897
 
898
  wsatend = 1;                  /* flag for trailing whitespace */
899
  ols = oe - 1;                 /* find last same */
900
  nls = ne - 1;
901
  while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
902
    {
903
      if (*ols != ' ')
904
        wsatend = 0;
905
      ols--;
906
      nls--;
907
    }
908
 
909
  if (wsatend)
910
    {
911
      ols = oe;
912
      nls = ne;
913
    }
914
  else if (*ols != *nls)
915
    {
916
      if (*ols)                 /* don't step past the NUL */
917
        ols++;
918
      if (*nls)
919
        nls++;
920
    }
921
 
922
  /* count of invisible characters in the current invisible line. */
923
  current_invis_chars = W_OFFSET (current_line, wrap_offset);
924
  if (_rl_last_v_pos != current_line)
925
    {
926
      _rl_move_vert (current_line);
927
      if (current_line == 0 && visible_wrap_offset)
928
        _rl_last_c_pos += visible_wrap_offset;
929
    }
930
 
931
  /* If this is the first line and there are invisible characters in the
932
     prompt string, and the prompt string has not changed, and the current
933
     cursor position is before the last invisible character in the prompt,
934
     and the index of the character to move to is past the end of the prompt
935
     string, then redraw the entire prompt string.  We can only do this
936
     reliably if the terminal supports a `cr' capability.
937
 
938
     This is not an efficiency hack -- there is a problem with redrawing
939
     portions of the prompt string if they contain terminal escape
940
     sequences (like drawing the `unbold' sequence without a corresponding
941
     `bold') that manifests itself on certain terminals. */
942
 
943
  lendiff = local_prompt ? strlen (local_prompt) : 0;
944
  od = ofd - old;       /* index of first difference in visible line */
945
  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
946
      term_cr && lendiff > visible_length && _rl_last_c_pos > 0 &&
947
      od > lendiff && _rl_last_c_pos < last_invisible)
948
    {
949
#if defined (__MSDOS__)
950
      putc ('\r', rl_outstream);
951
#else
952
      tputs (term_cr, 1, _rl_output_character_function);
953
#endif
954
      _rl_output_some_chars (local_prompt, lendiff);
955
      _rl_last_c_pos = lendiff;
956
    }
957
 
958
  _rl_move_cursor_relative (od, old);
959
 
960
  /* if (len (new) > len (old)) */
961
  lendiff = (nls - nfd) - (ols - ofd);
962
 
963
  /* If we are changing the number of invisible characters in a line, and
964
     the spot of first difference is before the end of the invisible chars,
965
     lendiff needs to be adjusted. */
966
  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
967
      current_invis_chars != visible_wrap_offset)
968
    lendiff += visible_wrap_offset - current_invis_chars;
969
 
970
  /* Insert (diff (len (old), len (new)) ch. */
971
  temp = ne - nfd;
972
  if (lendiff > 0)
973
    {
974
      /* Non-zero if we're increasing the number of lines. */
975
      int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
976
      /* Sometimes it is cheaper to print the characters rather than
977
         use the terminal's capabilities.  If we're growing the number
978
         of lines, make sure we actually cause the new line to wrap
979
         around on auto-wrapping terminals. */
980
      if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!_rl_term_autowrap || !gl))
981
        {
982
          /* If lendiff > visible_length and _rl_last_c_pos == 0 and
983
             _rl_horizontal_scroll_mode == 1, inserting the characters with
984
             term_IC or term_ic will screw up the screen because of the
985
             invisible characters.  We need to just draw them. */
986
          if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
987
                        lendiff <= visible_length || !current_invis_chars))
988
            {
989
              insert_some_chars (nfd, lendiff);
990
              _rl_last_c_pos += lendiff;
991
            }
992
          else if (*ols == 0)
993
            {
994
              /* At the end of a line the characters do not have to
995
                 be "inserted".  They can just be placed on the screen. */
996
              /* However, this screws up the rest of this block, which
997
                 assumes you've done the insert because you can. */
998
              _rl_output_some_chars (nfd, lendiff);
999
              _rl_last_c_pos += lendiff;
1000
            }
1001
          else
1002
            {
1003
              /* We have horizontal scrolling and we are not inserting at
1004
                 the end.  We have invisible characters in this line.  This
1005
                 is a dumb update. */
1006
              _rl_output_some_chars (nfd, temp);
1007
              _rl_last_c_pos += temp;
1008
              return;
1009
            }
1010
          /* Copy (new) chars to screen from first diff to last match. */
1011
          temp = nls - nfd;
1012
          if ((temp - lendiff) > 0)
1013
            {
1014
              _rl_output_some_chars (nfd + lendiff, temp - lendiff);
1015
              _rl_last_c_pos += temp - lendiff;
1016
            }
1017
        }
1018
      else
1019
        {
1020
          /* cannot insert chars, write to EOL */
1021
          _rl_output_some_chars (nfd, temp);
1022
          _rl_last_c_pos += temp;
1023
        }
1024
    }
1025
  else                          /* Delete characters from line. */
1026
    {
1027
      /* If possible and inexpensive to use terminal deletion, then do so. */
1028
      if (term_dc && (2 * temp) >= -lendiff)
1029
        {
1030
          /* If all we're doing is erasing the invisible characters in the
1031
             prompt string, don't bother.  It screws up the assumptions
1032
             about what's on the screen. */
1033
          if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
1034
              -lendiff == visible_wrap_offset)
1035
            lendiff = 0;
1036
 
1037
          if (lendiff)
1038
            delete_chars (-lendiff); /* delete (diff) characters */
1039
 
1040
          /* Copy (new) chars to screen from first diff to last match */
1041
          temp = nls - nfd;
1042
          if (temp > 0)
1043
            {
1044
              _rl_output_some_chars (nfd, temp);
1045
              _rl_last_c_pos += temp;
1046
            }
1047
        }
1048
      /* Otherwise, print over the existing material. */
1049
      else
1050
        {
1051
          if (temp > 0)
1052
            {
1053
              _rl_output_some_chars (nfd, temp);
1054
              _rl_last_c_pos += temp;
1055
            }
1056
          lendiff = (oe - old) - (ne - new);
1057
          if (lendiff)
1058
            {
1059
              if (_rl_term_autowrap && current_line < inv_botlin)
1060
                space_to_eol (lendiff);
1061
              else
1062
                _rl_clear_to_eol (lendiff);
1063
            }
1064
        }
1065
    }
1066
}
1067
 
1068
/* Tell the update routines that we have moved onto a new (empty) line. */
1069
int
1070
rl_on_new_line ()
1071
{
1072
  if (visible_line)
1073
    visible_line[0] = '\0';
1074
 
1075
  _rl_last_c_pos = _rl_last_v_pos = 0;
1076
  _rl_vis_botlin = last_lmargin = 0;
1077
  if (vis_lbreaks)
1078
    vis_lbreaks[0] = vis_lbreaks[1] = 0;
1079
  visible_wrap_offset = 0;
1080
  return 0;
1081
}
1082
 
1083
/* Tell the update routines that we have moved onto a new line with the
1084
   prompt already displayed.  Code originally from the version of readline
1085
   distributed with CLISP. */
1086
int
1087
rl_on_new_line_with_prompt ()
1088
{
1089
  int prompt_size, i, l, real_screenwidth, newlines;
1090
  char *prompt_last_line;
1091
 
1092
  /* Initialize visible_line and invisible_line to ensure that they can hold
1093
     the already-displayed prompt. */
1094
  prompt_size = strlen (rl_prompt) + 1;
1095
  init_line_structures (prompt_size);
1096
 
1097
  /* Make sure the line structures hold the already-displayed prompt for
1098
     redisplay. */
1099
  strcpy (visible_line, rl_prompt);
1100
  strcpy (invisible_line, rl_prompt);
1101
 
1102
  /* If the prompt contains newlines, take the last tail. */
1103
  prompt_last_line = strrchr (rl_prompt, '\n');
1104
  if (!prompt_last_line)
1105
    prompt_last_line = rl_prompt;
1106
 
1107
  l = strlen (prompt_last_line);
1108
  _rl_last_c_pos = l;
1109
 
1110
  /* Dissect prompt_last_line into screen lines. Note that here we have
1111
     to use the real screenwidth. Readline's notion of screenwidth might be
1112
     one less, see terminal.c. */
1113
  real_screenwidth = screenwidth + (_rl_term_autowrap ? 0 : 1);
1114
  _rl_last_v_pos = l / real_screenwidth;
1115
  /* If the prompt length is a multiple of real_screenwidth, we don't know
1116
     whether the cursor is at the end of the last line, or already at the
1117
     beginning of the next line. Output a newline just to be safe. */
1118
  if (l > 0 && (l % real_screenwidth) == 0)
1119
    _rl_output_some_chars ("\n", 1);
1120
  last_lmargin = 0;
1121
 
1122
  newlines = 0; i = 0;
1123
  while (i <= l)
1124
    {
1125
      _rl_vis_botlin = newlines;
1126
      vis_lbreaks[newlines++] = i;
1127
      i += real_screenwidth;
1128
    }
1129
  vis_lbreaks[newlines] = l;
1130
  visible_wrap_offset = 0;
1131
 
1132
  return 0;
1133
}
1134
 
1135
/* Actually update the display, period. */
1136
int
1137
rl_forced_update_display ()
1138
{
1139
  if (visible_line)
1140
    {
1141
      register char *temp = visible_line;
1142
 
1143
      while (*temp)
1144
        *temp++ = '\0';
1145
    }
1146
  rl_on_new_line ();
1147
  forced_display++;
1148
  (*rl_redisplay_function) ();
1149
  return 0;
1150
}
1151
 
1152
/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1153
   DATA is the contents of the screen line of interest; i.e., where
1154
   the movement is being done. */
1155
void
1156
_rl_move_cursor_relative (new, data)
1157
     int new;
1158
     char *data;
1159
{
1160
  register int i;
1161
 
1162
  /* If we don't have to do anything, then return. */
1163
  if (_rl_last_c_pos == new) return;
1164
 
1165
  /* It may be faster to output a CR, and then move forwards instead
1166
     of moving backwards. */
1167
  /* i == current physical cursor position. */
1168
  i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1169
  if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
1170
      (_rl_term_autowrap && i == screenwidth))
1171
    {
1172
#if defined (__MSDOS__)
1173
      putc ('\r', rl_outstream);
1174
#else
1175
      tputs (term_cr, 1, _rl_output_character_function);
1176
#endif /* !__MSDOS__ */
1177
      _rl_last_c_pos = 0;
1178
    }
1179
 
1180
  if (_rl_last_c_pos < new)
1181
    {
1182
      /* Move the cursor forward.  We do it by printing the command
1183
         to move the cursor forward if there is one, else print that
1184
         portion of the output buffer again.  Which is cheaper? */
1185
 
1186
      /* The above comment is left here for posterity.  It is faster
1187
         to print one character (non-control) than to print a control
1188
         sequence telling the terminal to move forward one character.
1189
         That kind of control is for people who don't know what the
1190
         data is underneath the cursor. */
1191
#if defined (HACK_TERMCAP_MOTION)
1192
      if (term_forward_char)
1193
        for (i = _rl_last_c_pos; i < new; i++)
1194
          tputs (term_forward_char, 1, _rl_output_character_function);
1195
      else
1196
        for (i = _rl_last_c_pos; i < new; i++)
1197
          putc (data[i], rl_outstream);
1198
#else
1199
      for (i = _rl_last_c_pos; i < new; i++)
1200
        putc (data[i], rl_outstream);
1201
#endif /* HACK_TERMCAP_MOTION */
1202
    }
1203
  else if (_rl_last_c_pos > new)
1204
    _rl_backspace (_rl_last_c_pos - new);
1205
  _rl_last_c_pos = new;
1206
}
1207
 
1208
/* PWP: move the cursor up or down. */
1209
void
1210
_rl_move_vert (to)
1211
     int to;
1212
{
1213
  register int delta, i;
1214
 
1215
  if (_rl_last_v_pos == to || to > screenheight)
1216
    return;
1217
 
1218
  if ((delta = to - _rl_last_v_pos) > 0)
1219
    {
1220
      for (i = 0; i < delta; i++)
1221
        putc ('\n', rl_outstream);
1222
#if defined (__MSDOS__)
1223
      putc ('\r', rl_outstream);
1224
#else
1225
      tputs (term_cr, 1, _rl_output_character_function);
1226
#endif
1227
      _rl_last_c_pos = 0;
1228
    }
1229
  else
1230
    {                   /* delta < 0 */
1231
#ifdef __MSDOS__
1232
      int row, col;
1233
 
1234
      i = fflush (rl_outstream); /* make sure the cursor pos is current! */
1235
      ScreenGetCursor (&row, &col);
1236
      ScreenSetCursor ((row + to - _rl_last_v_pos), col);
1237
      delta = i;
1238
#else /* !__MSDOS__ */
1239
      if (term_up && *term_up)
1240
        for (i = 0; i < -delta; i++)
1241
          tputs (term_up, 1, _rl_output_character_function);
1242
#endif /* !__MSDOS__ */
1243
    }
1244
 
1245
  _rl_last_v_pos = to;          /* Now TO is here */
1246
}
1247
 
1248
/* Physically print C on rl_outstream.  This is for functions which know
1249
   how to optimize the display.  Return the number of characters output. */
1250
int
1251
rl_show_char (c)
1252
     int c;
1253
{
1254
  int n = 1;
1255
  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
1256
    {
1257
      fprintf (rl_outstream, "M-");
1258
      n += 2;
1259
      c = UNMETA (c);
1260
    }
1261
 
1262
#if defined (DISPLAY_TABS)
1263
  if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
1264
#else
1265
  if (CTRL_CHAR (c) || c == RUBOUT)
1266
#endif /* !DISPLAY_TABS */
1267
    {
1268
      fprintf (rl_outstream, "C-");
1269
      n += 2;
1270
      c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
1271
    }
1272
 
1273
  putc (c, rl_outstream);
1274
  fflush (rl_outstream);
1275
  return n;
1276
}
1277
 
1278
int
1279
rl_character_len (c, pos)
1280
     register int c, pos;
1281
{
1282
  unsigned char uc;
1283
 
1284
  uc = (unsigned char)c;
1285
 
1286
  if (META_CHAR (uc))
1287
    return ((_rl_output_meta_chars == 0) ? 4 : 1);
1288
 
1289
  if (uc == '\t')
1290
    {
1291
#if defined (DISPLAY_TABS)
1292
      return (((pos | 7) + 1) - pos);
1293
#else
1294
      return (2);
1295
#endif /* !DISPLAY_TABS */
1296
    }
1297
 
1298
  if (CTRL_CHAR (c) || c == RUBOUT)
1299
    return (2);
1300
 
1301
  return ((isprint (uc)) ? 1 : 2);
1302
}
1303
 
1304
/* How to print things in the "echo-area".  The prompt is treated as a
1305
   mini-modeline. */
1306
 
1307
#if defined (USE_VARARGS)
1308
int
1309
#if defined (PREFER_STDARG)
1310
rl_message (const char *format, ...)
1311
#else
1312
rl_message (va_alist)
1313
     va_dcl
1314
#endif
1315
{
1316
  va_list args;
1317
#if defined (PREFER_VARARGS)
1318
  char *format;
1319
#endif
1320
 
1321
#if defined (PREFER_STDARG)
1322
  va_start (args, format);
1323
#else
1324
  va_start (args);
1325
  format = va_arg (args, char *);
1326
#endif
1327
 
1328
  vsprintf (msg_buf, format, args);
1329
  va_end (args);
1330
 
1331
  rl_display_prompt = msg_buf;
1332
  (*rl_redisplay_function) ();
1333
  return 0;
1334
}
1335
#else /* !USE_VARARGS */
1336
int
1337
rl_message (format, arg1, arg2)
1338
     char *format;
1339
{
1340
  sprintf (msg_buf, format, arg1, arg2);
1341
  rl_display_prompt = msg_buf;
1342
  (*rl_redisplay_function) ();
1343
  return 0;
1344
}
1345
#endif /* !USE_VARARGS */
1346
 
1347
/* How to clear things from the "echo-area". */
1348
int
1349
rl_clear_message ()
1350
{
1351
  rl_display_prompt = rl_prompt;
1352
  (*rl_redisplay_function) ();
1353
  return 0;
1354
}
1355
 
1356
int
1357
rl_reset_line_state ()
1358
{
1359
  rl_on_new_line ();
1360
 
1361
  rl_display_prompt = rl_prompt ? rl_prompt : "";
1362
  forced_display = 1;
1363
  return 0;
1364
}
1365
 
1366
static char *saved_local_prompt;
1367
static char *saved_local_prefix;
1368
static int saved_last_invisible;
1369
static int saved_visible_length;
1370
 
1371
void
1372
rl_save_prompt ()
1373
{
1374
  saved_local_prompt = local_prompt;
1375
  saved_local_prefix = local_prompt_prefix;
1376
  saved_last_invisible = last_invisible;
1377
  saved_visible_length = visible_length;
1378
 
1379
  local_prompt = local_prompt_prefix = (char *)0;
1380
  last_invisible = visible_length = 0;
1381
}
1382
 
1383
void
1384
rl_restore_prompt ()
1385
{
1386
  if (local_prompt)
1387
    free (local_prompt);
1388
  if (local_prompt_prefix)
1389
    free (local_prompt_prefix);
1390
 
1391
  local_prompt = saved_local_prompt;
1392
  local_prompt_prefix = saved_local_prefix;
1393
  last_invisible = saved_last_invisible;
1394
  visible_length = saved_visible_length;
1395
}
1396
 
1397
char *
1398
_rl_make_prompt_for_search (pchar)
1399
     int pchar;
1400
{
1401
  int len;
1402
  char *pmt;
1403
 
1404
  rl_save_prompt ();
1405
 
1406
  if (saved_local_prompt == 0)
1407
    {
1408
      len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
1409
      pmt = xmalloc (len + 2);
1410
      if (len)
1411
        strcpy (pmt, rl_prompt);
1412
      pmt[len] = pchar;
1413
      pmt[len+1] = '\0';
1414
    }
1415
  else
1416
    {
1417
      len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
1418
      pmt = xmalloc (len + 2);
1419
      if (len)
1420
        strcpy (pmt, saved_local_prompt);
1421
      pmt[len] = pchar;
1422
      pmt[len+1] = '\0';
1423
      local_prompt = savestring (pmt);
1424
      last_invisible = saved_last_invisible;
1425
      visible_length = saved_visible_length + 1;
1426
    }
1427
  return pmt;
1428
}
1429
 
1430
/* Quick redisplay hack when erasing characters at the end of the line. */
1431
void
1432
_rl_erase_at_end_of_line (l)
1433
     int l;
1434
{
1435
  register int i;
1436
 
1437
  _rl_backspace (l);
1438
  for (i = 0; i < l; i++)
1439
    putc (' ', rl_outstream);
1440
  _rl_backspace (l);
1441
  for (i = 0; i < l; i++)
1442
    visible_line[--_rl_last_c_pos] = '\0';
1443
  rl_display_fixed++;
1444
}
1445
 
1446
/* Clear to the end of the line.  COUNT is the minimum
1447
   number of character spaces to clear, */
1448
void
1449
_rl_clear_to_eol (count)
1450
     int count;
1451
{
1452
#ifndef __MSDOS__
1453
  if (term_clreol)
1454
    tputs (term_clreol, 1, _rl_output_character_function);
1455
  else
1456
#endif
1457
  if (count)
1458
    space_to_eol (count);
1459
}
1460
 
1461
/* Clear to the end of the line using spaces.  COUNT is the minimum
1462
   number of character spaces to clear, */
1463
static void
1464
space_to_eol (count)
1465
     int count;
1466
{
1467
  register int i;
1468
 
1469
  for (i = 0; i < count; i++)
1470
   putc (' ', rl_outstream);
1471
 
1472
  _rl_last_c_pos += count;
1473
}
1474
 
1475
void
1476
_rl_clear_screen ()
1477
{
1478
#if defined (__GO32__)
1479
  ScreenClear ();       /* FIXME: only works in text modes */
1480
  ScreenSetCursor (0, 0);  /* term_clrpag is "cl" which homes the cursor */
1481
#else
1482
  if (term_clrpag)
1483
    tputs (term_clrpag, 1, _rl_output_character_function);
1484
  else
1485
    crlf ();
1486
#endif
1487
}
1488
 
1489
/* Insert COUNT characters from STRING to the output stream. */
1490
static void
1491
insert_some_chars (string, count)
1492
     char *string;
1493
     int count;
1494
{
1495
#ifdef __MSDOS__
1496
  _rl_output_some_chars (string, count);
1497
#else  /* !__MSDOS__ */
1498
  /* If IC is defined, then we do not have to "enter" insert mode. */
1499
  if (term_IC)
1500
    {
1501
      char *buffer;
1502
      buffer = tgoto (term_IC, 0, count);
1503
      tputs (buffer, 1, _rl_output_character_function);
1504
      _rl_output_some_chars (string, count);
1505
    }
1506
  else
1507
    {
1508
      register int i;
1509
 
1510
      /* If we have to turn on insert-mode, then do so. */
1511
      if (term_im && *term_im)
1512
        tputs (term_im, 1, _rl_output_character_function);
1513
 
1514
      /* If there is a special command for inserting characters, then
1515
         use that first to open up the space. */
1516
      if (term_ic && *term_ic)
1517
        {
1518
          for (i = count; i--; )
1519
            tputs (term_ic, 1, _rl_output_character_function);
1520
        }
1521
 
1522
      /* Print the text. */
1523
      _rl_output_some_chars (string, count);
1524
 
1525
      /* If there is a string to turn off insert mode, we had best use
1526
         it now. */
1527
      if (term_ei && *term_ei)
1528
        tputs (term_ei, 1, _rl_output_character_function);
1529
    }
1530
#endif /* !__MSDOS__ */
1531
}
1532
 
1533
/* Delete COUNT characters from the display line. */
1534
static void
1535
delete_chars (count)
1536
     int count;
1537
{
1538
  if (count > screenwidth)      /* XXX */
1539
    return;
1540
 
1541
#ifndef __MSDOS__
1542
  if (term_DC && *term_DC)
1543
    {
1544
      char *buffer;
1545
      buffer = tgoto (term_DC, count, count);
1546
      tputs (buffer, count, _rl_output_character_function);
1547
    }
1548
  else
1549
    {
1550
      if (term_dc && *term_dc)
1551
        while (count--)
1552
          tputs (term_dc, 1, _rl_output_character_function);
1553
    }
1554
#endif /* !__MSDOS__ */
1555
}
1556
 
1557
void
1558
_rl_update_final ()
1559
{
1560
  int full_lines;
1561
 
1562
  full_lines = 0;
1563
  /* If the cursor is the only thing on an otherwise-blank last line,
1564
     compensate so we don't print an extra CRLF. */
1565
  if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
1566
        visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
1567
    {
1568
      _rl_vis_botlin--;
1569
      full_lines = 1;
1570
    }
1571
  _rl_move_vert (_rl_vis_botlin);
1572
  /* If we've wrapped lines, remove the final xterm line-wrap flag. */
1573
  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == screenwidth))
1574
    {
1575
      char *last_line;
1576
#if 0
1577
      last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]];
1578
#else
1579
      last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
1580
#endif
1581
      _rl_move_cursor_relative (screenwidth - 1, last_line);
1582
      _rl_clear_to_eol (0);
1583
      putc (last_line[screenwidth - 1], rl_outstream);
1584
    }
1585
  _rl_vis_botlin = 0;
1586
  crlf ();
1587
  fflush (rl_outstream);
1588
  rl_display_fixed++;
1589
}
1590
 
1591
/* Move to the start of the current line. */
1592
static void
1593
cr ()
1594
{
1595
  if (term_cr)
1596
    {
1597
#if defined (__MSDOS__)
1598
      putc ('\r', rl_outstream);
1599
#else
1600
      tputs (term_cr, 1, _rl_output_character_function);
1601
#endif
1602
      _rl_last_c_pos = 0;
1603
    }
1604
}
1605
 
1606
/* Redraw the last line of a multi-line prompt that may possibly contain
1607
   terminal escape sequences.  Called with the cursor at column 0 of the
1608
   line to draw the prompt on. */
1609
static void
1610
redraw_prompt (t)
1611
     char *t;
1612
{
1613
  char *oldp, *oldl, *oldlprefix;
1614
  int oldlen, oldlast, oldplen;
1615
 
1616
  /* Geez, I should make this a struct. */
1617
  oldp = rl_display_prompt;
1618
  oldl = local_prompt;
1619
  oldlprefix = local_prompt_prefix;
1620
  oldlen = visible_length;
1621
  oldplen = prefix_length;
1622
  oldlast = last_invisible;
1623
 
1624
  rl_display_prompt = t;
1625
  local_prompt = expand_prompt (t, &visible_length, &last_invisible);
1626
  local_prompt_prefix = (char *)NULL;
1627
  rl_forced_update_display ();
1628
 
1629
  rl_display_prompt = oldp;
1630
  local_prompt = oldl;
1631
  local_prompt_prefix = oldlprefix;
1632
  visible_length = oldlen;
1633
  prefix_length = oldplen;
1634
  last_invisible = oldlast;
1635
}
1636
 
1637
/* Redisplay the current line after a SIGWINCH is received. */
1638
void
1639
_rl_redisplay_after_sigwinch ()
1640
{
1641
  char *t;
1642
 
1643
  /* Clear the current line and put the cursor at column 0.  Make sure
1644
     the right thing happens if we have wrapped to a new screen line. */
1645
  if (term_cr)
1646
    {
1647
#if defined (__MSDOS__)
1648
      putc ('\r', rl_outstream);
1649
#else
1650
      tputs (term_cr, 1, _rl_output_character_function);
1651
#endif
1652
      _rl_last_c_pos = 0;
1653
#if defined (__MSDOS__)
1654
      space_to_eol (screenwidth);
1655
      putc ('\r', rl_outstream);
1656
#else
1657
      if (term_clreol)
1658
        tputs (term_clreol, 1, _rl_output_character_function);
1659
      else
1660
        {
1661
          space_to_eol (screenwidth);
1662
          tputs (term_cr, 1, _rl_output_character_function);
1663
        }
1664
#endif
1665
      if (_rl_last_v_pos > 0)
1666
        _rl_move_vert (0);
1667
    }
1668
  else
1669
    crlf ();
1670
 
1671
  /* Redraw only the last line of a multi-line prompt. */
1672
  t = strrchr (rl_display_prompt, '\n');
1673
  if (t)
1674
    redraw_prompt (++t);
1675
  else
1676
    rl_forced_update_display ();
1677
}
1678
 
1679
void
1680
_rl_clean_up_for_exit ()
1681
{
1682
  if (readline_echoing_p)
1683
    {
1684
      _rl_move_vert (_rl_vis_botlin);
1685
      _rl_vis_botlin = 0;
1686
      fflush (rl_outstream);
1687
      rl_restart_output (1, 0);
1688
    }
1689
}
1690
 
1691
void
1692
_rl_erase_entire_line ()
1693
{
1694
  cr ();
1695
  _rl_clear_to_eol (0);
1696
  cr ();
1697
  fflush (rl_outstream);
1698
}
1699
 
1700
/* return the `current display line' of the cursor -- the number of lines to
1701
   move up to get to the first screen line of the current readline line. */
1702
int
1703
_rl_current_display_line ()
1704
{
1705
  int ret, nleft;
1706
 
1707
  /* Find out whether or not there might be invisible characters in the
1708
     editing buffer. */
1709
  if (rl_display_prompt == rl_prompt)
1710
    nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length;
1711
  else
1712
    nleft = _rl_last_c_pos - screenwidth;
1713
 
1714
  if (nleft > 0)
1715
    ret = 1 + nleft / screenwidth;
1716
  else
1717
    ret = 0;
1718
 
1719
  return ret;
1720
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.