Source

acme with easy backwards search / dat.h

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
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 */
};

#define Buffer AcmeBuffer
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
{
	uint		addr;	/* disk address in bytes */
	union
	{
		uint	n;		/* number of used runes in block */
		Block	*next;	/* pointer to next in free list */
	} u;
};

struct Disk
{
	int		fd;
	uint		addr;	/* length of temp file */
	Block	*free[Maxblock/Blockincr+1];
};

Disk*	diskinit(void);
Block*	disknewblock(Disk*, uint);
void		diskrelease(Disk*, Block*);
void		diskread(Disk*, Block*, Rune*, uint);
void		diskwrite(Disk*, Block**, Rune*, uint);

struct Buffer
{
	uint	nc;
	Rune	*c;			/* cache */
	uint	cnc;			/* bytes in cache */
	uint	cmax;		/* size of allocated cache */
	uint	cq;			/* position of cache */
	int		cdirty;	/* cache needs to be written */
	uint	cbi;			/* index of cache Block */
	Block	**bl;		/* array of blocks */
	uint	nbl;			/* number of blocks */
};
void		bufinsert(Buffer*, uint, Rune*, uint);
void		bufdelete(Buffer*, uint, uint);
uint		bufload(Buffer*, uint, int, int*);
void		bufread(Buffer*, uint, Rune*, uint);
void		bufclose(Buffer*);
void		bufreset(Buffer*);

struct Elog
{
	short	type;		/* Delete, Insert, Filename */
	uint		q0;		/* location of change (unused in f) */
	uint		nd;		/* number of deleted characters */
	uint		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	b;			/* 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 */
	uvlong	qidpath;	/* of file when read */
	ulong		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*, uint, uint);
void		filedeltext(File*, Text*);
void		fileinsert(File*, uint, Rune*, uint);
uint		fileload(File*, uint, int, int*);
void		filemark(File*);
void		filereset(File*);
void		filesetname(File*, Rune*, int);
void		fileundelete(File*, Buffer*, uint, uint);
void		fileuninsert(File*, Buffer*, uint, uint);
void		fileunsetname(File*, Buffer*);
void		fileundo(File*, int, uint*, uint*);
uint		fileredoseq(File*);

enum	/* Text.what */
{
	Columntag,
	Rowtag,
	Tag,
	Body
};

struct Text
{
	File		*file;
	Frame	fr;
	Reffont	*reffont;
	uint	org;
	uint	q0;
	uint	q1;
	int	what;
	int	tabstop;
	Window	*w;
	Rectangle scrollr;
	Rectangle lastsr;
	Rectangle all;
	Row		*row;
	Column	*col;

	uint	eq0;	/* start of typing for ESC */
	uint	cq0;	/* cache position */
	int		ncache;	/* storage for insert */
	int		ncachealloc;
	Rune	*cache;
	int	nofill;
	int	needundo;
};

uint		textbacknl(Text*, uint, uint);
uint		textbsinsert(Text*, uint, Rune*, uint, int, int*);
int		textbswidth(Text*, Rune);
int		textclickhtmlmatch(Text*, uint*, uint*);
int		textclickmatch(Text*, int, int, int, uint*);
void		textclose(Text*);
void		textcolumnate(Text*, Dirlist**, int);
void		textcommit(Text*, int);
void		textconstrain(Text*, uint, uint, uint*, uint*);
void		textdelete(Text*, uint, uint, int);
void		textdoubleclick(Text*, uint*, uint*);
void		textfill(Text*);
void		textframescroll(Text*, int);
void		textinit(Text*, File*, Rectangle, Reffont*, Image**);
void		textinsert(Text*, uint, Rune*, uint, int);
int		textload(Text*, uint, char*, int);
Rune		textreadc(Text*, uint);
void		textredraw(Text*, Rectangle, Font*, Image*, int);
void		textreset(Text*);
int		textresize(Text*, Rectangle, int);
void		textscrdraw(Text*);
void		textscroll(Text*, int);
void		textselect(Text*);
int		textselect2(Text*, uint*, uint*, Text**);
int		textselect23(Text*, uint*, uint*, Image*, int);
int		textselect3(Text*, uint*, uint*);
void		textsetorigin(Text*, uint, int);
void		textsetselect(Text*, uint, uint);
void		textshow(Text*, uint, uint, int);
void		texttype(Text*, Rune);

struct Window
{
	QLock	lk;
	Ref	ref;
	Text		tag;
	Text		body;
	Rectangle	r;
	uchar	isdir;
	uchar	isscratch;
	uchar	filemenu;
	uchar	dirty;
	uchar	autoindent;
	int		id;
	Range	addr;
	Range	limit;
	uchar	nopen[QMAX];
	uchar	nomark;
	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;
	uint		ctlfid;
	char		*dumpstr;
	char		*dumpdir;
	int		dumpid;
	int		utflastqid;
	int		utflastboff;
	int		utflastq;
	int		tagsafe;		/* taglines is correct */
	int		tagexpand;
	int		taglines;
	Rectangle	tagtop;
	QLock	editoutlk;
	int		backwards;
};

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, 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	lk;
	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;
	uchar	type;
	uint	qid;
	uint	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;
	uchar	rpart[UTFmax];
};


struct Xfid
{
	void		*arg;	/* args to xfidinit */
	Fcall	fcall;
	Xfid	*next;
	Channel	*c;		/* chan(void(*)(Xfid*)) */
	Fid	*f;
	uchar	*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*, uint, int);
int		xfidruneread(Xfid*, Text*, uint, uint);

struct Reffont
{
	Ref	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
{
	uint	q0;
	uint	q1;
	Rune	*name;
	int	nname;
	char	*bname;
	int	jump;
	union{
		Text	*at;
		Rune	*ar;
	} u;
	int	(*agetc)(void*, uint);
	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)	((((ulong)(q).path)>>8) & 0xFFFFFF)
#define	FILE(q)	((q).path & 0xFF)

#undef FALSE
#undef TRUE

enum
{
	FALSE,
	TRUE,
	XXX
};

enum
{
	Empty	= 0,
	Null		= '-',
	Delete	= 'd',
	Insert	= 'i',
	Replace	= 'r',
	Filename	= 'f'
};

enum	/* editing */
{
	Inactive	= 0,
	Inserting,
	Collecting
};

uint		globalincref;
uint		seq;
uint		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;
int			swapscrollbuttons;
Window		*activewin;
Column		*activecol;
Buffer		snarfbuf;
Rectangle		nullrect;
int			fsyspid;
char			*cputype;
char			*objtype;
char			*home;
char			*fontnames[2];
Image		*tagcols[NCOL];
Image		*textcols[NCOL];
extern char		wdir[]; /* must use extern because no dimension given */
int			editing;
int			erroutfd;
int			messagesize;		/* negotiated in 9P version setup */
int			globalautoindent;
int			dodollarsigns;
char*		mtpt;

enum
{
	Kscrolloneup		= KF|0x20,
	Kscrollonedown	= KF|0x21
};

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]) */

QLock	editoutlk;

#define	STACK	65536