|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.