|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ ! 2: static char rcsid[] = "$Header: ins2.c,v 2.4 84/10/26 12:08:24 guido Exp $"; ! 3: ! 4: /* ! 5: * B editor -- Insert characters from keyboard. ! 6: */ ! 7: ! 8: #include "b.h" ! 9: #include "bobj.h" ! 10: #include "node.h" ! 11: #include "supr.h" ! 12: #include "queu.h" ! 13: #include "gram.h" ! 14: #include "tabl.h" ! 15: ! 16: ! 17: /* ! 18: * Insert a character. ! 19: */ ! 20: ! 21: Visible bool ! 22: ins_char(ep, c, alt_c) ! 23: register environ *ep; ! 24: int c; ! 25: int alt_c; ! 26: { ! 27: auto queue q = Qnil; ! 28: auto queue qf = Qnil; ! 29: auto value copyout(); ! 30: auto string str; ! 31: char buf[2]; ! 32: int where; ! 33: bool spwhere; ! 34: ! 35: higher(ep); ! 36: shrink(ep); ! 37: if (index("({[`'\"", c) && !ishole(ep)) { ! 38: /* Surround something. Wonder what will happen! */ ! 39: qf = (queue) copyout(ep); ! 40: if (!delbody(ep)) { ! 41: qrelease(qf); ! 42: return No; ! 43: } ! 44: } ! 45: fixit(ep); ! 46: ep->changed = Yes; ! 47: buf[0] = c; ! 48: buf[1] = 0; ! 49: if (!ins_string(ep, buf, &q, alt_c)) ! 50: return No; ! 51: if (!emptyqueue(q) || !emptyqueue(qf)) { ! 52: /* Slight variation on app_queue */ ! 53: if (!emptyqueue(qf) && emptyqueue(q)) ! 54: ritevhole(ep); /* Wizardry. Why does this work? */ ! 55: spwhere = ep->spflag; ! 56: ep->spflag = No; ! 57: where = focoffset(ep); ! 58: markpath(&ep->focus, 1); ! 59: ep->spflag = spwhere; ! 60: if (ep->mode == FHOLE && ep->s2 > 0) { ! 61: /* If we just caused a suggestion, insert the remains ! 62: after the suggested text, not after its first character. */ ! 63: str = ""; ! 64: if (!soften(ep, &str, 0)) { ! 65: ep->mode = ATEND; ! 66: leftvhole(ep); ! 67: if (symbol(tree(ep->focus)) == Hole) { ! 68: ep->mode = ATBEGIN; ! 69: leftvhole(ep); ! 70: } ! 71: } ! 72: } ! 73: if (!emptyqueue(q)) { /* Re-insert stuff queued by ins_string */ ! 74: if (!ins_queue(ep, &q, &q)) ! 75: return No; ! 76: where += spwhere; ! 77: spwhere = No; ! 78: } ! 79: if (!emptyqueue(qf)) { /* Re-insert deleted old focus */ ! 80: firstmarked(&ep->focus, 1) || Abort(); ! 81: fixfocus(ep, where); ! 82: if (!ins_queue(ep, &qf, &qf)) ! 83: return No; ! 84: } ! 85: firstmarked(&ep->focus, 1) || Abort(); ! 86: unmkpath(&ep->focus, 1); ! 87: ep->spflag = No; ! 88: fixfocus(ep, where + spwhere); ! 89: } ! 90: return Yes; ! 91: } ! 92: ! 93: ! 94: /* ! 95: * Insert a newline. ! 96: */ ! 97: ! 98: Visible bool ! 99: ins_newline(ep) ! 100: register environ *ep; ! 101: { ! 102: register node n; ! 103: register int sym; ! 104: auto bool mayindent; ! 105: ! 106: ep->changed = Yes; ! 107: if (!fiddle(ep, &mayindent)) ! 108: return No; ! 109: for (;;) { ! 110: switch (ep->mode) { ! 111: ! 112: case VHOLE: ! 113: ep->mode = ATEND; ! 114: continue; ! 115: ! 116: case FHOLE: ! 117: ep->s2 = lenitem(ep); ! 118: if (!fix_move(ep)) ! 119: return No; ! 120: continue; ! 121: ! 122: case ATEND: ! 123: if (!joinstring(&ep->focus, "\n", No, 0, mayindent)) { ! 124: if (!move_on(ep)) ! 125: return No; ! 126: continue; ! 127: } ! 128: s_downi(ep, 2); ! 129: s_downi(ep, 1); ! 130: ep->mode = WHOLE; ! 131: Assert((sym = symbol(tree(ep->focus))) == Hole || sym == Optional); ! 132: return Yes; ! 133: ! 134: case ATBEGIN: ! 135: n = tree(ep->focus); ! 136: if (Type(n) == Tex) { ! 137: ep->mode = ATEND; ! 138: continue; ! 139: } ! 140: sym = symbol(n); ! 141: if (sym == Hole || sym == Optional) { ! 142: ep->mode = WHOLE; ! 143: continue; ! 144: } ! 145: n = nodecopy(n); ! 146: if (!fitstring(&ep->focus, "\n", 0)) { ! 147: if (!down(&ep->focus)) ! 148: ep->mode = ATEND; ! 149: noderelease(n); ! 150: continue; ! 151: } ! 152: s_downrite(ep); ! 153: if (fitnode(&ep->focus, n)) { ! 154: noderelease(n); ! 155: s_up(ep); ! 156: s_down(ep); ! 157: ep->mode = WHOLE; ! 158: return Yes; ! 159: } ! 160: s_up(ep); ! 161: s_down(ep); ! 162: if (!fitnode(&ep->focus, n)) { ! 163: noderelease(n); ! 164: #ifndef NDEBUG ! 165: debug("[Sorry, I don't see how to insert a newline here]"); ! 166: #endif NDEBUG ! 167: return No; ! 168: } ! 169: noderelease(n); ! 170: ep->mode = ATBEGIN; ! 171: return Yes; ! 172: ! 173: case WHOLE: ! 174: Assert((sym = symbol(tree(ep->focus))) == Hole || sym == Optional); ! 175: if (!fitstring(&ep->focus, "\n", 0)) { ! 176: ep->mode = ATEND; ! 177: continue; ! 178: } ! 179: s_downi(ep, 1); ! 180: Assert((sym = symbol(tree(ep->focus))) == Hole || sym == Optional); ! 181: ep->mode = WHOLE; ! 182: return Yes; ! 183: ! 184: default: ! 185: Abort(); ! 186: ! 187: } ! 188: } ! 189: } ! 190: ! 191: ! 192: /* ! 193: * Refinement for ins_newline() to do the initial processing. ! 194: */ ! 195: ! 196: Hidden bool ! 197: fiddle(ep, pmayindent) ! 198: register environ *ep; ! 199: bool *pmayindent; ! 200: { ! 201: register int level; ! 202: auto string str = ""; ! 203: ! 204: higher(ep); ! 205: while (rnarrow(ep)) ! 206: ; ! 207: fixit(ep); ! 208: soften(ep, &str, 0); ! 209: higher(ep); ! 210: *pmayindent = Yes; ! 211: if (atdedent(ep)) { ! 212: *pmayindent = No; ! 213: s_up(ep); ! 214: level = Level(ep->focus); ! 215: delfocus(&ep->focus); ! 216: if (symbol(tree(ep->focus)) == Hole) { ! 217: if (hackhack(ep)) ! 218: return Yes; ! 219: } ! 220: while (Level(ep->focus) >= level) { ! 221: if (!nexthole(ep)) { ! 222: ep->mode = ATEND; ! 223: break; ! 224: } ! 225: } ! 226: if (ep->mode == ATEND) { ! 227: leftvhole(ep); ! 228: ep->mode = ATEND; ! 229: while (Level(ep->focus) >= level) { ! 230: if (!up(&ep->focus)) ! 231: return No; ! 232: } ! 233: } ! 234: return Yes; ! 235: } ! 236: return Yes; ! 237: } ! 238: ! 239: ! 240: /* ! 241: * "Hier komen de houthakkers." ! 242: * ! 243: * Incredibly ugly hack to delete a join whose second child begins with \n, ! 244: * such as a suite after an IF, FOR or WHILE or unit heading. ! 245: * Inspects the parent node. ! 246: * If this has rp[0] ands rp[1] both empty, replace it by its first child. ! 247: * (caller assures this makes sense). ! 248: * Return Yes if this happened AND rp[1] contained a \t. ! 249: */ ! 250: ! 251: Hidden Procedure ! 252: hackhack(ep) ! 253: environ *ep; ! 254: { ! 255: node n; ! 256: int ich = ichild(ep->focus); ! 257: string *rp; ! 258: ! 259: if (!up(&ep->focus)) ! 260: return No; ! 261: higher(ep); ! 262: rp = noderepr(tree(ep->focus)); ! 263: if (!Fw_zero(rp[0]) || !Fw_zero(rp[1])) { ! 264: s_downi(ep, ich); ! 265: return No; ! 266: } ! 267: n = nodecopy(firstchild(tree(ep->focus))); ! 268: delfocus(&ep->focus); ! 269: replace(&ep->focus, n); ! 270: ep->mode = ATEND; ! 271: return rp[1] && rp[1][0] == '\t'; ! 272: } ! 273: ! 274: ! 275: /* ! 276: * Refinement for fiddle() to find out whether we are at a possible ! 277: * decrease-indentation position. ! 278: */ ! 279: ! 280: Hidden bool ! 281: atdedent(ep) ! 282: register environ *ep; ! 283: { ! 284: register path pa; ! 285: register node npa; ! 286: register int i; ! 287: register int sym = symbol(tree(ep->focus)); ! 288: ! 289: if (sym != Hole && sym != Optional) ! 290: return No; ! 291: if (ichild(ep->focus) != 1) ! 292: return No; ! 293: switch (ep->mode) { ! 294: case FHOLE: ! 295: if (ep->s1 != 1 || ep->s2 != 0) ! 296: return No; ! 297: break; ! 298: case ATBEGIN: ! 299: case WHOLE: ! 300: case SUBSET: ! 301: break; ! 302: default: ! 303: return No; ! 304: } ! 305: pa = parent(ep->focus); ! 306: if (!pa) ! 307: return No; ! 308: npa = tree(pa); ! 309: if (fwidth(noderepr(npa)[0]) >= 0) ! 310: return No; ! 311: for (i = nchildren(npa); i > 1; --i) { ! 312: sym = symbol(child(npa, i)); ! 313: if (sym != Hole && sym != Optional) ! 314: return No; ! 315: } ! 316: return Yes; /* Sigh! */ ! 317: } ! 318: ! 319: /* ! 320: * Refinement for ins_node() and fiddle() to find the next hole, ! 321: * skipping blank space only. ! 322: */ ! 323: ! 324: Hidden bool ! 325: nexthole(ep) ! 326: register environ *ep; ! 327: { ! 328: register node n; ! 329: register int ich; ! 330: register string repr; ! 331: ! 332: do { ! 333: ich = ichild(ep->focus); ! 334: if (!up(&ep->focus)) ! 335: return No; ! 336: higher(ep); ! 337: n = tree(ep->focus); ! 338: repr = noderepr(n)[ich]; ! 339: if (!Fw_zero(repr) && !allspaces(repr)) ! 340: return No; ! 341: } while (ich >= nchildren(n)); ! 342: s_downi(ep, ich+1); ! 343: return Yes; ! 344: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.