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