570 lines
12 KiB
C
570 lines
12 KiB
C
/*
|
|
* This file is part of the UCB release of Plan 9. It is subject to the license
|
|
* terms in the LICENSE file found in the top-level directory of this
|
|
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
|
|
* part of the UCB release of Plan 9, including this file, may be copied,
|
|
* modified, propagated, or distributed except according to the terms contained
|
|
* in the LICENSE file.
|
|
*/
|
|
|
|
enum
|
|
{
|
|
Qdir,
|
|
Qacme,
|
|
Qcons,
|
|
Qconsctl,
|
|
Qdraw,
|
|
Qeditout,
|
|
Qindex,
|
|
Qlabel,
|
|
Qnew,
|
|
|
|
QWaddr,
|
|
QWbody,
|
|
QWctl,
|
|
QWdata,
|
|
QWeditout,
|
|
QWerrors,
|
|
QWevent,
|
|
QWrdsel,
|
|
QWwrsel,
|
|
QWtag,
|
|
QWxdata,
|
|
QMAX,
|
|
};
|
|
|
|
enum
|
|
{
|
|
Blockincr = 256,
|
|
Maxblock = 8*1024,
|
|
NRange = 10,
|
|
Infinity = 0x7FFFFFFF, /* huge value for regexp address */
|
|
};
|
|
|
|
typedef struct Block Block;
|
|
typedef struct Buffer Buffer;
|
|
typedef struct Command Command;
|
|
typedef struct Column Column;
|
|
typedef struct Dirlist Dirlist;
|
|
typedef struct Dirtab Dirtab;
|
|
typedef struct Disk Disk;
|
|
typedef struct Expand Expand;
|
|
typedef struct Fid Fid;
|
|
typedef struct File File;
|
|
typedef struct Elog Elog;
|
|
typedef struct Mntdir Mntdir;
|
|
typedef struct Range Range;
|
|
typedef struct Rangeset Rangeset;
|
|
typedef struct Reffont Reffont;
|
|
typedef struct Row Row;
|
|
typedef struct Runestr Runestr;
|
|
typedef struct Text Text;
|
|
typedef struct Timer Timer;
|
|
typedef struct Window Window;
|
|
typedef struct Xfid Xfid;
|
|
|
|
struct Runestr
|
|
{
|
|
Rune *r;
|
|
int nr;
|
|
};
|
|
|
|
struct Range
|
|
{
|
|
int q0;
|
|
int q1;
|
|
};
|
|
|
|
struct Block
|
|
{
|
|
uint32_t addr; /* disk address in bytes */
|
|
union
|
|
{
|
|
uint32_t n; /* number of used runes in block */
|
|
Block *next; /* pointer to next in free list */
|
|
};
|
|
};
|
|
|
|
struct Disk
|
|
{
|
|
int fd;
|
|
uint32_t addr; /* length of temp file */
|
|
Block *free[Maxblock/Blockincr+1];
|
|
};
|
|
|
|
Disk* diskinit(void);
|
|
Block* disknewblock(Disk*, uint32_t);
|
|
void diskrelease(Disk*, Block*);
|
|
void diskread(Disk*, Block*, Rune*, uint32_t);
|
|
void diskwrite(Disk*, Block**, Rune*, uint32_t);
|
|
|
|
struct Buffer
|
|
{
|
|
uint32_t nc;
|
|
Rune *c; /* cache */
|
|
uint32_t cnc; /* bytes in cache */
|
|
uint32_t cmax; /* size of allocated cache */
|
|
uint32_t cq; /* position of cache */
|
|
int cdirty; /* cache needs to be written */
|
|
uint32_t cbi; /* index of cache Block */
|
|
Block **bl; /* array of blocks */
|
|
uint32_t nbl; /* number of blocks */
|
|
};
|
|
void bufinsert(Buffer*, uint32_t, Rune*, uint32_t);
|
|
void bufdelete(Buffer*, uint32_t, uint32_t);
|
|
uint32_t bufload(Buffer*, uint32_t, int, int*);
|
|
void bufread(Buffer*, uint32_t, Rune*, uint32_t);
|
|
void bufclose(Buffer*);
|
|
void bufreset(Buffer*);
|
|
|
|
struct Elog
|
|
{
|
|
short type; /* Delete, Insert, Filename */
|
|
uint32_t q0; /* location of change (unused in f) */
|
|
uint32_t nd; /* number of deleted characters */
|
|
uint32_t nr; /* # runes in string or file name */
|
|
Rune *r;
|
|
};
|
|
void elogterm(File*);
|
|
void elogclose(File*);
|
|
void eloginsert(File*, int, Rune*, int);
|
|
void elogdelete(File*, int, int);
|
|
void elogreplace(File*, int, int, Rune*, int);
|
|
void elogapply(File*);
|
|
|
|
struct File
|
|
{
|
|
Buffer; /* the data */
|
|
Buffer delta; /* transcript of changes */
|
|
Buffer epsilon; /* inversion of delta for redo */
|
|
Buffer *elogbuf; /* log of pending editor changes */
|
|
Elog elog; /* current pending change */
|
|
Rune *name; /* name of associated file */
|
|
int nname; /* size of name */
|
|
uint64_t qidpath; /* of file when read */
|
|
uint32_t mtime; /* of file when read */
|
|
int dev; /* of file when read */
|
|
int unread; /* file has not been read from disk */
|
|
int editclean; /* mark clean after edit command */
|
|
|
|
int seq; /* if seq==0, File acts like Buffer */
|
|
int mod;
|
|
Text *curtext; /* most recently used associated text */
|
|
Text **text; /* list of associated texts */
|
|
int ntext;
|
|
int dumpid; /* used in dumping zeroxed windows */
|
|
};
|
|
File* fileaddtext(File*, Text*);
|
|
void fileclose(File*);
|
|
void filedelete(File*, uint32_t, uint32_t);
|
|
void filedeltext(File*, Text*);
|
|
void fileinsert(File*, uint32_t, Rune*, uint32_t);
|
|
uint32_t fileload(File*, uint32_t, int, int*);
|
|
void filemark(File*);
|
|
void filereset(File*);
|
|
void filesetname(File*, Rune*, int);
|
|
void fileundelete(File*, Buffer*, uint32_t, uint32_t);
|
|
void fileuninsert(File*, Buffer*, uint32_t, uint32_t);
|
|
void fileunsetname(File*, Buffer*);
|
|
void fileundo(File*, int, uint32_t*, uint32_t*);
|
|
uint32_t fileredoseq(File*);
|
|
|
|
enum /* Text.what */
|
|
{
|
|
Columntag,
|
|
Rowtag,
|
|
Tag,
|
|
Body,
|
|
};
|
|
|
|
struct Text
|
|
{
|
|
File *file;
|
|
Frame;
|
|
Reffont *reffont;
|
|
uint32_t org;
|
|
uint32_t q0;
|
|
uint32_t q1;
|
|
int what;
|
|
int tabstop;
|
|
Window *w;
|
|
Rectangle scrollr;
|
|
Rectangle lastsr;
|
|
Rectangle all;
|
|
Row *row;
|
|
Column *col;
|
|
|
|
uint32_t eq0; /* start of typing for ESC */
|
|
uint32_t cq0; /* cache position */
|
|
int ncache; /* storage for insert */
|
|
int ncachealloc;
|
|
Rune *cache;
|
|
int nofill;
|
|
};
|
|
|
|
uint32_t textbacknl(Text*, uint32_t, uint32_t);
|
|
uint32_t textbsinsert(Text*, uint32_t, Rune*,
|
|
uint32_t, int, int*);
|
|
int textbswidth(Text*, Rune);
|
|
int textclickmatch(Text*, int, int, int, uint32_t*);
|
|
void textclose(Text*);
|
|
void textcolumnate(Text*, Dirlist**, int);
|
|
void textcommit(Text*, int);
|
|
void textconstrain(Text*, uint32_t, uint32_t,
|
|
uint32_t*, uint32_t*);
|
|
void textdelete(Text*, uint32_t, uint32_t, int);
|
|
void textdoubleclick(Text*, uint32_t*, uint32_t*);
|
|
void textfill(Text*);
|
|
void textframescroll(Text*, int);
|
|
void textinit(Text*, File*, Rectangle, Reffont*, Image**);
|
|
void textinsert(Text*, uint32_t, Rune*, uint32_t,
|
|
int);
|
|
uint32_t textload(Text*, uint32_t, char*, int);
|
|
Rune textreadc(Text*, uint32_t);
|
|
void textredraw(Text*, Rectangle, Font*, Image*, int);
|
|
void textreset(Text*);
|
|
int textresize(Text*, Rectangle);
|
|
void textscrdraw(Text*);
|
|
void textscroll(Text*, int);
|
|
void textselect(Text*);
|
|
int textselect2(Text*, uint32_t*, uint32_t*, Text**);
|
|
int textselect23(Text*, uint32_t*, uint32_t*, Image*,
|
|
int);
|
|
int textselect3(Text*, uint32_t*, uint32_t*);
|
|
void textsetorigin(Text*, uint32_t, int);
|
|
void textsetselect(Text*, uint32_t, uint32_t);
|
|
void textshow(Text*, uint32_t, uint32_t, int);
|
|
void texttype(Text*, Rune);
|
|
|
|
struct Window
|
|
{
|
|
QLock;
|
|
Ref;
|
|
Text tag;
|
|
Text body;
|
|
Rectangle r;
|
|
uint8_t isdir;
|
|
uint8_t isscratch;
|
|
uint8_t filemenu;
|
|
uint8_t dirty;
|
|
uint8_t autoindent;
|
|
uint8_t showdel;
|
|
uint32_t noredraw;
|
|
int id;
|
|
Range addr;
|
|
Range limit;
|
|
uint8_t nopen[QMAX];
|
|
uint8_t nomark;
|
|
uint8_t noscroll;
|
|
Range wrselrange;
|
|
int rdselfd;
|
|
Column *col;
|
|
Xfid *eventx;
|
|
char *events;
|
|
int nevents;
|
|
int owner;
|
|
int maxlines;
|
|
Dirlist **dlp;
|
|
int ndl;
|
|
int putseq;
|
|
int nincl;
|
|
Rune **incl;
|
|
Reffont *reffont;
|
|
QLock ctllock;
|
|
uint32_t ctlfid;
|
|
char *dumpstr;
|
|
char *dumpdir;
|
|
int dumpid;
|
|
int utflastqid;
|
|
int utflastboff;
|
|
int utflastq;
|
|
int tagsafe; /* taglines is correct */
|
|
int tagexpand;
|
|
int taglines;
|
|
Rectangle tagtop;
|
|
};
|
|
|
|
void wininit(Window*, Window*, Rectangle);
|
|
void winlock(Window*, int);
|
|
void winlock1(Window*, int);
|
|
void winunlock(Window*);
|
|
void wintype(Window*, Text*, Rune);
|
|
void winundo(Window*, int);
|
|
void winsetname(Window*, Rune*, int);
|
|
void winsettag(Window*);
|
|
void winsettag1(Window*);
|
|
void wincommit(Window*, Text*);
|
|
int winresize(Window*, Rectangle, int);
|
|
void winclose(Window*);
|
|
void windelete(Window*);
|
|
int winclean(Window*, int);
|
|
void windirfree(Window*);
|
|
void winevent(Window*, char*, ...);
|
|
void winmousebut(Window*);
|
|
void winaddincl(Window*, Rune*, int);
|
|
void wincleartag(Window*);
|
|
char *winctlprint(Window*, char*, int);
|
|
|
|
struct Column
|
|
{
|
|
Rectangle r;
|
|
Text tag;
|
|
Row *row;
|
|
Window **w;
|
|
int nw;
|
|
int safe;
|
|
};
|
|
|
|
void colinit(Column*, Rectangle);
|
|
Window* coladd(Column*, Window*, Window*, int);
|
|
void colclose(Column*, Window*, int);
|
|
void colcloseall(Column*);
|
|
void colresize(Column*, Rectangle);
|
|
Text* colwhich(Column*, Point);
|
|
void coldragwin(Column*, Window*, int);
|
|
void colgrow(Column*, Window*, int);
|
|
int colclean(Column*);
|
|
void colsort(Column*);
|
|
void colmousebut(Column*);
|
|
|
|
struct Row
|
|
{
|
|
QLock;
|
|
Rectangle r;
|
|
Text tag;
|
|
Column **col;
|
|
int ncol;
|
|
|
|
};
|
|
|
|
void rowinit(Row*, Rectangle);
|
|
Column* rowadd(Row*, Column *c, int);
|
|
void rowclose(Row*, Column*, int);
|
|
Text* rowwhich(Row*, Point);
|
|
Column* rowwhichcol(Row*, Point);
|
|
void rowresize(Row*, Rectangle);
|
|
Text* rowtype(Row*, Rune, Point);
|
|
void rowdragcol(Row*, Column*, int but);
|
|
int rowclean(Row*);
|
|
void rowdump(Row*, char*);
|
|
int rowload(Row*, char*, int);
|
|
void rowloadfonts(char*);
|
|
|
|
struct Timer
|
|
{
|
|
int dt;
|
|
int cancel;
|
|
Channel *c; /* chan(int) */
|
|
Timer *next;
|
|
};
|
|
|
|
struct Command
|
|
{
|
|
int pid;
|
|
Rune *name;
|
|
int nname;
|
|
char *text;
|
|
char **av;
|
|
int iseditcmd;
|
|
Mntdir *md;
|
|
Command *next;
|
|
};
|
|
|
|
struct Dirtab
|
|
{
|
|
char *name;
|
|
uint8_t type;
|
|
uint32_t qid;
|
|
uint32_t perm;
|
|
};
|
|
|
|
struct Mntdir
|
|
{
|
|
int id;
|
|
int ref;
|
|
Rune *dir;
|
|
int ndir;
|
|
Mntdir *next;
|
|
int nincl;
|
|
Rune **incl;
|
|
};
|
|
|
|
struct Fid
|
|
{
|
|
int fid;
|
|
int busy;
|
|
int open;
|
|
Qid qid;
|
|
Window *w;
|
|
Dirtab *dir;
|
|
Fid *next;
|
|
Mntdir *mntdir;
|
|
int nrpart;
|
|
uint8_t rpart[UTFmax];
|
|
};
|
|
|
|
|
|
struct Xfid
|
|
{
|
|
void *arg; /* args to xfidinit */
|
|
Fcall;
|
|
Xfid *next;
|
|
Channel *c; /* chan(void(*)(Xfid*)) */
|
|
Fid *f;
|
|
uint8_t *buf;
|
|
int flushed;
|
|
|
|
};
|
|
|
|
void xfidctl(void *);
|
|
void xfidflush(Xfid*);
|
|
void xfidopen(Xfid*);
|
|
void xfidclose(Xfid*);
|
|
void xfidread(Xfid*);
|
|
void xfidwrite(Xfid*);
|
|
void xfidctlwrite(Xfid*, Window*);
|
|
void xfideventread(Xfid*, Window*);
|
|
void xfideventwrite(Xfid*, Window*);
|
|
void xfidindexread(Xfid*);
|
|
void xfidutfread(Xfid*, Text*, uint32_t, int);
|
|
int xfidruneread(Xfid*, Text*, uint32_t, uint32_t);
|
|
|
|
struct Reffont
|
|
{
|
|
Ref;
|
|
Font *f;
|
|
|
|
};
|
|
Reffont *rfget(int, int, int, char*);
|
|
void rfclose(Reffont*);
|
|
|
|
struct Rangeset
|
|
{
|
|
Range r[NRange];
|
|
};
|
|
|
|
struct Dirlist
|
|
{
|
|
Rune *r;
|
|
int nr;
|
|
int wid;
|
|
};
|
|
|
|
struct Expand
|
|
{
|
|
uint32_t q0;
|
|
uint32_t q1;
|
|
Rune *name;
|
|
int nname;
|
|
char *bname;
|
|
int jump;
|
|
union{
|
|
Text *at;
|
|
Rune *ar;
|
|
};
|
|
int (*agetc)(void*, uint32_t);
|
|
int a0;
|
|
int a1;
|
|
};
|
|
|
|
enum
|
|
{
|
|
/* fbufalloc() guarantees room off end of BUFSIZE */
|
|
BUFSIZE = Maxblock+IOHDRSZ, /* size from fbufalloc() */
|
|
RBUFSIZE = BUFSIZE/sizeof(Rune),
|
|
EVENTSIZE = 256,
|
|
Scrollwid = 12, /* width of scroll bar */
|
|
Scrollgap = 4, /* gap right of scroll bar */
|
|
Margin = 4, /* margin around text */
|
|
Border = 2, /* line between rows, cols, windows */
|
|
};
|
|
|
|
#define QID(w,q) ((w<<8)|(q))
|
|
#define WIN(q) ((((uint32_t)(q).path)>>8) & 0xFFFFFF)
|
|
#define FILE(q) ((q).path & 0xFF)
|
|
|
|
enum
|
|
{
|
|
FALSE,
|
|
TRUE,
|
|
XXX,
|
|
};
|
|
|
|
enum
|
|
{
|
|
Empty = 0,
|
|
Null = '-',
|
|
Delete = 'd',
|
|
Insert = 'i',
|
|
Replace = 'r',
|
|
Filename = 'f',
|
|
};
|
|
|
|
enum /* editing */
|
|
{
|
|
Inactive = 0,
|
|
Inserting,
|
|
Collecting,
|
|
};
|
|
|
|
uint32_t globalincref;
|
|
uint32_t seq;
|
|
uint32_t maxtab; /* size of a tab, in units of the '0' character */
|
|
|
|
Display *display;
|
|
Image *screen;
|
|
Font *font;
|
|
Mouse *mouse;
|
|
Mousectl *mousectl;
|
|
Keyboardctl *keyboardctl;
|
|
Reffont reffont;
|
|
Image *modbutton;
|
|
Image *colbutton;
|
|
Image *button;
|
|
Image *but2col;
|
|
Image *but3col;
|
|
Cursor boxcursor;
|
|
Row row;
|
|
int timerpid;
|
|
Disk *disk;
|
|
Text *seltext;
|
|
Text *argtext;
|
|
Text *mousetext; /* global because Text.close needs to clear it */
|
|
Text *typetext; /* global because Text.close needs to clear it */
|
|
Text *barttext; /* shared between mousetask and keyboardthread */
|
|
int bartflag;
|
|
Window *activewin;
|
|
Column *activecol;
|
|
Buffer snarfbuf;
|
|
Rectangle nullrect;
|
|
int fsyspid;
|
|
char *cputype;
|
|
char *objtype;
|
|
char *home;
|
|
char *fontnames[2];
|
|
char acmeerrorfile[128];
|
|
Image *tagcols[NCOL];
|
|
Image *textcols[NCOL];
|
|
int plumbsendfd;
|
|
int plumbeditfd;
|
|
char wdir[512];
|
|
int editing;
|
|
int messagesize; /* negotiated in 9P version setup */
|
|
int globalautoindent;
|
|
|
|
Channel *cplumb; /* chan(Plumbmsg*) */
|
|
Channel *cwait; /* chan(Waitmsg) */
|
|
Channel *ccommand; /* chan(Command*) */
|
|
Channel *ckill; /* chan(Rune*) */
|
|
Channel *cxfidalloc; /* chan(Xfid*) */
|
|
Channel *cxfidfree; /* chan(Xfid*) */
|
|
Channel *cnewwindow; /* chan(Channel*) */
|
|
Channel *mouseexit0; /* chan(int) */
|
|
Channel *mouseexit1; /* chan(int) */
|
|
Channel *cexit; /* chan(int) */
|
|
Channel *cerr; /* chan(char*) */
|
|
Channel *cedit; /* chan(int) */
|
|
Channel *cwarn; /* chan(void*)[1] (really chan(unit)[1]) */
|
|
|
|
#define STACK 8192
|