~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/3rdparty/qtcsh/ed.inputl.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ed.inputl.c: Input line handling.
 
3
 */
 
4
/*-
 
5
 * Copyright (c) 1980, 1991 The Regents of the University of California.
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer.
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 * 3. All advertising materials mentioning features or use of this software
 
17
 *    must display the following acknowledgement:
 
18
 *      This product includes software developed by the University of
 
19
 *      California, Berkeley and its contributors.
 
20
 * 4. Neither the name of the University nor the names of its contributors
 
21
 *    may be used to endorse or promote products derived from this software
 
22
 *    without specific prior written permission.
 
23
 *
 
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
34
 * SUCH DAMAGE.
 
35
 */
 
36
#include "sh.h"
 
37
 
 
38
RCSID("$Id$")
 
39
 
 
40
#include "ed.h"
 
41
#include "ed.defns.h"           /* for the function names */
 
42
#include "tw.h"                 /* for twenex stuff */
 
43
 
 
44
#define OKCMD (INBUFSIZE+INBUFSIZE)
 
45
 
 
46
/* ed.inputl -- routines to get a single line from the input. */
 
47
 
 
48
extern bool tellwhat;
 
49
extern bool MapsAreInited;
 
50
extern bool Tty_raw_mode;
 
51
 
 
52
/* mismatched first character */
 
53
static Char mismatch[] = 
 
54
    {'!', '^' , '\\', '-', '%', '\0', '"', '\'', '`', '\0' };
 
55
 
 
56
static  int     Repair          __P((void));
 
57
static  int     GetNextCommand  __P((KEYCMD *, Char *));
 
58
static  int     SpellLine       __P((int));
 
59
static  int     CompleteLine    __P((void));
 
60
static  void    RunCommand      __P((Char *));
 
61
static  void    doeval1         __P((Char **));
 
62
 
 
63
static bool rotate = 0;
 
64
 
 
65
 
 
66
static int
 
67
Repair()
 
68
{
 
69
    if (NeedsRedraw) {
 
70
        ClearLines();
 
71
        ClearDisp();
 
72
        NeedsRedraw = 0;
 
73
    }
 
74
    Refresh();
 
75
    Argument = 1;
 
76
    DoingArg = 0;
 
77
    curchoice = -1;
 
78
    return (int) (LastChar - InputBuf);
 
79
}
 
80
 
 
81
/* CCRETVAL */
 
82
int
 
83
Inputl()
 
84
{
 
85
    CCRETVAL retval;
 
86
    KEYCMD  cmdnum = 0;
 
87
    extern KEYCMD NumFuns;
 
88
    unsigned char tch;          /* the place where read() goes */
 
89
    Char    ch;
 
90
    int     num;                /* how many chars we have read at NL */
 
91
    int     expnum;
 
92
    struct varent *crct = inheredoc ? NULL : adrof(STRcorrect);
 
93
    struct varent *autol = adrof(STRautolist);
 
94
    struct varent *matchbeep = adrof(STRmatchbeep);
 
95
    struct varent *imode = adrof(STRinputmode);
 
96
    Char   *SaveChar, *CorrChar;
 
97
    Char    Origin[INBUFSIZE], Change[INBUFSIZE];
 
98
    int     matchval;           /* from tenematch() */
 
99
    COMMAND fn;
 
100
    int curlen = 0;
 
101
    int newlen;
 
102
    int idx;
 
103
 
 
104
    if (!MapsAreInited)         /* double extra just in case */
 
105
        ed_InitMaps();
 
106
 
 
107
    ClearDisp();                /* reset the display stuff */
 
108
    ResetInLine(0);             /* reset the input pointers */
 
109
    if (GettingInput)
 
110
        MacroLvl = -1;          /* editor was interrupted during input */
 
111
 
 
112
    if (imode) {
 
113
        if (!Strcmp(*(imode->vec), STRinsert))
 
114
            inputmode = MODE_INSERT;
 
115
        else if (!Strcmp(*(imode->vec), STRoverwrite))
 
116
            inputmode = MODE_REPLACE;
 
117
    }
 
118
 
 
119
#if defined(FIONREAD) && !defined(OREO)
 
120
    if (!Tty_raw_mode && MacroLvl < 0) {
 
121
# ifdef SUNOS4
 
122
        long chrs = 0;
 
123
# else /* !SUNOS4 */
 
124
        /* 
 
125
         * *Everyone* else has an int, but SunOS wants long!
 
126
         * This breaks where int != long (alpha)
 
127
         */
 
128
        int chrs = 0;
 
129
# endif /* SUNOS4 */
 
130
 
 
131
        (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
 
132
        if (chrs == 0) {
 
133
            if (Rawmode() < 0)
 
134
                return 0;
 
135
        }
 
136
    }
 
137
#endif /* FIONREAD && !OREO */
 
138
 
 
139
    GettingInput = 1;
 
140
    NeedsRedraw = 0;
 
141
 
 
142
    if (tellwhat) {
 
143
        copyn(InputBuf, WhichBuf, INBUFSIZE);
 
144
        LastChar = InputBuf + (LastWhich - WhichBuf);
 
145
        Cursor = InputBuf + (CursWhich - WhichBuf);
 
146
        tellwhat = 0;
 
147
        Hist_num = HistWhich;
 
148
    }
 
149
    if (Expand) {
 
150
        (void) e_up_hist(0);
 
151
        Expand = 0;
 
152
    }
 
153
    Refresh();                  /* print the prompt */
 
154
 
 
155
    for (num = OKCMD; num == OKCMD;) {  /* while still editing this line */
 
156
#ifdef DEBUG_EDIT
 
157
        if (Cursor > LastChar)
 
158
            xprintf("Cursor > LastChar\r\n");
 
159
        if (Cursor < InputBuf)
 
160
            xprintf("Cursor < InputBuf\r\n");
 
161
        if (Cursor > InputLim)
 
162
            xprintf("Cursor > InputLim\r\n");
 
163
        if (LastChar > InputLim)
 
164
            xprintf("LastChar > InputLim\r\n");
 
165
        if (InputLim != &InputBuf[INBUFSIZE - 2])
 
166
            xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n");
 
167
        if ((!DoingArg) && (Argument != 1))
 
168
            xprintf("(!DoingArg) && (Argument != 1)\r\n");
 
169
        if (CcKeyMap[0] == 0)
 
170
            xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
 
171
#endif
 
172
 
 
173
        /* if EOF or error */
 
174
        if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
 
175
            break;
 
176
        }
 
177
 
 
178
        if (cmdnum >= NumFuns) {/* BUG CHECK command */
 
179
#ifdef DEBUG_EDIT
 
180
            xprintf(CGETS(6, 1, "ERROR: illegal command from key 0%o\r\n"), ch);
 
181
#endif
 
182
            continue;           /* try again */
 
183
        }
 
184
 
 
185
        /* now do the real command */
 
186
        retval = (*CcFuncTbl[cmdnum]) (ch);
 
187
 
 
188
        /* save the last command here */
 
189
        LastCmd = cmdnum;
 
190
 
 
191
        /* make sure fn is initialized */
 
192
        fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
 
193
 
 
194
        /* use any return value */
 
195
        switch (retval) {
 
196
 
 
197
        case CC_REFRESH:
 
198
            Refresh();
 
199
            /*FALLTHROUGH*/
 
200
        case CC_NORM:           /* normal char */
 
201
            Argument = 1;
 
202
            DoingArg = 0;
 
203
            /*FALLTHROUGH*/
 
204
        case CC_ARGHACK:        /* Suggested by Rich Salz */
 
205
            /* <rsalz@pineapple.bbn.com> */
 
206
            curchoice = -1;
 
207
            curlen = (int) (LastChar - InputBuf);
 
208
            break;              /* keep going... */
 
209
 
 
210
        case CC_EOF:            /* end of file typed */
 
211
            curchoice = -1;
 
212
            curlen = (int) (LastChar - InputBuf);
 
213
            num = 0;
 
214
            break;
 
215
 
 
216
        case CC_WHICH:          /* tell what this command does */
 
217
            tellwhat = 1;
 
218
            copyn(WhichBuf, InputBuf, INBUFSIZE);
 
219
            LastWhich = WhichBuf + (LastChar - InputBuf);
 
220
            CursWhich = WhichBuf + (Cursor - InputBuf);
 
221
            *LastChar++ = '\n'; /* for the benifit of CSH */
 
222
            HistWhich = Hist_num;
 
223
            Hist_num = 0;       /* for the history commands */
 
224
            num = (int) (LastChar - InputBuf);  /* number characters read */
 
225
            break;
 
226
 
 
227
        case CC_NEWLINE:        /* normal end of line */
 
228
            curlen = 0;
 
229
            curchoice = -1;
 
230
            matchval = 1;
 
231
            if (crct && (!Strcmp(*(crct->vec), STRcmd) ||
 
232
                         !Strcmp(*(crct->vec), STRall))) {
 
233
                PastBottom();
 
234
                copyn(Origin, InputBuf, INBUFSIZE);
 
235
                SaveChar = LastChar;
 
236
                if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
 
237
                    PastBottom();
 
238
                    copyn(Change, InputBuf, INBUFSIZE);
 
239
                    *Strchr(Change, '\n') = '\0';
 
240
                    CorrChar = LastChar;        /* Save the corrected end */
 
241
                    LastChar = InputBuf;        /* Null the current line */
 
242
                    SoundBeep();
 
243
                    printprompt(2, short2str(Change));
 
244
                    Refresh();
 
245
                    if (read(SHIN, (char *) &tch, 1) < 0)
 
246
#ifdef convex
 
247
                        /*
 
248
                         * need to print error message in case file
 
249
                         * is migrated
 
250
                         */
 
251
                        if (errno && errno != EINTR)
 
252
                            stderror(ERR_SYSTEM, progname, strerror(errno));
 
253
#else
 
254
                        break;
 
255
#endif
 
256
                    ch = tch;
 
257
                    if (ch == 'y' || ch == ' ') {
 
258
                        LastChar = CorrChar;    /* Restore the corrected end */
 
259
                        xprintf(CGETS(6, 2, "yes\n"));
 
260
                    }
 
261
                    else {
 
262
                        copyn(InputBuf, Origin, INBUFSIZE);
 
263
                        LastChar = SaveChar;
 
264
                        if (ch == 'e') {
 
265
                            xprintf(CGETS(6, 3, "edit\n"));
 
266
                            *LastChar-- = '\0';
 
267
                            Cursor = LastChar;
 
268
                            printprompt(3, NULL);
 
269
                            ClearLines();
 
270
                            ClearDisp();
 
271
                            Refresh();
 
272
                            break;
 
273
                        }
 
274
                        else if (ch == 'a') {
 
275
                            xprintf(CGETS(6, 4, "abort\n"));
 
276
                            LastChar = InputBuf;   /* Null the current line */
 
277
                            Cursor = LastChar;
 
278
                            printprompt(0, NULL);
 
279
                            Refresh();
 
280
                            break;
 
281
                        }
 
282
                        xprintf(CGETS(6, 5, "no\n"));
 
283
                    }
 
284
                    flush();
 
285
                }
 
286
            } else if (crct && !Strcmp(*(crct->vec), STRcomplete)) {
 
287
                if (LastChar > InputBuf && LastChar[-1] == '\n') {
 
288
                    LastChar[-1] = '\0';
 
289
                    LastChar--;
 
290
                    Cursor = LastChar;
 
291
                }
 
292
                match_unique_match = 1;  /* match unique matches */
 
293
                matchval = CompleteLine();
 
294
                match_unique_match = 0;
 
295
                curlen = (int) (LastChar - InputBuf);
 
296
                if (matchval != 1) {
 
297
                    PastBottom();
 
298
                }
 
299
                if (matchval == 0) {
 
300
                    xprintf(CGETS(6, 6, "No matching command\n"));
 
301
                } else if (matchval == 2) {
 
302
                    xprintf(CGETS(6, 7, "Ambiguous command\n"));
 
303
                }
 
304
                if (NeedsRedraw) {
 
305
                    ClearLines();
 
306
                    ClearDisp();
 
307
                    NeedsRedraw = 0;
 
308
                }
 
309
                Refresh();
 
310
                Argument = 1;
 
311
                DoingArg = 0;
 
312
                if (matchval == 1) {
 
313
                    PastBottom();
 
314
                    *LastChar++ = '\n';
 
315
                    *LastChar = '\0';
 
316
                }
 
317
                curlen = (int) (LastChar - InputBuf);
 
318
            }
 
319
            else
 
320
                PastBottom();
 
321
 
 
322
            if (matchval == 1) {
 
323
                tellwhat = 0;   /* just in case */
 
324
                Hist_num = 0;   /* for the history commands */
 
325
                /* return the number of chars read */
 
326
                num = (int) (LastChar - InputBuf);
 
327
                /*
 
328
                 * For continuation lines, we set the prompt to prompt 2
 
329
                 */
 
330
                printprompt(1, NULL);
 
331
            }
 
332
            break;
 
333
 
 
334
        case CC_CORRECT:
 
335
            if (tenematch(InputBuf, Cursor - InputBuf, SPELL) < 0)
 
336
                SoundBeep();            /* Beep = No match/ambiguous */
 
337
            curlen = Repair();
 
338
            break;
 
339
 
 
340
        case CC_CORRECT_L:
 
341
            if (SpellLine(FALSE) < 0)
 
342
                SoundBeep();            /* Beep = No match/ambiguous */
 
343
            curlen = Repair();
 
344
            break;
 
345
 
 
346
 
 
347
        case CC_COMPLETE:
 
348
        case CC_COMPLETE_ALL:
 
349
        case CC_COMPLETE_FWD:
 
350
        case CC_COMPLETE_BACK:
 
351
            switch (retval) {
 
352
            case CC_COMPLETE:
 
353
                fn = RECOGNIZE;
 
354
                curlen = (int) (LastChar - InputBuf);
 
355
                curchoice = -1;
 
356
                rotate = 0;
 
357
                break;
 
358
            case CC_COMPLETE_ALL:
 
359
                fn = RECOGNIZE_ALL;
 
360
                curlen = (int) (LastChar - InputBuf);
 
361
                curchoice = -1;
 
362
                rotate = 0;
 
363
                break;
 
364
            case CC_COMPLETE_FWD:
 
365
                fn = RECOGNIZE_SCROLL;
 
366
                curchoice++;
 
367
                rotate = 1;
 
368
                break;
 
369
            case CC_COMPLETE_BACK:
 
370
                fn = RECOGNIZE_SCROLL;
 
371
                curchoice--;
 
372
                rotate = 1;
 
373
                break;
 
374
            default:
 
375
                abort();
 
376
            }
 
377
            if (InputBuf[curlen] && rotate) {
 
378
                newlen = (int) (LastChar - InputBuf);
 
379
                for (idx = (int) (Cursor - InputBuf); 
 
380
                     idx <= newlen; idx++)
 
381
                        InputBuf[idx - newlen + curlen] =
 
382
                        InputBuf[idx];
 
383
                LastChar = InputBuf + curlen;
 
384
                Cursor = Cursor - newlen + curlen;
 
385
            }
 
386
            curlen = (int) (LastChar - InputBuf);
 
387
 
 
388
 
 
389
            if (adrof(STRautoexpand))
 
390
                (void) e_expand_history(0);
 
391
            /*
 
392
             * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
 
393
             * A separate variable now controls beeping after
 
394
             * completion, independently of autolisting.
 
395
             */
 
396
            expnum = (int) (Cursor - InputBuf);
 
397
            switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){
 
398
            case 1:
 
399
                if (non_unique_match && matchbeep &&
 
400
                    (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
 
401
                    SoundBeep();
 
402
                break;
 
403
            case 0:
 
404
                if (matchbeep) {
 
405
                    if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
 
406
                        Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
 
407
                        Strcmp(*(matchbeep->vec), STRnotunique) == 0)
 
408
                        SoundBeep();
 
409
                }
 
410
                else
 
411
                    SoundBeep();
 
412
                break;
 
413
            default:
 
414
                if (matchval < 0) {     /* Error from tenematch */
 
415
                    curchoice = -1;
 
416
                    SoundBeep();
 
417
                    break;
 
418
                }
 
419
                if (matchbeep) {
 
420
                    if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
 
421
                         Strcmp(*(matchbeep->vec), STRnotunique) == 0))
 
422
                        SoundBeep();
 
423
                }
 
424
                else
 
425
                    SoundBeep();
 
426
                /*
 
427
                 * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an 
 
428
                 * attempted completion is ambiguous, list the choices.  
 
429
                 * (PWP: this is the best feature addition to tcsh I have 
 
430
                 * seen in many months.)
 
431
                 */
 
432
                if (autol && (Strcmp(*(autol->vec), STRambiguous) != 0 || 
 
433
                                     expnum == Cursor - InputBuf)) {
 
434
                    PastBottom();
 
435
                    fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
 
436
                    (void) tenematch(InputBuf, Cursor-InputBuf, fn);
 
437
                }
 
438
                break;
 
439
            }
 
440
            if (NeedsRedraw) {
 
441
                PastBottom();
 
442
                ClearLines();
 
443
                ClearDisp();
 
444
                NeedsRedraw = 0;
 
445
            }
 
446
            Refresh();
 
447
            Argument = 1;
 
448
            DoingArg = 0;
 
449
            break;
 
450
 
 
451
        case CC_LIST_CHOICES:
 
452
        case CC_LIST_ALL:
 
453
            if (InputBuf[curlen] && rotate) {
 
454
                newlen = (int) (LastChar - InputBuf);
 
455
                for (idx = (int) (Cursor - InputBuf); 
 
456
                     idx <= newlen; idx++)
 
457
                        InputBuf[idx - newlen + curlen] =
 
458
                        InputBuf[idx];
 
459
                LastChar = InputBuf + curlen;
 
460
                Cursor = Cursor - newlen + curlen;
 
461
            }
 
462
            curlen = (int) (LastChar - InputBuf);
 
463
            if (curchoice >= 0)
 
464
                curchoice--;
 
465
 
 
466
            fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST;
 
467
            /* should catch ^C here... */
 
468
            if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0)
 
469
                SoundBeep();
 
470
            Refresh();
 
471
            Argument = 1;
 
472
            DoingArg = 0;
 
473
            break;
 
474
 
 
475
 
 
476
        case CC_LIST_GLOB:
 
477
            if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0)
 
478
                SoundBeep();
 
479
            curlen = Repair();
 
480
            break;
 
481
 
 
482
        case CC_EXPAND_GLOB:
 
483
            if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0)
 
484
                SoundBeep();            /* Beep = No match */
 
485
            curlen = Repair();
 
486
            break;
 
487
 
 
488
        case CC_NORMALIZE_PATH:
 
489
            if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0)
 
490
                SoundBeep();            /* Beep = No match */
 
491
            curlen = Repair();
 
492
            break;
 
493
 
 
494
        case CC_EXPAND_VARS:
 
495
            if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0)
 
496
                SoundBeep();            /* Beep = No match */
 
497
            curlen = Repair();
 
498
            break;
 
499
 
 
500
        case CC_NORMALIZE_COMMAND:
 
501
            if (tenematch(InputBuf, Cursor - InputBuf, COMMAND_NORMALIZE) <= 0)
 
502
                SoundBeep();            /* Beep = No match */
 
503
            curlen = Repair();
 
504
            break;
 
505
 
 
506
        case CC_HELPME:
 
507
            xputchar('\n');
 
508
            /* should catch ^C here... */
 
509
            (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP);
 
510
            Refresh();
 
511
            Argument = 1;
 
512
            DoingArg = 0;
 
513
            curchoice = -1;
 
514
            curlen = (int) (LastChar - InputBuf);
 
515
            break;
 
516
 
 
517
        case CC_FATAL:          /* fatal error, reset to known state */
 
518
#ifdef DEBUG_EDIT
 
519
            xprintf(CGETS(7, 8, "*** editor fatal ERROR ***\r\n\n"));
 
520
#endif                          /* DEBUG_EDIT */
 
521
            /* put (real) cursor in a known place */
 
522
            ClearDisp();        /* reset the display stuff */
 
523
            ResetInLine(1);     /* reset the input pointers */
 
524
            Refresh();          /* print the prompt again */
 
525
            Argument = 1;
 
526
            DoingArg = 0;
 
527
            curchoice = -1;
 
528
            curlen = (int) (LastChar - InputBuf);
 
529
            break;
 
530
 
 
531
        case CC_ERROR:
 
532
        default:                /* functions we don't know about */
 
533
            DoingArg = 0;
 
534
            Argument = 1;
 
535
            SoundBeep();
 
536
            flush();
 
537
            curchoice = -1;
 
538
            curlen = (int) (LastChar - InputBuf);
 
539
            break;
 
540
        }
 
541
    }
 
542
    (void) Cookedmode();        /* make sure the tty is set up correctly */
 
543
    GettingInput = 0;
 
544
    flush();                    /* flush any buffered output */
 
545
    return num;
 
546
}
 
547
 
 
548
void
 
549
PushMacro(str)
 
550
    Char   *str;
 
551
{
 
552
    if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
 
553
        MacroLvl++;
 
554
        KeyMacro[MacroLvl] = str;
 
555
    }
 
556
    else {
 
557
        SoundBeep();
 
558
        flush();
 
559
    }
 
560
}
 
561
 
 
562
/*
 
563
 * Like eval, only using the current file descriptors
 
564
 */
 
565
static Char **gv = NULL, **gav = NULL;
 
566
 
 
567
static void
 
568
doeval1(v)
 
569
    Char **v;
 
570
{
 
571
    Char  **oevalvec;
 
572
    Char   *oevalp;
 
573
    int     my_reenter;
 
574
    Char  **savegv;
 
575
    jmp_buf_t osetexit;
 
576
 
 
577
    oevalvec = evalvec;
 
578
    oevalp = evalp;
 
579
    savegv = gv;
 
580
    gav = v;
 
581
 
 
582
 
 
583
    gflag = 0, tglob(gav);
 
584
    if (gflag) {
 
585
        gv = gav = globall(gav);
 
586
        gargv = 0;
 
587
        if (gav == 0)
 
588
            stderror(ERR_NOMATCH);
 
589
        gav = copyblk(gav);
 
590
    }
 
591
    else {
 
592
        gv = NULL;
 
593
        gav = copyblk(gav);
 
594
        trim(gav);
 
595
    }
 
596
 
 
597
    getexit(osetexit);
 
598
 
 
599
    /* PWP: setjmp/longjmp bugfix for optimizing compilers */
 
600
#ifdef cray
 
601
    my_reenter = 1;             /* assume non-zero return val */
 
602
    if (setexit() == 0) {
 
603
        my_reenter = 0;         /* Oh well, we were wrong */
 
604
#else /* !cray */
 
605
    if ((my_reenter = setexit()) == 0) {
 
606
#endif /* cray */
 
607
        evalvec = gav;
 
608
        evalp = 0;
 
609
        process(0);
 
610
    }
 
611
 
 
612
    evalvec = oevalvec;
 
613
    evalp = oevalp;
 
614
    doneinp = 0;
 
615
 
 
616
    if (gv)
 
617
        blkfree(gv);
 
618
 
 
619
    gv = savegv;
 
620
    resexit(osetexit);
 
621
    if (my_reenter)
 
622
        stderror(ERR_SILENT);
 
623
}
 
624
 
 
625
static void
 
626
RunCommand(str)
 
627
    Char *str;
 
628
{
 
629
    Char *cmd[2];
 
630
 
 
631
    xputchar('\n');     /* Start on a clean line */
 
632
 
 
633
    cmd[0] = str;
 
634
    cmd[1] = NULL;
 
635
 
 
636
    (void) Cookedmode();
 
637
    GettingInput = 0;
 
638
 
 
639
    doeval1(cmd);
 
640
    
 
641
    (void) Rawmode();
 
642
    GettingInput = 1;
 
643
 
 
644
    ClearLines();
 
645
    ClearDisp();
 
646
    NeedsRedraw = 0;
 
647
    Refresh();
 
648
}
 
649
 
 
650
static int
 
651
GetNextCommand(cmdnum, ch)
 
652
    KEYCMD *cmdnum;
 
653
    register Char *ch;
 
654
{
 
655
    KEYCMD  cmd = 0;
 
656
    int     num;
 
657
 
 
658
    while (cmd == 0 || cmd == F_XKEY) {
 
659
        if ((num = GetNextChar(ch)) != 1) {     /* if EOF or error */
 
660
            return num;
 
661
        }
 
662
#ifdef  KANJI
 
663
        if (!adrof(STRnokanji) && (*ch & META)) {
 
664
            MetaNext = 0;
 
665
            cmd = F_INSERT;
 
666
            break;
 
667
        }
 
668
        else
 
669
#endif /* KANJI */
 
670
        if (MetaNext) {
 
671
            MetaNext = 0;
 
672
            *ch |= META;
 
673
        }
 
674
        /* XXX: This needs to be fixed so that we don't just truncate
 
675
         * the character, we unquote it.
 
676
         */
 
677
        if (*ch < NT_NUM_KEYS)
 
678
            cmd = CurrentKeyMap[*ch];
 
679
        else
 
680
            cmd = CurrentKeyMap[(unsigned char) *ch];
 
681
        if (cmd == F_XKEY) {
 
682
            XmapVal val;
 
683
            CStr cstr;
 
684
            cstr.buf = ch;
 
685
            cstr.len = Strlen(ch);
 
686
            switch (GetXkey(&cstr, &val)) {
 
687
            case XK_CMD:
 
688
                cmd = val.cmd;
 
689
                break;
 
690
            case XK_STR:
 
691
                PushMacro(val.str.buf);
 
692
                break;
 
693
            case XK_EXE:
 
694
                RunCommand(val.str.buf);
 
695
                break;
 
696
            default:
 
697
                abort();
 
698
                break;
 
699
            }
 
700
        }
 
701
        if (!AltKeyMap) 
 
702
            CurrentKeyMap = CcKeyMap;
 
703
    }
 
704
    *cmdnum = cmd;
 
705
    return OKCMD;
 
706
}
 
707
 
 
708
int
 
709
GetNextChar(cp)
 
710
    register Char *cp;
 
711
{
 
712
    register int num_read;
 
713
    int     tried = 0;
 
714
    unsigned char tcp;
 
715
 
 
716
    for (;;) {
 
717
        if (MacroLvl < 0) {
 
718
            if (!Load_input_line())
 
719
                break;
 
720
        }
 
721
        if (*KeyMacro[MacroLvl] == 0) {
 
722
            MacroLvl--;
 
723
            continue;
 
724
        }
 
725
        *cp = *KeyMacro[MacroLvl]++ & CHAR;
 
726
        if (*KeyMacro[MacroLvl] == 0) { /* Needed for QuoteMode On */
 
727
            MacroLvl--;
 
728
        }
 
729
        return (1);
 
730
    }
 
731
 
 
732
    if (Rawmode() < 0)          /* make sure the tty is set up correctly */
 
733
        return 0;               /* oops: SHIN was closed */
 
734
 
 
735
#ifdef WINNT
 
736
    __nt_want_vcode = 1;
 
737
#endif /* WINNT */
 
738
    while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1) {
 
739
        if (errno == EINTR)
 
740
            continue;
 
741
        if (!tried && fixio(SHIN, errno) != -1)
 
742
            tried = 1;
 
743
        else {
 
744
#ifdef convex
 
745
            /* need to print error message in case the file is migrated */
 
746
            if (errno != EINTR)
 
747
                stderror(ERR_SYSTEM, progname, strerror(errno));
 
748
#endif  /* convex */
 
749
#ifdef WINNT
 
750
            __nt_want_vcode = 0;
 
751
#endif /* WINNT */
 
752
            *cp = '\0';
 
753
            return -1;
 
754
        }
 
755
    }
 
756
#ifdef WINNT
 
757
    if (__nt_want_vcode == 2)
 
758
        *cp = __nt_vcode;
 
759
    else
 
760
        *cp = tcp;
 
761
    __nt_want_vcode = 0;
 
762
#else
 
763
    *cp = tcp;
 
764
#endif /* WINNT */
 
765
    return num_read;
 
766
}
 
767
 
 
768
/*
 
769
 * SpellLine - do spelling correction on the entire command line
 
770
 * (which may have trailing newline).
 
771
 * If cmdonly is set, only check spelling of command words.
 
772
 * Return value:
 
773
 * -1: Something was incorrectible, and nothing was corrected
 
774
 *  0: Everything was correct
 
775
 *  1: Something was corrected
 
776
 */
 
777
static int
 
778
SpellLine(cmdonly)
 
779
    int     cmdonly;
 
780
{
 
781
    int     endflag, matchval;
 
782
    Char   *argptr, *OldCursor, *OldLastChar;
 
783
 
 
784
    OldLastChar = LastChar;
 
785
    OldCursor = Cursor;
 
786
    argptr = InputBuf;
 
787
    endflag = 1;
 
788
    matchval = 0;
 
789
    do {
 
790
        while (ismetahash(*argptr) || iscmdmeta(*argptr))
 
791
            argptr++;
 
792
        for (Cursor = argptr;
 
793
             *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
 
794
                                 (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
 
795
             Cursor++)
 
796
             continue;
 
797
        if (*Cursor == '\0') {
 
798
            Cursor = LastChar;
 
799
            if (LastChar[-1] == '\n')
 
800
                Cursor--;
 
801
            endflag = 0;
 
802
        }
 
803
        /* Obey current history character settings */
 
804
        mismatch[0] = HIST;
 
805
        mismatch[1] = HISTSUB;
 
806
        if (!Strchr(mismatch, *argptr) &&
 
807
            (!cmdonly || starting_a_command(argptr, InputBuf))) {
 
808
#ifdef WINNT
 
809
            /*
 
810
             * This hack avoids correcting drive letter changes
 
811
             */
 
812
            if((Cursor - InputBuf) != 2 || (char)InputBuf[1] != ':')
 
813
#endif /* WINNT */
 
814
            {
 
815
#ifdef HASH_SPELL_CHECK
 
816
                Char save;
 
817
                size_t len = Cursor - InputBuf;
 
818
 
 
819
                save = InputBuf[len];
 
820
                InputBuf[len] = '\0';
 
821
                if (find_cmd(InputBuf, 0) != 0) {
 
822
                    InputBuf[len] = save;
 
823
                    argptr = Cursor;
 
824
                    continue;
 
825
                }
 
826
                InputBuf[len] = save;
 
827
#endif /* HASH_SPELL_CHECK */
 
828
                switch (tenematch(InputBuf, Cursor - InputBuf, SPELL)) {
 
829
                case 1:         /* corrected */
 
830
                    matchval = 1;
 
831
                    break;
 
832
                case -1:                /* couldn't be corrected */
 
833
                    if (!matchval)
 
834
                        matchval = -1;
 
835
                    break;
 
836
                default:                /* was correct */
 
837
                    break;
 
838
                }
 
839
            }
 
840
            if (LastChar != OldLastChar) {
 
841
                if (argptr < OldCursor)
 
842
                    OldCursor += (LastChar - OldLastChar);
 
843
                OldLastChar = LastChar;
 
844
            }
 
845
        }
 
846
        argptr = Cursor;
 
847
    } while (endflag);
 
848
    Cursor = OldCursor;
 
849
    return matchval;
 
850
}
 
851
 
 
852
/*
 
853
 * CompleteLine - do command completion on the entire command line
 
854
 * (which may have trailing newline).
 
855
 * Return value:
 
856
 *  0: No command matched or failure
 
857
 *  1: One command matched
 
858
 *  2: Several commands matched
 
859
 */
 
860
static int
 
861
CompleteLine()
 
862
{
 
863
    int     endflag, tmatch;
 
864
    Char   *argptr, *OldCursor, *OldLastChar;
 
865
 
 
866
    OldLastChar = LastChar;
 
867
    OldCursor = Cursor;
 
868
    argptr = InputBuf;
 
869
    endflag = 1;
 
870
    do {
 
871
        while (ismetahash(*argptr) || iscmdmeta(*argptr))
 
872
            argptr++;
 
873
        for (Cursor = argptr;
 
874
             *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
 
875
                                 (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
 
876
             Cursor++)
 
877
             continue;
 
878
        if (*Cursor == '\0') {
 
879
            Cursor = LastChar;
 
880
            if (LastChar[-1] == '\n')
 
881
                Cursor--;
 
882
            endflag = 0;
 
883
        }
 
884
        if (!Strchr(mismatch, *argptr) && starting_a_command(argptr, InputBuf)) {
 
885
            tmatch = tenematch(InputBuf, Cursor - InputBuf, RECOGNIZE);
 
886
            if (tmatch <= 0) {
 
887
                return 0;
 
888
            } else if (tmatch > 1) {
 
889
                return 2;
 
890
            }
 
891
            if (LastChar != OldLastChar) {
 
892
                if (argptr < OldCursor)
 
893
                    OldCursor += (LastChar - OldLastChar);
 
894
                OldLastChar = LastChar;
 
895
            }
 
896
        }
 
897
        argptr = Cursor;
 
898
    } while (endflag);
 
899
    Cursor = OldCursor;
 
900
    return 1;
 
901
}
 
902