Annotation of coherent/g/usr/bin/me/random.c, revision 1.1.1.1

1.1       root        1: /* @(microEMACS)random.c
                      2:  *
                      3:  * This file contains the command processing functions for a number of 
                      4:  * random commands.  There is no functional grouping here, for sure.
                      5:  */
                      6: #include       <stdio.h>
                      7: #include       "ed.h"
                      8: 
                      9: /*
                     10:  * Return current column.  Stop at first non-blank given TRUE argument.
                     11:  */
                     12: getccol(bflg)
                     13: int bflg;
                     14: {
                     15:        register int i;
                     16:        register int col = 0;
                     17:        register WINDOW *lcurwp;
                     18:        unsigned c;
                     19: 
                     20:        lcurwp = curwp;
                     21:        for (i=0; i<lcurwp->w_doto; ++i) {
                     22:                c = lgetc(lcurwp->w_dotp, i);
                     23:                if (c != ' ' && c != '\t' && bflg)
                     24:                        break;
                     25:                switch (dblchr(c)) {
                     26:                case 2:
                     27:                        taber(col);
                     28:                        break;
                     29:                case 1:
                     30:                        ++col;
                     31:                }
                     32:                ++col;
                     33:        }
                     34:        return (col);
                     35: }
                     36: 
                     37: /*
                     38:  * Set fill column to n, if given, otherwise use the current cursor
                     39:  * column. Either way, tell user where the fill column really is. 
                     40:  */
                     41: setfillcol(f, n)
                     42: register int n;
                     43: {
                     44:        if (!n)
                     45:                bind.fillcol = 0;
                     46:        else if (n == 1)
                     47:                bind.fillcol = getccol(FALSE);
                     48:        else
                     49:                bind.fillcol = n - 1;
                     50: 
                     51:        if (bind.fillcol)
                     52:                mlwrite("[Wrap at column %d]", bind.fillcol+1);
                     53:        else
                     54:                mlwrite("Word wrap turned off");
                     55:        return (TRUE);
                     56: }
                     57: 
                     58: /*
                     59:  * Display the current position of the cursor,
                     60:  * in origin 1 X-Y coordinates, the character that is
                     61:  * under the cursor (in hex), and the fraction of the
                     62:  * text that is before the cursor. The displayed column
                     63:  * is not the current column, but the column that would
                     64:  * be used on an infinite width display. Normally this
                     65:  * is bound to "C-X =".
                     66:  */
                     67: showcpos(f, n)
                     68: {
                     69:        register LINE   *clp;
                     70:        register long   nch = 0L;
                     71:        register long   nbc;
                     72:        register int    cbo = 0;
                     73:        register int    linecnt = 1;
                     74:        register int    cac;
                     75:        register int    curline = 0;
                     76:        int             ratio;
                     77:        int             col;
                     78: 
                     79:        clp = lforw(curbp->b_linep);            /* Grovel the data.     */
                     80: 
                     81:        for (;;) {
                     82:                if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
                     83:                        curline = linecnt;
                     84:                        nbc = nch;
                     85:                        if (cbo == llength(clp))
                     86:                                cac = '\n';
                     87:                        else
                     88:                                cac = lgetc(clp, cbo);
                     89:                }
                     90:                if (cbo == llength(clp)) {
                     91:                        if (clp == curbp->b_linep)
                     92:                                break;
                     93:                        clp = lforw(clp);
                     94:                        ++linecnt;
                     95:                        cbo = 0;
                     96:                } else
                     97:                        ++cbo;
                     98:                ++nch;
                     99:        }
                    100:        col = getccol(FALSE)+1;                 /* Get real column.     */
                    101:        ratio = 0;                              /* Ratio before dot.    */
                    102:        if (nch != 0)
                    103:                ratio = (100L*nbc) / nch;
                    104:        mlwrite("X=%d Y=%d CH=0x%x .=%ld (%d%% of %ld) line %d of %d",
                    105:                col, currow+1, cac, nbc, ratio, nch, curline, linecnt);
                    106:        return (TRUE);
                    107: }
                    108: 
                    109: /*
                    110:  * Twiddle the two characters on either side of
                    111:  * dot. If dot is at the end of the line twiddle the
                    112:  * two characters before it. Return with an error if dot
                    113:  * is at the beginning of line; it seems to be a bit
                    114:  * pointless to make this work. This fixes up a very
                    115:  * common typo with a single stroke. Normally bound
                    116:  * to "C-T". This always works within a line, so
                    117:  * "WFEDIT" is good enough.
                    118:  */
                    119: twiddle(f, n)
                    120: {
                    121:        register WINDOW *lcurwp;
                    122:        register LINE   *dotp;
                    123:        register int    doto;
                    124:        register int    cl;
                    125:        register int    cr;
                    126: 
                    127:        lcurwp = curwp;
                    128:        dotp = lcurwp->w_dotp;
                    129:        doto = lcurwp->w_doto;
                    130:        if (doto==llength(dotp) && --doto<0)
                    131:                return (FALSE);
                    132:        cr = lgetc(dotp, doto);
                    133:        if (--doto < 0)
                    134:                return (FALSE);
                    135:        cl = lgetc(dotp, doto);
                    136:        lputc(dotp, doto+0, cr);
                    137:        lputc(dotp, doto+1, cl);
                    138:        lchange(WFEDIT);
                    139:        return (TRUE);
                    140: }
                    141: 
                    142: /*
                    143:  * Quote the next character, and insert it into the buffer.  All the characters
                    144:  * are taken literally, with the exception of the newline, which always has
                    145:  * its line splitting meaning.  The character is always read, even if it is
                    146:  * inserted 0 times, for regularity.  If executing a macro, get the character
                    147:  * from memory, otherwise, get it from the keyboard.
                    148:  * Bound to "C-Q"
                    149:  */
                    150: quote(f, n)
                    151: register int n;
                    152: {
                    153:        register int    s;
                    154:        register int    c;
                    155: 
                    156:        if (kbdmop != NULL)             /* if in a macro, get from memory */
                    157:                c = *kbdmop++;          /* fixes a bug in an old version  */
                    158:        else                            /* where the quoted character was */
                    159:                c = tgetc();            /* not remembered.                */
                    160:        if (kbdmip != NULL)
                    161:                *kbdmip++ = c;          /* if defining a macro, remember */
                    162:        if (n < 0)
                    163:                return (FALSE);
                    164:        if (n == 0)
                    165:                return (TRUE);
                    166:        if (c == '\n') {
                    167:                do {
                    168:                        s = lnewline();
                    169:                } while (s==TRUE && --n);
                    170:                return (s);
                    171:        }
                    172:        return (linsert(n, c));
                    173: }
                    174: 
                    175: /*
                    176:  * Get character by value, and insert it into the buffer.  All the characters
                    177:  * are taken literally, with the exception of the newline, which always has
                    178:  * its line splitting meaning.  The character is always read, even if it is
                    179:  * inserted 0 times, for regularity.
                    180:  * Bound to "M-Q"
                    181:  */
                    182: quoteval(f, n)
                    183: register int n;
                    184: {
                    185:        register int    s;
                    186:        register int    c;
                    187:        char buf[10];   /* big enough */
                    188: 
                    189:        if (TRUE != (s = mlreply("value of char to insert ", buf, sizeof(buf))))
                    190:                return (s);
                    191: 
                    192:        if (n < 0)
                    193:                return (FALSE);
                    194:        if (n == 0)
                    195:                return (TRUE);
                    196: 
                    197:        c = atoi(buf);
                    198:        if (c == '\n') {
                    199:                do {
                    200:                        s = lnewline();
                    201:                } while (s==TRUE && --n);
                    202:                return (s);
                    203:        }
                    204:        return (linsert(n, c));
                    205: }
                    206: 
                    207: /*
                    208:  * Toggle autoindent flag.
                    209:  */
                    210: autoind(f, n)
                    211: {
                    212:        bind.autoindent ^= 1;
                    213: }
                    214: 
                    215: /*
                    216:  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
                    217:  * tab into file.  If given argument, n, of zero, change to true tabs.
                    218:  * If n > 1, simulate tab stop every n-characters using spaces.
                    219:  * This has to be done in this slightly funny way because the
                    220:  * tab (in ASCII) has been turned into "C-I" (in 10
                    221:  * bit code) already. Bound to "C-I".
                    222:  */
                    223: tab(f, n)
                    224: register int n;
                    225: {
                    226:        if (n == 1)             /* normal tabbing */
                    227:                return (bind.tabsize ?
                    228:                        linsert(bind.tabsize - (getccol(FALSE)%bind.tabsize),' ') :
                    229:                        linsert(1, '\t'));
                    230: 
                    231:        if (n < 0) {    /* change the meaning of tab character */
                    232:                bind.tabsiz = -n;
                    233:                curwp->w_flag |= WFMODE|WFFORCE|WFHARD;
                    234:                return (TRUE);
                    235:        }
                    236: 
                    237:        /* change the meaning of tab key */
                    238:        if (!(bind.tabsize = n)) {
                    239:                bind.tabsiz = 8;        /* back to the default for 0 */
                    240:                curwp->w_flag |= WFMODE|WFFORCE|WFHARD;
                    241:        }
                    242:        return (TRUE);
                    243: }
                    244: 
                    245: /*
                    246:  * Open up some blank space. The basic plan
                    247:  * is to insert a bunch of newlines, and then back
                    248:  * up over them. Everything is done by the subcommand
                    249:  * procerssors. They even handle the looping. Normally
                    250:  * this is bound to "C-O".
                    251:  */
                    252: openline(f, n)
                    253: register int n;
                    254: {
                    255:        register int    i;
                    256:        register int    s;
                    257: 
                    258:        if (n < 0)
                    259:                return (FALSE);
                    260:        if (n == 0)
                    261:                return (TRUE);
                    262:        i = n;                                  /* Insert newlines.     */
                    263:        do {
                    264:                s = lnewline();
                    265:        } while (s==TRUE && --i);
                    266:        if (s == TRUE)                          /* Then back up overtop */
                    267:                s = backchar(f, n);             /* of them all.         */
                    268:        return (s);
                    269: }
                    270: 
                    271: /*
                    272:  * Insert a newline. Bound to "C-M".
                    273:  * If you are at the end of the line and the
                    274:  * next line is a blank line, just move into the
                    275:  * blank line. This makes "C-O" and "C-X C-O" work
                    276:  * nicely, and reduces the ammount of screen
                    277:  * update that has to be done. This would not be
                    278:  * as critical if screen update were a lot
                    279:  * more efficient.
                    280:  */
                    281: newline(f, n)
                    282: register int n;
                    283: {
                    284:        register LINE   *lp;
                    285:        register int    s;
                    286: 
                    287:        if (n < 0)
                    288:                return (FALSE);
                    289:        while (n--) {
                    290:                lp = curwp->w_dotp;
                    291:                if (llength(lp) == curwp->w_doto
                    292:                && lp != curbp->b_linep
                    293:                && llength(lforw(lp)) == 0) {
                    294:                        if ((s=forwchar(FALSE, 1)) != TRUE)
                    295:                                return (s);
                    296:                } else if ((s=lnewline()) != TRUE)
                    297:                        return (s);
                    298:        }
                    299:        return (TRUE);
                    300: }
                    301: 
                    302: /*
                    303:  * Delete blank lines around dot.
                    304:  * What this command does depends if dot is
                    305:  * sitting on a blank line. If dot is sitting on a
                    306:  * blank line, this command deletes all the blank lines
                    307:  * above and below the current line. If it is sitting
                    308:  * on a non blank line then it deletes all of the
                    309:  * blank lines after the line. Normally this command
                    310:  * is bound to "C-X C-O". Any argument is ignored.
                    311:  */
                    312: deblank(f, n)
                    313: {
                    314:        register LINE   *lp1;
                    315:        register LINE   *lp2;
                    316:        register int    nld;
                    317:        register WINDOW *lcurwp;
                    318: 
                    319:        lcurwp = curwp;
                    320:        lp1 = lcurwp->w_dotp;
                    321:        while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
                    322:                lp1 = lp2;
                    323:        lp2 = lp1;
                    324:        nld = 0;
                    325:        while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
                    326:                ++nld;
                    327:        if (nld == 0)
                    328:                return (TRUE);
                    329:        lcurwp->w_dotp = lforw(lp1);
                    330:        lcurwp->w_doto = 0;
                    331:        return (ldelete(nld, FALSE));
                    332: }
                    333: 
                    334: /*
                    335:  * Insert a newline, then enough
                    336:  * tabs and spaces to duplicate the indentation
                    337:  * of the previous line. Assumes tabs are every eight
                    338:  * characters. Quite simple. Figure out the indentation
                    339:  * of the current line. Insert a newline by calling
                    340:  * the standard routine. Insert the indentation by
                    341:  * inserting the right number of tabs and spaces.
                    342:  * Return TRUE if all ok. Return FALSE if one
                    343:  * of the subcomands failed. Normally bound
                    344:  * to "C-J".
                    345:  */
                    346: indent(f, n)
                    347: {
                    348:        register int    nicol;
                    349:        register int    c;
                    350:        register int    i;
                    351: 
                    352:        if (n < 0)
                    353:                return (FALSE);
                    354:        while (n--) {
                    355:                nicol = 0;
                    356:                for (i=0; i<llength(curwp->w_dotp); ++i) {
                    357:                        c = lgetc(curwp->w_dotp, i);
                    358:                        if (c!=' ' && c!='\t')
                    359:                                break;
                    360:                        if (c == '\t')
                    361:                                taber(nicol);
                    362:                        ++nicol;
                    363:                }
                    364:                if (lnewline() == FALSE
                    365:                || ((i=nicol/bind.tabsiz)!=0 && linsert(i, '\t')==FALSE)
                    366:                || ((i=nicol%bind.tabsiz)!=0 && linsert(i,  ' ')==FALSE))
                    367:                        return (FALSE);
                    368:        }
                    369:        return (TRUE);
                    370: }
                    371: 
                    372: /*
                    373:  * Delete forward. This is real
                    374:  * easy, because the basic delete routine does
                    375:  * all of the work. Watches for negative arguments,
                    376:  * and does the right thing. If any argument is
                    377:  * present, it kills rather than deletes, to prevent
                    378:  * loss of text if typed with a big argument.
                    379:  * Normally bound to "C-D".
                    380:  */
                    381: forwdel(f, n)
                    382: {
                    383:        if (n < 0)
                    384:                return (backdel(f, -n));
                    385:        if (f != FALSE) {                       /* Really a kill.       */
                    386:                if ((lastflag&CFKILL) == 0)
                    387:                        kdelete();
                    388:                thisflag |= CFKILL;
                    389:        }
                    390:        return (ldelete(n, f));
                    391: }
                    392: 
                    393: /*
                    394:  * Delete backwards. This is quite easy too,
                    395:  * because it's all done with other functions. Just
                    396:  * move the cursor back, and delete forwards.
                    397:  * Like delete forward, this actually does a kill
                    398:  * if presented with an argument. Bound to both
                    399:  * "RUBOUT" and "C-H".
                    400:  */
                    401: backdel(f, n)
                    402: {
                    403:        register int    s;
                    404: 
                    405:        if (n < 0)
                    406:                return (forwdel(f, -n));
                    407:        if (f != FALSE) {                       /* Really a kill.       */
                    408:                if ((lastflag&CFKILL) == 0)
                    409:                        kdelete();
                    410:                thisflag |= CFKILL;
                    411:        }
                    412:        if ((s=backchar(f, n)) == TRUE)
                    413:                s = ldelete(n, f);
                    414:        return (s);
                    415: }
                    416: 
                    417: /*
                    418:  * Kill text. If called without an argument,
                    419:  * it kills from dot to the end of the line, unless it
                    420:  * is at the end of the line, when it kills the newline.
                    421:  * If called with an argument of 0, it kills from the
                    422:  * start of the line to dot. If called with a positive
                    423:  * argument, it kills from dot forward over that number
                    424:  * of newlines. If called with a negative argument it
                    425:  * kills backwards that number of newlines. Normally
                    426:  * bound to "C-K".
                    427:  */
                    428: kill(f, n)
                    429: {
                    430:        register int    chunk;
                    431:        register LINE   *nextp;
                    432: 
                    433:        if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
                    434:                kdelete();                      /* last wasn't a kill.  */
                    435:        thisflag |= CFKILL;
                    436:        if (f == FALSE) {
                    437:                chunk = llength(curwp->w_dotp)-curwp->w_doto;
                    438:                if (chunk == 0)
                    439:                        chunk = 1;
                    440:        } else if (n == 0) {
                    441:                chunk = curwp->w_doto;
                    442:                curwp->w_doto = 0;
                    443:        } else if (n > 0) {
                    444:                chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
                    445:                nextp = lforw(curwp->w_dotp);
                    446:                while (--n) {
                    447:                        if (nextp == curbp->b_linep)
                    448:                                return (FALSE);
                    449:                        chunk += llength(nextp)+1;
                    450:                        nextp = lforw(nextp);
                    451:                }
                    452:        } else {
                    453:                mlwrite("neg kill");
                    454:                return (FALSE);
                    455:        }
                    456:        return (ldelete(chunk, TRUE));
                    457: }
                    458: 
                    459: /*
                    460:  * Yank text back from the kill buffer. This
                    461:  * is really easy. All of the work is done by the
                    462:  * standard insert routines. All you do is run the loop,
                    463:  * and check for errors. Bound to "C-Y". The blank
                    464:  * lines are inserted with a call to "newline"
                    465:  * instead of a call to "lnewline" so that the magic
                    466:  * stuff that happens when you type a carriage
                    467:  * return also happens when a carriage return is
                    468:  * yanked back from the kill buffer.
                    469:  */
                    470: yank(f, n)
                    471: {
                    472:        register int    c;
                    473:        register int    i;
                    474:        extern   int    kused;
                    475: 
                    476:        if (n < 0)
                    477:                return (FALSE);
                    478:        while (n--) {
                    479:                i = 0;
                    480:                while ((c=kremove(i)) >= 0) {
                    481:                        if (c == '\n') {
                    482:                                if (newline(FALSE, 1) == FALSE)
                    483:                                        return (FALSE);
                    484:                        } else {
                    485:                                if (linsert(1, c) == FALSE)
                    486:                                        return (FALSE);
                    487:                        }
                    488:                        ++i;
                    489:                }
                    490:        }
                    491:        return (TRUE);
                    492: }
                    493: 
                    494: #if    GEM
                    495: /*
                    496:  * singlecase the characters in the given buffer. this is used for
                    497:  * buffer and file names on the ST, since everything becomes uppercase
                    498:  * (whether you like it or not) from the desktop and in file names.
                    499:  * this routine assumes ASCII.
                    500:  */
                    501: fixname(bp)
                    502: register uchar *bp;
                    503: {
                    504:        register unsigned c;
                    505: 
                    506:        while (c = *bp)
                    507: #if    UPPERNM
                    508:                if (c >= 'a' && c <= 'z')
                    509:                        *bp++ = c & ~0x20;      /* Lower to upper case */
                    510: #else
                    511:                if (c >= 'A' && c <= 'Z')
                    512:                        *bp++ = c | 0x20;       /* Upper to lower case */
                    513: #endif
                    514:                else
                    515:                        ++bp;
                    516: }
                    517: #endif
                    518: 
                    519: setfold(f,n)
                    520: {
                    521:        if (f)
                    522:                bind.ffold = n;
                    523:        else
                    524:                bind.ffold = !bind.ffold;
                    525:        if (bind.ffold)
                    526:                mlwrite("[Case fold on search]");
                    527:        else
                    528:                mlwrite("[Match case on search]");
                    529:        return TRUE;
                    530: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.