Annotation of GNUtools/emacs/src/cm.c, revision 1.1

1.1     ! root        1: /* Cursor motion subroutines for GNU Emacs.
        !             2:    Copyright (C) 1985 Free Software Foundation, Inc.
        !             3:     based primarily on public domain code written by Chris Torek
        !             4: 
        !             5: This file is part of GNU Emacs.
        !             6: 
        !             7: GNU Emacs is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 1, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU Emacs is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU Emacs; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: 
        !            22: #include "config.h"
        !            23: #include <stdio.h>
        !            24: #include "cm.h"
        !            25: #include "termhooks.h"
        !            26: 
        !            27: #define        BIG     9999            /* 9999 good on VAXen.  For 16 bit machines
        !            28:                                   use about 2000.... */
        !            29: 
        !            30: char *tgoto ();
        !            31: 
        !            32: extern char *BC, *UP;
        !            33: 
        !            34: int cost;              /* sums up costs */
        !            35: 
        !            36: /* ARGSUSED */
        !            37: evalcost (c)
        !            38:      char c;
        !            39: {
        !            40:   cost++;
        !            41: }
        !            42: 
        !            43: void
        !            44: cmputc (c)
        !            45:      char c;
        !            46: {
        !            47:   if (termscript)
        !            48:     fputc (c & 0177, termscript);
        !            49:   putchar (c & 0177);
        !            50: }
        !            51: 
        !            52: /* NEXT TWO ARE DONE WITH MACROS */
        !            53: #if 0
        !            54: /*
        !            55:  * Assume the cursor is at row row, column col.  Normally used only after
        !            56:  * clearing the screen, when the cursor is at (0, 0), but what the heck,
        !            57:  * let's let the guy put it anywhere.
        !            58:  */
        !            59: 
        !            60: static
        !            61: at (row, col) {
        !            62:     curY = row;
        !            63:     curX = col;
        !            64: }
        !            65: 
        !            66: /*
        !            67:  * Add n columns to the current cursor position.
        !            68:  */
        !            69: 
        !            70: static
        !            71: addcol (n) {
        !            72:     curX += n;
        !            73: 
        !            74:     /*
        !            75:      * If cursor hit edge of screen, what happened?
        !            76:      * N.B.: DO NOT!! write past edge of screen.  If you do, you
        !            77:      * deserve what you get.  Furthermore, on terminals with
        !            78:      * autowrap (but not magicwrap), don't write in the last column
        !            79:      * of the last line.
        !            80:      */
        !            81: 
        !            82:     if (curX == Wcm.cm_cols) {
        !            83:        /*
        !            84:         * Well, if magicwrap, still there, past the edge of the
        !            85:         * screen (!).  If autowrap, on the col 0 of the next line.
        !            86:         * Otherwise on last column.
        !            87:         */
        !            88: 
        !            89:        if (Wcm.cm_magicwrap)
        !            90:            ;                   /* "limbo" */
        !            91:        else if (Wcm.cm_autowrap) {
        !            92:            curX = 0;
        !            93:            curY++;             /* Beware end of screen! */
        !            94:        }
        !            95:        else
        !            96:            curX--;
        !            97:     }
        !            98: }
        !            99: #endif
        !           100: 
        !           101: /*
        !           102:  * (Re)Initialize the cost factors, given the output speed of the terminal
        !           103:  * in the variable ospeed.  (Note: this holds B300, B9600, etc -- ie stuff
        !           104:  * out of <sgtty.h>.)
        !           105:  */
        !           106: 
        !           107: cmcostinit ()
        !           108: {
        !           109:     char *p;
        !           110: 
        !           111: #define        COST(x,e)       (x ? (cost = 0, tputs (x, 1, e), cost) : BIG)
        !           112: #define CMCOST(x,e)    ((x == 0) ? BIG : (p = tgoto(x, 0, 0), COST(p ,e)))
        !           113: 
        !           114:     Wcm.cc_up =                COST (Wcm.cm_up, evalcost);
        !           115:     Wcm.cc_down =      COST (Wcm.cm_down, evalcost);
        !           116:     Wcm.cc_left =      COST (Wcm.cm_left, evalcost);
        !           117:     Wcm.cc_right =     COST (Wcm.cm_right, evalcost);
        !           118:     Wcm.cc_home =      COST (Wcm.cm_home, evalcost);
        !           119:     Wcm.cc_cr =                COST (Wcm.cm_cr, evalcost);
        !           120:     Wcm.cc_ll =                COST (Wcm.cm_ll, evalcost);
        !           121:     Wcm.cc_tab =       Wcm.cm_tabwidth ? COST (Wcm.cm_tab, evalcost) : BIG;
        !           122: 
        !           123:     /*
        !           124:      * These last three are actually minimum costs.  When (if) they are
        !           125:      * candidates for the least-cost motion, the real cost is computed.
        !           126:      * (Note that "0" is the assumed to generate the minimum cost.
        !           127:      * While this is not necessarily true, I have yet to see a terminal
        !           128:      * for which is not; all the terminals that have variable-cost
        !           129:      * cursor motion seem to take straight numeric values.  --ACT)
        !           130:      */
        !           131: 
        !           132:     Wcm.cc_abs =  CMCOST (Wcm.cm_abs, evalcost);
        !           133:     Wcm.cc_habs = CMCOST (Wcm.cm_habs, evalcost);
        !           134:     Wcm.cc_vabs = CMCOST (Wcm.cm_vabs, evalcost);
        !           135: 
        !           136: #undef CMCOST
        !           137: #undef COST
        !           138: }
        !           139: 
        !           140: /*
        !           141:  * Calculate the cost to move from (srcy, srcx) to (dsty, dstx) using
        !           142:  * up and down, and left and right, motions, and tabs.  If doit is set
        !           143:  * actually perform the motion.
        !           144:  */
        !           145: 
        !           146: static
        !           147: calccost (srcy, srcx, dsty, dstx, doit)
        !           148: {
        !           149:     register int    deltay,
        !           150:                     deltax,
        !           151:                     c,
        !           152:                     totalcost;
        !           153:     int     ntabs,
        !           154:             n2tabs,
        !           155:             tabx,
        !           156:             tab2x,
        !           157:             tabcost;
        !           158:     register char  *p;
        !           159: 
        !           160:     /* If have just wrapped on a terminal with xn,
        !           161:        don't believe the cursor position: give up here
        !           162:        and force use of absolute positioning.  */
        !           163: 
        !           164:     if (curX == Wcm.cm_cols)
        !           165:       goto fail;
        !           166: 
        !           167:     totalcost = 0;
        !           168:     if ((deltay = dsty - srcy) == 0)
        !           169:        goto x;
        !           170:     if (deltay < 0)
        !           171:        p = Wcm.cm_up, c = Wcm.cc_up, deltay = -deltay;
        !           172:     else
        !           173:        p = Wcm.cm_down, c = Wcm.cc_down;
        !           174:     if (c == BIG) {            /* caint get thar from here */
        !           175:        if (doit)
        !           176:            printf ("OOPS");
        !           177:        return c;
        !           178:     }
        !           179:     totalcost = c * deltay;
        !           180:     if (doit)
        !           181:        while (--deltay >= 0)
        !           182:            tputs (p, 1, cmputc);
        !           183: x: 
        !           184:     if ((deltax = dstx - srcx) == 0)
        !           185:        goto done;
        !           186:     if (deltax < 0) {
        !           187:        p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
        !           188:        goto dodelta;           /* skip all the tab junk */
        !           189:     }
        !           190:     /* Tabs (the toughie) */
        !           191:     if (Wcm.cc_tab >= BIG || !Wcm.cm_usetabs)
        !           192:        goto olddelta;          /* forget it! */
        !           193: 
        !           194:     /* 
        !           195:      * ntabs is # tabs towards but not past dstx; n2tabs is one more
        !           196:      * (ie past dstx), but this is only valid if that is not past the
        !           197:      * right edge of the screen.  We can check that at the same time
        !           198:      * as we figure out where we would be if we use the tabs (which
        !           199:      * we will put into tabx (for ntabs) and tab2x (for n2tabs)).
        !           200:      */
        !           201: 
        !           202:     ntabs = (deltax + srcx % Wcm.cm_tabwidth) / Wcm.cm_tabwidth;
        !           203:     n2tabs = ntabs + 1;
        !           204:     tabx = (srcx / Wcm.cm_tabwidth + ntabs) * Wcm.cm_tabwidth;
        !           205:     tab2x = tabx + Wcm.cm_tabwidth;
        !           206: 
        !           207:     if (tab2x >= Wcm.cm_cols)  /* too far (past edge) */
        !           208:        n2tabs = 0;
        !           209: 
        !           210:     /* 
        !           211:      * Now set tabcost to the cost for using ntabs, and c to the cost
        !           212:      * for using n2tabs, then pick the minimum.
        !           213:      */
        !           214: 
        !           215:                   /* cost for ntabs     +    cost for right motion */
        !           216:     tabcost = ntabs ? ntabs * Wcm.cc_tab + (dstx - tabx) * Wcm.cc_right
        !           217:                    : BIG;
        !           218: 
        !           219:                   /* cost for n2tabs    +    cost for left motion */
        !           220:     c = n2tabs  ?    n2tabs * Wcm.cc_tab + (tab2x - dstx) * Wcm.cc_left
        !           221:                : BIG;
        !           222: 
        !           223:     if (c < tabcost)           /* then cheaper to overshoot & back up */
        !           224:        ntabs = n2tabs, tabcost = c, tabx = tab2x;
        !           225: 
        !           226:     if (tabcost >= BIG)                /* caint use tabs */
        !           227:        goto newdelta;
        !           228: 
        !           229:     /* 
        !           230:      * See if tabcost is less than just moving right
        !           231:      */
        !           232: 
        !           233:     if (tabcost < (deltax * Wcm.cc_right)) {
        !           234:        totalcost += tabcost;   /* use the tabs */
        !           235:        if (doit)
        !           236:            while (--ntabs >= 0)
        !           237:                tputs (Wcm.cm_tab, 1, cmputc);
        !           238:        srcx = tabx;
        !           239:     }
        !           240: 
        !           241:     /* 
        !           242:      * Now might as well just recompute the delta.
        !           243:      */
        !           244: 
        !           245: newdelta: 
        !           246:     if ((deltax = dstx - srcx) == 0)
        !           247:        goto done;
        !           248: olddelta: 
        !           249:     if (deltax > 0)
        !           250:        p = Wcm.cm_right, c = Wcm.cc_right;
        !           251:     else
        !           252:        p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
        !           253: 
        !           254: dodelta: 
        !           255:     if (c == BIG) {            /* caint get thar from here */
        !           256: fail:
        !           257:        if (doit)
        !           258:            printf ("OOPS");
        !           259:        return BIG;
        !           260:     }
        !           261:     totalcost += c * deltax;
        !           262:     if (doit)
        !           263:        while (--deltax >= 0)
        !           264:            tputs (p, 1, cmputc);
        !           265: done: 
        !           266:     return totalcost;
        !           267: }
        !           268: 
        !           269: losecursor ()
        !           270: {
        !           271:   curY = -1;
        !           272: }
        !           273: 
        !           274: #define        USEREL  0
        !           275: #define        USEHOME 1
        !           276: #define        USELL   2
        !           277: #define        USECR   3
        !           278: 
        !           279: cmgoto (row, col)
        !           280: {
        !           281:     int     homecost,
        !           282:             crcost,
        !           283:             llcost,
        !           284:             relcost,
        !           285:             directcost;
        !           286:     int     use;
        !           287:     char   *p,
        !           288:            *dcm;
        !           289: 
        !           290:   /* First the degenerate case */
        !           291:   if (row == curY && col == curX) /* already there */
        !           292:     return;
        !           293: 
        !           294:   if (curY >= 0 && curX >= 0)
        !           295:     {
        !           296:       /* 
        !           297:        * Pick least-cost motions
        !           298:        */
        !           299: 
        !           300:       relcost = calccost (curY, curX, row, col, 0);
        !           301:       use = USEREL;
        !           302:       if ((homecost = Wcm.cc_home) < BIG)
        !           303:          homecost += calccost (0, 0, row, col, 0);
        !           304:       if (homecost < relcost)
        !           305:          relcost = homecost, use = USEHOME;
        !           306:       if ((llcost = Wcm.cc_ll) < BIG)
        !           307:          llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0);
        !           308:       if (llcost < relcost)
        !           309:          relcost = llcost, use = USELL;
        !           310:       if ((crcost = Wcm.cc_cr) < BIG) {
        !           311:          if (Wcm.cm_autolf)
        !           312:              if (curY + 1 >= Wcm.cm_rows)
        !           313:                  crcost = BIG;
        !           314:              else
        !           315:                  crcost += calccost (curY + 1, 0, row, col, 0);
        !           316:          else
        !           317:              crcost += calccost (curY, 0, row, col, 0);
        !           318:       }
        !           319:       if (crcost < relcost)
        !           320:          relcost = crcost, use = USECR;
        !           321:       directcost = Wcm.cc_abs, dcm = Wcm.cm_abs;
        !           322:       if (row == curY && Wcm.cc_habs < BIG)
        !           323:          directcost = Wcm.cc_habs, dcm = Wcm.cm_habs;
        !           324:       else if (col == curX && Wcm.cc_vabs < BIG)
        !           325:          directcost = Wcm.cc_vabs, dcm = Wcm.cm_vabs;
        !           326:     }
        !           327:   else
        !           328:     {
        !           329:       directcost = 0, relcost = 100000;
        !           330:       dcm = Wcm.cm_abs;
        !           331:     }
        !           332: 
        !           333:   /* 
        !           334:    * In the following comparison, the = in <= is because when the costs
        !           335:    * are the same, it looks nicer (I think) to move directly there.
        !           336:    */
        !           337:   if (directcost <= relcost)
        !           338:     {
        !           339:       /* compute REAL direct cost */
        !           340:       cost = 0;
        !           341:       p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) :
        !           342:                               tgoto (dcm, col, row);
        !           343:       tputs (p, 1, evalcost);
        !           344:       if (cost <= relcost)
        !           345:        {       /* really is cheaper */
        !           346:          tputs (p, 1, cmputc);
        !           347:          curY = row, curX = col;
        !           348:          return;
        !           349:        }
        !           350:     }
        !           351: 
        !           352:   switch (use)
        !           353:     {
        !           354:     case USEHOME: 
        !           355:       tputs (Wcm.cm_home, 1, cmputc);
        !           356:       curY = 0, curX = 0;
        !           357:       break;
        !           358: 
        !           359:     case USELL: 
        !           360:       tputs (Wcm.cm_ll, 1, cmputc);
        !           361:       curY = Wcm.cm_rows - 1, curX = 0;
        !           362:       break;
        !           363: 
        !           364:     case USECR: 
        !           365:       tputs (Wcm.cm_cr, 1, cmputc);
        !           366:       if (Wcm.cm_autolf)
        !           367:        curY++;
        !           368:       curX = 0;
        !           369:       break;
        !           370:     }
        !           371: 
        !           372:   (void) calccost (curY, curX, row, col, 1);
        !           373:   curY = row, curX = col;
        !           374: }
        !           375: 
        !           376: /* Clear out all terminal info.
        !           377:    Used before copying into it the info on the actual terminal.
        !           378:  */
        !           379: 
        !           380: Wcm_clear ()
        !           381: {
        !           382:   bzero (&Wcm, sizeof Wcm);
        !           383:   UP = 0;
        !           384:   BC = 0;
        !           385: }
        !           386: 
        !           387: /*
        !           388:  * Initialized stuff
        !           389:  * Return 0 if can do CM.
        !           390:  */
        !           391: 
        !           392: Wcm_init ()
        !           393: {
        !           394:   /* Check that we know the size of the screen.... */
        !           395:   if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0)
        !           396:     return - 1;
        !           397:   if (Wcm.cm_abs && !Wcm.cm_ds)
        !           398:     return 0;
        !           399:   /* Require up and left, and, if no absolute, down and right */
        !           400:   if (!Wcm.cm_up || !Wcm.cm_left)
        !           401:     return - 1;
        !           402:   if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right))
        !           403:     return - 1;
        !           404:   return 0;
        !           405: }

unix.superglobalmegacorp.com

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