|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ ! 2: static char rcsid[] = "$Header: move.c,v 2.4 85/08/22 16:05:16 timo Exp $"; ! 3: ! 4: /* ! 5: * B editor -- Process arrow keys in four directions, plus TAB. ! 6: */ ! 7: ! 8: #include "b.h" ! 9: #include "bobj.h" ! 10: #include "node.h" ! 11: #include "supr.h" ! 12: #include "gram.h" ! 13: ! 14: #define Left (-1) ! 15: #define Rite 1 ! 16: ! 17: ! 18: /* ! 19: * Common code for PREVIOUS and NEXT commands. ! 20: */ ! 21: ! 22: Hidden bool ! 23: prevnext(ep, direction) ! 24: environ *ep; ! 25: { ! 26: node n; ! 27: node n1; ! 28: int nch; ! 29: int i; ! 30: int len; ! 31: int sym; ! 32: string *rp; ! 33: ! 34: higher(ep); ! 35: switch (ep->mode) { ! 36: case VHOLE: ! 37: case FHOLE: ! 38: case ATBEGIN: ! 39: case ATEND: ! 40: if (direction == Left) ! 41: leftvhole(ep); ! 42: else ! 43: ritevhole(ep); ! 44: } ! 45: ! 46: for (;;) { ! 47: n = tree(ep->focus); ! 48: nch = nchildren(n); ! 49: rp = noderepr(n); ! 50: ! 51: switch (ep->mode) { ! 52: ! 53: case ATBEGIN: ! 54: case ATEND: ! 55: ep->mode = WHOLE; ! 56: continue; ! 57: ! 58: case VHOLE: ! 59: case FHOLE: ! 60: if (direction == Rite) { ! 61: if (ep->s1&1) ! 62: len = Fwidth(rp[ep->s1/2]); ! 63: else { ! 64: n1 = child(n, ep->s1/2); ! 65: len = width(n1); ! 66: } ! 67: } ! 68: if (direction == Rite ? ep->s2 >= len : ep->s2 <= 0) { ! 69: ep->mode = SUBSET; ! 70: ep->s2 = ep->s1; ! 71: return nextchar(ep, direction); ! 72: } ! 73: ep->s2 += direction; ! 74: return Yes; ! 75: ! 76: case SUBRANGE: ! 77: if (direction == Rite) { ! 78: if (ep->s1&1) ! 79: len = Fwidth(rp[ep->s1/2]); ! 80: else { ! 81: n1 = child(n, ep->s1/2); ! 82: len = width(n1); ! 83: } ! 84: } ! 85: if (direction == Left ? ep->s2 <= 0 : ep->s3 >= len-1) { ! 86: ep->mode = SUBSET; ! 87: ep->s2 = ep->s1; ! 88: return nextchar(ep, direction); ! 89: } ! 90: if (direction == Rite) ! 91: ep->s2 = ++ep->s3; ! 92: else ! 93: ep->s3 = --ep->s2; ! 94: return Yes; ! 95: ! 96: case SUBSET: ! 97: if (direction == Rite ? ep->s2 > 2*nch : ep->s1 <= 1) { ! 98: ep->mode = WHOLE; ! 99: continue; ! 100: } ! 101: if (direction == Rite) ! 102: ep->s1 = ++ep->s2; ! 103: else ! 104: ep->s2 = --ep->s1; ! 105: if (ep->s1&1) { ! 106: if (!Fw_positive(rp[ep->s1/2]) || allspaces(rp[ep->s1/2])) ! 107: continue; ! 108: } ! 109: else { ! 110: sym = symbol(n); ! 111: if (downi(&ep->focus, ep->s1/2)) { ! 112: n = tree(ep->focus); ! 113: if (((value)n)->type == Tex) ! 114: s_up(ep); ! 115: else { ! 116: if (ep->s1 == 2*nch && direction == Rite ! 117: && issublist(sym) && samelevel(sym, symbol(n))) { ! 118: ep->mode = SUBLIST; ! 119: ep->s3 = 1; ! 120: return Yes; ! 121: } ! 122: ep->mode = WHOLE; ! 123: if (width(n) == 0) ! 124: continue; ! 125: } ! 126: } ! 127: } ! 128: return Yes; ! 129: ! 130: case SUBLIST: ! 131: sym = symbol(n); ! 132: if (direction == Left) { ! 133: i = ichild(ep->focus); ! 134: if (!up(&ep->focus)) ! 135: return No; ! 136: higher(ep); ! 137: n = tree(ep->focus); ! 138: if (i == nchildren(n) && samelevel(sym, symbol(n))) { ! 139: ep->s3 = 1; ! 140: return Yes; ! 141: } ! 142: ep->mode = SUBSET; ! 143: ep->s1 = ep->s2 = 2*i; ! 144: continue; ! 145: } ! 146: for (i = ep->s3; i > 0; --i) ! 147: if (!downrite(&ep->focus)) ! 148: return No; /* Sorry... */ ! 149: if (samelevel(sym, symbol(tree(ep->focus)))) ! 150: ep->s3 = 1; ! 151: else ! 152: ep->mode = WHOLE; ! 153: return Yes; ! 154: ! 155: case WHOLE: ! 156: i = ichild(ep->focus); ! 157: if (!up(&ep->focus)) ! 158: return No; ! 159: higher(ep); ! 160: ep->mode = SUBSET; ! 161: ep->s1 = ep->s2 = 2*i; ! 162: continue; ! 163: ! 164: default: ! 165: Abort(); ! 166: } ! 167: } ! 168: /* Not reached */ ! 169: } ! 170: ! 171: Visible bool leftarrow(ep) ! 172: environ *ep; ! 173: { ! 174: int w; ! 175: bool hole; ! 176: ! 177: if (narrow(ep)) { ! 178: while (narrow(ep)) ! 179: ; ! 180: return Yes; ! 181: } ! 182: hole= ep->mode == WHOLE; /* Can't narrow and still WHOLE: */ ! 183: /* a real hole which needs some hacking. */ ! 184: if (!previous(ep)) ! 185: return No; ! 186: if (hole) { ! 187: for (;;) { ! 188: w= focwidth(ep); ! 189: if (w >= 0 && w <= 1) ! 190: break; ! 191: if (!rnarrow(ep)) ! 192: return No; ! 193: } ! 194: narrow(ep); ! 195: } ! 196: else { ! 197: while (rnarrow(ep)) ! 198: ; ! 199: } ! 200: return Yes; ! 201: } ! 202: ! 203: Visible bool ritearrow(ep) ! 204: environ *ep; ! 205: { ! 206: while (narrow(ep)) ! 207: ; ! 208: if (!next(ep)) ! 209: return No; ! 210: while (narrow(ep)) ! 211: ; ! 212: return Yes; ! 213: } ! 214: ! 215: ! 216: Visible bool ! 217: previous(ep) ! 218: environ *ep; ! 219: { ! 220: if (!prevnext(ep, Left)) ! 221: return No; ! 222: return Yes; ! 223: } ! 224: ! 225: ! 226: Visible bool ! 227: next(ep) ! 228: environ *ep; ! 229: { ! 230: if (!prevnext(ep, Rite)) ! 231: return No; ! 232: return Yes; ! 233: } ! 234: ! 235: ! 236: /* ! 237: * Position focus at next or previous char relative to current position. ! 238: * Assume current position given as SUBSET. ! 239: */ ! 240: ! 241: Hidden bool ! 242: nextchar(ep, direction) ! 243: register environ *ep; ! 244: register int direction; ! 245: { ! 246: register int ich; ! 247: register int nch; ! 248: register node n; ! 249: node n1; ! 250: register int len; ! 251: string *rp; ! 252: ! 253: Assert(ep->mode == SUBSET); ! 254: for (;;) { ! 255: n = tree(ep->focus); ! 256: rp = noderepr(n); ! 257: nch = nchildren(n); ! 258: if (direction == Left) ! 259: ep->s2 = --ep->s1; ! 260: else ! 261: ep->s1 = ++ep->s2; ! 262: if (direction == Left ? ep->s1 < 1 : ep->s2 > 2*nch+1) { ! 263: ich = ichild(ep->focus); ! 264: if (!up(&ep->focus)) ! 265: return No; /* *ep is garbage now! */ ! 266: higher(ep); ! 267: ep->s1 = ep->s2 = 2*ich; ! 268: continue; ! 269: } ! 270: if (ep->s1&1) { ! 271: len = Fwidth(rp[ep->s1/2]); ! 272: if (len > 0) { ! 273: ep->mode = SUBRANGE; ! 274: ep->s2 = ep->s3 = direction == Left ? len-1 : 0; ! 275: return Yes; ! 276: } ! 277: continue; ! 278: } ! 279: n1 = child(n, ep->s1/2); ! 280: len = width(n1); ! 281: if (len == 0) ! 282: continue; ! 283: if (!downi(&ep->focus, ep->s1/2)) ! 284: return No; /* Sorry... */ ! 285: n = tree(ep->focus); ! 286: if (((value)n)->type == Tex) { ! 287: s_up(ep); ! 288: ep->mode = SUBRANGE; ! 289: ep->s2 = ep->s3 = direction == Left ? len-1 : 0; ! 290: return Yes; ! 291: } ! 292: if (direction == Left) { ! 293: nch = nchildren(n); ! 294: ep->s1 = ep->s2 = 2*(nch+1); ! 295: } ! 296: else ! 297: ep->s1 = ep->s2 = 0; ! 298: } ! 299: /* Not reached */ ! 300: } ! 301: ! 302: ! 303: /* ! 304: * Up and down arrows. ! 305: */ ! 306: ! 307: Hidden bool ! 308: updownarrow(ep, yincr) ! 309: environ *ep; ! 310: int yincr; ! 311: { ! 312: int y, x; ! 313: ! 314: while (narrow(ep)) ! 315: ; ! 316: y= lineno(ep) + yincr; ! 317: x= colno(ep); ! 318: if (!gotoyx(ep, y, x)) ! 319: return No; ! 320: gotofix(ep, y, x); ! 321: while (narrow(ep)) ! 322: ; ! 323: return Yes; ! 324: } ! 325: ! 326: Visible bool ! 327: uparrow(ep) ! 328: environ *ep; ! 329: { ! 330: return updownarrow(ep, -1); ! 331: } ! 332: ! 333: Visible bool ! 334: downarrow(ep) ! 335: environ *ep; ! 336: { ! 337: return updownarrow(ep, 1); ! 338: } ! 339: ! 340: Visible bool ! 341: upline(ep) ! 342: register environ *ep; ! 343: { ! 344: register int y; ! 345: ! 346: y = lineno(ep); ! 347: if (y <= 0) ! 348: return No; ! 349: if (!gotoyx(ep, y-1, 0)) ! 350: return No; ! 351: oneline(ep); ! 352: return Yes; ! 353: } ! 354: ! 355: Visible bool ! 356: downline(ep) ! 357: register environ *ep; ! 358: { ! 359: register int w; ! 360: ! 361: if (!parent(ep->focus) && ep->mode == ATEND) ! 362: return No; /* Superfluous? */ ! 363: w = -focwidth(ep); ! 364: if (w <= 0) ! 365: w = 1; ! 366: if (!gotoyx(ep, lineno(ep) + w, 0)) ! 367: return No; ! 368: oneline(ep); ! 369: return Yes; ! 370: } ! 371: ! 372: ! 373: /* ! 374: * ACCEPT command ! 375: * move to next Hole hole or to end of suggestion or to end of line. ! 376: */ ! 377: ! 378: ! 379: Visible bool ! 380: accept(ep) ! 381: environ *ep; ! 382: { ! 383: int i; ! 384: string repr; ! 385: ! 386: shrink(ep); ! 387: switch (ep->mode) { ! 388: case ATBEGIN: ! 389: case ATEND: ! 390: case FHOLE: ! 391: case VHOLE: ! 392: ritevhole(ep); ! 393: } ! 394: if (symbol(tree(ep->focus)) == Hole) ! 395: ep->mode = ATEND; ! 396: switch (ep->mode) { ! 397: case ATBEGIN: ! 398: case SUBLIST: ! 399: case WHOLE: ! 400: i = 1; ! 401: break; ! 402: case ATEND: ! 403: i = 2*nchildren(tree(ep->focus)) + 2; ! 404: break; ! 405: case SUBRANGE: ! 406: case VHOLE: ! 407: case FHOLE: ! 408: i = ep->s1; ! 409: if (ep->s2 > 0 && i > 2*nchildren(tree(ep->focus))) ! 410: ++i; /* Kludge so after E?LSE: the focus moves to ELSE: ? */ ! 411: break; ! 412: case SUBSET: ! 413: i = ep->s1 - 1; ! 414: break; ! 415: default: ! 416: Abort(); ! 417: } ! 418: ep->mode = WHOLE; ! 419: for (;;) { ! 420: if (i/2 == nchildren(tree(ep->focus))) { ! 421: repr = noderepr(tree(ep->focus))[i/2]; ! 422: if (Fw_positive(repr)) ! 423: break; ! 424: } ! 425: if (tabstop(ep, i + 1)) ! 426: return Yes; ! 427: i = 2*ichild(ep->focus) + 1; ! 428: if (!up(&ep->focus)) ! 429: break; ! 430: higher(ep); ! 431: } ! 432: ep->mode = ATEND; ! 433: return Yes; ! 434: } ! 435: ! 436: ! 437: /* ! 438: * Find suitable tab stops for accept. ! 439: */ ! 440: ! 441: Hidden bool ! 442: tabstop(ep, i) ! 443: environ *ep; ! 444: int i; ! 445: { ! 446: node n = tree(ep->focus); ! 447: int nch; ! 448: string repr; ! 449: ! 450: if (Type(n) == Tex) ! 451: return No; ! 452: nch = nchildren(n); ! 453: if (i/2 > nch) ! 454: return No; ! 455: if (symbol(n) == Hole) { ! 456: ep->mode = WHOLE; ! 457: return Yes; ! 458: } ! 459: if (i < 2) { ! 460: i = 2; ! 461: if (width(n) < 0) { ! 462: repr = noderepr(n)[0]; ! 463: if (Fw_negative(repr)) { ! 464: ep->mode = ATBEGIN; ! 465: leftvhole(ep); ! 466: return Yes; ! 467: } ! 468: } ! 469: } ! 470: for (i /= 2; i <= nch; ++i) { ! 471: s_downi(ep, i); ! 472: if (tabstop(ep, 1)) ! 473: return Yes; ! 474: s_up(ep); ! 475: } ! 476: return No; ! 477: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.