📄 insert.c
字号:
char save[LBSIZE], buf[LBSIZE]; Line *startline = atline; int startchar = atchar; lsave(); if (whatbuf) modify(); (void) ltobuf(atline, genbuf); strcpy(save, &genbuf[atchar]); (void) ltobuf(fline, buf); if (fline == tline) buf[tchar] = '\0'; linecopy(genbuf, atchar, &buf[fchar]); atline->l_dline = putline(genbuf); makedirty(atline); fline = fline->l_next; while (fline != tline->l_next) { newline = listput(whatbuf, atline); newline->l_dline = fline->l_dline; makedirty(newline); fline = fline->l_next; atline = newline; atchar = 0; } getline(atline->l_dline, genbuf); atchar += tchar; linecopy(genbuf, atchar, save); atline->l_dline = putline(genbuf); makedirty(atline); IFixMarks(startline, startchar, atline, atchar); bp.p_line = atline; bp.p_char = atchar; this_cmd = YANKCMD; getDOT(); /* Whatever used to be in linebuf */ return &bp;}voidYankPop(){ Line *line, *last; Mark *mp = CurMark(); Bufpos *dot; int dir = -1; /* Direction to rotate the ring */ if (last_cmd != YANKCMD) complain("Yank something first!"); lfreelist(reg_delete(mp->m_line, mp->m_char, curline, curchar)); /* Now must find a recently killed region. */ if (arg_value() < 0) dir = 1; killptr += dir; for (;;) { if (killptr < 0) killptr = NUMKILLS - 1; else if (killptr >= NUMKILLS) killptr = 0; if (killbuf[killptr]) break; killptr += dir; } this_cmd = YANKCMD; line = killbuf[killptr]; last = lastline(line); dot = DoYank(line, 0, last, length(last), curline, curchar, curbuf); MarkSet(CurMark(), curline, curchar); SetDot(dot);}/* This is an attempt to reduce the amount of memory taken up by each line. Without this each malloc of a line uses sizeof (line) + sizeof(HEADER) where line is 3 words and HEADER is 1 word. This is going to allocate memory in chucks of CHUNKSIZE * sizeof (line) and divide each chuck into Lines. A line is free in a chunk when its line->l_dline == NULL_DADDR, so freeline sets l_dline to NULL_DADDR. */#define CHUNKSIZE 300struct chunk { struct chunk *c_nextchunk; /* Next chunk of lines */ int c_nlines; /* Number of lines in this chunk (so they don't all have to be CHUNKSIZE long). */ Line c_block[1 /* or larger */]; /* Chunk of memory */};private struct chunk *fchunk = NULL; /* first chunk */private Line *ffline = NULL; /* First free line */private Line *faline = NULL; /* First available line */private voidfreeline(line)register Line *line;{ line->l_dline = NULL_DADDR; line->l_next = ffline; if (ffline) ffline->l_prev = line; line->l_prev = NULL; ffline = line;}/* Make sure that there are no dangling references to lines in the free list, * then move them to the end of the avail list. */private voidRecycleLines(){ if (ffline == NULL) return; /* nothing to do */ ChkErrorLines(); /* ChkWindowLines(); -- nothing needs attention */ /* ChkBufLines(); -- nothing needs attention */ if (faline == NULL) { faline = ffline; } else { Line *laline = lastline(faline); laline->l_next = ffline; ffline->l_prev = laline; } ffline = NULL;}voidlfreelist(first)register Line *first;{ if (first != NULL) lfreereg(first, lastline(first));}/* Append region from line1 to line2 onto the free list of lines */voidlfreereg(line1, line2)register Line *line1, *line2;{ register Line *next, *last = line2->l_next; while (line1 != last) { next = line1->l_next; freeline(line1); line1 = next; }}private boolnewchunk(){ register Line *newline; register int i; struct chunk *f; int nlines = CHUNKSIZE; bool done_gc = NO; for (;;) { f = (struct chunk *) malloc( (sizeof(struct chunk) - sizeof(Line)) + (sizeof(Line) * nlines)); if (f != NULL) break; if (!done_gc) { GCchunks(); done_gc = YES; } else { nlines /= 2; if (nlines <= 0) return NO; } } f->c_nlines = nlines; for (i = 0, newline = f->c_block; i < nlines; newline++, i++) { newline->l_dline = NULL_DADDR; newline->l_next = faline; if (faline) faline->l_prev = newline; newline->l_prev = NULL; faline = newline; } f->c_nextchunk = fchunk; fchunk = f; return YES;}/* New BUFfer LINE */Line *nbufline(){ register Line *newline; if (faline == NULL) { RecycleLines(); if (faline == NULL) { if (!newchunk()) complain("[Out of lines] "); } } newline = faline; faline = newline->l_next; if (faline) faline->l_prev = NULL; return newline;}/* Remove the free lines, in chunk c, from the free list because they are no longer free. */private voidremfreelines(c)register struct chunk *c;{ register Line *lp; register int i; for (lp = c->c_block, i = c->c_nlines; i != 0 ; lp++, i--) { if (lp->l_prev == NULL) faline = lp->l_next; else lp->l_prev->l_next = lp->l_next; if (lp->l_next != NULL) lp->l_next->l_prev = lp->l_prev; }}/* This is used to garbage collect the chunks of lines when malloc fails and we are NOT looking for a new buffer line. This goes through each chunk, and if every line in a given chunk is not allocated, the entire chunk is `free'd by "free()". *//* ??? I think that this WILL be called when we are looking for a new * buffer line: nbufline() => newchunk() => GCchunks() -- DHR */voidGCchunks(){ register struct chunk *cp; struct chunk *prev = NULL, *next; register int i; register Line *newline; RecycleLines(); for (cp = fchunk; cp != NULL; cp = next) { next = cp->c_nextchunk; for (i = cp->c_nlines, newline = cp->c_block; ; newline++, i--) { if (i == 0) { /* Empty: unlink and free it!!! */ if (prev == NULL) fchunk = cp->c_nextchunk; else prev->c_nextchunk = cp->c_nextchunk; remfreelines(cp); free((UnivPtr) cp); break; } if (newline->l_dline != NULL_DADDR) { /* it's a keeper */ prev = cp; break; } } }}#ifdef LISP#include "re.h"/* Grind S-Expr */voidGSexpr(){ Bufpos dot, end; if (linebuf[curchar] != '(') complain((char *)NULL); DOTsave(&dot); FSexpr(); DOTsave(&end); SetDot(&dot); for (;;) { if (curline == end.p_line) break; line_move(FORWARD, 1, NO); if (!blnkp(linebuf)) (void) lisp_indent(); } SetDot(&dot);}/* lisp_indent() indents a new line in Lisp Mode, according to where the matching close-paren would go if we typed that (sort of). */private List *specials = NULL;private voidinit_specials(){ static char *const words[] = { "case", "def", "dolist", "fluid-let", "lambda", "let", "lexpr", "macro", "named-l", /* named-let and named-lambda */ "nlambda", "prog", "selectq", NULL }; char *const *wordp = words; while (*wordp != NULL) list_push(&specials, (UnivPtr) *wordp++);}voidAddSpecial(){ char *word; register List *lp; if (specials == NULL) init_specials(); word = ask((char *)NULL, ProcFmt); for (lp = specials; lp != NULL; lp = list_next(lp)) if (strcmp((char *) list_data(lp), word) == 0) return; /* already in list */ (void) list_push(&specials, (UnivPtr) copystr(word));}private Bufpos *lisp_indent(){ Bufpos *bp, savedot; int goal; bp = m_paren(')', BACKWARD, NO, YES); if (bp == NULL) return NULL; /* We want to end up (atom atom atom ... ^ here. */ DOTsave(&savedot); SetDot(bp); f_char(1); if (linebuf[curchar] != '(') { register List *lp; if (specials == NULL) init_specials(); for (lp = specials; lp != NULL; lp = list_next(lp)) if (casencmp((char *) list_data(lp), &linebuf[curchar], strlen((char *) list_data(lp))) == 0) break; if (lp == NULL) { /* not special */ int c_char = curchar; WITH_TABLE(curbuf->b_major) f_word(1); END_TABLE(); if (LookingAt("[ \t]*;\\|[ \t]*$", linebuf, curchar)) { curchar = c_char; } else { while (linebuf[curchar] == ' ') curchar += 1; } } else { curchar += 1; } } goal = calc_pos(linebuf, curchar); SetDot(&savedot); Bol(); n_indent(goal); return bp;}#endif /* LISP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -