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