1: /************************************************************************* 2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is * 3: * provided to you without charge for use only on a licensed Unix * 4: * system. You may copy JOVE provided that this notice is included with * 5: * the copy. You may not sell copies of this program or versions * 6: * modified for use on microcomputer systems, unless the copies are * 7: * included with a Unix system distribution and the source is provided. * 8: *************************************************************************/ 9: 10: #include "jove.h" 11: #include "ctype.h" 12: #include <signal.h> 13: #ifdef ANSICODES 14: #include "termcap.h" 15: #endif 16: 17: Digit() 18: { 19: GetExp(LastKeyStruck); 20: } 21: 22: Digit0() 23: { 24: GetExp('0'); 25: } 26: 27: Digit1() 28: { 29: GetExp('1'); 30: } 31: 32: Digit2() 33: { 34: GetExp('2'); 35: } 36: 37: Digit3() 38: { 39: GetExp('3'); 40: } 41: 42: Digit4() 43: { 44: GetExp('4'); 45: } 46: 47: Digit5() 48: { 49: GetExp('5'); 50: } 51: 52: Digit6() 53: { 54: GetExp('6'); 55: } 56: 57: Digit7() 58: { 59: GetExp('7'); 60: } 61: 62: Digit8() 63: { 64: GetExp('8'); 65: } 66: 67: Digit9() 68: { 69: GetExp('9'); 70: } 71: 72: prCTIME() 73: { 74: s_mess(": %f %s", get_time((long *) 0, (char *) 0, 0, -1)); 75: } 76: 77: extern int alarmed; 78: 79: FourTime() 80: { 81: int oldc = LastKeyStruck, 82: newc; 83: int nexp; 84: 85: alarmed = 0; 86: exp_p = 1; 87: this_cmd = ARG_CMD; 88: do { 89: if ((nexp = exp * 4) != 0) 90: exp = nexp; 91: if (!alarmed) 92: newc = waitchar(); 93: else 94: newc = getch(); 95: if (alarmed) 96: message(key_strokes); 97: } while (newc == oldc); 98: Ungetc(newc); 99: } 100: 101: int exp_p, 102: exp; 103: 104: GetExp(c) 105: { 106: int sign = 1, 107: i, 108: digited = 0; 109: 110: if (!isdigit(c) && c != '-') 111: complain((char *) 0); 112: if (exp_p) 113: i = exp; 114: else 115: i = 0; 116: if (c == '-') { 117: sign = -1; 118: goto goread; 119: } 120: for (;;) { 121: if (alarmed) 122: message(key_strokes); 123: if (isdigit(c)) { 124: i = i * 10 + (c - '0'); 125: digited++; 126: } else { 127: if (digited) 128: exp_p = 1; 129: else 130: i = 1; 131: exp = i * sign; 132: this_cmd = ARG_CMD; 133: Ungetc(c); 134: return; 135: } 136: goread: if (!alarmed) 137: c = waitchar(); 138: else { 139: add_mess(NullStr); 140: c = getch(); 141: } 142: } 143: } 144: 145: ChrToOct() 146: { 147: int c; 148: 149: c = waitchar(); 150: if (alarmed) 151: message(key_strokes); 152: ins_str(sprint("\\%03o", c), NO); 153: } 154: 155: StrLength() 156: { 157: static char inquotes[] = "Where are the quotes?"; 158: char *first = StrIndex(-1, linebuf, curchar, '"'), 159: *last = StrIndex(1, linebuf, curchar + 1, '"'), 160: c; 161: int numchars = 0; 162: 163: if (first == 0 || last == 0) 164: complain(inquotes); 165: first++; 166: while (first < last) { 167: c = *first++; 168: if (c == '\\') { 169: int num; 170: 171: if (!isdigit(*first)) 172: ++first; 173: else { 174: num = 3; 175: while (num-- && isdigit(*first++) && first < last) 176: ; 177: } 178: } 179: numchars++; 180: } 181: s_mess("%d characters", numchars); 182: } 183: 184: /* Transpos cur_char with cur_char - 1 */ 185: 186: TransChar() 187: { 188: char before; 189: 190: if (curchar == 0 || (eolp() && curchar == 1)) 191: complain((char *) 0); /* BEEP */ 192: exp = 1; 193: if (eolp()) 194: BackChar(); 195: before = linebuf[curchar - 1]; 196: DelPChar(); 197: ForChar(); 198: Insert(before); 199: } 200: 201: /* Switch current line with previous one */ 202: 203: TransLines() 204: { 205: disk_line old_prev; 206: 207: if (firstp(curline)) 208: return; 209: exp = 1; 210: lsave(); 211: old_prev = curline->l_prev->l_dline; 212: curline->l_prev->l_dline = curline->l_dline; 213: curline->l_dline = old_prev; 214: getDOT(); 215: if (!lastp(curline)) 216: line_move(FORWARD, NO); 217: modify(); 218: } 219: 220: Leave() 221: { 222: longjmp(mainjmp, QUIT); 223: } 224: 225: /* If argument is specified, kill that many lines down. Otherwise, 226: if we "appear" to be at the end of a line, i.e. everything to the 227: right of the cursor is white space, we delete the line separator 228: as if we were at the end of the line. */ 229: 230: KillEOL() 231: { 232: Line *line2; 233: int char2; 234: 235: if (exp_p) { 236: if (exp == 0) { /* Kill to beginning of line */ 237: line2 = curline; 238: char2 = 0; 239: } else { 240: line2 = next_line(curline, exp); 241: if ((LineDist(curline, line2) < exp) || (line2 == curline)) 242: char2 = length(line2); 243: else 244: char2 = 0; 245: } 246: } else if (blnkp(&linebuf[curchar])) { 247: line2 = next_line(curline, 1); 248: if (line2 == curline) 249: char2 = length(curline); 250: else 251: char2 = 0; 252: } else { 253: line2 = curline; 254: char2 = length(curline); 255: } 256: reg_kill(line2, char2, 0); 257: } 258: 259: /* Kill to beginning of sentence */ 260: 261: KillBos() 262: { 263: exp = -exp; 264: KillEos(); 265: } 266: 267: /* Kill to end of sentence */ 268: 269: KillEos() 270: { 271: Line *line1; 272: int char1; 273: 274: line1 = curline; 275: char1 = curchar; 276: Eos(); 277: reg_kill(line1, char1, 1); 278: } 279: 280: KillExpr() 281: { 282: Line *line1; 283: int char1; 284: 285: line1 = curline; 286: char1 = curchar; 287: FSexpr(); 288: reg_kill(line1, char1, 1); 289: } 290: 291: EscPrefix() 292: { 293: HandlePref(pref1map); 294: } 295: 296: CtlxPrefix() 297: { 298: HandlePref(pref2map); 299: } 300: 301: MiscPrefix() 302: { 303: HandlePref(miscmap); 304: } 305: 306: HandlePref(map) 307: data_obj **map; 308: { 309: register data_obj *cp; 310: register int c; 311: 312: c = waitchar(); 313: if (c == CTL(G)) { 314: message("[Aborted]"); 315: rbell(); 316: return; 317: } 318: 319: if (alarmed) 320: message(key_strokes); 321: 322: cp = map[c]; 323: if (cp == 0) { 324: s_mess("[%sunbound]", key_strokes); 325: rbell(); 326: } else 327: ExecCmd(cp); 328: } 329: 330: Yank() 331: { 332: Line *line, 333: *lp; 334: Bufpos *dot; 335: 336: if (killbuf[killptr] == 0) 337: complain("[Nothing to yank!]"); 338: lsave(); 339: this_cmd = YANKCMD; 340: line = killbuf[killptr]; 341: lp = lastline(line); 342: dot = DoYank(line, 0, lp, length(lp), curline, curchar, curbuf); 343: SetMark(); 344: SetDot(dot); 345: } 346: 347: WtModBuf() 348: { 349: if (!ModBufs(NO)) 350: message("[No buffers need saving]"); 351: else 352: put_bufs(exp_p); 353: } 354: 355: put_bufs(askp) 356: { 357: register Buffer *oldb = curbuf, 358: *b; 359: 360: for (b = world; b != 0; b = b->b_next) { 361: if (!IsModified(b) || b->b_type != B_FILE) 362: continue; 363: SetBuf(b); /* Make this current Buffer */ 364: if (curbuf->b_fname == 0) { 365: char *newname; 366: 367: newname = ask(NullStr, "Buffer \"%s\" needs a file name; type Return to skip: ", b->b_name); 368: if (*newname == 0) 369: continue; 370: setfname(b, newname); 371: } 372: if (SaveBuf(askp)) 373: unmodify(); 374: } 375: SetBuf(oldb); 376: } 377: 378: SaveBuf(askp) 379: { 380: char *yorn; 381: 382: if (askp) { 383: yorn = ask((char *) 0, "Write %s? ", curbuf->b_fname); 384: if (*yorn != 'Y' && *yorn != 'y') 385: return 0; 386: } 387: file_write(curbuf->b_fname, 0); 388: return 1; 389: } 390: 391: DOTsave(buf) 392: Bufpos *buf; 393: { 394: buf->p_line = curline; 395: buf->p_char = curchar; 396: } 397: 398: ToIndent() 399: { 400: register char *cp, 401: c; 402: 403: for (cp = linebuf; c = *cp; cp++) 404: if (c != ' ' && c != '\t') 405: break; 406: curchar = cp - linebuf; 407: } 408: 409: GoLine() 410: { 411: Line *newline; 412: 413: #ifndef ANSICODES 414: if (exp_p == 0) 415: return; 416: #else 417: if (exp_p == 0 || exp <= 0) { 418: if (SP) 419: putpad(SP, 1); /* Ask for cursor position */ 420: return; 421: } 422: #endif 423: newline = next_line(curbuf->b_first, exp - 1); 424: PushPntp(newline); 425: SetLine(newline); 426: } 427: 428: #ifdef ANSICODES 429: MoveToCursor(line, col) 430: { 431: register struct scrimage *sp = &PhysScreen[line]; 432: 433: while (sp->s_id == NULL) 434: sp = &PhysScreen[--line]; 435: if (sp->s_flags & MODELINE) 436: complain((char *) 0); 437: if (curwind != sp->s_window) 438: SetWind(sp->s_window); 439: SetLine(sp->s_lp); 440: curchar = how_far(sp->s_lp, col); 441: } 442: 443: AnsiCodes() 444: { 445: int c; 446: int num1 = 0; 447: int num2; 448: static char *unsupported = "[Unsupported ANSI code received]"; 449: 450: while (isdigit(c = getch())) 451: num1 = (num1*10) + (c - '0'); 452: 453: switch (c) { 454: case ';': 455: num2 = 0; 456: while (isdigit(c = getch())) 457: num2 = (num2*10) + (c - '0'); 458: switch (c) { 459: case 'R': 460: MoveToCursor(--num1, --num2); 461: break; 462: case 'H': 463: Eow(); Bol(); 464: break; 465: default: 466: complain(unsupported); 467: } 468: break; 469: case 'A': 470: line_move(BACKWARD, NO); 471: break; 472: case 'B': 473: line_move(FORWARD, NO); 474: break; 475: case 'C': 476: ForChar(); 477: break; 478: case 'D': 479: BackChar(); 480: break; 481: case 'H': 482: Bow(); 483: break; 484: case 'J': 485: if (num1 == 2) { 486: ClAndRedraw(); 487: break; 488: } 489: /* FALL THROUGH */ 490: default: 491: complain(unsupported); 492: } 493: } 494: #endif ANSICODES 495: 496: NotModified() 497: { 498: unmodify(); 499: } 500: 501: SetLMargin() 502: { 503: LMargin = calc_pos(linebuf, curchar); 504: } 505: 506: SetRMargin() 507: { 508: RMargin = calc_pos(linebuf, curchar); 509: }