|
|
1.1 ! root 1: /* ! 2: * The routines in this file ! 3: * implement commands that work word at ! 4: * a time. There are all sorts of word mode ! 5: * commands. If I do any sentence and/or paragraph ! 6: * mode commands, they are likely to be put in ! 7: * this file. ! 8: */ ! 9: #include <stdio.h> ! 10: #if NORMAL_CHARS ! 11: #include <ctype.h> ! 12: #endif ! 13: #include "ed.h" ! 14: ! 15: /* ! 16: * Word wrap on input. ! 17: * called when data is typed in checks that we are at an ! 18: * end of line. And then trys to wrap the line. ! 19: */ ! 20: void ! 21: wrapword() ! 22: { ! 23: register LINE *clp; ! 24: ! 25: if (llength(clp = curwp->w_dotp) == curwp->w_doto) ! 26: wrapblock(clp, 0, llength(clp), 0); ! 27: } ! 28: ! 29: /* ! 30: * Refill region between mark and cursor. ! 31: */ ! 32: fillregion(f, n) ! 33: { ! 34: REGION region; ! 35: ! 36: if (getregion(®ion) != TRUE) ! 37: return (FALSE); ! 38: ! 39: if (!bind.fillcol) { ! 40: mlwrite("Use <ctl-x> f to set fill collumn first"); ! 41: return (FALSE); ! 42: } ! 43: return (wrapblock(region.r_linep, region.r_offset, region.r_size, ! 44: truecol(region.r_linep, region.r_offset))); ! 45: } ! 46: ! 47: /* ! 48: * wrap a block of data. Gets the start address, size and ! 49: * true collum of the start. Triggers when printable chars ! 50: * are over wrap length and there is white space before them. ! 51: */ ! 52: wrapblock(lineP, offset, size, trueCol) ! 53: register LINE *lineP; ! 54: short offset, size, trueCol; ! 55: { ! 56: int blackCt, whiteCt; ! 57: ! 58: for (blackCt = whiteCt = 0; size-- > 0; offset++) { ! 59: if (offset == llength(lineP)) { ! 60: if (!size) ! 61: break; ! 62: whiteCt = blackCt = 0; ! 63: while (!llength(lineP = lforw(lineP))) { ! 64: size--; ! 65: trueCol = 0; ! 66: offset = -1; ! 67: } ! 68: if (-1 == offset) ! 69: continue; ! 70: curwp->w_doto = offset; ! 71: curwp->w_dotp = lineP = lback(lineP); ! 72: ldelete(1, FALSE); ! 73: linsert(whiteCt = 1, ' '); ! 74: trueCol++; ! 75: offset = curwp->w_doto - 1; ! 76: lineP = curwp->w_dotp; ! 77: continue; ! 78: } ! 79: switch (lgetc(lineP, offset)) { ! 80: case '\t': ! 81: taber(trueCol); ! 82: case ' ': ! 83: if (!blackCt) ! 84: whiteCt++; ! 85: else { ! 86: whiteCt = 1; ! 87: blackCt = 0; ! 88: } ! 89: break; ! 90: default: ! 91: if (!blackCt) ! 92: blackCt = 1; ! 93: else ! 94: blackCt++; ! 95: } ! 96: if ((trueCol++ > bind.fillcol) && whiteCt && blackCt) { ! 97: curwp->w_dotp = lineP; ! 98: curwp->w_doto = offset -= whiteCt + blackCt - 1; ! 99: lnewline(); ! 100: ldelete(whiteCt, FALSE); ! 101: whiteCt = 0; ! 102: offset = (trueCol = blackCt) - 1; ! 103: lineP = curwp->w_dotp; ! 104: } ! 105: } ! 106: curwp->w_doto = llength(curwp->w_dotp); ! 107: return (TRUE); ! 108: } ! 109: ! 110: /* ! 111: * Return TRUE if the character at dot is a character that is considered ! 112: * to be white space. Used in wordwrap. ! 113: * The whitespace character list is hard coded. Should be setable. ! 114: */ ! 115: inwhite() ! 116: { ! 117: register int c; ! 118: ! 119: if (curwp->w_doto == llength(curwp->w_dotp)) ! 120: return (FALSE); ! 121: c = lgetc(curwp->w_dotp, curwp->w_doto); ! 122: if (c == ' ' || c == '\t' ) ! 123: return (TRUE); ! 124: return (FALSE); ! 125: } ! 126: ! 127: /* ! 128: * Move the cursor backward to the last bit of whitespace... ! 129: * All of the details of motion are performed by the "backchar" and "forwchar" ! 130: * routines. Error if you try to move beyond the buffers. ! 131: */ ! 132: backwhite() ! 133: { ! 134: if (backchar(FALSE, 1) == FALSE) ! 135: return (FALSE); ! 136: while (!inwhite()) { ! 137: if (backchar(FALSE, 1) == FALSE) ! 138: return (FALSE); ! 139: } ! 140: return (forwchar(FALSE, 1)); ! 141: } ! 142: ! 143: /* ! 144: * Move the cursor backward by "n" words. All of the details of motion ! 145: * are performed by the "backchar" and "forwchar" routines. Error if you ! 146: * try to move beyond the buffers. ! 147: */ ! 148: backword(f, n) ! 149: { ! 150: if (n < 0) ! 151: return (forwword(f, -n)); ! 152: if (backchar(FALSE, 1) == FALSE) ! 153: return (FALSE); ! 154: while (n--) { ! 155: while (inword() == FALSE) { ! 156: if (backchar(FALSE, 1) == FALSE) ! 157: return (FALSE); ! 158: } ! 159: while (inword() != FALSE) { ! 160: if (backchar(FALSE, 1) == FALSE) ! 161: return (FALSE); ! 162: } ! 163: } ! 164: return (forwchar(FALSE, 1)); ! 165: } ! 166: ! 167: /* ! 168: * Move the cursor forward by the specified number of words. All of the ! 169: * motion is done by "forwchar". Error if you try and move beyond the ! 170: * buffer's end. ! 171: */ ! 172: forwword(f, n) ! 173: { ! 174: if (n < 0) ! 175: return (backword(f, -n)); ! 176: while (n--) { ! 177: while (inword() == FALSE) { ! 178: if (forwchar(FALSE, 1) == FALSE) ! 179: return (FALSE); ! 180: } ! 181: while (inword() != FALSE) { ! 182: if (forwchar(FALSE, 1) == FALSE) ! 183: return (FALSE); ! 184: } ! 185: } ! 186: return (TRUE); ! 187: } ! 188: ! 189: /* ! 190: * There is no pattern I can discover to the upper and lower case ! 191: * of the wierd umlauts etc tacked on to ascii. These tables are the ! 192: * convertable wierd characters upFor has the upper case and loFor ! 193: * the corresponding lower case. ! 194: */ ! 195: static uchar upFor[8] = { 0x80, 0x9A, 0x90, 0x8E, 0x8F, 0x92, 0x99, 0 }; ! 196: static uchar loFor[8] = { 0x87, 0x81, 0x82, 0x84, 0x86, 0x91, 0x94, 0 }; ! 197: ! 198: /* ! 199: * Turn a char to upper case. ! 200: */ ! 201: capChar() ! 202: { ! 203: register int c; ! 204: ! 205: if (c = islow(lgetc(curwp->w_dotp, curwp->w_doto))) { ! 206: lputc(curwp->w_dotp, curwp->w_doto, c); ! 207: lchange(WFHARD); ! 208: } ! 209: return (forwchar(FALSE, 1)); ! 210: } ! 211: ! 212: /* ! 213: * If character is lower case return upper case version. ! 214: * else return 0 ! 215: */ ! 216: islow(c) ! 217: register int c; ! 218: { ! 219: #if NORMAL_CHARS ! 220: return (islower(c) ? toupper(c) : 0); ! 221: #else ! 222: int i, d; ! 223: ! 224: if (c>='a' && c<='z') ! 225: return (c - ('a'-'A')); ! 226: ! 227: if (c & 0x80) ! 228: for (i = 0; d = loFor[i]; i++) ! 229: if (d == c) ! 230: return (upFor[i]); ! 231: return (0); ! 232: #endif ! 233: } ! 234: ! 235: /* ! 236: * Turn a char to lower case. ! 237: */ ! 238: lowChar() ! 239: { ! 240: register int c; ! 241: ! 242: if (c = ishi(lgetc(curwp->w_dotp, curwp->w_doto))) { ! 243: lputc(curwp->w_dotp, curwp->w_doto, c); ! 244: lchange(WFHARD); ! 245: } ! 246: return (forwchar(FALSE, 1)); ! 247: } ! 248: ! 249: /* ! 250: * If character is upper case return lower case version. ! 251: * else return 0 ! 252: */ ! 253: ishi(c) ! 254: register int c; ! 255: { ! 256: #if NORMAL_CHARS ! 257: return (isupper(c) ? tolower(c) : 0); ! 258: #else ! 259: int i, d; ! 260: ! 261: if (c>='A' && c<='Z') ! 262: return (c - ('A'-'a')); ! 263: ! 264: if (c & 0x80) ! 265: for (i = 0; d = upFor[i]; i++) ! 266: if (d == c) ! 267: return (loFor[i]); ! 268: return (0); ! 269: #endif ! 270: } ! 271: ! 272: /* ! 273: * Move the cursor forward by the specified number of words. As you move, ! 274: * convert any characters to upper case. Error if you try and move beyond ! 275: * the end of the buffer. ! 276: * Bound to "M-U". ! 277: */ ! 278: upperword(f, n) ! 279: { ! 280: if (n < 0) ! 281: return (FALSE); ! 282: while (n--) { ! 283: while (inword() == FALSE) ! 284: if (forwchar(FALSE, 1) == FALSE) ! 285: return (FALSE); ! 286: ! 287: while (inword() != FALSE) ! 288: if (capChar() == FALSE) ! 289: return (FALSE); ! 290: } ! 291: return (TRUE); ! 292: } ! 293: ! 294: /* ! 295: * Move the cursor forward by the specified number of words. As you move ! 296: * convert characters to lower case. Error if you try and move over the ! 297: * end of the buffer. ! 298: * Bound to "M-L". ! 299: */ ! 300: lowerword(f, n) ! 301: { ! 302: register int c; ! 303: ! 304: if (n < 0) ! 305: return (FALSE); ! 306: while (n--) { ! 307: while (inword() == FALSE) ! 308: if (forwchar(FALSE, 1) == FALSE) ! 309: return (FALSE); ! 310: ! 311: while (inword() != FALSE) ! 312: if (lowChar() == FALSE) ! 313: return (FALSE); ! 314: } ! 315: return (TRUE); ! 316: } ! 317: ! 318: /* ! 319: * Move the cursor forward by ! 320: * the specified number of words. As you move ! 321: * convert the first character of the word to upper ! 322: * case, and subsequent characters to lower case. Error ! 323: * if you try and move past the end of the buffer. ! 324: * Bound to "M-C". ! 325: */ ! 326: capword(f, n) ! 327: { ! 328: register int c; ! 329: ! 330: if (n < 0) ! 331: return (FALSE); ! 332: while (n--) { ! 333: while (inword() == FALSE) ! 334: if (forwchar(FALSE, 1) == FALSE) ! 335: return (FALSE); ! 336: ! 337: if (inword() != FALSE) { ! 338: if (capChar() == FALSE) ! 339: return (FALSE); ! 340: while (inword() != FALSE) ! 341: if (lowChar() == FALSE) ! 342: return (FALSE); ! 343: } ! 344: } ! 345: return (TRUE); ! 346: } ! 347: ! 348: /* ! 349: * Kill forward by "n" words. ! 350: * Remember the location of dot. Move forward ! 351: * by the right number of words. Put dot back where ! 352: * it was and issue the kill command for the ! 353: * right number of characters. Bound to "M-D". ! 354: */ ! 355: delfword(f, n) ! 356: { ! 357: register int size; ! 358: register LINE *dotp; ! 359: register int doto; ! 360: ! 361: if (n < 0) ! 362: return (FALSE); ! 363: dotp = curwp->w_dotp; ! 364: doto = curwp->w_doto; ! 365: size = 0; ! 366: if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ ! 367: kdelete(); /* last wasn't a kill. */ ! 368: thisflag |= CFKILL; ! 369: while (n--) { ! 370: while (inword() == FALSE) { ! 371: if (forwchar(FALSE, 1) == FALSE) ! 372: return (FALSE); ! 373: ++size; ! 374: } ! 375: while (inword() != FALSE) { ! 376: if (forwchar(FALSE, 1) == FALSE) ! 377: return (FALSE); ! 378: ++size; ! 379: } ! 380: } ! 381: curwp->w_dotp = dotp; ! 382: curwp->w_doto = doto; ! 383: return (ldelete(size, TRUE)); ! 384: } ! 385: ! 386: /* ! 387: * Kill backwards by "n" words. ! 388: * Move backwards by the desired number of ! 389: * words, counting the characters. When dot is ! 390: * finally moved to its resting place, fire off ! 391: * the kill command. Bound to "M-Rubout" and ! 392: * to "M-Backspace". ! 393: */ ! 394: delbword(f, n) ! 395: { ! 396: register int size; ! 397: ! 398: if (n < 0) ! 399: return (FALSE); ! 400: if (backchar(FALSE, 1) == FALSE) ! 401: return (FALSE); ! 402: size = 0; ! 403: if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ ! 404: kdelete(); /* last wasn't a kill. */ ! 405: thisflag |= CFKILL; ! 406: while (n--) { ! 407: while (inword() == FALSE) { ! 408: if (backchar(FALSE, 1) == FALSE) ! 409: return (FALSE); ! 410: ++size; ! 411: } ! 412: while (inword() != FALSE) { ! 413: if (backchar(FALSE, 1) == FALSE) ! 414: return (FALSE); ! 415: ++size; ! 416: } ! 417: } ! 418: if (forwchar(FALSE, 1) == FALSE) ! 419: return (FALSE); ! 420: return (ldelete(size, TRUE)); ! 421: } ! 422: ! 423: /* ! 424: * Return TRUE if the character at dot ! 425: * is a character that is considered to be ! 426: * part of a word. The word character list is hard ! 427: * coded. Should be setable. ! 428: */ ! 429: inword() ! 430: { ! 431: register int c; ! 432: ! 433: if (curwp->w_doto == llength(curwp->w_dotp)) ! 434: return (FALSE); ! 435: c = lgetc(curwp->w_dotp, curwp->w_doto); ! 436: if (c>='a' && c<='z') ! 437: return (TRUE); ! 438: if (c>='A' && c<='Z') ! 439: return (TRUE); ! 440: if (c>='0' && c<='9') ! 441: return (TRUE); ! 442: if (c=='$' || c=='_' || c=='\\') /* For identifiers */ ! 443: return (TRUE); ! 444: if (c & 0x80) ! 445: return (TRUE); ! 446: return (FALSE); ! 447: } ! 448: ! 449: #if LIBHELP ! 450: /* ! 451: * Lookup the current word. ! 452: * Error if you try and move past the end of the buffer. ! 453: * Bound to "M-M-". Count is passed to lookup routine. ! 454: */ ! 455: lookupword(f, n) ! 456: { ! 457: static uchar wordplace[128]; ! 458: register uchar *cp; ! 459: ! 460: while (inword() != FALSE) /* Get to beginning of word */ ! 461: if (backchar(FALSE, 1) == FALSE) ! 462: break; ! 463: ! 464: while (inword() == FALSE) { /* Advance to next word */ ! 465: if (forwchar(FALSE, 1) == FALSE) ! 466: return (FALSE); ! 467: } ! 468: ! 469: cp = wordplace; ! 470: while (inword() != FALSE) { ! 471: *cp++ = lgetc(curwp->w_dotp, curwp->w_doto); ! 472: if (forwchar(FALSE, 1) == FALSE) ! 473: break; ! 474: } ! 475: *cp = '\0'; ! 476: return do_lookup(wordplace, f, n); ! 477: } ! 478: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.