📄 b.c
字号:
} pprev(p); } while (p->hdr != q->hdr); --p->ofst; --p->byte; if (GCHAR(p) == '\n') --p->line; } return p;}/* find backward substring s in text pointed by p and set p on the first of found substring */P *prfind(P *p, unsigned char *s, int len){ P *q = pdup(p, USTR "prfind"); if (frfind(q, s, len)) { rgetto(p, q); prm(q); return p; } else { prm(q); return NULL; }}/* same as prfind() but case insensitive */P *prifind(P *p, unsigned char *s, int len){ P *q = pdup(p, USTR "prifind"); if (frifind(q, s, len)) { rgetto(p, q); prm(q); return p; } else { prm(q); return NULL; }}/* copy text between 'from' and 'to' into new buffer */B *bcpy(P *from, P *to){ H anchor, *l; unsigned char *ptr; P *q; if (from->byte >= to->byte) return bmk(from->b); q = pdup(from, USTR "bcpy"); izque(H, link, &anchor); if (q->hdr == to->hdr) { l = halloc(); ptr = vlock(vmem, l->seg); if (q->ofst != q->hdr->hole) gstgap(q->hdr, q->ptr, q->ofst); l->nlines = mcnt(q->ptr + q->hdr->ehole, '\n', l->hole = to->ofst - q->ofst); mmove(ptr, q->ptr + q->hdr->ehole, l->hole); vchanged(ptr); vunlock(ptr); enqueb(H, link, &anchor, l); } else { l = halloc(); ptr = vlock(vmem, l->seg); if (q->ofst != q->hdr->hole) gstgap(q->hdr, q->ptr, q->ofst); l->nlines = mcnt(q->ptr + q->hdr->ehole, '\n', l->hole = SEGSIZ - q->hdr->ehole); mmove(ptr, q->ptr + q->hdr->ehole, l->hole); vchanged(ptr); vunlock(ptr); enqueb(H, link, &anchor, l); pnext(q); while (q->hdr != to->hdr) { l = halloc(); ptr = vlock(vmem, l->seg); l->nlines = q->hdr->nlines; mmove(ptr, q->ptr, q->hdr->hole); mmove(ptr + q->hdr->hole, q->ptr + q->hdr->ehole, SEGSIZ - q->hdr->ehole); l->hole = GSIZE(q->hdr); vchanged(ptr); vunlock(ptr); enqueb(H, link, &anchor, l); pnext(q); } if (to->ofst) { l = halloc(); ptr = vlock(vmem, l->seg); if (to->ofst != to->hdr->hole) gstgap(to->hdr, to->ptr, to->ofst); l->nlines = mcnt(to->ptr, '\n', to->ofst); mmove(ptr, to->ptr, l->hole = to->ofst); vchanged(ptr); vunlock(ptr); enqueb(H, link, &anchor, l); } } l = anchor.link.next; deque(H, link, &anchor); prm(q); return bmkchn(l, from->b, to->byte - from->byte, to->line - from->line);}/* Coalesce small blocks into a single larger one */void pcoalesce(P *p){ if (p->hdr != p->b->eof->hdr && GSIZE(p->hdr) + GSIZE(p->hdr->link.next) <= SEGSIZ - SEGSIZ / 4) { H *hdr = p->hdr->link.next; unsigned char *ptr = vlock(vmem, hdr->seg); int osize = GSIZE(p->hdr); int size = GSIZE(hdr); P *q; gstgap(hdr, ptr, size); ginsm(p->hdr, p->ptr, GSIZE(p->hdr), ptr, size); p->hdr->nlines += hdr->nlines; vunlock(ptr); hfree(deque_f(H, link, hdr)); for (q = p->link.next; q != p; q = q->link.next) if (q->hdr == hdr) { q->hdr = p->hdr; if (q->ptr) { vunlock(q->ptr); q->ptr = vlock(vmem, q->hdr->seg); } q->ofst += osize; } } if (p->hdr != p->b->bof->hdr && GSIZE(p->hdr) + GSIZE(p->hdr->link.prev) <= SEGSIZ - SEGSIZ / 4) { H *hdr = p->hdr->link.prev; unsigned char *ptr = vlock(vmem, hdr->seg); int size = GSIZE(hdr); P *q; gstgap(hdr, ptr, size); ginsm(p->hdr, p->ptr, 0, ptr, size); p->hdr->nlines += hdr->nlines; vunlock(ptr); hfree(deque_f(H, link, hdr)); p->ofst += size; for (q = p->link.next; q != p; q = q->link.next) if (q->hdr == hdr) { q->hdr = p->hdr; if (q->ptr) vunlock(q->ptr); q->ptr = vlock(vmem, q->hdr->seg); } else if (q->hdr == p->hdr) q->ofst += size; }}/* Delete the text between two pointers from a buffer and return it in a new * buffer. * * This routine calls these functions: * gstgap - to position gaps * halloc - to allocate new header/segment pairs * vlock - virtual memory routines * vunlock * vchanged * vupcount * mcnt - to count NLs * snip - queue routines * enqueb * splicef * scrdel - to tell screen update to scroll when NLs are deleted * bmkchn - to make a buffer out of a chain *//* This is only to be used for bdel() */static B *bcut(P *from, P *to){ H *h, /* The deleted text */ *i; unsigned char *ptr; P *p; long nlines; /* No. EOLs to delete */ long amnt; /* No. bytes to delete */ int toamnt; /* Amount to delete from segment in 'to' */ int bofmove = 0; /* Set if bof got deleted */ struct lattr_db *db; if (!(amnt = to->byte - from->byte)) return NULL; /* ...nothing to delete */ nlines = to->line - from->line; if (from->hdr == to->hdr) { /* Delete is within a single segment */ /* Move gap to deletion point */ if (from->ofst != from->hdr->hole) gstgap(from->hdr, from->ptr, from->ofst); /* Store the deleted text */ h = halloc(); ptr = vlock(vmem, h->seg); mmove(ptr, from->ptr + from->hdr->ehole, (int) amnt); h->hole = amnt; h->nlines = nlines; vchanged(ptr); vunlock(ptr); /* Delete */ from->hdr->ehole += amnt; from->hdr->nlines -= nlines; toamnt = amnt; } else { /* Delete crosses segments */ H *a; if ((toamnt = to->ofst) != 0) { /* Delete beginning of to */ /* Move gap to deletion point */ /* To could be deleted if it's at the end of the file */ if (to->ofst != to->hdr->hole) gstgap(to->hdr, to->ptr, to->ofst); /* Save deleted text */ i = halloc(); ptr = vlock(vmem, i->seg); mmove(ptr, to->ptr, to->hdr->hole); i->hole = to->hdr->hole; i->nlines = mcnt(to->ptr, '\n', to->hdr->hole); vchanged(ptr); vunlock(ptr); /* Delete */ to->hdr->nlines -= i->nlines; to->hdr->hole = 0; } else i = 0; /* Delete end of from */ if (!from->ofst) { /* ... unless from needs to be deleted too */ a = from->hdr->link.prev; h = NULL; if (a == from->b->eof->hdr) bofmove = 1; } else { a = from->hdr; /* Move gap to deletion point */ if (from->ofst != from->hdr->hole) gstgap(from->hdr, from->ptr, from->ofst); /* Save deleted text */ h = halloc(); ptr = vlock(vmem, h->seg); mmove(ptr, from->ptr + from->hdr->ehole, SEGSIZ - from->hdr->ehole); h->hole = SEGSIZ - from->hdr->ehole; h->nlines = mcnt(ptr, '\n', h->hole); vchanged(ptr); vunlock(ptr); /* Delete */ from->hdr->nlines -= h->nlines; from->hdr->ehole = SEGSIZ; } /* Make from point to header/segment of to */ from->hdr = to->hdr; vunlock(from->ptr); from->ptr = to->ptr; vupcount(to->ptr); from->ofst = 0; /* Delete headers/segments between a and to->hdr (if there are any) */ if (a->link.next != to->hdr) if (!h) { h = snip(H, link, a->link.next, to->hdr->link.prev); if (i) enqueb(H, link, h, i); } else { splicef(H, link, h, snip(H, link, a->link.next, to->hdr->link.prev)); if (i) enqueb(H, link, h, i); } else if (!h) h = i; else if (i) enqueb(H, link, h, i); } /* If to is empty, then it must have been at the end of the file. If the file did not become empty, delete to */ if (!GSIZE(to->hdr) && from->byte) { H *ph = from->hdr->link.prev; hfree(deque_f(H, link, from->hdr)); vunlock(from->ptr); from->hdr = ph; from->ptr = vlock(vmem, from->hdr->seg); from->ofst = GSIZE(ph); vunlock(from->b->eof->ptr); from->b->eof->ptr = from->ptr; vupcount(from->ptr); from->b->eof->hdr = from->hdr; from->b->eof->ofst = from->ofst; } /* The deletion is now done */ /* Scroll if necessary */ if (bofmove) pset(from->b->bof, from); for (db = from->b->db; db; db = db->next) lattr_del(db, from->line, nlines); if (!pisbol(from)) { scrdel(from->b, from->line, nlines, 1); delerr(from->b->name, from->line, nlines); } else { scrdel(from->b, from->line, nlines, 0); delerr(from->b->name, from->line, nlines); } /* Fix pointers */ for (p = from->link.next; p != from; p = p->link.next) if (p->line == from->line && p->byte > from->byte) p->valcol = 0; for (p = from->link.next; p != from; p = p->link.next) { if (p->byte >= from->byte) { if (p->byte <= from->byte + amnt) { if (p->ptr) { pset(p, from); } else { poffline(pset(p, from)); } } else { if (p->hdr == to->hdr) p->ofst -= toamnt; p->byte -= amnt; p->line -= nlines; } } } pcoalesce(from); /* Make buffer out of deleted text and return it */ return bmkchn(h, from->b, amnt, nlines);}void bdel(P *from, P *to){ if (to->byte - from->byte) { B *b = bcut(from, to); if (from->b->undo) undodel(from->b->undo, from->byte, b); else brm(b); from->b->changed = 1; }}/* Split a block at p's ofst *//* p is placed in the new block such that it points to the same text but with * p->ofst==0 */static void bsplit(P *p){ if (p->ofst) { H *hdr; unsigned char *ptr; P *pp; hdr = halloc(); ptr = vlock(vmem, hdr->seg); if (p->ofst != p->hdr->hole) gstgap(p->hdr, p->ptr, p->ofst); mmove(ptr, p->ptr + p->hdr->ehole, SEGSIZ - p->hdr->ehole); hdr->hole = SEGSIZ - p->hdr->ehole; hdr->nlines = mcnt(ptr, '\n', hdr->hole); p->hdr->nlines -= hdr->nlines; vchanged(ptr); p->hdr->ehole = SEGSIZ; enquef(H, link, p->hdr, hdr); vunlock(p->ptr); for (pp = p->link.next; pp != p; pp = pp->link.next) if (pp->hdr == p->hdr && pp->ofst >= p->ofst) { pp->hdr = hdr; if (pp->ptr) { vunlock(pp->ptr); pp->ptr = ptr; vupcount(ptr); } pp->ofst -= p->ofst; } p->ptr = ptr; p->hdr = hdr; p->ofst = 0; }}/* Make a chain out of a block of memory (the block must not be empty) */static H *bldchn(unsigned char *blk, int size, long *nlines){ H anchor, *l; *nlines = 0; izque(H, link, &anchor); do { unsigned char *ptr; int amnt; ptr = vlock(vmem, (l = halloc())->seg); if (size > SEGSIZ) amnt = SEGSIZ; else amnt = size; mmove(ptr, blk, amnt); l->hole = amnt; l->ehole = SEGSIZ; (*nlines) += (l->nlines = mcnt(ptr, '\n', amnt)); vchanged(ptr); vunlock(ptr); enqueb(H, link, &anchor, l); blk += amnt; size -= amnt; } while (size); l = anchor.link.next; deque(H, link, &anchor); return l;}/* Insert a chain into a buffer (this does not update pointers) */static void inschn(P *p, H *a){ if (!p->b->eof->byte) { /* P's buffer is empty: replace the empty segment in p with a */ hfree(p->hdr); p->hdr = a; vunlock(p->ptr); p->ptr = vlock(vmem, a->seg); pset(p->b->bof, p); p->b->eof->hdr = a->link.prev; vunlock(p->b->eof->ptr); p->b->eof->ptr = vlock(vmem, p->b->eof->hdr->seg); p->b->eof->ofst = GSIZE(p->b->eof->hdr); } else if (piseof(p)) { /* We're at the end of the file: append a to the file */ p->b->eof->hdr = a->link.prev; spliceb(H, link, p->b->bof->hdr, a); vunlock(p->b->eof->ptr); p->b->eof->ptr = vlock(vmem, p->b->eof->hdr->seg); p->b->eof->ofst = GSIZE(p->b->eof->hdr); p->hdr = a; vunlock(p->ptr); p->ptr = vlock(vmem, p->hdr->seg); p->ofst = 0; } else if (pisbof(p)) { /* We're at the beginning of the file: insert chain and set bof pointer */ p->hdr = spliceb_f(H, link, p->hdr, a); vunlock(p->ptr); p->ptr = vlock(vmem, a->seg); pset(p->b->bof, p); } else { /* We're in the middle of the file: split and insert */ bsplit(p); p->hdr = spliceb_f(H, link, p->hdr, a); vunlock(p->ptr); p->ptr = vlock(vmem, a->seg); }}static void fixupins(P *p, long amnt, long nlines, H *hdr, int hdramnt){ P *pp; struct lattr_db *db; if (!pisbol(p)) scrins(p->b, p->line, nlines, 1); else scrins(p->b, p->line, nlines, 0); for (db = p->b->db; db; db = db->next) lattr_ins(db, p->line, nlines); inserr(p->b->name, p->line, nlines, pisbol(p)); /* FIXME: last arg ??? */ for (pp = p->link.next; pp != p; pp = pp->link.next) if (pp->line == p->line && (pp->byte > p->byte || (pp->end && pp->byte == p->byte))) pp->valcol = 0; for (pp = p->link.next; pp != p; pp = pp->link.next) if (pp->byte == p->byte && !pp->end) if (pp->ptr) pset(pp, p); else poffline(pset(pp, p)); else if (pp->byte > p->byte || (pp->end && pp->byte == p->byte)) { pp->byte += amnt; pp->line += nlines; if (pp->hdr == hdr) pp->ofst += hdramnt; } if (p->b->undo) undoins(p->b->undo, p, amnt); p->b->changed = 1;}/* Insert a buffer at pointer position (the buffer goes away) */P *binsb(P *p, B *b){ if (b->eof->byte) { P *q = pdup(p, USTR "binsb"); inschn(q, b->bof->hdr); b->eof->hdr = halloc(); fixupins(q, b->eof->byte, b->eof->line, NULL, 0); pcoalesce(q); prm(q); } brm(b); return p;}/* insert memory block 'blk' at 'p' */P *binsm(P *p, unsigned char *blk, int amnt){ long nlines; H *h = NULL; int hdramnt = 0; /* Only used if h is set */ P *q; if (!amnt) return p; q = pdup(p, USTR "binsm"); if (amnt <= GGAPSZ(q->hdr)) { h = q->hdr; hdramnt = amnt; ginsm(q->hdr, q->ptr, q->ofst, blk, amnt); q->hdr->nlines += (nlines = mcnt(blk, '\n', amnt)); } else if (!q->ofst && q->hdr != q->b->bof->hdr && amnt <= GGAPSZ(q->hdr->link.prev)) { pprev(q); ginsm(q->hdr, q->ptr, q->ofst, blk, amnt); q->hdr->nlines += (nlines = mcnt(blk, '\n', amnt)); } else { H *a = bldchn(blk, amnt, &nlines); inschn(q, a); } fixupins(q, (long) amnt, nlines, h, hdramnt); pcoalesce(q); prm(q); return p;}/* insert byte 'c' at 'p' */P *binsbyte(P *p, unsigned char c){ if (p->b->o.crlf && c == '\n') return binsm(p, USTR "\r\n", 2); else return binsm(p, &c, 1);}/* UTF-8 encode a character and insert it */P *binsc(P *p, int c){ if (c>127 && p->b->o.charmap->type) { unsigned char buf[8]; int len = utf8_encode(buf,c); return binsm(p,buf,len); } else { unsigned char ch = c; if (p->b->o.crlf && c == '\n') return binsm(p, USTR "\r\n", 2); else return binsm(p, &ch, 1); }}/* insert zero-terminated string 's' at 'p' */P *binss(P *p, unsigned char *s){ return binsm(p, s, zlen(s));}/* Read 'size' bytes from file or stream. Stops and returns amnt. read * when requested size has been read or when end of file condition occurs. * Returns with -2 in error for read error or 0 in error for success. */static int bkread(int fi, unsigned char *buff, int size){ int a, b; if (!size) { berror = 0; return 0; } for (a = b = 0; (a < size) && ((b = joe_read(fi, buff + a, size - a)) > 0); a += b) ; if (b < 0) berror = -2; else berror = 0; return a;}/* Read up to 'max' bytes from a file into a buffer *//* Returns with 0 in error or -2 in error for read error */B *bread(int fi, long int max){ H anchor, *l; long lines = 0, total = 0; int amnt; unsigned char *seg; izque(H, link, &anchor); berror = 0; while (seg = vlock(vmem, (l = halloc())->seg), !berror && (amnt = bkread(fi, seg, max >= SEGSIZ ? SEGSIZ : (int) max))) { total += amnt; max -= amnt; l->hole = amnt; lines += (l->nlines = mcnt(seg, '\n', amnt)); vchanged(seg); vunlock(seg); enqueb(H, link, &anchor, l); } hfree(l); vunlock(seg); if (!total) return bmk(NULL); l = anchor.link.next; deque(H, link, &anchor); return bmkchn(l, NULL, total, lines);}/* Parse file name. * * Removes ',xxx,yyy' from end of name and puts their value into skip and amnt * Replaces ~user/ with directory of given user * Replaces ~/ with $HOME * * Returns new variable length string. */unsigned char *parsens(unsigned char *s, off_t *skip, off_t *amnt){ unsigned char *n = vsncpy(NULL, 0, sz(s)); int x; *skip = 0; *amnt = MAXLONG; x = sLEN(n) - 1; if (x > 0 && n[x] >= '0' && n[x] <= '9') { for (x = sLEN(n) - 1; x > 0 && ((n[x] >= '0' && n[x] <= '9') || n[x] == 'x' || n[x] == 'X'); --x) ; if (n[x] == ',') { n[x] = 0;#if SIZEOF_LONG_LONG && SIZEOF_OFF_T == SIZEOF_LONG_LONG if (n[x + 1] == 'x' || n[x + 1] == 'X') sscanf((char *)(n + x + 2), "%llx", skip); else if (n[x + 1] == '0' && (n[x + 2] == 'x' || n[x + 2] == 'X')) sscanf((char *)(n + x + 3), "%llx", skip); else if (n[x + 1] == '0') sscanf((char *)(n + x + 1), "%llo", skip); else sscanf((char *)(n + x + 1), "%lld", skip);#else if (n[x + 1] == 'x' || n[x + 1] == 'X') sscanf((char *)(n + x + 2), "%lx", skip); else if (n[x + 1] == '0' && (n[x + 2] == 'x' || n[x + 2] == 'X')) sscanf((char *)(n + x + 3), "%lx", skip); else if (n[x + 1] == '0') sscanf((char *)(n + x + 1), "%lo", skip); else sscanf((char *)(n + x + 1), "%ld", skip);#endif --x; if (x > 0 && n[x] >= '0' && n[x] <= '9') { for (; x > 0 && ((n[x] >= '0' && n[x] <= '9') || n[x] == 'x' || n[x] == 'X'); --x) ; if (n[x] == ',') { n[x] = 0; *amnt = *skip;#if SIZEOF_LONG_LONG && SIZEOF_OFF_T == SIZEOF_LONG_LONG if (n[x + 1] == 'x' || n[x + 1] == 'X') sscanf((char *)(n + x + 2), "%llx", skip); else if (n[x + 1] == '0' && (n[x + 2] == 'x' || n[x + 2] == 'X')) sscanf((char *)(n + x + 3), "%llx", skip); else if (n[x + 1] == '0') sscanf((char *)(n + x + 1), "%llo", skip); else sscanf((char *)(n + x + 1), "%lld", skip);#else if (n[x + 1] == 'x' || n[x + 1] == 'X') sscanf((char *)(n + x + 2), "%lx", skip); else if (n[x + 1] == '0' && (n[x + 2] == 'x' || n[x + 2] == 'X')) sscanf((char *)(n + x + 3), "%lx", skip); else if (n[x + 1] == '0') sscanf((char *)(n + x + 1), "%lo", skip); else sscanf((char *)(n + x + 1), "%ld", skip);#endif } } } } /* Don't do this here: do it in prompt buffer instead, so we're just like the shell doing it on the command line. */ /* n = canonical(n); */ return n;}/* Canonicalize file name: do ~ expansion */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -