📄 b.c
字号:
/* * Editor engine * Copyright * (C) 1992 Joseph H. Allen * * This file is part of JOE (Joe's Own Editor) */#include "types.h"#ifdef HAVE_PWD_H#include <pwd.h>#endifextern int errno;#ifdef WITH_SELINUX#include <selinux/selinux.h>static int selinux_enabled = -1;#endifunsigned char stdbuf[stdsiz];int guesscrlf = 0;int guessindent = 0;int berror;int force = 0;VFILE *vmem;unsigned char *msgs[] = { USTR _("No error"), USTR _("New File"), USTR _("Error reading file"), USTR _("Error seeking file"), USTR _("Error opening file"), USTR _("Error writing file"), USTR _("File on disk is newer")};/* Get size of gap (amount of free space) */#define GGAPSZ(hdr) ((hdr)->ehole - (hdr)->hole)/* Get number of characters in gap buffer */#define GSIZE(hdr) (SEGSIZ - GGAPSZ(hdr))/* Get char from buffer (with jumping around the gap) */#define GCHAR(p) ((p)->ofst >= (p)->hdr->hole ? (p)->ptr[(p)->ofst + GGAPSZ((p)->hdr)] \ : (p)->ptr[(p)->ofst])/* Set position of gap */static void gstgap(H *hdr, unsigned char *ptr, int ofst){ if (ofst > hdr->hole) { mmove(ptr + hdr->hole, ptr + hdr->ehole, ofst - hdr->hole); vchanged(ptr); } else if (ofst < hdr->hole) { mmove(ptr + hdr->ehole - (hdr->hole - ofst), ptr + ofst, hdr->hole - ofst); vchanged(ptr); } hdr->ehole = ofst + hdr->ehole - hdr->hole; hdr->hole = ofst;}/* Insert a block */static void ginsm(H *hdr, unsigned char *ptr, int ofst, unsigned char *blk, int size){ if (ofst != hdr->hole) gstgap(hdr, ptr, ofst); mmove(ptr + hdr->hole, blk, size); hdr->hole += size; vchanged(ptr);}/* Read block */static void grmem(H *hdr, unsigned char *ptr, int ofst, unsigned char *blk, int size){ if (ofst < hdr->hole) if (size > hdr->hole - ofst) { mmove(blk, ptr + ofst, hdr->hole - ofst); mmove(blk + hdr->hole - ofst, ptr + hdr->ehole, size - (hdr->hole - ofst)); } else mmove(blk, ptr + ofst, size); else mmove(blk, ptr + ofst + hdr->ehole - hdr->hole, size);}static H nhdrs = { {&nhdrs, &nhdrs} };static H ohdrs = { {&ohdrs, &ohdrs} };/* Header allocation */static H *halloc(void){ H *h; if (qempty(H, link, &ohdrs)) { h = (H *) alitem(&nhdrs, sizeof(H)); h->seg = my_valloc(vmem, (long) SEGSIZ); } else h = deque_f(H, link, ohdrs.link.next); h->hole = 0; h->ehole = SEGSIZ; h->nlines = 0; izque(H, link, h); return h;}static void hfree(H *h){ enquef(H, link, &ohdrs, h);}static void hfreechn(H *h){ splicef(H, link, &ohdrs, h);}static P frptrs = { {&frptrs, &frptrs} };/* Pointer allocation */static P *palloc(void){ return alitem(&frptrs, sizeof(P));}static void pfree(P *p){ enquef(P, link, &frptrs, p);}/* Doubly linked list of buffers and free buffer structures */static B bufs = { {&bufs, &bufs} };static B frebufs = { {&frebufs, &frebufs} };void set_file_pos_orphaned(){ B *b; for (b = bufs.link.next; b != &bufs; b = b->link.next) if (b->orphan && b->oldcur) set_file_pos(b->name,b->oldcur->line);}/* Find next buffer in list: for multi-file search and replace *//* This does not bump reference count on found buffer */B *bafter(B *b){ for (b = b->link.next; b->internal || b->scratch || b == &bufs; b = b->link.next); return b;}int udebug_joe(BW *bw){ unsigned char buf[1024]; B *b; P *p; binss(bw->cursor, USTR "Buffers and pointers (the number of pointers per buffer should not grow, except for 20 from markpos):\n\n"); pnextl(bw->cursor); for (b = bufs.link.next; b != &bufs; b = b->link.next) { if (b->name) joe_snprintf_1(buf, sizeof(buf), "Buffer %s\n", b->name); else joe_snprintf_1(buf, sizeof(buf), "Buffer 0x%p\n", (void *)b); binss(bw->cursor, buf); pnextl(bw->cursor); for (p = b->bof->link.next; p != b->bof; p = p->link.next) { joe_snprintf_1(buf, sizeof(buf), " Pointer created by %s\n", p->tracker); binss(bw->cursor, buf); pnextl(bw->cursor); } } dump_syntax(bw); return 0;}B *bnext(void){ B *b; do { b = bufs.link.prev; deque(B, link, &bufs); enqueb(B, link, b, &bufs); } while (b->internal); return b;}B *bprev(void){ B *b; do { b = bufs.link.next; deque(B, link, &bufs); enquef(B, link, b, &bufs); } while (b->internal); return b;}/* Make a buffer out of a chain */static B *bmkchn(H *chn, B *prop, long amnt, long nlines){ B *b = alitem(&frebufs, sizeof(B)); b->undo = undomk(b); if (prop) b->o = prop->o; else b->o = pdefault; mset(b->marks, 0, sizeof(b->marks)); b->rdonly = 0; b->orphan = 0; b->oldcur = NULL; b->oldtop = NULL; b->backup = 1; b->internal = 1; b->scratch = 0; b->changed = 0; b->gave_notice = 0; b->locked = 0; b->ignored_lock = 0; b->didfirst = 0; b->count = 1; b->name = NULL; b->er = -3; b->bof = palloc(); b->mod_time = 0; b->check_time = time(NULL); izque(P, link, b->bof); b->bof->end = 0; b->bof->b = b; b->bof->owner = NULL; b->bof->hdr = chn; b->bof->ptr = vlock(vmem, b->bof->hdr->seg); b->bof->ofst = 0; b->bof->byte = 0; b->bof->line = 0; b->bof->col = 0; b->bof->xcol = 0; b->bof->valcol = 1; b->bof->tracker = USTR "bmkchn"; b->eof = pdup(b->bof, USTR "bmkchn"); b->eof->end = 1; vunlock(b->eof->ptr); b->eof->hdr = chn->link.prev; b->eof->ptr = vlock(vmem, b->eof->hdr->seg); b->eof->ofst = GSIZE(b->eof->hdr); b->eof->byte = amnt; b->eof->line = nlines; b->eof->valcol = 0; b->pid = 0; b->out = -1; b->db = 0; b->parseone = 0; enquef(B, link, &bufs, b); pcoalesce(b->bof); pcoalesce(b->eof); return b;}/* Create an empty buffer */B *bmk(B *prop){ return bmkchn(halloc(), prop, 0L, 0L);}/* Eliminate a buffer */void brm(B *b){ if (b && !--b->count) { if (b->changed) abrerr(b->name); if (b->locked && !b->ignored_lock && plain_file(b)) unlock_it(b->name); if (b == errbuf) errbuf = NULL; if (b->undo) undorm(b->undo); hfreechn(b->eof->hdr); while (!qempty(P, link, b->bof)) prm(b->bof->link.next); prm(b->bof); if (b->name) joe_free(b->name); if (b->db) rm_all_lattr_db(b->db); demote(B, link, &frebufs, b); }}void brmall(){ while (!qempty(B, link, &bufs)) brm(bufs.link.next);}P *poffline(P *p){ if (p->ptr) { vunlock(p->ptr); p->ptr = NULL; } return p;}P *ponline(P *p){ if (!p->ptr) p->ptr = vlock(vmem, p->hdr->seg); return p;}B *boffline(B *b){ P *p = b->bof; do { poffline(p); } while ((p = p->link.next) != b->bof); return b;}B *bonline(B *b){ P *p = b->bof; do { ponline(p); } while ((p = p->link.next) != b->bof); return b;}P *pdup(P *p, unsigned char *tr){ P *n = palloc(); n->end = 0; n->ptr = NULL; n->owner = NULL; n->tracker = tr; enquef(P, link, p, n); return pset(n, p);}P *pdupown(P *p, P **o, unsigned char *tr){ P *n = palloc(); n->end = 0; n->ptr = NULL; n->owner = o; n->tracker = tr; enquef(P, link, p, n); pset(n, p); if (*o) prm(*o); *o = n; return n;}void prm(P *p){ if (!p) return; if (p->owner) *p->owner = NULL; if (p->ptr) vunlock(p->ptr); pfree(deque_f(P, link, p));}P *pset(P *n, P *p){ if (n != p) { n->b = p->b; n->ofst = p->ofst; n->hdr = p->hdr; if (n->ptr) vunlock(n->ptr); if (p->ptr) { n->ptr = p->ptr; vupcount(n->ptr); } else n->ptr = vlock(vmem, n->hdr->seg); n->byte = p->byte; n->line = p->line; n->col = p->col; n->valcol = p->valcol; } return n;}P *p_goto_bof(P *p){ return pset(p, p->b->bof);}P *p_goto_eof(P *p){ return pset(p, p->b->eof);}/* is p at the beginning of file? */int pisbof(P *p){ return p->hdr == p->b->bof->hdr && !p->ofst;}/* is p at the end of file? */int piseof(P *p){ return p->ofst == GSIZE(p->hdr);}/* is p at the end of line? */int piseol(P *p){ int c; if (piseof(p)) return 1; c = brc(p); if (c == '\n') return 1; if (p->b->o.crlf) if (c == '\r') { P *q = pdup(p, USTR "piseol"); pfwrd(q, 1L); if (pgetb(q) == '\n') { prm(q); return 1; } else prm(q); } return 0;}/* is p at the beginning of line? */int pisbol(P *p){ int c; if (pisbof(p)) return 1; c = prgetb(p); pgetb(p); return c == '\n';}/* is p at the beginning of word? */int pisbow(P *p){ P *q = pdup(p, USTR "pisbow"); int c = brc(p); int d = prgetc(q); prm(q); if (joe_isalnum_(p->b->o.charmap,c) && (!joe_isalnum_(p->b->o.charmap,d) || pisbof(p))) return 1; else return 0;}/* is p at the end of word? */int piseow(P *p){ P *q = pdup(p, USTR "piseow"); int d = brc(q); int c = prgetc(q); prm(q); if (joe_isalnum_(p->b->o.charmap,c) && (!joe_isalnum_(p->b->o.charmap,d) || piseof(p))) return 1; else return 0;}/* is p on the blank line (ie. full of spaces/tabs)? */int pisblank(P *p){ P *q = pdup(p, USTR "pisblank"); p_goto_bol(q); while (joe_isblank(p->b->o.charmap,brc(q))) pgetb(q); if (piseol(q)) { prm(q); return 1; } else { prm(q); return 0; }}/* is p at end of line or spaces followed by end of line? */int piseolblank(P *p){ P *q = pdup(p, USTR "piseolblank"); while (joe_isblank(p->b->o.charmap,brc(q))) pgetb(q); if (piseol(q)) { prm(q); return 1; } else { prm(q); return 0; }}/* return column of first nonblank character */long pisindent(P *p){ P *q = pdup(p, USTR "pisindent"); long col; p_goto_bol(q); while (joe_isblank(p->b->o.charmap,brc(q))) pgetc(q); col = q->col; prm(q); return col;}/* return true if all characters to left of cursor match c */int pispure(P *p,int c){ P *q = pdup(p, USTR "pispure"); p_goto_bol(q); while (q->byte!=p->byte) if (pgetc(q)!=c) { prm(q); return 0; } prm(q); return 1;}int pnext(P *p){ if (p->hdr == p->b->eof->hdr) { p->ofst = GSIZE(p->hdr); return 0; } p->hdr = p->hdr->link.next; p->ofst = 0; vunlock(p->ptr); p->ptr = vlock(vmem, p->hdr->seg); return 1;}int pprev(P *p){ if (p->hdr == p->b->bof->hdr) { p->ofst = 0; return 0; } p->hdr = p->hdr->link.prev; p->ofst = GSIZE(p->hdr); vunlock(p->ptr); p->ptr = vlock(vmem, p->hdr->seg); return 1;}/* return current byte and move p to the next byte. column will be unchanged. */int pgetb(P *p){ unsigned char c; if (p->ofst == GSIZE(p->hdr)) return NO_MORE_DATA; c = GCHAR(p); if (++p->ofst == GSIZE(p->hdr)) pnext(p); ++p->byte; if (c == '\n') { ++(p->line); p->col = 0; p->valcol = 1; } else if (p->b->o.crlf && c == '\r') { if (brc(p) == '\n') return pgetb(p); else p->valcol = 0; } else { p->valcol = 0; } return c;}/* return current character and move p to the next character. column will be updated if it was valid. */int pgetc(P *p){ if (p->b->o.charmap->type) { int val; int c; /* , oc; */ int d; int n; /* , m; */ int wid = 0; val = p->valcol; /* Remember if column number was valid */ c = pgetb(p); /* Get first byte */ /* oc = c; */ if (c==NO_MORE_DATA) return c; if ((c&0xE0)==0xC0) { /* Two bytes */ n = 1; c &= 0x1F; } else if ((c&0xF0)==0xE0) { /* Three bytes */ n = 2; c &= 0x0F; } else if ((c&0xF8)==0xF0) { /* Four bytes */ n = 3; c &= 0x07; } else if ((c&0xFC)==0xF8) { /* Five bytes */ n = 4; c &= 0x03; } else if ((c&0xFE)==0xFC) { /* Six bytes */ n = 5; c &= 0x01; } else if ((c&0x80)==0x00) { /* One byte */ n = 0; } else { /* 128-191, 254, 255: Not a valid UTF-8 start character */ n = 0; c = 'X'; /* c -= 384; */ } /* m = n; */ if (n) { while (n) { d = brc(p); if ((d&0xC0)!=0x80) break; pgetb(p); c = ((c<<6)|(d&0x3F)); --n; } if (n) { /* FIXME: there was a bad UTF-8 sequence */ /* How to represent this? */ /* pbkwd(p,m-n); c = oc - 384; */ c = 'X'; wid = 1; } else if (val) wid = joe_wcwidth(1,c); } else { wid = 1; } if (val) { /* Update column no. if it was valid to start with */ p->valcol = 1; if (c=='\t') p->col += (p->b->o.tab) - (p->col) % (p->b->o.tab); else if (c=='\n') p->col = 0; else p->col += wid; } return c; } else { unsigned char c; if (p->ofst == GSIZE(p->hdr)) return NO_MORE_DATA; c = GCHAR(p); if (++p->ofst == GSIZE(p->hdr)) pnext(p); ++p->byte; if (c == '\n') { ++(p->line); p->col = 0; p->valcol = 1; } else if (p->b->o.crlf && c == '\r') { if (brc(p) == '\n') return pgetc(p); else ++p->col; } else { if (c == '\t') p->col += (p->b->o.tab) - (p->col) % (p->b->o.tab); else ++(p->col); } return c; }}/* move p n characters forward */P *pfwrd(P *p, long n){ if (!n) return p; p->valcol = 0; do { if (p->ofst == GSIZE(p->hdr)) do { if (!p->ofst) { p->byte += GSIZE(p->hdr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -