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: 11: #ifdef MAC 12: # undef private 13: # define private 14: #endif 15: 16: #ifdef LINT_ARGS 17: private void to_sent(int); 18: #else 19: private void to_sent(); 20: #endif 21: 22: #ifdef MAC 23: # undef private 24: # define private static 25: #endif 26: 27: static int line_pos; 28: 29: void 30: f_char(n) 31: register int n; 32: { 33: if (n < 0) { 34: b_char(-n); 35: return; 36: } 37: while (--n >= 0) { 38: if (eolp()) { /* Go to the next Line */ 39: if (curline->l_next == 0) 40: break; 41: SetLine(curline->l_next); 42: } else 43: curchar += 1; 44: } 45: } 46: 47: void 48: b_char(n) 49: register int n; 50: { 51: if (n < 0) { 52: f_char(-n); 53: return; 54: } 55: while (--n >= 0) { 56: if (bolp()) { 57: if (curline->l_prev == 0) 58: break; 59: SetLine(curline->l_prev); 60: Eol(); 61: } else 62: curchar -= 1; 63: } 64: } 65: 66: void 67: ForChar() 68: { 69: f_char(arg_value()); 70: } 71: 72: void 73: BackChar() 74: { 75: b_char(arg_value()); 76: } 77: 78: void 79: NextLine() 80: { 81: if ((curline == curbuf->b_last) && eolp()) 82: complain(NullStr); 83: line_move(FORWARD, arg_value(), YES); 84: } 85: 86: void 87: PrevLine() 88: { 89: if ((curline == curbuf->b_first) && bolp()) 90: complain(NullStr); 91: line_move(BACKWARD, arg_value(), YES); 92: } 93: 94: /* moves to a different line in DIR; LINE_CMD says whether this is 95: being called from NextLine() or PrevLine(), in which case it tries 96: to line up the column with the column of the current line */ 97: 98: void 99: line_move(dir, n, line_cmd) 100: { 101: Line *(*proc)() = (dir == FORWARD) ? next_line : prev_line; 102: Line *line; 103: 104: line = (*proc)(curline, n); 105: if (line == curline) { 106: if (dir == FORWARD) 107: Eol(); 108: else 109: Bol(); 110: return; 111: } 112: 113: if (line_cmd) { 114: this_cmd = LINECMD; 115: if (last_cmd != LINECMD) 116: line_pos = calc_pos(linebuf, curchar); 117: } 118: SetLine(line); /* curline is in linebuf now */ 119: if (line_cmd) 120: curchar = how_far(curline, line_pos); 121: } 122: 123: /* returns what cur_char should be for that position col */ 124: 125: int 126: how_far(line, col) 127: Line *line; 128: { 129: register char *lp; 130: register int pos, 131: c; 132: char *base; 133: 134: base = lp = lcontents(line); 135: pos = 0; 136: 137: while (pos < col && (c = (*lp & CHARMASK))) { 138: if (c == '\t') 139: pos += (tabstop - (pos % tabstop)); 140: else if (isctrl(c)) 141: pos += 2; 142: else 143: pos += 1; 144: lp += 1; 145: } 146: 147: return lp - base; 148: } 149: 150: void 151: Bol() 152: { 153: curchar = 0; 154: } 155: 156: void 157: Eol() 158: { 159: curchar = strlen(linebuf); 160: } 161: 162: void 163: Eof() 164: { 165: PushPntp(curbuf->b_last); 166: ToLast(); 167: } 168: 169: void 170: Bof() 171: { 172: PushPntp(curbuf->b_first); 173: ToFirst(); 174: } 175: 176: /* Move forward (if dir > 0) or backward (if dir < 0) a sentence. Deals 177: with all the kludgery involved with paragraphs, and moving backwards 178: is particularly yucky. */ 179: 180: private void 181: to_sent(dir) 182: { 183: Bufpos *new, 184: old; 185: extern char *ParaStr; 186: 187: DOTsave(&old); 188: 189: new = dosearch("^[ \t]*$\\|[?.!]", dir, 1); 190: if (new == 0) { 191: if (dir == BACKWARD) 192: ToFirst(); 193: else 194: ToLast(); 195: return; 196: } 197: SetDot(new); 198: if (dir < 0) { 199: to_word(1); 200: if ((old.p_line == curline && old.p_char <= curchar) || 201: (inorder(new->p_line, new->p_char, old.p_line, old.p_char) && 202: inorder(old.p_line, old.p_char, curline, curchar))) { 203: SetDot(new); 204: to_sent(dir); 205: } 206: return; /* We're there? */ 207: } 208: if (blnkp(linebuf)) { 209: Bol(); 210: b_char(1); 211: if (old.p_line == curline && old.p_char >= curchar) { 212: to_word(1); /* Oh brother this is painful */ 213: to_sent(1); 214: } 215: } else { 216: extern int REbom; 217: 218: curchar = REbom + 1; /* Just after the [?.!] */ 219: if (LookingAt("[\")] *\\|[\")]$", linebuf, curchar)) 220: curchar += 1; 221: else if (!eolp() && !LookingAt(" *", linebuf, curchar)) 222: to_sent(dir); 223: } 224: } 225: 226: void 227: Bos() 228: { 229: register int num = arg_value(); 230: 231: if (num < 0) { 232: negate_arg_value(); 233: Eos(); 234: return; 235: } 236: 237: while (--num >= 0) { 238: to_sent(-1); 239: if (bobp()) 240: break; 241: } 242: } 243: 244: void 245: Eos() 246: { 247: register int num = arg_value(); 248: 249: if (num < 0) { 250: negate_arg_value(); 251: Bos(); 252: return; 253: } 254: 255: while (--num >= 0) { 256: to_sent(1); 257: if (eobp()) 258: break; 259: } 260: } 261: 262: void 263: f_word(num) 264: register int num; 265: { 266: register char c; 267: if (num < 0) { 268: b_word(-num); 269: return; 270: } 271: while (--num >= 0) { 272: to_word(FORWARD); 273: while ((c = linebuf[curchar]) != 0 && isword(c)) 274: curchar += 1; 275: if (eobp()) 276: break; 277: } 278: this_cmd = 0; /* Semi kludge to stop some unfavorable behavior */ 279: } 280: 281: void 282: b_word(num) 283: register int num; 284: { 285: register char c; 286: 287: if (num < 0) { 288: f_word(-num); 289: return; 290: } 291: while (--num >= 0) { 292: to_word(BACKWARD); 293: while (!bolp() && (c = linebuf[curchar - 1], isword(c))) 294: curchar -= 1; 295: if (bobp()) 296: break; 297: } 298: this_cmd = 0; 299: } 300: 301: void 302: ForWord() 303: { 304: f_word(arg_value()); 305: } 306: 307: void 308: BackWord() 309: { 310: b_word(arg_value()); 311: }