vcmd.c

Go to the documentation of this file.
00001 /* vcmd.c */
00002 
00003 /* Author:
00004  *      Steve Kirkendall
00005  *      14407 SW Teal Blvd. #C
00006  *      Beaverton, OR 97005
00007  *      kirkenda@cs.pdx.edu
00008  */
00009 
00010 
00011 /* This file contains the functions that handle VI commands */
00012 
00013 
00014 #include "config.h"
00015 #include "ctype.h"
00016 #include "vi.h"
00017 #if MSDOS
00018 # include <process.h>
00019 # include <string.h>
00020 #endif
00021 #if TOS
00022 # include <osbind.h>
00023 # include <string.h>
00024 #endif
00025 #if OSK
00026 # include <stdio.h>
00027 #endif
00028 
00029 
00030 /* This function puts the editor in EX mode */
00031 MARK v_quit()
00032 {
00033         move(LINES - 1, 0);
00034         mode = MODE_EX;
00035         return cursor;
00036 }
00037 
00038 /* This function causes the screen to be redrawn */
00039 MARK v_redraw()
00040 {
00041         redraw(MARK_UNSET, FALSE);
00042         return cursor;
00043 }
00044 
00045 /* This function executes a string of EX commands, and waits for a user keystroke
00046  * before returning to the VI screen.  If that keystroke is another ':', then
00047  * another EX command is read and executed.
00048  */
00049 /*ARGSUSED*/
00050 MARK v_1ex(m, text)
00051         MARK    m;      /* the current line */
00052         char    *text;  /* the first command to execute */
00053 {
00054         /* run the command.  be careful about modes & output */
00055         exwrote = (mode == MODE_COLON);
00056         doexcmd(text);
00057         exrefresh();
00058 
00059         /* if mode is no longer MODE_VI, then we should quit right away! */
00060         if (mode != MODE_VI && mode != MODE_COLON)
00061                 return cursor;
00062 
00063         /* The command did some output.  Wait for a keystoke. */
00064         if (exwrote)
00065         {
00066                 mode = MODE_VI; 
00067                 msg("[Hit <RETURN> to continue]");
00068                 if (getkey(0) == ':')
00069                 {       mode = MODE_COLON;
00070                         addch('\n');
00071                 }
00072                 else
00073                         redraw(MARK_UNSET, FALSE);
00074         }
00075 
00076         return cursor;
00077 }
00078 
00079 /* This function undoes the last change */
00080 /*ARGSUSED*/
00081 MARK v_undo(m)
00082         MARK    m;      /* (ignored) */
00083 {
00084         if (undo())
00085         {
00086                 redraw(MARK_UNSET, FALSE);
00087         }
00088         return cursor;
00089 }
00090 
00091 /* This function deletes the character(s) that the cursor is on */
00092 MARK v_xchar(m, cnt, cmd)
00093         MARK    m;      /* where to start deletions */
00094         long    cnt;    /* number of chars to delete */
00095         int     cmd;    /* either 'x' or 'X' */
00096 {
00097         DEFAULT(1);
00098 
00099         /* for 'X', adjust so chars are deleted *BEFORE* cursor */
00100         if (cmd == 'X')
00101         {
00102                 if (markidx(m) < cnt)
00103                         return MARK_UNSET;
00104                 m -= cnt;
00105         }
00106 
00107         /* make sure we don't try to delete more thars than there are */
00108         pfetch(markline(m));
00109         if (markidx(m + cnt) > plen)
00110         {
00111                 cnt = plen - markidx(m);
00112         }
00113         if (cnt == 0L)
00114         {
00115                 return MARK_UNSET;
00116         }
00117 
00118         /* do it */
00119         ChangeText
00120         {
00121                 cut(m, m + cnt);
00122                 delete(m, m + cnt);
00123         }
00124         return m;
00125 }
00126 
00127 /* This function defines a mark */
00128 /*ARGSUSED*/
00129 MARK v_mark(m, count, key)
00130         MARK    m;      /* where the mark will be */
00131         long    count;  /* (ignored) */
00132         int     key;    /* the ASCII label of the mark */
00133 {
00134         if (key < 'a' || key > 'z')
00135         {
00136                 msg("Marks must be from a to z");
00137         }
00138         else
00139         {
00140                 mark[key - 'a'] = m;
00141         }
00142         return m;
00143 }
00144 
00145 /* This function toggles upper & lower case letters */
00146 MARK v_ulcase(m, cnt)
00147         MARK    m;      /* where to make the change */
00148         long    cnt;    /* number of chars to flip */
00149 {
00150         REG char        *pos;
00151         REG int         j;
00152 
00153         DEFAULT(1);
00154 
00155         /* fetch the current version of the line */
00156         pfetch(markline(m));
00157 
00158         /* for each position in the line */
00159         for (j = 0, pos = &ptext[markidx(m)]; j < cnt && *pos; j++, pos++)
00160         {
00161                 if (isupper(*pos))
00162                 {
00163                         tmpblk.c[j] = tolower(*pos);
00164                 }
00165                 else
00166                 {
00167                         tmpblk.c[j] = toupper(*pos);
00168                 }
00169         }
00170 
00171         /* if the new text is different from the old, then change it */
00172         if (strncmp(tmpblk.c, &ptext[markidx(m)], j))
00173         {
00174                 ChangeText
00175                 {
00176                         tmpblk.c[j] = '\0';
00177                         change(m, m + j, tmpblk.c);
00178                 }
00179         }
00180 
00181         return m + j;
00182 }
00183 
00184 
00185 MARK v_replace(m, cnt, key)
00186         MARK    m;      /* first char to be replaced */
00187         long    cnt;    /* number of chars to replace */
00188         int     key;    /* what to replace them with */
00189 {
00190         REG char        *text;
00191         REG int         i;
00192 
00193         DEFAULT(1);
00194 
00195         /* map ^M to '\n' */
00196         if (key == '\r')
00197         {
00198                 key = '\n';
00199         }
00200 
00201         /* make sure the resulting line isn't too long */
00202         if (cnt > BLKSIZE - 2 - markidx(m))
00203         {
00204                 cnt = BLKSIZE - 2 - markidx(m);
00205         }
00206 
00207         /* build a string of the desired character with the desired length */
00208         for (text = tmpblk.c, i = cnt; i > 0; i--)
00209         {
00210                 *text++ = key;
00211         }
00212         *text = '\0';
00213 
00214         /* make sure cnt doesn't extend past EOL */
00215         pfetch(markline(m));
00216         key = markidx(m);
00217         if (key + cnt > plen)
00218         {
00219                 cnt = plen - key;
00220         }
00221 
00222         /* do the replacement */
00223         ChangeText
00224         {
00225                 change(m, m + cnt, tmpblk.c);
00226         }
00227 
00228         if (*tmpblk.c == '\n')
00229         {
00230                 return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
00231         }
00232         else
00233         {
00234                 return m + cnt - 1;
00235         }
00236 }
00237 
00238 MARK v_overtype(m)
00239         MARK            m;      /* where to start overtyping */
00240 {
00241         MARK            end;    /* end of a substitution */
00242         static long     width;  /* width of a single-line replace */
00243 
00244         /* the "doingdot" version of replace is really a substitution */
00245         if (doingdot)
00246         {
00247                 /* was the last one really repeatable? */
00248                 if (width < 0)
00249                 {
00250                         msg("Can't repeat a multi-line overtype command");
00251                         return MARK_UNSET;
00252                 }
00253 
00254                 /* replacing nothing by nothing?  Don't bother */
00255                 if (width == 0)
00256                 {
00257                         return m;
00258                 }
00259 
00260                 /* replace some chars by repeated text */
00261                 return v_subst(m, width);
00262         }
00263 
00264         /* Normally, we input starting here, in replace mode */
00265         ChangeText
00266         {
00267                 end = input(m, m, WHEN_VIREP, FALSE);
00268         }
00269 
00270         /* if we ended on the same line we started on, then this
00271          * overtype is repeatable via the dot key.
00272          */
00273         if (markline(end) == markline(m) && end >= m - 1L)
00274         {
00275                 width = end - m + 1L;
00276         }
00277         else /* it isn't repeatable */
00278         {
00279                 width = -1L;
00280         }
00281 
00282         return end;
00283 }
00284 
00285 
00286 /* This function selects which cut buffer to use */
00287 /*ARGSUSED*/
00288 MARK v_selcut(m, cnt, key)
00289         MARK    m;
00290         long    cnt;
00291         int     key;
00292 {
00293         cutname(key);
00294         return m;
00295 }
00296 
00297 /* This function pastes text from a cut buffer */
00298 /*ARGSUSED*/
00299 MARK v_paste(m, cnt, cmd)
00300         MARK    m;      /* where to paste the text */
00301         long    cnt;    /* (ignored) */
00302         int     cmd;    /* either 'p' or 'P' */
00303 {
00304         MARK    dest;
00305 
00306         ChangeText
00307         {
00308                 /* paste the text, and find out where it ends */
00309                 dest = paste(m, cmd == 'p', TRUE);
00310 
00311                 /* was that a line-mode paste? */
00312                 if (dest && markline(dest) != markline(m))
00313                 {
00314                         /* line-mode pastes leave the cursor at the front
00315                          * of the first pasted line.
00316                          */
00317                         dest = m;
00318                         if (cmd == 'p')
00319                         {
00320                                 dest += BLKSIZE;
00321                         }
00322                         force_flags |= FRNT;
00323                 }
00324         }
00325         return dest;
00326 }
00327 
00328 /* This function yanks text into a cut buffer */
00329 MARK v_yank(m, n)
00330         MARK    m, n;   /* range of text to yank */
00331 {
00332         cut(m, n);
00333         return m;
00334 }
00335 
00336 /* This function deletes a range of text */
00337 MARK v_delete(m, n)
00338         MARK    m, n;   /* range of text to delete */
00339 {
00340         /* illegal to try and delete nothing */
00341         if (n <= m)
00342         {
00343                 return MARK_UNSET;
00344         }
00345 
00346         /* Do it */
00347         ChangeText
00348         {
00349                 cut(m, n);
00350                 delete(m, n);
00351         }
00352         return m;
00353 }
00354 
00355 
00356 /* This starts input mode without deleting anything */
00357 MARK v_insert(m, cnt, key)
00358         MARK    m;      /* where to start (sort of) */
00359         long    cnt;    /* repeat how many times? */
00360         int     key;    /* what command is this for? {a,A,i,I,o,O} */
00361 {
00362         int     wasdot;
00363         long    reps;
00364         int     above;  /* boolean: new line going above old line? */
00365 
00366         DEFAULT(1);
00367 
00368         ChangeText
00369         {
00370                 /* tweak the insertion point, based on command key */
00371                 above = FALSE;
00372                 switch (key)
00373                 {
00374                   case 'i':
00375                         break;
00376 
00377                   case 'a':
00378                         pfetch(markline(m));
00379                         if (plen > 0)
00380                         {
00381                                 m++;
00382                         }
00383                         break;
00384 
00385                   case 'I':
00386                         m = m_front(m, 1L);
00387                         break;
00388 
00389                   case 'A':
00390                         pfetch(markline(m));
00391                         m = (m & ~(BLKSIZE - 1)) + plen;
00392                         break;
00393 
00394                   case 'O':
00395                         m &= ~(BLKSIZE - 1);
00396                         add(m, "\n");
00397                         above = TRUE;
00398                         break;
00399 
00400                   case 'o':
00401                         m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
00402                         add(m, "\n");
00403                         break;
00404                 }
00405 
00406                 /* insert the same text once or more */
00407                 for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
00408                 {
00409                         m = input(m, m, WHEN_VIINP, above) + 1;
00410                 }
00411                 if (markidx(m) > 0)
00412                 {
00413                         m--;
00414                 }
00415 
00416                 doingdot = wasdot;
00417         }
00418 
00419 #ifndef CRUNCH
00420 # ifndef NO_EXTENSIONS
00421         if (key == 'i' && *o_inputmode && mode == MODE_VI)
00422         {
00423                 msg("Now in command mode!  To return to input mode, hit <i>");
00424         }
00425 # endif
00426 #endif
00427 
00428         return m;
00429 }
00430 
00431 /* This starts input mode with some text deleted */
00432 MARK v_change(m, n)
00433         MARK    m, n;   /* the range of text to change */
00434 {
00435         int     lnmode; /* is this a line-mode change? */
00436 
00437         /* swap them if they're in reverse order */
00438         if (m > n)
00439         {
00440                 MARK    tmp;
00441                 tmp = m;
00442                 m = n;
00443                 n = tmp;
00444         }
00445 
00446         /* for line mode, retain the last newline char */
00447         lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
00448         if (lnmode)
00449         {
00450                 n -= BLKSIZE;
00451                 pfetch(markline(n));
00452                 n = (n & ~(BLKSIZE - 1)) + plen;
00453         }
00454 
00455         ChangeText
00456         {
00457                 cut(m, n);
00458                 m = input(m, n, WHEN_VIINP, FALSE);
00459         }
00460 
00461         return m;
00462 }
00463 
00464 /* This function replaces a given number of characters with input */
00465 MARK v_subst(m, cnt)
00466         MARK    m;      /* where substitutions start */
00467         long    cnt;    /* number of chars to replace */
00468 {
00469         DEFAULT(1);
00470 
00471         /* make sure we don't try replacing past EOL */
00472         pfetch(markline(m));
00473         if (markidx(m) + cnt > plen)
00474         {
00475                 cnt = plen - markidx(m);
00476         }
00477 
00478         /* Go for it! */
00479         ChangeText
00480         {
00481                 cut(m, m + cnt);
00482                 m = input(m, m + cnt, WHEN_VIINP, FALSE);
00483         }
00484         return m;
00485 }
00486 
00487 /* This calls the ex "join" command to join some lines together */
00488 MARK v_join(m, cnt)
00489         MARK    m;      /* the first line to be joined */
00490         long    cnt;    /* number of other lines to join */
00491 {
00492         MARK    joint;  /* where the lines were joined */
00493 
00494         DEFAULT(1);
00495 
00496         /* figure out where the joint will be */
00497         pfetch(markline(m));
00498         joint = (m & ~(BLKSIZE - 1)) + plen;
00499 
00500         /* join the lines */
00501         cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
00502 
00503         /* the cursor should be left at the joint */
00504         return joint;
00505 }
00506 
00507 
00508 /* This calls the ex "<" command to shift some lines left */
00509 MARK v_lshift(m, n)
00510         MARK    m, n;   /* range of lines to shift */
00511 {
00512         /* adjust for inclusive endmarks in ex */
00513         n -= BLKSIZE;
00514 
00515         cmd_shift(m, n, CMD_SHIFTL, FALSE, (char *)0);
00516 
00517         return m;
00518 }
00519 
00520 /* This calls the ex ">" command to shift some lines right */
00521 MARK v_rshift(m, n)
00522         MARK    m, n;   /* range of lines to shift */
00523 {
00524         /* adjust for inclusive endmarks in ex */
00525         n -= BLKSIZE;
00526 
00527         cmd_shift(m, n, CMD_SHIFTR, FALSE, (char *)0);
00528 
00529         return m;
00530 }
00531 
00532 /* This filters some lines through a preset program, to reformat them */
00533 MARK v_reformat(m, n)
00534         MARK    m, n;   /* range of lines to shift */
00535 {
00536         /* adjust for inclusive endmarks in ex */
00537         n -= BLKSIZE;
00538 
00539         /* run the filter command */
00540         filter(m, n, o_equalprg, TRUE);
00541 
00542         redraw(MARK_UNSET, FALSE);
00543         return m;
00544 }
00545 
00546 
00547 /* This runs some lines through a filter program */
00548 MARK v_filter(m, n)
00549         MARK    m, n;   /* range of lines to shift */
00550 {
00551         char    cmdln[150];     /* a shell command line */
00552 
00553         /* adjust for inclusive endmarks in ex */
00554         n -= BLKSIZE;
00555 
00556         if (vgets('!', cmdln, sizeof(cmdln)) > 0)
00557         {
00558                 filter(m, n, cmdln, TRUE);
00559         }
00560 
00561         redraw(MARK_UNSET, FALSE);
00562         return m;
00563 }
00564 
00565 
00566 /* This function runs the ex "file" command to show the file's status */
00567 MARK v_status()
00568 {
00569         cmd_file(cursor, cursor, CMD_FILE, 0, "");
00570         return cursor;
00571 }
00572 
00573 
00574 /* This function runs the ":&" command to repeat the previous :s// */
00575 MARK v_again(m, n)
00576         MARK    m, n;
00577 {
00578         cmd_substitute(m, n - BLKSIZE, CMD_SUBAGAIN, TRUE, "");
00579         return cursor;
00580 }
00581 
00582 
00583 
00584 /* This function switches to the previous file, if possible */
00585 MARK v_switch()
00586 {
00587         if (!*prevorig)
00588                 msg("No previous file");
00589         else
00590         {       strcpy(tmpblk.c, prevorig);
00591                 cmd_edit(cursor, cursor, CMD_EDIT, 0, tmpblk.c);
00592         }
00593         return cursor;
00594 }
00595 
00596 /* This function does a tag search on a keyword */
00597 /*ARGSUSED*/
00598 MARK v_tag(keyword, m, cnt)
00599         char    *keyword;
00600         MARK    m;
00601         long    cnt;
00602 {
00603         /* move the cursor to the start of the tag name, where m is */
00604         cursor = m;
00605 
00606         /* perform the tag search */
00607         cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
00608 
00609         return cursor;
00610 }
00611 
00612 #ifndef NO_EXTENSIONS
00613 /* This function looks up a keyword by calling the helpprog program */
00614 /*ARGSUSED*/
00615 MARK v_keyword(keyword, m, cnt)
00616         char    *keyword;
00617         MARK    m;
00618         long    cnt;
00619 {
00620         int     waswarn;
00621         char    cmdline[130];
00622 
00623         move(LINES - 1, 0);
00624         addstr("---------------------------------------------------------\n");
00625         clrtoeol();
00626         refresh();
00627         sprintf(cmdline, "%s %s", o_keywordprg, keyword);
00628         waswarn = *o_warn;
00629         *o_warn = FALSE;
00630         suspend_curses();
00631         if (system(cmdline))
00632         {
00633                 addstr("<<< failed >>>\n");
00634         }
00635         resume_curses(FALSE);
00636         mode = MODE_VI;
00637         redraw(MARK_UNSET, FALSE);
00638         *o_warn = waswarn;
00639 
00640         return m;
00641 }
00642 
00643 
00644 
00645 MARK v_increment(keyword, m, cnt)
00646         char    *keyword;
00647         MARK    m;
00648         long    cnt;
00649 {
00650         static  sign;
00651         char    newval[12];
00652         long    atol();
00653 
00654         DEFAULT(1);
00655 
00656         /* get one more keystroke, unless doingdot */
00657         if (!doingdot)
00658         {
00659                 sign = getkey(0);
00660         }
00661 
00662         /* adjust the number, based on that second keystroke */
00663         switch (sign)
00664         {
00665           case '+':
00666           case '#':
00667                 cnt = atol(keyword) + cnt;
00668                 break;
00669 
00670           case '-':
00671                 cnt = atol(keyword) - cnt;
00672                 break;
00673 
00674           case '=':
00675                 break;
00676 
00677           default:
00678                 return MARK_UNSET;
00679         }
00680         sprintf(newval, "%ld", cnt);
00681 
00682         ChangeText
00683         {
00684                 change(m, m + strlen(keyword), newval);
00685         }
00686 
00687         return m;
00688 }
00689 #endif
00690 
00691 
00692 /* This function acts like the EX command "xit" */
00693 /*ARGSUSED*/
00694 MARK v_xit(m, cnt, key)
00695         MARK    m;      /* ignored */
00696         long    cnt;    /* ignored */
00697         int     key;    /* must be a second 'Z' */
00698 {
00699         /* if second char wasn't 'Z', fail */
00700         if (key != 'Z')
00701         {
00702                 return MARK_UNSET;
00703         }
00704 
00705         /* move the cursor to the bottom of the screen */
00706         move(LINES - 1, 0);
00707         clrtoeol();
00708 
00709         /* do the xit command */
00710         cmd_xit(m, m, CMD_XIT, FALSE, "");
00711 
00712         /* return the cursor */
00713         return m;
00714 }
00715 
00716 
00717 /* This function undoes changes to a single line, if possible */
00718 MARK v_undoline(m)
00719         MARK    m;      /* where we hope to undo the change */
00720 {
00721         /* make sure we have the right line in the buffer */
00722         if (markline(m) != U_line)
00723         {
00724                 return MARK_UNSET;
00725         }
00726 
00727         /* fix it */
00728         ChangeText
00729         {
00730                 strcat(U_text, "\n");
00731                 change(MARK_AT_LINE(U_line), MARK_AT_LINE(U_line + 1), U_text);
00732         }
00733 
00734         /* nothing in the buffer anymore */
00735         U_line = -1L;
00736 
00737         /* return, with the cursor at the front of the line */
00738         return m & ~(BLKSIZE - 1);
00739 }
00740 
00741 
00742 #ifndef NO_ERRLIST
00743 MARK v_errlist(m)
00744         MARK    m;
00745 {
00746         cmd_errlist(m, m, CMD_ERRLIST, FALSE, "");
00747         return cursor;
00748 }
00749 #endif
00750 
00751 
00752 #ifndef NO_AT
00753 /*ARGSUSED*/
00754 MARK v_at(m, cnt, key)
00755         MARK    m;
00756         long    cnt;
00757         int     key;
00758 {
00759         int     size;
00760 
00761         size = cb2str(key, tmpblk.c, BLKSIZE);
00762         if (size <= 0 || size == BLKSIZE)
00763         {
00764                 return MARK_UNSET;
00765         }
00766 
00767         execmap(0, tmpblk.c, FALSE);
00768         return cursor;
00769 }
00770 #endif
00771 
00772 
00773 #ifdef SIGTSTP
00774 MARK v_suspend()
00775 {
00776         cmd_suspend(MARK_UNSET, MARK_UNSET, CMD_SUSPEND, FALSE, "");
00777         return MARK_UNSET;
00778 }
00779 #endif
00780 
00781 
00782 #ifndef NO_VISIBLE
00783 /*ARGSUSED*/
00784 MARK v_start(m, cnt, cmd)
00785         MARK    m;      /* starting point for a v or V command */
00786         long    cnt;    /* ignored */
00787         int     cmd;    /* either 'v' or 'V' */
00788 {
00789         if (V_from)
00790         {
00791                 V_from = MARK_UNSET;
00792         }
00793         else
00794         {
00795                 V_from = m;
00796                 V_linemd = isupper(cmd);
00797         }
00798         return m;
00799 }
00800 #endif
00801 
00802 #ifndef NO_POPUP
00803 # define MENU_HEIGHT 11
00804 # define MENU_WIDTH  23
00805 MARK v_popup(m, n)
00806         MARK            m, n;   /* the range of text to change */
00807 {
00808         int             i;
00809         int             y, x;   /* position where the window will pop up at */
00810         int             key;    /* keystroke from the user */
00811         int             sel;    /* index of the selected operation */
00812         static int      dfltsel;/* default value of sel */
00813         static char     *labels[11] =
00814         {
00815                 "ESC cancel!         ",
00816                 " d  delete (cut)    ",
00817                 " y  yank (copy)     ",
00818                 " p  paste after     ",
00819                 " P  paste before    ",
00820                 " >  more indented   ",
00821                 " <  less indented   ",
00822                 " =  reformat        ",
00823                 " !  external filter ",
00824                 " ZZ save & exit     ",
00825                 " u  undo previous   "
00826         };
00827 
00828         /* try to position the menu near the cursor */
00829         x = physcol - (MENU_WIDTH / 2);
00830         if (x < 0)
00831                 x = 0;
00832         else if (x + MENU_WIDTH + 2 > COLS)
00833                 x = COLS - MENU_WIDTH - 2;
00834         if (markline(cursor) < topline || markline(cursor) > botline)
00835                 y = 0;
00836         else if (markline(cursor) + 1L + MENU_HEIGHT > botline)
00837                 y = (int)(markline(cursor) - topline) - MENU_HEIGHT;
00838         else
00839                 y = (int)(markline(cursor) - topline) + 1L;
00840 
00841         /* draw the menu */
00842         for (sel = 0; sel < MENU_HEIGHT; sel++)
00843         {
00844                 move(y + sel, x);
00845                 do_POPUP();
00846                 if (sel == dfltsel)
00847                         qaddstr("-->");
00848                 else
00849                         qaddstr("   ");
00850                 qaddstr(labels[sel]);
00851                 do_SE();
00852         }
00853 
00854         /* get a selection */
00855         move(y + dfltsel, x + 4);
00856         for (sel = dfltsel; (key = getkey(WHEN_POPUP)) != '\\' && key != '\r'; )
00857         {
00858                 /* erase the selection arrow */
00859                 move(y + sel, x);
00860                 do_POPUP();
00861                 qaddstr("   ");
00862                 qaddstr(labels[sel]);
00863                 do_SE();
00864 
00865                 /* process the user's keystroke */
00866                 if (key == 'j' && sel < MENU_HEIGHT - 1)
00867                 {
00868                         sel++;
00869                 }
00870                 else if (key == 'k' && sel > 0)
00871                 {
00872                         sel--;
00873                 }
00874                 else if (key == '\033')
00875                 {
00876                         sel = 0;
00877                         break;
00878                 }
00879                 else
00880                 {
00881                         for (i = 1; i < MENU_HEIGHT && labels[i][1] != key; i++)
00882                         {
00883                         }
00884                         if (i < MENU_HEIGHT)
00885                         {
00886                                 sel = i;
00887                                 break;
00888                         }
00889                 }
00890 
00891                 /* redraw the arrow, possibly in a new place */
00892                 move(y + sel, x);
00893                 do_POPUP();
00894                 qaddstr("-->");
00895                 qaddstr(labels[sel]);
00896                 do_SE();
00897                 move(y + sel, x + 4);
00898         }
00899 
00900         /* in most cases, the default selection is "paste after" */
00901         dfltsel = 3;
00902 
00903         /* perform the appropriate action */
00904         switch (sel)
00905         {
00906           case 0:
00907                 m = cursor;
00908                 dfltsel = 0;
00909                 break;
00910 
00911           case 1: /* delete (cut) */
00912                 m = v_delete(m, n);
00913                 break;
00914 
00915           case 2: /* yank (copy) */
00916                 m = v_yank(m, n);
00917                 break;
00918 
00919           case 3: /* paste after */
00920                 m = v_paste(n, 1L, 'P');
00921                 break;
00922 
00923           case 4: /* paste before */
00924                 m = v_paste(m, 1L, 'P');
00925                 dfltsel = 4;
00926                 break;
00927 
00928           case 5: /* more indented */
00929                 m = v_rshift(m, n);
00930                 dfltsel = 5;
00931                 break;
00932 
00933           case 6: /* less indented */
00934                 m = v_lshift(m, n);
00935                 dfltsel = 6;
00936                 break;
00937 
00938           case 7: /* reformat */
00939                 m = v_reformat(m, n);
00940                 dfltsel = 7;
00941                 break;
00942 
00943           case 8: /* external filter */
00944                 m = v_filter(m, n);
00945                 dfltsel = 0;
00946                 break;
00947 
00948           case 9: /* save & exit */
00949                 /* get confirmation first */
00950                 do
00951                 {
00952                         key = getkey(0);
00953                 } while (key != '\\' && key != 'Z' && key != '\r'    /* good */
00954                       && key != '\033');                             /* bad  */
00955                 if (key != '\033')
00956                 {
00957                         m = v_xit(m, 0L, 'Z');
00958                 }
00959                 break;
00960 
00961           case 10: /* undo previous */
00962                 m = v_undo(m);
00963                 dfltsel = 9;
00964                 break;
00965         }
00966 
00967         /* arrange for the menu to be erased (except that "chg from kbd"
00968          * already erased it, and "save & exit" doesn't care)
00969          */
00970         if (sel != 5 && sel != 9)
00971                 redraw(MARK_UNSET, FALSE);
00972 
00973         return m;
00974 }
00975 #endif /* undef NO_POPUP */

Generated on Fri Apr 14 22:56:53 2006 for minix by  doxygen 1.4.6