1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
   2: static char rcsid[] = "$Header: goto.c,v 2.4 85/08/22 16:03:06 timo Exp $";
   3: 
   4: /*
   5:  * B editor -- Random access focus positioning.
   6:  */
   7: 
   8: #include "b.h"
   9: #include "feat.h"
  10: #include "erro.h"
  11: #include "node.h"
  12: #include "gram.h"
  13: #include "supr.h"
  14: 
  15: 
  16: extern int winheight;
  17: extern int winstart;
  18: 
  19: 
  20: #define BEFORE (-1)
  21: #define INSIDE 0
  22: #define BEYOND 1
  23: 
  24: 
  25: /*
  26:  * Random cursor positioning (e.g., with a mouse).
  27:  */
  28: 
  29: Visible bool
  30: gotocursor(ep)
  31:     environ *ep;
  32: {
  33:     int y;
  34:     int x;
  35: 
  36:     if (!sense(&y, &x))
  37:         return No;
  38: #ifdef SCROLLBAR
  39:     if (y == winheight)
  40:         return gotoscrollbar(ep, y, x);
  41: #endif SCROLLBAR
  42:     if (!backtranslate(&y, &x))
  43:         return No;
  44:     if (!gotoyx(ep, y, x))
  45:         return No;
  46:     gotofix(ep, y, x);
  47:     return Yes;
  48: }
  49: 
  50: #ifdef SCROLLBAR
  51: 
  52: /*
  53:  * Special case for goto: user pointed at some point in the scroll bar.
  54:  * Go directly to the corresponding line.
  55:  * (The scroll bar is only present when winstart == 0; it extends from
  56:  * col 0 to winheight-1 inclusive.)
  57:  */
  58: 
  59: Hidden bool
  60: gotoscrollbar(ep, y, x)
  61:     environ *ep;
  62:     int y;
  63:     int x;
  64: {
  65:     int w;
  66: 
  67:     if (winstart != 0 || x >= winheight) { /* Not within scroll bar */
  68:         error(GOTO_OUT);
  69:         return No;
  70:     }
  71:     top(&ep->focus);
  72:     ep->mode = WHOLE;
  73:     higher(ep);
  74:     w = width(tree(ep->focus));
  75:     if (w >= 0)
  76:         w = 1;
  77:     else
  78:         w = 1-w;
  79:     if (!gotoyx(ep, x * w / winheight, 0))
  80:         return No;
  81:     oneline(ep);
  82:     return Yes;
  83: }
  84: 
  85: #endif SCROLLBAR
  86: 
  87: /*
  88:  * Set the focus to the smallest node or subset surrounding
  89:  * the position (y, x).
  90:  */
  91: 
  92: Visible bool
  93: gotoyx(ep, y, x)
  94:     register environ *ep;
  95:     register int y;
  96:     register int x;
  97: {
  98:     register node n;
  99:     register string *rp;
 100:     register int i;
 101:     register int pc;
 102: 
 103:     ep->mode = WHOLE;
 104:     while ((pc = poscomp(ep->focus, y, x)) != INSIDE) {
 105:         if (!up(&ep->focus)) {
 106:             if (pc == BEFORE)
 107:                 ep->mode = ATBEGIN;
 108:             else
 109:                 ep->mode = ATEND;
 110:             higher(ep);
 111:             return No;
 112:         }
 113:     }
 114:     higher(ep);
 115:     for (;;) {
 116:         switch (poscomp(ep->focus, y, x)) {
 117: 
 118:         case BEFORE:
 119:             i = ichild(ep->focus);
 120:             n = tree(parent(ep->focus)); /* Parent's !!! */
 121:             rp = noderepr(n);
 122:             if (Fw_positive(rp[i-1])) {
 123:                 s_up(ep);
 124:                 ep->s1 = ep->s2 = 2*i - 1;
 125:                 ep->mode = SUBSET;
 126:             }
 127:             else if (left(&ep->focus))
 128:                 ep->mode = ATEND;
 129:             else
 130:                 ep->mode = ATBEGIN;
 131:             return Yes;
 132: 
 133:         case INSIDE:
 134:             n = tree(ep->focus);
 135:             if (nchildren(n) >= 1 && Type(firstchild(n)) != Tex) {
 136:                 s_down(ep);
 137:                 continue;
 138:             }
 139:             ep->mode = WHOLE;
 140:             return Yes;
 141: 
 142:         case BEYOND:
 143:             if (rite(&ep->focus))
 144:                 continue;
 145:             n = tree(parent(ep->focus)); /* Parent's !!! */
 146:             rp = noderepr(n);
 147:             i = ichild(ep->focus);
 148:             if (Fw_positive(rp[i])) {
 149:                 s_up(ep);
 150:                 ep->s1 = ep->s2 = 2*i + 1;
 151:                 ep->mode = SUBSET;
 152:             }
 153:             else
 154:                 ep->mode = ATEND;
 155:             return Yes;
 156: 
 157:         default:
 158:             Abort();
 159:             /* NOTREACHED */
 160: 
 161:         }
 162:     }
 163: }
 164: 
 165: 
 166: /*
 167:  * Deliver relative position of (y, x) with respect to focus p:
 168:  * BEFORE: (y, x) precedes focus;
 169:  * INSIDE: (y, x) contained in focus;
 170:  * EAFTER:  (y, x) follows focus.
 171: 
 172:  */
 173: 
 174: Hidden int
 175: poscomp(p, y, x)
 176:     register path p;
 177:     register int y;
 178:     register int x;
 179: {
 180:     register int ly;
 181:     register int lx;
 182:     register int w;
 183:     register string *rp;
 184:     register node n;
 185: 
 186:     ly = Ycoord(p);
 187:     lx = Xcoord(p);
 188:     if (y < ly || y == ly && (lx < 0 || x < lx))
 189:         return BEFORE;
 190:     n = tree(p);
 191:     w = width(n);
 192:     if (w < 0) {
 193:         if (y == ly) { /* Hack for position beyond end of previous line */
 194:             rp = noderepr(n);
 195:             if (Fw_negative(rp[0]))
 196:                 return BEFORE;
 197:         }
 198:         ly += -w;
 199:         lx = -1;
 200:     }
 201:     else {
 202:         if (lx >= 0)
 203:             lx += w;
 204:     }
 205:     if (y < ly || y == ly && (lx < 0 || x < lx))
 206:         return INSIDE;
 207:     return BEYOND;
 208: }
 209: 
 210: 
 211: /*
 212:  * Position focus exactly at character indicated by (y, x) if possible.
 213:  * If this is the start of something larger, position focus at largest
 214:  * object starting here.
 215:  */
 216: 
 217: Visible Procedure
 218: gotofix(ep, y, x)
 219:     environ *ep;
 220:     int y;
 221:     int x;
 222: {
 223:     int fx;
 224:     int fy;
 225:     int len;
 226:     string repr;
 227: 
 228:     switch (ep->mode) {
 229: 
 230:     case ATBEGIN:
 231:     case ATEND:
 232:         return; /* No change; the mouse pointed in the margin. */
 233: 
 234:     case SUBSET:
 235:         if (ep->s1 > 1) {
 236:             fx = Xcoord(ep->focus);
 237:             fy = Ycoord(ep->focus);
 238:             len = focoffset(ep);
 239:             if (len < 0 || fy != y)
 240:                 return;
 241:             if ((ep->s1&1) && fx + len >= x-1) {
 242:                 repr = noderepr(tree(ep->focus))[ep->s1/2];
 243:                 if ((repr && repr[0] == ' ') != (fx + len == x))
 244:                     return;
 245:             }
 246:             else if (fx + len == x)
 247:                 return;
 248:         }
 249:         ep->mode = WHOLE;
 250:         /* Fall through */
 251:     case WHOLE:
 252:         fx = Xcoord(ep->focus);
 253:         fy = Ycoord(ep->focus);
 254:         if (y != fy)
 255:             return;
 256:         if (x <= fx ) {
 257:             for (;;) {
 258:                 if (ichild(ep->focus) > 1)
 259:                     break;
 260:                 if (!up(&ep->focus))
 261:                     break;
 262:                 repr = noderepr(tree(ep->focus))[0];
 263:                 if (!Fw_zero(repr)) {
 264:                     s_down(ep);
 265:                     break;
 266:                 }
 267:                 higher(ep);
 268:             }
 269:             if (issublist(symbol(tree(ep->focus))))
 270:                 fixsublist(ep);
 271:             return;
 272:         }
 273:         fixfocus(ep, x - fx);
 274:         ritevhole(ep);
 275:         switch(ep->mode) {
 276:         case VHOLE:
 277:             len = width(tree(ep->focus));
 278:             break;
 279:         case FHOLE:
 280:             len = fwidth(noderepr(tree(ep->focus))[ep->s1/2]);
 281:             break;
 282:         default:
 283:             return;
 284:         }
 285:         if (ep->s2 < len) {
 286:             ep->mode = SUBRANGE;
 287:             ep->s3 = ep->s2;
 288:         }
 289:         return;
 290: 
 291:     default:
 292:         Abort();
 293:     }
 294: }
 295: 
 296: 
 297: /*
 298:  * Refinement for gotoyx -- don't show right sublist of something.
 299:  */
 300: 
 301: Hidden Procedure
 302: fixsublist(ep)
 303:     environ *ep;
 304: {
 305:     path pa = parent(ep->focus);
 306:     node n;
 307: 
 308:     if (!pa)
 309:         return;
 310:     n = tree(pa);
 311:     if (nchildren(n) > ichild(ep->focus))
 312:         return;
 313:     if (samelevel(symbol(n), symbol(tree(ep->focus)))) {
 314:         ep->mode = SUBLIST;
 315:         ep->s3 = 1;
 316:     }
 317: }

Defined functions

fixsublist defined in line 301; used 1 times
gotocursor defined in line 29; used 1 times
gotofix defined in line 217; used 2 times
gotoscrollbar defined in line 59; used 1 times
  • in line 40
gotoyx defined in line 92; used 6 times
poscomp defined in line 174; used 2 times

Defined variables

rcsid defined in line 2; never used

Defined macros

BEFORE defined in line 20; used 3 times
BEYOND defined in line 22; used 1 times
INSIDE defined in line 21; used 2 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2599
Valid CSS Valid XHTML 1.0 Strict