[BACK]Return to word.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/word.c, Revision 1.19

1.19    ! lum         1: /*     $OpenBSD: word.c,v 1.18 2015/12/29 19:44:32 lum Exp $   */
1.10      kjell       2:
                      3: /* This file is in the public domain. */
1.4       niklas      4:
1.1       deraadt     5: /*
                      6:  *             Word mode commands.
1.5       mickey      7:  * The routines in this file implement commands that work word at a time.
1.3       millert     8:  * There are all sorts of word mode commands.
                      9:  */
1.17      bcallah    10:
                     11: #include <sys/queue.h>
                     12: #include <signal.h>
1.18      lum        13: #include <errno.h>
1.17      bcallah    14: #include <stdio.h>
1.18      lum        15: #include <stdlib.h>
                     16: #include <string.h>
1.3       millert    17:
                     18: #include "def.h"
1.1       deraadt    19:
1.11      kjell      20: RSIZE  countfword(void);
1.18      lum        21: int    grabword(char **);
1.11      kjell      22:
1.1       deraadt    23: /*
1.5       mickey     24:  * Move the cursor backward by "n" words. All of the details of motion are
1.3       millert    25:  * performed by the "backchar" and "forwchar" routines.
1.1       deraadt    26:  */
1.2       millert    27: /* ARGSUSED */
1.3       millert    28: int
1.8       cloder     29: backword(int f, int n)
1.1       deraadt    30: {
1.2       millert    31:        if (n < 0)
1.9       db         32:                return (forwword(f | FFRAND, -n));
1.1       deraadt    33:        if (backchar(FFRAND, 1) == FALSE)
1.9       db         34:                return (FALSE);
1.1       deraadt    35:        while (n--) {
                     36:                while (inword() == FALSE) {
                     37:                        if (backchar(FFRAND, 1) == FALSE)
1.9       db         38:                                return (TRUE);
1.1       deraadt    39:                }
                     40:                while (inword() != FALSE) {
                     41:                        if (backchar(FFRAND, 1) == FALSE)
1.9       db         42:                                return (TRUE);
1.1       deraadt    43:                }
                     44:        }
1.9       db         45:        return (forwchar(FFRAND, 1));
1.1       deraadt    46: }
                     47:
                     48: /*
1.3       millert    49:  * Move the cursor forward by the specified number of words.  All of the
1.1       deraadt    50:  * motion is done by "forwchar".
                     51:  */
1.2       millert    52: /* ARGSUSED */
1.3       millert    53: int
1.8       cloder     54: forwword(int f, int n)
1.1       deraadt    55: {
                     56:        if (n < 0)
1.9       db         57:                return (backword(f | FFRAND, -n));
1.1       deraadt    58:        while (n--) {
                     59:                while (inword() == FALSE) {
                     60:                        if (forwchar(FFRAND, 1) == FALSE)
1.9       db         61:                                return (TRUE);
1.1       deraadt    62:                }
                     63:                while (inword() != FALSE) {
                     64:                        if (forwchar(FFRAND, 1) == FALSE)
1.9       db         65:                                return (TRUE);
1.1       deraadt    66:                }
                     67:        }
1.18      lum        68:        return (TRUE);
                     69: }
                     70:
                     71: /*
                     72:  * Transpose 2 words.
                     73:  * The function below is artifically restricted to only a maximum of 1 iteration
                     74:  * at the moment because the 'undo' functionality within mg needs amended for
                     75:  * multiple movements of point, backwards and forwards.
                     76:  */
                     77: int
                     78: transposeword(int f, int n)
                     79: {
                     80:        struct line     *tmp1_w_dotp = NULL;
                     81:        struct line     *tmp2_w_dotp = NULL;
                     82:        int              tmp2_w_doto = 0;
                     83:        int              tmp1_w_dotline = 0;
                     84:        int              tmp2_w_dotline = 0;
                     85:        int              tmp1_w_doto;
                     86:        int              i;             /* start-of-line space counter */
                     87:        int              ret, s;
                     88:        int              newline;
                     89:        int              leave = 0;
                     90:        int              tmp_len;
                     91:        char            *word1 = NULL;
                     92:        char            *word2 = NULL;
                     93:        char            *chr;
                     94:
                     95:        if (n == 0)
                     96:                return (TRUE);
                     97:
                     98:        n = 1; /* remove this line to allow muliple-iterations */
                     99:
                    100:        if ((s = checkdirty(curbp)) != TRUE)
                    101:                return (s);
                    102:        if (curbp->b_flag & BFREADONLY) {
                    103:                dobeep();
                    104:                ewprintf("Buffer is read-only");
                    105:                return (FALSE);
                    106:        }
                    107:        undo_boundary_enable(FFRAND, 0);
                    108:
                    109:        /* go backwards to find the start of a word to transpose. */
                    110:        (void)backword(FFRAND, 1);
                    111:        ret = grabword(&word1);
                    112:        if (ret == ABORT) {
                    113:                ewprintf("No word to the left to tranpose.");
                    114:                return (FALSE);
                    115:        }
                    116:        if (ret < 0) {
                    117:                dobeep();
                    118:                ewprintf("Error copying word: %s", strerror(ret));
                    119:                free(word1);
                    120:                return (FALSE);
                    121:        }
                    122:
                    123:        while (n-- > 0) {
                    124:                i = 0;
                    125:                newline = 0;
                    126:
                    127:                tmp1_w_doto = curwp->w_doto;
                    128:                tmp1_w_dotline = curwp->w_dotline;
                    129:                tmp1_w_dotp = curwp->w_dotp;
                    130:
                    131:                /* go forward and find next word. */
                    132:                while (inword() == FALSE) {
                    133:                        if (forwchar(FFRAND, 1) == FALSE) {
                    134:                                leave = 1;
                    135:                                if (tmp1_w_dotline < curwp->w_dotline)
                    136:                                        curwp->w_dotline--;
                    137:                                ewprintf("Don't have two things to transpose");
                    138:                                break;
                    139:                        }
                    140:                        if (curwp->w_doto == 0) {
                    141:                                newline = 1;
                    142:                                i = 0;
                    143:                        } else if (newline)
                    144:                                i++;
                    145:                }
                    146:                if (leave) {
                    147:                        tmp2_w_doto = tmp1_w_doto;
                    148:                        tmp2_w_dotline = tmp1_w_dotline;
                    149:                        tmp2_w_dotp = tmp1_w_dotp;
                    150:                        break;
                    151:                }
                    152:                tmp2_w_doto = curwp->w_doto;
                    153:                tmp2_w_dotline = curwp->w_dotline;
                    154:                tmp2_w_dotp = curwp->w_dotp;
                    155:
                    156:                ret = grabword(&word2);
1.19    ! lum       157:                if (ret < 0 || ret == ABORT) {
1.18      lum       158:                        dobeep();
                    159:                        ewprintf("Error copying word: %s", strerror(ret));
                    160:                        free(word1);
                    161:                        return (FALSE);
                    162:                }
                    163:                tmp_len = strlen(word2);
                    164:                tmp2_w_doto += tmp_len;
                    165:
                    166:                curwp->w_doto = tmp1_w_doto;
                    167:                curwp->w_dotline = tmp1_w_dotline;
                    168:                curwp->w_dotp = tmp1_w_dotp;
                    169:
                    170:                /* insert shuffled along word */
                    171:                for (chr = word2; *chr != '\0'; ++chr)
                    172:                        linsert(1, *chr);
                    173:
                    174:                if (newline)
                    175:                        tmp2_w_doto = i;
                    176:
                    177:                curwp->w_doto = tmp2_w_doto;
                    178:                curwp->w_dotline = tmp2_w_dotline;
                    179:                curwp->w_dotp = tmp2_w_dotp;
                    180:
                    181:                word2 = NULL;
                    182:        }
                    183:        curwp->w_doto = tmp2_w_doto;
                    184:        curwp->w_dotline = tmp2_w_dotline;
                    185:        curwp->w_dotp = tmp2_w_dotp;
                    186:
                    187:        /* insert very first word in its new position */
                    188:        for (chr = word1; *chr != '\0'; ++chr)
                    189:                linsert(1, *chr);
                    190:
                    191:        if (leave)
                    192:                (void)backword(FFRAND, 1);
                    193:
                    194:        free(word1);
                    195:        free(word2);
                    196:
                    197:        undo_boundary_enable(FFRAND, 1);
                    198:
                    199:        return (TRUE);
                    200: }
                    201:
                    202: /*
                    203:  * copy and delete word.
                    204: */
                    205: int
                    206: grabword(char **word)
                    207: {
                    208:        int c;
                    209:
                    210:        while (inword() == TRUE) {
                    211:                c = lgetc(curwp->w_dotp, curwp->w_doto);
                    212:                if (*word == NULL) {
                    213:                        if (asprintf(word, "%c", c) == -1)
                    214:                                return (errno);
                    215:                } else {
                    216:                        if (asprintf(word, "%s%c", *word, c) == -1)
                    217:                                return (errno);
                    218:                }
                    219:                (void)forwdel(FFRAND, 1);
                    220:        }
                    221:        if (*word == NULL)
                    222:                return (ABORT);
1.9       db        223:        return (TRUE);
1.1       deraadt   224: }
                    225:
                    226: /*
1.3       millert   227:  * Move the cursor forward by the specified number of words.  As you move,
1.1       deraadt   228:  * convert any characters to upper case.
                    229:  */
1.2       millert   230: /* ARGSUSED */
1.3       millert   231: int
1.8       cloder    232: upperword(int f, int n)
1.1       deraadt   233: {
1.15      kjell     234:        int     c, s;
1.11      kjell     235:        RSIZE   size;
1.1       deraadt   236:
1.15      kjell     237:        if ((s = checkdirty(curbp)) != TRUE)
                    238:                return (s);
1.7       vincent   239:        if (curbp->b_flag & BFREADONLY) {
1.16      lum       240:                dobeep();
1.7       vincent   241:                ewprintf("Buffer is read-only");
                    242:                return (FALSE);
                    243:        }
                    244:
1.2       millert   245:        if (n < 0)
1.9       db        246:                return (FALSE);
1.1       deraadt   247:        while (n--) {
                    248:                while (inword() == FALSE) {
                    249:                        if (forwchar(FFRAND, 1) == FALSE)
1.9       db        250:                                return (TRUE);
1.1       deraadt   251:                }
1.11      kjell     252:                size = countfword();
                    253:                undo_add_change(curwp->w_dotp, curwp->w_doto, size);
1.12      deraadt   254:
1.1       deraadt   255:                while (inword() != FALSE) {
                    256:                        c = lgetc(curwp->w_dotp, curwp->w_doto);
                    257:                        if (ISLOWER(c) != FALSE) {
                    258:                                c = TOUPPER(c);
                    259:                                lputc(curwp->w_dotp, curwp->w_doto, c);
1.14      kjell     260:                                lchange(WFFULL);
1.1       deraadt   261:                        }
                    262:                        if (forwchar(FFRAND, 1) == FALSE)
1.9       db        263:                                return (TRUE);
1.1       deraadt   264:                }
                    265:        }
1.9       db        266:        return (TRUE);
1.1       deraadt   267: }
                    268:
                    269: /*
1.3       millert   270:  * Move the cursor forward by the specified number of words.  As you move
1.1       deraadt   271:  * convert characters to lower case.
                    272:  */
1.2       millert   273: /* ARGSUSED */
1.3       millert   274: int
1.8       cloder    275: lowerword(int f, int n)
1.1       deraadt   276: {
1.15      kjell     277:        int     c, s;
1.11      kjell     278:        RSIZE   size;
1.1       deraadt   279:
1.15      kjell     280:        if ((s = checkdirty(curbp)) != TRUE)
                    281:                return (s);
1.7       vincent   282:        if (curbp->b_flag & BFREADONLY) {
1.16      lum       283:                dobeep();
1.7       vincent   284:                ewprintf("Buffer is read-only");
                    285:                return (FALSE);
                    286:        }
1.2       millert   287:        if (n < 0)
1.9       db        288:                return (FALSE);
1.1       deraadt   289:        while (n--) {
                    290:                while (inword() == FALSE) {
                    291:                        if (forwchar(FFRAND, 1) == FALSE)
1.9       db        292:                                return (TRUE);
1.1       deraadt   293:                }
1.11      kjell     294:                size = countfword();
                    295:                undo_add_change(curwp->w_dotp, curwp->w_doto, size);
                    296:
1.1       deraadt   297:                while (inword() != FALSE) {
                    298:                        c = lgetc(curwp->w_dotp, curwp->w_doto);
                    299:                        if (ISUPPER(c) != FALSE) {
                    300:                                c = TOLOWER(c);
                    301:                                lputc(curwp->w_dotp, curwp->w_doto, c);
1.14      kjell     302:                                lchange(WFFULL);
1.1       deraadt   303:                        }
                    304:                        if (forwchar(FFRAND, 1) == FALSE)
1.9       db        305:                                return (TRUE);
1.1       deraadt   306:                }
                    307:        }
1.9       db        308:        return (TRUE);
1.1       deraadt   309: }
                    310:
                    311: /*
1.3       millert   312:  * Move the cursor forward by the specified number of words.  As you move
1.5       mickey    313:  * convert the first character of the word to upper case, and subsequent
                    314:  * characters to lower case.  Error if you try to move past the end of the
1.3       millert   315:  * buffer.
1.1       deraadt   316:  */
1.2       millert   317: /* ARGSUSED */
1.3       millert   318: int
1.8       cloder    319: capword(int f, int n)
1.1       deraadt   320: {
1.15      kjell     321:        int     c, s;
1.11      kjell     322:        RSIZE   size;
1.1       deraadt   323:
1.15      kjell     324:        if ((s = checkdirty(curbp)) != TRUE)
                    325:                return (s);
1.7       vincent   326:        if (curbp->b_flag & BFREADONLY) {
1.16      lum       327:                dobeep();
1.7       vincent   328:                ewprintf("Buffer is read-only");
                    329:                return (FALSE);
                    330:        }
                    331:
1.2       millert   332:        if (n < 0)
1.9       db        333:                return (FALSE);
1.1       deraadt   334:        while (n--) {
                    335:                while (inword() == FALSE) {
                    336:                        if (forwchar(FFRAND, 1) == FALSE)
1.9       db        337:                                return (TRUE);
1.1       deraadt   338:                }
1.11      kjell     339:                size = countfword();
                    340:                undo_add_change(curwp->w_dotp, curwp->w_doto, size);
                    341:
1.1       deraadt   342:                if (inword() != FALSE) {
                    343:                        c = lgetc(curwp->w_dotp, curwp->w_doto);
                    344:                        if (ISLOWER(c) != FALSE) {
                    345:                                c = TOUPPER(c);
                    346:                                lputc(curwp->w_dotp, curwp->w_doto, c);
1.14      kjell     347:                                lchange(WFFULL);
1.1       deraadt   348:                        }
                    349:                        if (forwchar(FFRAND, 1) == FALSE)
1.9       db        350:                                return (TRUE);
1.1       deraadt   351:                        while (inword() != FALSE) {
                    352:                                c = lgetc(curwp->w_dotp, curwp->w_doto);
                    353:                                if (ISUPPER(c) != FALSE) {
                    354:                                        c = TOLOWER(c);
                    355:                                        lputc(curwp->w_dotp, curwp->w_doto, c);
1.14      kjell     356:                                        lchange(WFFULL);
1.1       deraadt   357:                                }
                    358:                                if (forwchar(FFRAND, 1) == FALSE)
1.9       db        359:                                        return (TRUE);
1.1       deraadt   360:                        }
                    361:                }
                    362:        }
1.9       db        363:        return (TRUE);
1.1       deraadt   364: }
1.11      kjell     365:
                    366: /*
                    367:  * Count characters in word, from current position
                    368:  */
                    369: RSIZE
                    370: countfword()
                    371: {
1.13      deraadt   372:        RSIZE            size;
                    373:        struct line     *dotp;
                    374:        int              doto;
1.11      kjell     375:
                    376:        dotp = curwp->w_dotp;
                    377:        doto = curwp->w_doto;
                    378:        size = 0;
                    379:
                    380:        while (inword() != FALSE) {
                    381:                if (forwchar(FFRAND, 1) == FALSE)
                    382:                        /* hit the end of the buffer */
                    383:                        goto out;
                    384:                ++size;
                    385:        }
                    386: out:
                    387:        curwp->w_dotp = dotp;
                    388:        curwp->w_doto = doto;
                    389:        return (size);
                    390: }
                    391:
1.1       deraadt   392:
                    393: /*
                    394:  * Kill forward by "n" words.
                    395:  */
1.2       millert   396: /* ARGSUSED */
1.3       millert   397: int
1.8       cloder    398: delfword(int f, int n)
1.1       deraadt   399: {
1.13      deraadt   400:        RSIZE            size;
                    401:        struct line     *dotp;
                    402:        int              doto;
1.15      kjell     403:        int s;
1.1       deraadt   404:
1.15      kjell     405:        if ((s = checkdirty(curbp)) != TRUE)
                    406:                return (s);
1.7       vincent   407:        if (curbp->b_flag & BFREADONLY) {
1.16      lum       408:                dobeep();
1.7       vincent   409:                ewprintf("Buffer is read-only");
                    410:                return (FALSE);
                    411:        }
1.1       deraadt   412:        if (n < 0)
1.9       db        413:                return (FALSE);
1.3       millert   414:
                    415:        /* purge kill buffer */
                    416:        if ((lastflag & CFKILL) == 0)
1.1       deraadt   417:                kdelete();
1.3       millert   418:
1.1       deraadt   419:        thisflag |= CFKILL;
                    420:        dotp = curwp->w_dotp;
                    421:        doto = curwp->w_doto;
                    422:        size = 0;
1.3       millert   423:
1.1       deraadt   424:        while (n--) {
                    425:                while (inword() == FALSE) {
                    426:                        if (forwchar(FFRAND, 1) == FALSE)
1.3       millert   427:                                /* hit the end of the buffer */
                    428:                                goto out;
1.1       deraadt   429:                        ++size;
                    430:                }
                    431:                while (inword() != FALSE) {
                    432:                        if (forwchar(FFRAND, 1) == FALSE)
1.3       millert   433:                                /* hit the end of the buffer */
                    434:                                goto out;
1.1       deraadt   435:                        ++size;
                    436:                }
                    437:        }
                    438: out:
                    439:        curwp->w_dotp = dotp;
                    440:        curwp->w_doto = doto;
                    441:        return (ldelete(size, KFORW));
                    442: }
                    443:
                    444: /*
1.5       mickey    445:  * Kill backwards by "n" words.  The rules for success and failure are now
                    446:  * different, to prevent strange behavior at the start of the buffer.  The
                    447:  * command only fails if something goes wrong with the actual delete of the
                    448:  * characters.  It is successful even if no characters are deleted, or if you
                    449:  * say delete 5 words, and there are only 4 words left.  I considered making
                    450:  * the first call to "backchar" special, but decided that that would just be
1.3       millert   451:  * weird. Normally this is bound to "M-Rubout" and to "M-Backspace".
1.1       deraadt   452:  */
1.2       millert   453: /* ARGSUSED */
1.3       millert   454: int
1.8       cloder    455: delbword(int f, int n)
1.1       deraadt   456: {
1.3       millert   457:        RSIZE   size;
1.15      kjell     458:        int s;
1.7       vincent   459:
1.15      kjell     460:        if ((s = checkdirty(curbp)) != TRUE)
                    461:                return (s);
1.7       vincent   462:        if (curbp->b_flag & BFREADONLY) {
1.16      lum       463:                dobeep();
1.7       vincent   464:                ewprintf("Buffer is read-only");
                    465:                return (FALSE);
                    466:        }
1.1       deraadt   467:
1.2       millert   468:        if (n < 0)
1.9       db        469:                return (FALSE);
1.3       millert   470:
                    471:        /* purge kill buffer */
                    472:        if ((lastflag & CFKILL) == 0)
1.1       deraadt   473:                kdelete();
                    474:        thisflag |= CFKILL;
                    475:        if (backchar(FFRAND, 1) == FALSE)
1.3       millert   476:                /* hit buffer start */
                    477:                return (TRUE);
                    478:
                    479:        /* one deleted */
                    480:        size = 1;
1.1       deraadt   481:        while (n--) {
                    482:                while (inword() == FALSE) {
                    483:                        if (backchar(FFRAND, 1) == FALSE)
1.3       millert   484:                                /* hit buffer start */
                    485:                                goto out;
1.1       deraadt   486:                        ++size;
                    487:                }
                    488:                while (inword() != FALSE) {
                    489:                        if (backchar(FFRAND, 1) == FALSE)
1.3       millert   490:                                /* hit buffer start */
                    491:                                goto out;
1.1       deraadt   492:                        ++size;
                    493:                }
                    494:        }
                    495:        if (forwchar(FFRAND, 1) == FALSE)
1.9       db        496:                return (FALSE);
1.3       millert   497:
                    498:        /* undo assumed delete */
                    499:        --size;
1.1       deraadt   500: out:
1.9       db        501:        return (ldelete(size, KBACK));
1.1       deraadt   502: }
                    503:
                    504: /*
1.3       millert   505:  * Return TRUE if the character at dot is a character that is considered to be
1.9       db        506:  * part of a word. The word character list is hard coded. Should be settable.
1.1       deraadt   507:  */
1.3       millert   508: int
1.8       cloder    509: inword(void)
1.2       millert   510: {
                    511:        /* can't use lgetc in ISWORD due to bug in OSK cpp */
1.9       db        512:        return (curwp->w_doto != llength(curwp->w_dotp) &&
                    513:            ISWORD(curwp->w_dotp->l_text[curwp->w_doto]));
1.1       deraadt   514: }