~ubuntu-branches/ubuntu/quantal/less/quantal

« back to all changes in this revision

Viewing changes to command.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Schoepf
  • Date: 2002-04-04 16:43:52 UTC
  • Revision ID: james.westby@ubuntu.com-20020404164352-qldq048yoc7x5sd5
Tags: upstream-374
ImportĀ upstreamĀ versionĀ 374

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1984-2000  Mark Nudelman
 
3
 *
 
4
 * You may distribute under the terms of either the GNU General Public
 
5
 * License or the Less License, as specified in the README file.
 
6
 *
 
7
 * For more information about less, or for information on how to 
 
8
 * contact the author, see the README file.
 
9
 */
 
10
 
 
11
 
 
12
/*
 
13
 * User-level command processor.
 
14
 */
 
15
 
 
16
#include "less.h"
 
17
#if MSDOS_COMPILER==WIN32C
 
18
#include <windows.h>
 
19
#endif
 
20
#include "position.h"
 
21
#include "option.h"
 
22
#include "cmd.h"
 
23
 
 
24
extern int erase_char, kill_char;
 
25
extern int sigs;
 
26
extern int quit_at_eof;
 
27
extern int quit_if_one_screen;
 
28
extern int squished;
 
29
extern int hit_eof;
 
30
extern int sc_width;
 
31
extern int sc_height;
 
32
extern int swindow;
 
33
extern int jump_sline;
 
34
extern int quitting;
 
35
extern int wscroll;
 
36
extern int top_scroll;
 
37
extern int ignore_eoi;
 
38
extern int secure;
 
39
extern int hshift;
 
40
extern int show_attn;
 
41
extern char *every_first_cmd;
 
42
extern char *curr_altfilename;
 
43
extern char version[];
 
44
extern struct scrpos initial_scrpos;
 
45
extern IFILE curr_ifile;
 
46
extern void constant *ml_search;
 
47
extern void constant *ml_examine;
 
48
#if SHELL_ESCAPE || PIPEC
 
49
extern void constant *ml_shell;
 
50
#endif
 
51
#if EDITOR
 
52
extern char *editor;
 
53
extern char *editproto;
 
54
#endif
 
55
extern int screen_trashed;      /* The screen has been overwritten */
 
56
extern int shift_count;
 
57
 
 
58
static char ungot[UNGOT_SIZE];
 
59
static char *ungotp = NULL;
 
60
#if SHELL_ESCAPE
 
61
static char *shellcmd = NULL;   /* For holding last shell command for "!!" */
 
62
#endif
 
63
static int mca;                 /* The multicharacter command (action) */
 
64
static int search_type;         /* The previous type of search */
 
65
static int number;              /* The number typed by the user */
 
66
static char optchar;
 
67
static int optflag;
 
68
static int optgetname;
 
69
static POSITION bottompos;
 
70
#if PIPEC
 
71
static char pipec;
 
72
#endif
 
73
 
 
74
static void multi_search();
 
75
 
 
76
/*
 
77
 * Move the cursor to lower left before executing a command.
 
78
 * This looks nicer if the command takes a long time before
 
79
 * updating the screen.
 
80
 */
 
81
        static void
 
82
cmd_exec()
 
83
{
 
84
        clear_attn();
 
85
        lower_left();
 
86
        flush();
 
87
}
 
88
 
 
89
/*
 
90
 * Set up the display to start a new multi-character command.
 
91
 */
 
92
        static void
 
93
start_mca(action, prompt, mlist, cmdflags)
 
94
        int action;
 
95
        char *prompt;
 
96
        void *mlist;
 
97
        int cmdflags;
 
98
{
 
99
        mca = action;
 
100
        clear_cmd();
 
101
        cmd_putstr(prompt);
 
102
        set_mlist(mlist, cmdflags);
 
103
}
 
104
 
 
105
        public int
 
106
in_mca()
 
107
{
 
108
        return (mca != 0 && mca != A_PREFIX);
 
109
}
 
110
 
 
111
/*
 
112
 * Set up the display to start a new search command.
 
113
 */
 
114
        static void
 
115
mca_search()
 
116
{
 
117
        if (search_type & SRCH_FORW)
 
118
                mca = A_F_SEARCH;
 
119
        else
 
120
                mca = A_B_SEARCH;
 
121
 
 
122
        clear_cmd();
 
123
 
 
124
        if (search_type & SRCH_NO_MATCH)
 
125
                cmd_putstr("Non-match ");
 
126
        if (search_type & SRCH_FIRST_FILE)
 
127
                cmd_putstr("First-file ");
 
128
        if (search_type & SRCH_PAST_EOF)
 
129
                cmd_putstr("EOF-ignore ");
 
130
        if (search_type & SRCH_NO_MOVE)
 
131
                cmd_putstr("Keep-pos ");
 
132
        if (search_type & SRCH_NO_REGEX)
 
133
                cmd_putstr("Regex-off ");
 
134
 
 
135
        if (search_type & SRCH_FORW)
 
136
                cmd_putstr("/");
 
137
        else
 
138
                cmd_putstr("?");
 
139
        set_mlist(ml_search, 0);
 
140
}
 
141
 
 
142
/*
 
143
 * Set up the display to start a new toggle-option command.
 
144
 */
 
145
        static void
 
146
mca_opt_toggle()
 
147
{
 
148
        int no_prompt;
 
149
        int flag;
 
150
        char *dash;
 
151
        
 
152
        no_prompt = (optflag & OPT_NO_PROMPT);
 
153
        flag = (optflag & ~OPT_NO_PROMPT);
 
154
        dash = (flag == OPT_NO_TOGGLE) ? "_" : "-";
 
155
 
 
156
        mca = A_OPT_TOGGLE;
 
157
        clear_cmd();
 
158
        cmd_putstr(dash);
 
159
        if (optgetname)
 
160
                cmd_putstr(dash);
 
161
        if (no_prompt)
 
162
                cmd_putstr("(P)");
 
163
        switch (flag)
 
164
        {
 
165
        case OPT_UNSET:
 
166
                cmd_putstr("+");
 
167
                break;
 
168
        case OPT_SET:
 
169
                cmd_putstr("!");
 
170
                break;
 
171
        }
 
172
        set_mlist(NULL, 0);
 
173
}
 
174
 
 
175
/*
 
176
 * Execute a multicharacter command.
 
177
 */
 
178
        static void
 
179
exec_mca()
 
180
{
 
181
        register char *cbuf;
 
182
 
 
183
        cmd_exec();
 
184
        cbuf = get_cmdbuf();
 
185
 
 
186
        switch (mca)
 
187
        {
 
188
        case A_F_SEARCH:
 
189
        case A_B_SEARCH:
 
190
                multi_search(cbuf, number);
 
191
                break;
 
192
        case A_FIRSTCMD:
 
193
                /*
 
194
                 * Skip leading spaces or + signs in the string.
 
195
                 */
 
196
                while (*cbuf == '+' || *cbuf == ' ')
 
197
                        cbuf++;
 
198
                if (every_first_cmd != NULL)
 
199
                        free(every_first_cmd);
 
200
                if (*cbuf == '\0')
 
201
                        every_first_cmd = NULL;
 
202
                else
 
203
                        every_first_cmd = save(cbuf);
 
204
                break;
 
205
        case A_OPT_TOGGLE:
 
206
                toggle_option(optchar, cbuf, optflag);
 
207
                optchar = '\0';
 
208
                break;
 
209
        case A_F_BRACKET:
 
210
                match_brac(cbuf[0], cbuf[1], 1, number);
 
211
                break;
 
212
        case A_B_BRACKET:
 
213
                match_brac(cbuf[1], cbuf[0], 0, number);
 
214
                break;
 
215
#if EXAMINE
 
216
        case A_EXAMINE:
 
217
                if (secure)
 
218
                        break;
 
219
                edit_list(cbuf);
 
220
                /* If tag structure is loaded then clean it up. */
 
221
                cleantags();
 
222
                break;
 
223
#endif
 
224
#if SHELL_ESCAPE
 
225
        case A_SHELL:
 
226
                /*
 
227
                 * !! just uses whatever is in shellcmd.
 
228
                 * Otherwise, copy cmdbuf to shellcmd,
 
229
                 * expanding any special characters ("%" or "#").
 
230
                 */
 
231
                if (*cbuf != '!')
 
232
                {
 
233
                        if (shellcmd != NULL)
 
234
                                free(shellcmd);
 
235
                        shellcmd = fexpand(cbuf);
 
236
                }
 
237
 
 
238
                if (secure)
 
239
                        break;
 
240
                if (shellcmd == NULL)
 
241
                        lsystem("", "!done");
 
242
                else
 
243
                        lsystem(shellcmd, "!done");
 
244
                break;
 
245
#endif
 
246
#if PIPEC
 
247
        case A_PIPE:
 
248
                if (secure)
 
249
                        break;
 
250
                (void) pipe_mark(pipec, cbuf);
 
251
                error("|done", NULL_PARG);
 
252
                break;
 
253
#endif
 
254
        }
 
255
}
 
256
 
 
257
/*
 
258
 * Add a character to a multi-character command.
 
259
 */
 
260
        static int
 
261
mca_char(c)
 
262
        int c;
 
263
{
 
264
        char *p;
 
265
        int flag;
 
266
        char buf[3];
 
267
        PARG parg;
 
268
 
 
269
        switch (mca)
 
270
        {
 
271
        case 0:
 
272
                /*
 
273
                 * Not in a multicharacter command.
 
274
                 */
 
275
                return (NO_MCA);
 
276
 
 
277
        case A_PREFIX:
 
278
                /*
 
279
                 * In the prefix of a command.
 
280
                 * This not considered a multichar command
 
281
                 * (even tho it uses cmdbuf, etc.).
 
282
                 * It is handled in the commands() switch.
 
283
                 */
 
284
                return (NO_MCA);
 
285
 
 
286
        case A_DIGIT:
 
287
                /*
 
288
                 * Entering digits of a number.
 
289
                 * Terminated by a non-digit.
 
290
                 */
 
291
                if ((c < '0' || c > '9') && 
 
292
                  editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID)
 
293
                {
 
294
                        /*
 
295
                         * Not part of the number.
 
296
                         * Treat as a normal command character.
 
297
                         */
 
298
                        number = cmd_int();
 
299
                        mca = 0;
 
300
                        cmd_accept();
 
301
                        return (NO_MCA);
 
302
                }
 
303
                break;
 
304
 
 
305
        case A_OPT_TOGGLE:
 
306
                /*
 
307
                 * Special case for the TOGGLE_OPTION command.
 
308
                 * If the option letter which was entered is a
 
309
                 * single-char option, execute the command immediately,
 
310
                 * so user doesn't have to hit RETURN.
 
311
                 * If the first char is + or -, this indicates
 
312
                 * OPT_UNSET or OPT_SET respectively, instead of OPT_TOGGLE.
 
313
                 * "--" begins inputting a long option name.
 
314
                 */
 
315
                if (optchar == '\0' && len_cmdbuf() == 0)
 
316
                {
 
317
                        flag = (optflag & ~OPT_NO_PROMPT);
 
318
                        if (flag == OPT_NO_TOGGLE)
 
319
                        {
 
320
                                switch (c)
 
321
                                {
 
322
                                case '_':
 
323
                                        /* "__" = long option name. */
 
324
                                        optgetname = TRUE;
 
325
                                        mca_opt_toggle();
 
326
                                        return (MCA_MORE);
 
327
                                }
 
328
                        } else
 
329
                        {
 
330
                                switch (c)
 
331
                                {
 
332
                                case '+':
 
333
                                        /* "-+" = UNSET. */
 
334
                                        optflag = (flag == OPT_UNSET) ?
 
335
                                                OPT_TOGGLE : OPT_UNSET;
 
336
                                        mca_opt_toggle();
 
337
                                        return (MCA_MORE);
 
338
                                case '!':
 
339
                                        /* "-!" = SET */
 
340
                                        optflag = (flag == OPT_SET) ?
 
341
                                                OPT_TOGGLE : OPT_SET;
 
342
                                        mca_opt_toggle();
 
343
                                        return (MCA_MORE);
 
344
                                case CONTROL('P'):
 
345
                                        optflag ^= OPT_NO_PROMPT;
 
346
                                        mca_opt_toggle();
 
347
                                        return (MCA_MORE);
 
348
                                case '-':
 
349
                                        /* "--" = long option name. */
 
350
                                        optgetname = TRUE;
 
351
                                        mca_opt_toggle();
 
352
                                        return (MCA_MORE);
 
353
                                }
 
354
                        }
 
355
                }
 
356
                if (optgetname)
 
357
                {
 
358
                        /*
 
359
                         * We're getting a long option name.
 
360
                         * See if we've matched an option name yet.
 
361
                         * If so, display the complete name and stop 
 
362
                         * accepting chars until user hits RETURN.
 
363
                         */
 
364
                        struct loption *o;
 
365
                        char *oname;
 
366
                        int lc;
 
367
 
 
368
                        if (c == '\n' || c == '\r')
 
369
                        {
 
370
                                /*
 
371
                                 * When the user hits RETURN, make sure
 
372
                                 * we've matched an option name, then
 
373
                                 * pretend he just entered the equivalent
 
374
                                 * option letter.
 
375
                                 */
 
376
                                if (optchar == '\0')
 
377
                                {
 
378
                                        parg.p_string = get_cmdbuf();
 
379
                                        error("There is no --%s option", &parg);
 
380
                                        return (MCA_DONE);
 
381
                                }
 
382
                                optgetname = FALSE;
 
383
                                cmd_reset();
 
384
                                c = optchar;
 
385
                        } else
 
386
                        {
 
387
                                if (optchar != '\0')
 
388
                                {
 
389
                                        /*
 
390
                                         * Already have a match for the name.
 
391
                                         * Don't accept anything but erase/kill.
 
392
                                         */
 
393
                                        if (c == erase_char || c == kill_char)
 
394
                                                return (MCA_DONE);
 
395
                                        return (MCA_MORE);
 
396
                                }
 
397
                                /*
 
398
                                 * Add char to cmd buffer and try to match
 
399
                                 * the option name.
 
400
                                 */
 
401
                                if (cmd_char(c) == CC_QUIT)
 
402
                                        return (MCA_DONE);
 
403
                                p = get_cmdbuf();
 
404
                                lc = islower(p[0]);
 
405
                                o = findopt_name(&p, &oname, NULL);
 
406
                                if (o != NULL)
 
407
                                {
 
408
                                        /*
 
409
                                         * Got a match.
 
410
                                         * Remember the option letter and
 
411
                                         * display the full option name.
 
412
                                         */
 
413
                                        optchar = o->oletter;
 
414
                                        if (!lc && islower(optchar))
 
415
                                                optchar = toupper(optchar);
 
416
                                        cmd_reset();
 
417
                                        mca_opt_toggle();
 
418
                                        for (p = oname;  *p != '\0';  p++)
 
419
                                        {
 
420
                                                c = *p;
 
421
                                                if (!lc && islower(c))
 
422
                                                        c = toupper(c);
 
423
                                                if (cmd_char(c) != CC_OK)
 
424
                                                        return (MCA_DONE);
 
425
                                        }
 
426
                                }
 
427
                                return (MCA_MORE);
 
428
                        }
 
429
                } else
 
430
                {
 
431
                        if (c == erase_char || c == kill_char)
 
432
                                break;
 
433
                        if (optchar != '\0')
 
434
                                /* We already have the option letter. */
 
435
                                break;
 
436
                }
 
437
 
 
438
                optchar = c;
 
439
                if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE ||
 
440
                    single_char_option(c))
 
441
                {
 
442
                        toggle_option(c, "", optflag);
 
443
                        return (MCA_DONE);
 
444
                }
 
445
                /*
 
446
                 * Display a prompt appropriate for the option letter.
 
447
                 */
 
448
                if ((p = opt_prompt(c)) == NULL)
 
449
                {
 
450
                        buf[0] = '-';
 
451
                        buf[1] = c;
 
452
                        buf[2] = '\0';
 
453
                        p = buf;
 
454
                }
 
455
                start_mca(A_OPT_TOGGLE, p, (void*)NULL, 0);
 
456
                return (MCA_MORE);
 
457
 
 
458
        case A_F_SEARCH:
 
459
        case A_B_SEARCH:
 
460
                /*
 
461
                 * Special case for search commands.
 
462
                 * Certain characters as the first char of 
 
463
                 * the pattern have special meaning:
 
464
                 *      !  Toggle the NO_MATCH flag
 
465
                 *      *  Toggle the PAST_EOF flag
 
466
                 *      @  Toggle the FIRST_FILE flag
 
467
                 */
 
468
                if (len_cmdbuf() > 0)
 
469
                        /*
 
470
                         * Only works for the first char of the pattern.
 
471
                         */
 
472
                        break;
 
473
 
 
474
                flag = 0;
 
475
                switch (c)
 
476
                {
 
477
                case CONTROL('E'): /* ignore END of file */
 
478
                case '*':
 
479
                        flag = SRCH_PAST_EOF;
 
480
                        break;
 
481
                case CONTROL('F'): /* FIRST file */
 
482
                case '@':
 
483
                        flag = SRCH_FIRST_FILE;
 
484
                        break;
 
485
                case CONTROL('K'): /* KEEP position */
 
486
                        flag = SRCH_NO_MOVE;
 
487
                        break;
 
488
                case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
 
489
                        flag = SRCH_NO_REGEX;
 
490
                        break;
 
491
                case CONTROL('N'): /* NOT match */
 
492
                case '!':
 
493
                        flag = SRCH_NO_MATCH;
 
494
                        break;
 
495
                }
 
496
                if (flag != 0)
 
497
                {
 
498
                        search_type ^= flag;
 
499
                        mca_search();
 
500
                        return (MCA_MORE);
 
501
                }
 
502
                break;
 
503
        }
 
504
 
 
505
        /*
 
506
         * Any other multicharacter command
 
507
         * is terminated by a newline.
 
508
         */
 
509
        if (c == '\n' || c == '\r')
 
510
        {
 
511
                /*
 
512
                 * Execute the command.
 
513
                 */
 
514
                exec_mca();
 
515
                return (MCA_DONE);
 
516
        }
 
517
 
 
518
        /*
 
519
         * Append the char to the command buffer.
 
520
         */
 
521
        if (cmd_char(c) == CC_QUIT)
 
522
                /*
 
523
                 * Abort the multi-char command.
 
524
                 */
 
525
                return (MCA_DONE);
 
526
 
 
527
        if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2)
 
528
        {
 
529
                /*
 
530
                 * Special case for the bracket-matching commands.
 
531
                 * Execute the command after getting exactly two
 
532
                 * characters from the user.
 
533
                 */
 
534
                exec_mca();
 
535
                return (MCA_DONE);
 
536
        }
 
537
 
 
538
        /*
 
539
         * Need another character.
 
540
         */
 
541
        return (MCA_MORE);
 
542
}
 
543
 
 
544
/*
 
545
 * Make sure the screen is displayed.
 
546
 */
 
547
        static void
 
548
make_display()
 
549
{
 
550
        /*
 
551
         * If nothing is displayed yet, display starting from initial_scrpos.
 
552
         */
 
553
        if (empty_screen())
 
554
        {
 
555
                if (initial_scrpos.pos == NULL_POSITION)
 
556
                        /*
 
557
                         * {{ Maybe this should be:
 
558
                         *    jump_loc(ch_zero(), jump_sline);
 
559
                         *    but this behavior seems rather unexpected 
 
560
                         *    on the first screen. }}
 
561
                         */
 
562
                        jump_loc(ch_zero(), 1);
 
563
                else
 
564
                        jump_loc(initial_scrpos.pos, initial_scrpos.ln);
 
565
        } else if (screen_trashed)
 
566
        {
 
567
                int save_top_scroll;
 
568
                save_top_scroll = top_scroll;
 
569
                top_scroll = 1;
 
570
                repaint();
 
571
                top_scroll = save_top_scroll;
 
572
        }
 
573
}
 
574
 
 
575
/*
 
576
 * Display the appropriate prompt.
 
577
 */
 
578
        static void
 
579
prompt()
 
580
{
 
581
        register char *p;
 
582
 
 
583
        if (ungotp != NULL && ungotp > ungot)
 
584
        {
 
585
                /*
 
586
                 * No prompt necessary if commands are from 
 
587
                 * ungotten chars rather than from the user.
 
588
                 */
 
589
                return;
 
590
        }
 
591
 
 
592
        /*
 
593
         * Make sure the screen is displayed.
 
594
         */
 
595
        make_display();
 
596
        bottompos = position(BOTTOM_PLUS_ONE);
 
597
 
 
598
        /*
 
599
         * If the -E flag is set and we've hit EOF on the last file, quit.
 
600
         */
 
601
        if ((quit_at_eof == OPT_ONPLUS || quit_if_one_screen) &&
 
602
            hit_eof && !(ch_getflags() & CH_HELPFILE) && 
 
603
            next_ifile(curr_ifile) == NULL_IFILE)
 
604
                quit(QUIT_OK);
 
605
        quit_if_one_screen = FALSE;
 
606
#if 0 /* This doesn't work well because some "te"s clear the screen. */
 
607
        /*
 
608
         * If the -e flag is set and we've hit EOF on the last file,
 
609
         * and the file is squished (shorter than the screen), quit.
 
610
         */
 
611
        if (quit_at_eof && squished &&
 
612
            next_ifile(curr_ifile) == NULL_IFILE)
 
613
                quit(QUIT_OK);
 
614
#endif
 
615
 
 
616
#if MSDOS_COMPILER==WIN32C
 
617
        /* 
 
618
         * In Win32, display the file name in the window title.
 
619
         */
 
620
        if (!(ch_getflags() & CH_HELPFILE))
 
621
                SetConsoleTitle(pr_expand("Less?f - %f.", 0));
 
622
#endif
 
623
        /*
 
624
         * Select the proper prompt and display it.
 
625
         */
 
626
        clear_cmd();
 
627
        p = pr_string();
 
628
        if (p == NULL)
 
629
                putchr(':');
 
630
        else
 
631
        {
 
632
                so_enter();
 
633
                putstr(p);
 
634
                so_exit();
 
635
        }
 
636
}
 
637
 
 
638
/*
 
639
 * Display the less version message.
 
640
 */
 
641
        public void
 
642
dispversion()
 
643
{
 
644
        PARG parg;
 
645
 
 
646
        parg.p_string = version;
 
647
        error("less %s", &parg);
 
648
}
 
649
 
 
650
/*
 
651
 * Get command character.
 
652
 * The character normally comes from the keyboard,
 
653
 * but may come from ungotten characters
 
654
 * (characters previously given to ungetcc or ungetsc).
 
655
 */
 
656
        public int
 
657
getcc()
 
658
{
 
659
        if (ungotp == NULL)
 
660
                /*
 
661
                 * Normal case: no ungotten chars, so get one from the user.
 
662
                 */
 
663
                return (getchr());
 
664
 
 
665
        if (ungotp > ungot)
 
666
                /*
 
667
                 * Return the next ungotten char.
 
668
                 */
 
669
                return (*--ungotp);
 
670
 
 
671
        /*
 
672
         * We have just run out of ungotten chars.
 
673
         */
 
674
        ungotp = NULL;
 
675
        if (len_cmdbuf() == 0 || !empty_screen())
 
676
                return (getchr());
 
677
        /*
 
678
         * Command is incomplete, so try to complete it.
 
679
         */
 
680
        switch (mca)
 
681
        {
 
682
        case A_DIGIT:
 
683
                /*
 
684
                 * We have a number but no command.  Treat as #g.
 
685
                 */
 
686
                return ('g');
 
687
 
 
688
        case A_F_SEARCH:
 
689
        case A_B_SEARCH:
 
690
                /*
 
691
                 * We have "/string" but no newline.  Add the \n.
 
692
                 */
 
693
                return ('\n'); 
 
694
 
 
695
        default:
 
696
                /*
 
697
                 * Some other incomplete command.  Let user complete it.
 
698
                 */
 
699
                return (getchr());
 
700
        }
 
701
}
 
702
 
 
703
/*
 
704
 * "Unget" a command character.
 
705
 * The next getcc() will return this character.
 
706
 */
 
707
        public void
 
708
ungetcc(c)
 
709
        int c;
 
710
{
 
711
        if (ungotp == NULL)
 
712
                ungotp = ungot;
 
713
        if (ungotp >= ungot + sizeof(ungot))
 
714
        {
 
715
                error("ungetcc overflow", NULL_PARG);
 
716
                quit(QUIT_ERROR);
 
717
        }
 
718
        *ungotp++ = c;
 
719
}
 
720
 
 
721
/*
 
722
 * Unget a whole string of command characters.
 
723
 * The next sequence of getcc()'s will return this string.
 
724
 */
 
725
        public void
 
726
ungetsc(s)
 
727
        char *s;
 
728
{
 
729
        register char *p;
 
730
 
 
731
        for (p = s + strlen(s) - 1;  p >= s;  p--)
 
732
                ungetcc(*p);
 
733
}
 
734
 
 
735
/*
 
736
 * Search for a pattern, possibly in multiple files.
 
737
 * If SRCH_FIRST_FILE is set, begin searching at the first file.
 
738
 * If SRCH_PAST_EOF is set, continue the search thru multiple files.
 
739
 */
 
740
        static void
 
741
multi_search(pattern, n)
 
742
        char *pattern;
 
743
        int n;
 
744
{
 
745
        register int nomore;
 
746
        IFILE save_ifile;
 
747
        int changed_file;
 
748
 
 
749
        changed_file = 0;
 
750
        save_ifile = save_curr_ifile();
 
751
 
 
752
        if (search_type & SRCH_FIRST_FILE)
 
753
        {
 
754
                /*
 
755
                 * Start at the first (or last) file 
 
756
                 * in the command line list.
 
757
                 */
 
758
                if (search_type & SRCH_FORW)
 
759
                        nomore = edit_first();
 
760
                else
 
761
                        nomore = edit_last();
 
762
                if (nomore)
 
763
                {
 
764
                        unsave_ifile(save_ifile);
 
765
                        return;
 
766
                }
 
767
                changed_file = 1;
 
768
                search_type &= ~SRCH_FIRST_FILE;
 
769
        }
 
770
 
 
771
        for (;;)
 
772
        {
 
773
                n = search(search_type, pattern, n);
 
774
                /*
 
775
                 * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared
 
776
                 * after being used once.  This allows "n" to work after
 
777
                 * using a /@@ search.
 
778
                 */
 
779
                search_type &= ~SRCH_NO_MOVE;
 
780
                if (n == 0)
 
781
                {
 
782
                        /*
 
783
                         * Found it.
 
784
                         */
 
785
                        unsave_ifile(save_ifile);
 
786
                        return;
 
787
                }
 
788
 
 
789
                if (n < 0)
 
790
                        /*
 
791
                         * Some kind of error in the search.
 
792
                         * Error message has been printed by search().
 
793
                         */
 
794
                        break;
 
795
 
 
796
                if ((search_type & SRCH_PAST_EOF) == 0)
 
797
                        /*
 
798
                         * We didn't find a match, but we're
 
799
                         * supposed to search only one file.
 
800
                         */
 
801
                        break;
 
802
                /*
 
803
                 * Move on to the next file.
 
804
                 */
 
805
                if (search_type & SRCH_FORW)
 
806
                        nomore = edit_next(1);
 
807
                else
 
808
                        nomore = edit_prev(1);
 
809
                if (nomore)
 
810
                        break;
 
811
                changed_file = 1;
 
812
        }
 
813
 
 
814
        /*
 
815
         * Didn't find it.
 
816
         * Print an error message if we haven't already.
 
817
         */
 
818
        if (n > 0)
 
819
                error("Pattern not found", NULL_PARG);
 
820
 
 
821
        if (changed_file)
 
822
        {
 
823
                /*
 
824
                 * Restore the file we were originally viewing.
 
825
                 */
 
826
                reedit_ifile(save_ifile);
 
827
        }
 
828
}
 
829
 
 
830
/*
 
831
 * Main command processor.
 
832
 * Accept and execute commands until a quit command.
 
833
 */
 
834
        public void
 
835
commands()
 
836
{
 
837
        register int c;
 
838
        register int action;
 
839
        register char *cbuf;
 
840
        int newaction;
 
841
        int save_search_type;
 
842
        char *extra;
 
843
        char tbuf[2];
 
844
        PARG parg;
 
845
        IFILE old_ifile;
 
846
        IFILE new_ifile;
 
847
        char *tagfile;
 
848
 
 
849
        search_type = SRCH_FORW;
 
850
        wscroll = (sc_height + 1) / 2;
 
851
        newaction = A_NOACTION;
 
852
 
 
853
        for (;;)
 
854
        {
 
855
                mca = 0;
 
856
                cmd_accept();
 
857
                number = 0;
 
858
                optchar = '\0';
 
859
 
 
860
                /*
 
861
                 * See if any signals need processing.
 
862
                 */
 
863
                if (sigs)
 
864
                {
 
865
                        psignals();
 
866
                        if (quitting)
 
867
                                quit(QUIT_SAVED_STATUS);
 
868
                }
 
869
 
 
870
                /*
 
871
                 * See if window size changed, for systems that don't
 
872
                 * generate SIGWINCH.
 
873
                 */
 
874
                check_winch();
 
875
 
 
876
                /*
 
877
                 * Display prompt and accept a character.
 
878
                 */
 
879
                cmd_reset();
 
880
                prompt();
 
881
                if (sigs)
 
882
                        continue;
 
883
                if (newaction == A_NOACTION)
 
884
                        c = getcc();
 
885
 
 
886
        again:
 
887
                if (sigs)
 
888
                        continue;
 
889
 
 
890
                if (newaction != A_NOACTION)
 
891
                {
 
892
                        action = newaction;
 
893
                        newaction = A_NOACTION;
 
894
                } else
 
895
                {
 
896
                        /*
 
897
                         * If we are in a multicharacter command, call mca_char.
 
898
                         * Otherwise we call fcmd_decode to determine the
 
899
                         * action to be performed.
 
900
                         */
 
901
                        if (mca)
 
902
                                switch (mca_char(c))
 
903
                                {
 
904
                                case MCA_MORE:
 
905
                                        /*
 
906
                                         * Need another character.
 
907
                                         */
 
908
                                        c = getcc();
 
909
                                        goto again;
 
910
                                case MCA_DONE:
 
911
                                        /*
 
912
                                         * Command has been handled by mca_char.
 
913
                                         * Start clean with a prompt.
 
914
                                         */
 
915
                                        continue;
 
916
                                case NO_MCA:
 
917
                                        /*
 
918
                                         * Not a multi-char command
 
919
                                         * (at least, not anymore).
 
920
                                         */
 
921
                                        break;
 
922
                                }
 
923
 
 
924
                        /*
 
925
                         * Decode the command character and decide what to do.
 
926
                         */
 
927
                        if (mca)
 
928
                        {
 
929
                                /*
 
930
                                 * We're in a multichar command.
 
931
                                 * Add the character to the command buffer
 
932
                                 * and display it on the screen.
 
933
                                 * If the user backspaces past the start 
 
934
                                 * of the line, abort the command.
 
935
                                 */
 
936
                                if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0)
 
937
                                        continue;
 
938
                                cbuf = get_cmdbuf();
 
939
                        } else
 
940
                        {
 
941
                                /*
 
942
                                 * Don't use cmd_char if we're starting fresh
 
943
                                 * at the beginning of a command, because we
 
944
                                 * don't want to echo the command until we know
 
945
                                 * it is a multichar command.  We also don't
 
946
                                 * want erase_char/kill_char to be treated
 
947
                                 * as line editing characters.
 
948
                                 */
 
949
                                tbuf[0] = c;
 
950
                                tbuf[1] = '\0';
 
951
                                cbuf = tbuf;
 
952
                        }
 
953
                        extra = NULL;
 
954
                        action = fcmd_decode(cbuf, &extra);
 
955
                        /*
 
956
                         * If an "extra" string was returned,
 
957
                         * process it as a string of command characters.
 
958
                         */
 
959
                        if (extra != NULL)
 
960
                                ungetsc(extra);
 
961
                }
 
962
                /*
 
963
                 * Clear the cmdbuf string.
 
964
                 * (But not if we're in the prefix of a command,
 
965
                 * because the partial command string is kept there.)
 
966
                 */
 
967
                if (action != A_PREFIX)
 
968
                        cmd_reset();
 
969
 
 
970
                switch (action)
 
971
                {
 
972
                case A_DIGIT:
 
973
                        /*
 
974
                         * First digit of a number.
 
975
                         */
 
976
                        start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE);
 
977
                        goto again;
 
978
 
 
979
                case A_F_WINDOW:
 
980
                        /*
 
981
                         * Forward one window (and set the window size).
 
982
                         */
 
983
                        if (number > 0)
 
984
                                swindow = number;
 
985
                        /* FALLTHRU */
 
986
                case A_F_SCREEN:
 
987
                        /*
 
988
                         * Forward one screen.
 
989
                         */
 
990
                        if (number <= 0)
 
991
                                number = get_swindow();
 
992
                        cmd_exec();
 
993
                        if (show_attn)
 
994
                                set_attnpos(bottompos);
 
995
                        forward(number, 0, 1);
 
996
                        break;
 
997
 
 
998
                case A_B_WINDOW:
 
999
                        /*
 
1000
                         * Backward one window (and set the window size).
 
1001
                         */
 
1002
                        if (number > 0)
 
1003
                                swindow = number;
 
1004
                        /* FALLTHRU */
 
1005
                case A_B_SCREEN:
 
1006
                        /*
 
1007
                         * Backward one screen.
 
1008
                         */
 
1009
                        if (number <= 0)
 
1010
                                number = get_swindow();
 
1011
                        cmd_exec();
 
1012
                        backward(number, 0, 1);
 
1013
                        break;
 
1014
 
 
1015
                case A_F_LINE:
 
1016
                        /*
 
1017
                         * Forward N (default 1) line.
 
1018
                         */
 
1019
                        if (number <= 0)
 
1020
                                number = 1;
 
1021
                        cmd_exec();
 
1022
                        if (show_attn == OPT_ONPLUS && number > 1)
 
1023
                                set_attnpos(bottompos);
 
1024
                        forward(number, 0, 0);
 
1025
                        break;
 
1026
 
 
1027
                case A_B_LINE:
 
1028
                        /*
 
1029
                         * Backward N (default 1) line.
 
1030
                         */
 
1031
                        if (number <= 0)
 
1032
                                number = 1;
 
1033
                        cmd_exec();
 
1034
                        backward(number, 0, 0);
 
1035
                        break;
 
1036
 
 
1037
                case A_FF_LINE:
 
1038
                        /*
 
1039
                         * Force forward N (default 1) line.
 
1040
                         */
 
1041
                        if (number <= 0)
 
1042
                                number = 1;
 
1043
                        cmd_exec();
 
1044
                        if (show_attn == OPT_ONPLUS && number > 1)
 
1045
                                set_attnpos(bottompos);
 
1046
                        forward(number, 1, 0);
 
1047
                        break;
 
1048
 
 
1049
                case A_BF_LINE:
 
1050
                        /*
 
1051
                         * Force backward N (default 1) line.
 
1052
                         */
 
1053
                        if (number <= 0)
 
1054
                                number = 1;
 
1055
                        cmd_exec();
 
1056
                        backward(number, 1, 0);
 
1057
                        break;
 
1058
                
 
1059
                case A_FF_SCREEN:
 
1060
                        /*
 
1061
                         * Force forward one screen.
 
1062
                         */
 
1063
                        if (number <= 0)
 
1064
                                number = get_swindow();
 
1065
                        cmd_exec();
 
1066
                        if (show_attn == OPT_ONPLUS)
 
1067
                                set_attnpos(bottompos);
 
1068
                        forward(number, 1, 0);
 
1069
                        break;
 
1070
 
 
1071
                case A_F_FOREVER:
 
1072
                        /*
 
1073
                         * Forward forever, ignoring EOF.
 
1074
                         */
 
1075
                        if (ch_getflags() & CH_HELPFILE)
 
1076
                                break;
 
1077
                        cmd_exec();
 
1078
                        jump_forw();
 
1079
                        ignore_eoi = 1;
 
1080
                        hit_eof = 0;
 
1081
                        while (!sigs)
 
1082
                                forward(1, 0, 0);
 
1083
                        ignore_eoi = 0;
 
1084
                        /*
 
1085
                         * This gets us back in "F mode" after processing 
 
1086
                         * a non-abort signal (e.g. window-change).  
 
1087
                         */
 
1088
                        if (sigs && !ABORT_SIGS())
 
1089
                                newaction = A_F_FOREVER;
 
1090
                        break;
 
1091
 
 
1092
                case A_F_SCROLL:
 
1093
                        /*
 
1094
                         * Forward N lines 
 
1095
                         * (default same as last 'd' or 'u' command).
 
1096
                         */
 
1097
                        if (number > 0)
 
1098
                                wscroll = number;
 
1099
                        cmd_exec();
 
1100
                        if (show_attn == OPT_ONPLUS)
 
1101
                                set_attnpos(bottompos);
 
1102
                        forward(wscroll, 0, 0);
 
1103
                        break;
 
1104
 
 
1105
                case A_B_SCROLL:
 
1106
                        /*
 
1107
                         * Forward N lines 
 
1108
                         * (default same as last 'd' or 'u' command).
 
1109
                         */
 
1110
                        if (number > 0)
 
1111
                                wscroll = number;
 
1112
                        cmd_exec();
 
1113
                        backward(wscroll, 0, 0);
 
1114
                        break;
 
1115
 
 
1116
                case A_FREPAINT:
 
1117
                        /*
 
1118
                         * Flush buffers, then repaint screen.
 
1119
                         * Don't flush the buffers on a pipe!
 
1120
                         */
 
1121
                        if (ch_getflags() & CH_CANSEEK)
 
1122
                        {
 
1123
                                ch_flush();
 
1124
                                clr_linenum();
 
1125
#if HILITE_SEARCH
 
1126
                                clr_hilite();
 
1127
#endif
 
1128
                        }
 
1129
                        /* FALLTHRU */
 
1130
                case A_REPAINT:
 
1131
                        /*
 
1132
                         * Repaint screen.
 
1133
                         */
 
1134
                        cmd_exec();
 
1135
                        repaint();
 
1136
                        break;
 
1137
 
 
1138
                case A_GOLINE:
 
1139
                        /*
 
1140
                         * Go to line N, default beginning of file.
 
1141
                         */
 
1142
                        if (number <= 0)
 
1143
                                number = 1;
 
1144
                        cmd_exec();
 
1145
                        jump_back(number);
 
1146
                        break;
 
1147
 
 
1148
                case A_PERCENT:
 
1149
                        /*
 
1150
                         * Go to a specified percentage into the file.
 
1151
                         */
 
1152
                        if (number < 0)
 
1153
                                number = 0;
 
1154
                        if (number > 100)
 
1155
                                number = 100;
 
1156
                        cmd_exec();
 
1157
                        jump_percent(number);
 
1158
                        break;
 
1159
 
 
1160
                case A_GOEND:
 
1161
                        /*
 
1162
                         * Go to line N, default end of file.
 
1163
                         */
 
1164
                        cmd_exec();
 
1165
                        if (number <= 0)
 
1166
                                jump_forw();
 
1167
                        else
 
1168
                                jump_back(number);
 
1169
                        break;
 
1170
 
 
1171
                case A_GOPOS:
 
1172
                        /*
 
1173
                         * Go to a specified byte position in the file.
 
1174
                         */
 
1175
                        cmd_exec();
 
1176
                        if (number < 0)
 
1177
                                number = 0;
 
1178
                        jump_line_loc((POSITION)number, jump_sline);
 
1179
                        break;
 
1180
 
 
1181
                case A_STAT:
 
1182
                        /*
 
1183
                         * Print file name, etc.
 
1184
                         */
 
1185
                        if (ch_getflags() & CH_HELPFILE)
 
1186
                                break;
 
1187
                        cmd_exec();
 
1188
                        parg.p_string = eq_message();
 
1189
                        error("%s", &parg);
 
1190
                        break;
 
1191
 
 
1192
                case A_VERSION:
 
1193
                        /*
 
1194
                         * Print version number, without the "@(#)".
 
1195
                         */
 
1196
                        cmd_exec();
 
1197
                        dispversion();
 
1198
                        break;
 
1199
 
 
1200
                case A_QUIT:
 
1201
                        /*
 
1202
                         * Exit.
 
1203
                         */
 
1204
                        if (curr_ifile != NULL_IFILE && 
 
1205
                            ch_getflags() & CH_HELPFILE)
 
1206
                        {
 
1207
                                /*
 
1208
                                 * Quit while viewing the help file
 
1209
                                 * just means return to viewing the
 
1210
                                 * previous file.
 
1211
                                 */
 
1212
                                if (edit_prev(1) == 0)
 
1213
                                        break;
 
1214
                        }
 
1215
                        if (extra != NULL)
 
1216
                                quit(*extra);
 
1217
                        quit(QUIT_OK);
 
1218
                        break;
 
1219
 
 
1220
/*
 
1221
 * Define abbreviation for a commonly used sequence below.
 
1222
 */
 
1223
#define DO_SEARCH()     if (number <= 0) number = 1;    \
 
1224
                        mca_search();                   \
 
1225
                        cmd_exec();                     \
 
1226
                        multi_search((char *)NULL, number);
 
1227
 
 
1228
 
 
1229
                case A_F_SEARCH:
 
1230
                        /*
 
1231
                         * Search forward for a pattern.
 
1232
                         * Get the first char of the pattern.
 
1233
                         */
 
1234
                        search_type = SRCH_FORW;
 
1235
                        if (number <= 0)
 
1236
                                number = 1;
 
1237
                        mca_search();
 
1238
                        c = getcc();
 
1239
                        goto again;
 
1240
 
 
1241
                case A_B_SEARCH:
 
1242
                        /*
 
1243
                         * Search backward for a pattern.
 
1244
                         * Get the first char of the pattern.
 
1245
                         */
 
1246
                        search_type = SRCH_BACK;
 
1247
                        if (number <= 0)
 
1248
                                number = 1;
 
1249
                        mca_search();
 
1250
                        c = getcc();
 
1251
                        goto again;
 
1252
 
 
1253
                case A_AGAIN_SEARCH:
 
1254
                        /*
 
1255
                         * Repeat previous search.
 
1256
                         */
 
1257
                        DO_SEARCH();
 
1258
                        break;
 
1259
                
 
1260
                case A_T_AGAIN_SEARCH:
 
1261
                        /*
 
1262
                         * Repeat previous search, multiple files.
 
1263
                         */
 
1264
                        search_type |= SRCH_PAST_EOF;
 
1265
                        DO_SEARCH();
 
1266
                        break;
 
1267
 
 
1268
                case A_REVERSE_SEARCH:
 
1269
                        /*
 
1270
                         * Repeat previous search, in reverse direction.
 
1271
                         */
 
1272
                        save_search_type = search_type;
 
1273
                        search_type = SRCH_REVERSE(search_type);
 
1274
                        DO_SEARCH();
 
1275
                        search_type = save_search_type;
 
1276
                        break;
 
1277
 
 
1278
                case A_T_REVERSE_SEARCH:
 
1279
                        /* 
 
1280
                         * Repeat previous search, 
 
1281
                         * multiple files in reverse direction.
 
1282
                         */
 
1283
                        save_search_type = search_type;
 
1284
                        search_type = SRCH_REVERSE(search_type);
 
1285
                        search_type |= SRCH_PAST_EOF;
 
1286
                        DO_SEARCH();
 
1287
                        search_type = save_search_type;
 
1288
                        break;
 
1289
 
 
1290
                case A_UNDO_SEARCH:
 
1291
                        undo_search();
 
1292
                        break;
 
1293
 
 
1294
                case A_HELP:
 
1295
                        /*
 
1296
                         * Help.
 
1297
                         */
 
1298
                        if (ch_getflags() & CH_HELPFILE)
 
1299
                                break;
 
1300
                        cmd_exec();
 
1301
                        (void) edit(FAKE_HELPFILE);
 
1302
                        break;
 
1303
 
 
1304
                case A_EXAMINE:
 
1305
#if EXAMINE
 
1306
                        /*
 
1307
                         * Edit a new file.  Get the filename.
 
1308
                         */
 
1309
                        if (secure)
 
1310
                        {
 
1311
                                error("Command not available", NULL_PARG);
 
1312
                                break;
 
1313
                        }
 
1314
                        start_mca(A_EXAMINE, "Examine: ", ml_examine, 0);
 
1315
                        c = getcc();
 
1316
                        goto again;
 
1317
#else
 
1318
                        error("Command not available", NULL_PARG);
 
1319
                        break;
 
1320
#endif
 
1321
                        
 
1322
                case A_VISUAL:
 
1323
                        /*
 
1324
                         * Invoke an editor on the input file.
 
1325
                         */
 
1326
#if EDITOR
 
1327
                        if (secure)
 
1328
                        {
 
1329
                                error("Command not available", NULL_PARG);
 
1330
                                break;
 
1331
                        }
 
1332
                        if (ch_getflags() & CH_HELPFILE)
 
1333
                                break;
 
1334
                        if (strcmp(get_filename(curr_ifile), "-") == 0)
 
1335
                        {
 
1336
                                error("Cannot edit standard input", NULL_PARG);
 
1337
                                break;
 
1338
                        }
 
1339
                        if (curr_altfilename != NULL)
 
1340
                        {
 
1341
                                error("Cannot edit file processed with LESSOPEN", 
 
1342
                                        NULL_PARG);
 
1343
                                break;
 
1344
                        }
 
1345
                        start_mca(A_SHELL, "!", ml_shell, 0);
 
1346
                        /*
 
1347
                         * Expand the editor prototype string
 
1348
                         * and pass it to the system to execute.
 
1349
                         * (Make sure the screen is displayed so the
 
1350
                         * expansion of "+%lm" works.)
 
1351
                         */
 
1352
                        make_display();
 
1353
                        cmd_exec();
 
1354
                        lsystem(pr_expand(editproto, 0), (char*)NULL);
 
1355
                        break;
 
1356
#else
 
1357
                        error("Command not available", NULL_PARG);
 
1358
                        break;
 
1359
#endif
 
1360
 
 
1361
                case A_NEXT_FILE:
 
1362
                        /*
 
1363
                         * Examine next file.
 
1364
                         */
 
1365
                        if (ntags())
 
1366
                        {
 
1367
                                error("No next file", NULL_PARG);
 
1368
                                break;
 
1369
                        }
 
1370
                        if (number <= 0)
 
1371
                                number = 1;
 
1372
                        if (edit_next(number))
 
1373
                        {
 
1374
                                if (quit_at_eof && hit_eof && 
 
1375
                                    !(ch_getflags() & CH_HELPFILE))
 
1376
                                        quit(QUIT_OK);
 
1377
                                parg.p_string = (number > 1) ? "(N-th) " : "";
 
1378
                                error("No %snext file", &parg);
 
1379
                        }
 
1380
                        break;
 
1381
 
 
1382
                case A_PREV_FILE:
 
1383
                        /*
 
1384
                         * Examine previous file.
 
1385
                         */
 
1386
                        if (ntags())
 
1387
                        {
 
1388
                                error("No previous file", NULL_PARG);
 
1389
                                break;
 
1390
                        }
 
1391
                        if (number <= 0)
 
1392
                                number = 1;
 
1393
                        if (edit_prev(number))
 
1394
                        {
 
1395
                                parg.p_string = (number > 1) ? "(N-th) " : "";
 
1396
                                error("No %sprevious file", &parg);
 
1397
                        }
 
1398
                        break;
 
1399
 
 
1400
                case A_NEXT_TAG:
 
1401
                        if (number <= 0)
 
1402
                                number = 1;
 
1403
                        tagfile = nexttag(number);
 
1404
                        if (tagfile == NULL)
 
1405
                        {
 
1406
                                error("No next tag", NULL_PARG);
 
1407
                                break;
 
1408
                        }
 
1409
                        if (edit(tagfile) == 0)
 
1410
                        {
 
1411
                                POSITION pos = tagsearch();
 
1412
                                if (pos != NULL_POSITION)
 
1413
                                        jump_loc(pos, jump_sline);
 
1414
                        }
 
1415
                        break;
 
1416
 
 
1417
                case A_PREV_TAG:
 
1418
                        if (number <= 0)
 
1419
                                number = 1;
 
1420
                        tagfile = prevtag(number);
 
1421
                        if (tagfile == NULL)
 
1422
                        {
 
1423
                                error("No previous tag", NULL_PARG);
 
1424
                                break;
 
1425
                        }
 
1426
                        if (edit(tagfile) == 0)
 
1427
                        {
 
1428
                                POSITION pos = tagsearch();
 
1429
                                if (pos != NULL_POSITION)
 
1430
                                        jump_loc(pos, jump_sline);
 
1431
                        }
 
1432
                        break;
 
1433
 
 
1434
                case A_INDEX_FILE:
 
1435
                        /*
 
1436
                         * Examine a particular file.
 
1437
                         */
 
1438
                        if (number <= 0)
 
1439
                                number = 1;
 
1440
                        if (edit_index(number))
 
1441
                                error("No such file", NULL_PARG);
 
1442
                        break;
 
1443
 
 
1444
                case A_REMOVE_FILE:
 
1445
                        if (ch_getflags() & CH_HELPFILE)
 
1446
                                break;
 
1447
                        old_ifile = curr_ifile;
 
1448
                        new_ifile = getoff_ifile(curr_ifile);
 
1449
                        if (new_ifile == NULL_IFILE)
 
1450
                        {
 
1451
                                bell();
 
1452
                                break;
 
1453
                        }
 
1454
                        if (edit_ifile(new_ifile) != 0)
 
1455
                        {
 
1456
                                reedit_ifile(old_ifile);
 
1457
                                break;
 
1458
                        }
 
1459
                        del_ifile(old_ifile);
 
1460
                        break;
 
1461
 
 
1462
                case A_OPT_TOGGLE:
 
1463
                        optflag = OPT_TOGGLE;
 
1464
                        optgetname = FALSE;
 
1465
                        mca_opt_toggle();
 
1466
                        c = getcc();
 
1467
                        goto again;
 
1468
 
 
1469
                case A_DISP_OPTION:
 
1470
                        /*
 
1471
                         * Report a flag setting.
 
1472
                         */
 
1473
                        optflag = OPT_NO_TOGGLE;
 
1474
                        optgetname = FALSE;
 
1475
                        mca_opt_toggle();
 
1476
                        c = getcc();
 
1477
                        goto again;
 
1478
 
 
1479
                case A_FIRSTCMD:
 
1480
                        /*
 
1481
                         * Set an initial command for new files.
 
1482
                         */
 
1483
                        start_mca(A_FIRSTCMD, "+", (void*)NULL, 0);
 
1484
                        c = getcc();
 
1485
                        goto again;
 
1486
 
 
1487
                case A_SHELL:
 
1488
                        /*
 
1489
                         * Shell escape.
 
1490
                         */
 
1491
#if SHELL_ESCAPE
 
1492
                        if (secure)
 
1493
                        {
 
1494
                                error("Command not available", NULL_PARG);
 
1495
                                break;
 
1496
                        }
 
1497
                        start_mca(A_SHELL, "!", ml_shell, 0);
 
1498
                        c = getcc();
 
1499
                        goto again;
 
1500
#else
 
1501
                        error("Command not available", NULL_PARG);
 
1502
                        break;
 
1503
#endif
 
1504
 
 
1505
                case A_SETMARK:
 
1506
                        /*
 
1507
                         * Set a mark.
 
1508
                         */
 
1509
                        if (ch_getflags() & CH_HELPFILE)
 
1510
                                break;
 
1511
                        start_mca(A_SETMARK, "mark: ", (void*)NULL, 0);
 
1512
                        c = getcc();
 
1513
                        if (c == erase_char || c == kill_char ||
 
1514
                            c == '\n' || c == '\r')
 
1515
                                break;
 
1516
                        setmark(c);
 
1517
                        break;
 
1518
 
 
1519
                case A_GOMARK:
 
1520
                        /*
 
1521
                         * Go to a mark.
 
1522
                         */
 
1523
                        start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0);
 
1524
                        c = getcc();
 
1525
                        if (c == erase_char || c == kill_char || 
 
1526
                            c == '\n' || c == '\r')
 
1527
                                break;
 
1528
                        gomark(c);
 
1529
                        break;
 
1530
 
 
1531
                case A_PIPE:
 
1532
#if PIPEC
 
1533
                        if (secure)
 
1534
                        {
 
1535
                                error("Command not available", NULL_PARG);
 
1536
                                break;
 
1537
                        }
 
1538
                        start_mca(A_PIPE, "|mark: ", (void*)NULL, 0);
 
1539
                        c = getcc();
 
1540
                        if (c == erase_char || c == kill_char)
 
1541
                                break;
 
1542
                        if (c == '\n' || c == '\r')
 
1543
                                c = '.';
 
1544
                        if (badmark(c))
 
1545
                                break;
 
1546
                        pipec = c;
 
1547
                        start_mca(A_PIPE, "!", ml_shell, 0);
 
1548
                        c = getcc();
 
1549
                        goto again;
 
1550
#else
 
1551
                        error("Command not available", NULL_PARG);
 
1552
                        break;
 
1553
#endif
 
1554
 
 
1555
                case A_B_BRACKET:
 
1556
                case A_F_BRACKET:
 
1557
                        start_mca(action, "Brackets: ", (void*)NULL, 0);
 
1558
                        c = getcc();
 
1559
                        goto again;
 
1560
 
 
1561
                case A_LSHIFT:
 
1562
                        if (number > 0)
 
1563
                                shift_count = number;
 
1564
                        else
 
1565
                                number = (shift_count > 0) ?
 
1566
                                        shift_count : sc_width / 2;
 
1567
                        if (number > hshift)
 
1568
                                number = hshift;
 
1569
                        hshift -= number;
 
1570
                        screen_trashed = 1;
 
1571
                        break;
 
1572
 
 
1573
                case A_RSHIFT:
 
1574
                        if (number > 0)
 
1575
                                shift_count = number;
 
1576
                        else
 
1577
                                number = (shift_count > 0) ?
 
1578
                                        shift_count : sc_width / 2;
 
1579
                        hshift += number;
 
1580
                        screen_trashed = 1;
 
1581
                        break;
 
1582
 
 
1583
                case A_PREFIX:
 
1584
                        /*
 
1585
                         * The command is incomplete (more chars are needed).
 
1586
                         * Display the current char, so the user knows
 
1587
                         * what's going on, and get another character.
 
1588
                         */
 
1589
                        if (mca != A_PREFIX)
 
1590
                        {
 
1591
                                cmd_reset();
 
1592
                                start_mca(A_PREFIX, " ", (void*)NULL,
 
1593
                                        CF_QUIT_ON_ERASE);
 
1594
                                (void) cmd_char(c);
 
1595
                        }
 
1596
                        c = getcc();
 
1597
                        goto again;
 
1598
 
 
1599
                case A_NOACTION:
 
1600
                        break;
 
1601
 
 
1602
                default:
 
1603
                        bell();
 
1604
                        break;
 
1605
                }
 
1606
        }
 
1607
}