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: /* Routines to perform all kinds of deletion. */ 9: 10: #include "jove.h" 11: 12: /* Assumes that either line1 or line2 is actual the current line, so it can 13: put its result into linebuf. */ 14: 15: void 16: patchup(line1, char1, line2, char2) 17: Line *line1, 18: *line2; 19: register int char1, 20: char2; 21: { 22: if (line1 != line2) 23: ChkWindows(line1, line2); 24: DotTo(line1, char1); 25: modify(); 26: linecopy(linebuf, curchar, lcontents(line2) + char2); 27: 28: /* The following is a redisplay optimization. */ 29: if (line1 != line2 && (char1 == 0 && char2 == 0)) 30: line1->l_dline = line2->l_dline; 31: 32: DFixMarks(line1, char1, line2, char2); 33: makedirty(curline); 34: } 35: 36: /* Deletes the region by unlinking the lines in the middle, 37: and patching things up. The unlinked lines are still in 38: order. */ 39: 40: Line * 41: reg_delete(line1, char1, line2, char2) 42: Line *line1, 43: *line2; 44: { 45: register Line *retline; 46: 47: if ((line1 == line2 && char1 == char2) || line2 == 0) 48: complain((char *) 0); 49: (void) fixorder(&line1, &char1, &line2, &char2); 50: 51: retline = nbufline(); /* New buffer line */ 52: 53: (void) ltobuf(line1, genbuf); 54: if (line1 == line2) 55: genbuf[char2] = '\0'; 56: 57: retline->l_prev = 0; 58: retline->l_dline = putline(&genbuf[char1]); 59: patchup(line1, char1, line2, char2); 60: 61: if (line1 == line2) 62: retline->l_next = 0; 63: else { 64: retline->l_next = line1->l_next; 65: (void) ltobuf(line2, genbuf); 66: genbuf[char2] = '\0'; 67: line2->l_dline = putline(genbuf); 68: /* Shorten this line */ 69: } 70: 71: if (line1 != line2) { 72: line1->l_next = line2->l_next; 73: if (line1->l_next) 74: line1->l_next->l_prev = line1; 75: else 76: curbuf->b_last = line1; 77: line2->l_next = 0; 78: } 79: 80: return retline; 81: } 82: 83: void 84: lremove(line1, line2) 85: register Line *line1, 86: *line2; 87: { 88: Line *next = line1->l_next; 89: 90: if (line1 == line2) 91: return; 92: line1->l_next = line2->l_next; 93: if (line1->l_next) 94: line1->l_next->l_prev = line1; 95: else 96: curbuf->b_last = line1; 97: lfreereg(next, line2); /* Put region at end of free line list. */ 98: } 99: 100: /* Delete character forward */ 101: 102: void 103: DelNChar() 104: { 105: del_char(FORWARD, arg_value()); 106: } 107: 108: /* Delete character backward */ 109: 110: void 111: DelPChar() 112: { 113: if (MinorMode(OverWrite)) { 114: int count = min(arg_value(), curchar); 115: 116: b_char(count); 117: 118: /* overwrite with spaces */ 119: set_arg_value(count); 120: LastKeyStruck = ' '; 121: SelfInsert(); 122: 123: b_char(count); 124: } else 125: del_char(BACKWARD, arg_value()); 126: } 127: 128: /* Delete some characters. If deleting forward then call for_char 129: to the final position otherwise call back_char. Then delete the 130: region between the two with patchup(). */ 131: 132: void 133: del_char(dir, num) 134: { 135: Bufpos before, 136: after; 137: int killp = (abs(num) > 1); 138: 139: DOTsave(&before); 140: if (dir == FORWARD) 141: f_char(num); 142: else 143: b_char(num); 144: if (before.p_line == curline && before.p_char == curchar) 145: complain((char *) 0); 146: if (killp) 147: reg_kill(before.p_line, before.p_char, 1); 148: else { 149: DOTsave(&after); 150: (void) fixorder(&before.p_line, &before.p_char, &after.p_line, &after.p_char); 151: patchup(before.p_line, before.p_char, after.p_line, after.p_char); 152: lremove(before.p_line, after.p_line); 153: } 154: } 155: 156: /* This kills a region between point, and line1/char1 and puts it on 157: the kill-ring. If the last command was one of the kill commands, 158: the region is appended (prepended if backwards) to the last entry. */ 159: 160: int killptr = 0; 161: Line *killbuf[NUMKILLS]; 162: 163: void 164: reg_kill(line2, char2, dot_moved) 165: Line *line2; 166: { 167: Line *nl, 168: *line1 = curline; 169: int char1 = curchar; 170: int backwards; 171: 172: backwards = !fixorder(&line1, &char1, &line2, &char2); 173: /* This is a kludge! But it possible for commands that don't 174: know which direction they are deleting in (e.g., delete 175: previous word could have been called with a negative argument 176: in which case, it wouldn't know that it really deleted 177: forward. */ 178: 179: if (!dot_moved) 180: backwards = !backwards; 181: 182: DotTo(line1, char1); 183: 184: nl = reg_delete(line1, char1, line2, char2); 185: 186: if (last_cmd != KILLCMD) { 187: killptr = ((killptr + 1) % NUMKILLS); 188: lfreelist(killbuf[killptr]); 189: killbuf[killptr] = nl; 190: } else { 191: Line *lastln = lastline(nl); 192: 193: if (backwards) 194: (void) DoYank(nl, 0, lastln, length(lastln), killbuf[killptr], 0, (Buffer *) 0); 195: else { 196: Line *olastln = lastline(killbuf[killptr]); 197: 198: (void) DoYank(nl, 0, lastln, length(lastln), olastln, length(olastln), (Buffer *) 0); 199: } 200: } 201: this_cmd = KILLCMD; 202: } 203: 204: void 205: DelReg() 206: { 207: register Mark *mp = CurMark(); 208: 209: reg_kill(mp->m_line, mp->m_char, 0); 210: } 211: 212: /* Save a region. A pretend kill. */ 213: 214: void 215: CopyRegion() 216: { 217: register Line *nl; 218: register Mark *mp; 219: register int status; 220: 221: mp = CurMark(); 222: if (mp->m_line == curline && mp->m_char == curchar) 223: complain((char *) 0); 224: 225: killptr = ((killptr + 1) % NUMKILLS); 226: if (killbuf[killptr]) 227: lfreelist(killbuf[killptr]); 228: nl = killbuf[killptr] = nbufline(); 229: SavLine(nl, NullStr); 230: nl->l_next = nl->l_prev = 0; 231: 232: status = inorder(mp->m_line, mp->m_char, curline, curchar); 233: if (status == -1) 234: return; 235: 236: if (status) 237: (void) DoYank(mp->m_line, mp->m_char, curline, curchar, 238: nl, 0, (Buffer *) 0); 239: else 240: (void) DoYank(curline, curchar, mp->m_line, mp->m_char, 241: nl, 0, (Buffer *) 0); 242: } 243: 244: void 245: DelWtSpace() 246: { 247: register char *ep = &linebuf[curchar], 248: *sp = &linebuf[curchar]; 249: 250: while (*ep == ' ' || *ep == '\t') 251: ep += 1; 252: while (sp > linebuf && *(sp - 1) == ' ' || *(sp - 1) == '\t') 253: sp -= 1; 254: if (sp != ep) { 255: curchar = sp - linebuf; 256: DFixMarks(curline, curchar, curline, curchar + (ep - sp)); 257: strcpy(sp, ep); 258: makedirty(curline); 259: modify(); 260: } 261: } 262: 263: void 264: DelBlnkLines() 265: { 266: register Mark *dot; 267: int all; 268: 269: if (!blnkp(&linebuf[curchar])) 270: return; 271: dot = MakeMark(curline, curchar, M_FLOATER); 272: all = !blnkp(linebuf); 273: while (blnkp(linebuf) && curline->l_prev) 274: SetLine(curline->l_prev); 275: all |= (firstp(curline)); 276: Eol(); 277: DelWtSpace(); 278: line_move(FORWARD, 1, NO); 279: while (blnkp(linebuf) && !eobp()) { 280: DelWtSpace(); 281: del_char(FORWARD, 1); 282: } 283: if (!all && !eobp()) 284: open_lines(1); 285: ToMark(dot); 286: DelMark(dot); 287: } 288: 289: void 290: DelNWord() 291: { 292: dword(1); 293: } 294: 295: void 296: DelPWord() 297: { 298: dword(0); 299: } 300: 301: void 302: dword(forward) 303: { 304: Bufpos savedot; 305: 306: DOTsave(&savedot); 307: if (forward) 308: ForWord(); 309: else 310: BackWord(); 311: reg_kill(savedot.p_line, savedot.p_char, 1); 312: }