Commit Diff


commit - e2a141ae0952c2d28a9f500bb9da6dc72e57be3c
commit + b4704695f1c7c3ade4b6748ae50129fb404f5214
blob - 852a8f7f1e803c2662691fffa27510cb0e448c02
blob + 2fdda118f6a24e605187160a126ca78a0345c2e5
--- man/man1/acme.1
+++ man/man1/acme.1
@@ -4,7 +4,7 @@ acme, win, awd \- interactive text windows
 .SH SYNOPSIS
 .B acme
 [
-.B -abr
+.B -aibr
 ]
 [
 .B -f
@@ -203,6 +203,16 @@ The option
 .B -a
 causes each window to start in
 autoindent mode.
+.PP
+When a window is in spacesindent mode
+(see the
+.B Spaces
+command below) and a tab character is typed,
+acme indents the line with spaces equal to the current
+tabstop for the window. The option
+.B -i
+causes each window to start in spacesindent
+mode.
 .SS "Directory context
 Each window's tag names a directory: explicitly if the window
 holds a directory; implicitly if it holds a regular file
@@ -469,6 +479,17 @@ Place selected text in snarf buffer.
 Arrange the windows in the column from top to bottom in lexicographical
 order based on their names.
 .TP
+.B Spaces
+Set the spacesindent mode according to the argument:
+.B on
+and
+.B off
+set the mode for the current window;
+.B ON
+and
+.B OFF
+set the mode for all existing and future windows.
+.TP
 .B Tab
 Set the width of tab stops for this window to the value of the argument, in units of widths of the zero
 character.
blob - 0e6bc0fd7f077ef5453d5c33736924aa8424c2a3
blob + 9342965d3bcf2e5dbf0ba29d929734f2f1e5d7eb
--- src/cmd/acme/acme.c
+++ src/cmd/acme/acme.c
@@ -78,7 +78,7 @@ threadmain(int argc, char *argv[])
 		}
 		break;
 	case 'a':
-		globalautoindent = TRUE;
+		globalindent[AUTOINDENT] = TRUE;
 		break;
 	case 'b':
 		bartflag = TRUE;
@@ -101,6 +101,9 @@ threadmain(int argc, char *argv[])
 		if(fontnames[1] == nil)
 			goto Usage;
 		break;
+	case 'i':
+		globalindent[SPACESINDENT] = TRUE;
+		break;
 	case 'l':
 		loadfile = ARGF();
 		if(loadfile == nil)
@@ -121,7 +124,7 @@ threadmain(int argc, char *argv[])
 		break;
 	default:
 	Usage:
-		fprint(2, "usage: acme -a -c ncol -f fontname -F fixedwidthfontname -l loadfile -W winsize\n");
+		fprint(2, "usage: acme -aib -c ncol -f fontname -F fixedwidthfontname -l loadfile -W winsize\n");
 		threadexitsall("usage");
 	}ARGEND
 
blob - e540605a316dbcc3fa05f4205e0f4e6b0a674b57
blob + e05783ba445aa224611fd83536641a79f1c16d0f
--- src/cmd/acme/dat.h
+++ src/cmd/acme/dat.h
@@ -229,6 +229,13 @@ void		textsetselect(Text*, uint, uint);
 void		textshow(Text*, uint, uint, int);
 void		texttype(Text*, Rune);
 
+enum
+{
+	SPACESINDENT	= 0,
+	AUTOINDENT,
+	NINDENT,
+};
+
 struct Window
 {
 	QLock	lk;
@@ -240,7 +247,7 @@ struct Window
 	uchar	isscratch;
 	uchar	filemenu;
 	uchar	dirty;
-	uchar	autoindent;
+	uchar	indent[NINDENT];
 	uchar	showdel;
 	int		id;
 	Range	addr;
@@ -552,7 +559,7 @@ extern char		wdir[]; /* must use extern because no dim
 int			editing;
 int			erroutfd;
 int			messagesize;		/* negotiated in 9P version setup */
-int			globalautoindent;
+int			globalindent[NINDENT];
 int			dodollarsigns;
 char*		mtpt;
 
blob - 1dd0228895443eeef4c05f91ec6f5f9c3ad21068
blob + 9171d7a998d764c0eb6d3e10a5e14cdccf2e3624
--- src/cmd/acme/exec.c
+++ src/cmd/acme/exec.c
@@ -92,6 +92,7 @@ static Rune LRedo[] = { 'R', 'e', 'd', 'o', 0 };
 static Rune LSend[] = { 'S', 'e', 'n', 'd', 0 };
 static Rune LSnarf[] = { 'S', 'n', 'a', 'r', 'f', 0 };
 static Rune LSort[] = { 'S', 'o', 'r', 't', 0 };
+static Rune LSpaces[] = { 'S', 'p', 'a', 'c', 'e', 's', 0 };
 static Rune LTab[] = { 'T', 'a', 'b', 0 };
 static Rune LUndo[] = { 'U', 'n', 'd', 'o', 0 };
 static Rune LZerox[] = { 'Z', 'e', 'r', 'o', 'x', 0 };
@@ -109,7 +110,7 @@ Exectab exectab[] = {
 	{ LGet,		get,		FALSE,	TRUE,	XXX		},
 	{ LID,		id,		FALSE,	XXX,		XXX		},
 	{ LIncl,		incl,		FALSE,	XXX,		XXX		},
-	{ LIndent,		indent,	FALSE,	XXX,		XXX		},
+	{ LIndent,	indent,		FALSE,	AUTOINDENT,		XXX		},
 	{ LKill,		xkill,		FALSE,	XXX,		XXX		},
 	{ LLoad,		dump,	FALSE,	FALSE,	XXX		},
 	{ LLocal,		local,	FALSE,	XXX,		XXX		},
@@ -123,6 +124,7 @@ Exectab exectab[] = {
 	{ LSend,		sendx,	TRUE,	XXX,		XXX		},
 	{ LSnarf,		cut,		FALSE,	TRUE,	FALSE	},
 	{ LSort,		sort,		FALSE,	XXX,		XXX		},
+	{ LSpaces,	indent,		FALSE,	SPACESINDENT,	XXX		},
 	{ LTab,		tab,		FALSE,	XXX,		XXX		},
 	{ LUndo,		undo,	FALSE,	TRUE,	XXX		},
 	{ LZerox,		zeroxx,	FALSE,	XXX,		XXX		},
@@ -915,7 +917,7 @@ put(Text *et, Text *_0, Text *argt, int _1, int _2, Ru
 		warning(nil, "no file name\n");
 		return;
 	}
-	if(w->autoindent)
+	if(w->indent[AUTOINDENT])
 		trimspaces(et);
 	namer = bytetorune(name, &nname);
 	putfile(f, 0, f->b.nc, namer, nname);
@@ -1387,66 +1389,75 @@ incl(Text *et, Text *_0, Text *argt, int _1, int _2, R
 static Rune LON[] = { 'O', 'N', 0 };
 static Rune LOFF[] = { 'O', 'F', 'F', 0 };
 static Rune Lon[] = { 'o', 'n', 0 };
+static Rune Loff[] = { 'o', 'f', 'f', 0 };
 
 enum {
 	IGlobal = -2,
 	IError = -1,
-	Ion = 0,
-	Ioff = 1
 };
 
 static int
-indentval(Rune *s, int n)
+indentval(Rune *s, int n, int type)
 {
+	static char *strs[] = {
+		[SPACESINDENT] = "Spaces",
+		[AUTOINDENT] = "Indent",
+	};
+
 	if(n < 2)
 		return IError;
 	if(runestrncmp(s, LON, n) == 0){
-		globalautoindent = TRUE;
-		warning(nil, "Indent ON\n");
+		globalindent[type] = TRUE;
+		warning(nil, "%s ON\n", strs[type]);
 		return IGlobal;
 	}
 	if(runestrncmp(s, LOFF, n) == 0){
-		globalautoindent = FALSE;
-		warning(nil, "Indent OFF\n");
+		globalindent[type] = FALSE;
+		warning(nil, "%s OFF\n", strs[type]);
 		return IGlobal;
 	}
-	return runestrncmp(s, Lon, n) == 0;
+	if(runestrncmp(s, Lon, n) == 0)
+		return TRUE;
+	if(runestrncmp(s, Loff, n) == 0)
+		return FALSE;
+	return IError;
 }
 
 static void
 fixindent(Window *w, void *arg)
 {
-	USED(arg);
-	w->autoindent = globalautoindent;
+	int t;
+
+	t = (int)arg;
+	w->indent[t] = globalindent[t];
 }
 
 void
-indent(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
+indent(Text *et, Text* _0, Text *argt, int type, int _1, Rune *arg, int narg)
 {
 	Rune *a, *r;
 	Window *w;
-	int na, len, autoindent;
+	int na, len, ival;
 
 	USED(_0);
 	USED(_1);
-	USED(_2);
 
 	w = nil;
 	if(et!=nil && et->w!=nil)
 		w = et->w;
-	autoindent = IError;
+	ival = IError;
 	getarg(argt, FALSE, TRUE, &r, &len);
 	if(r!=nil && len>0)
-		autoindent = indentval(r, len);
+		ival = indentval(r, len, type);
 	else{
 		a = findbl(arg, narg, &na);
 		if(a != arg)
-			autoindent = indentval(arg, narg-na);
+			ival = indentval(arg, narg-na, type);
 	}
-	if(autoindent == IGlobal)
-		allwindows(fixindent, nil);
-	else if(w != nil && autoindent >= 0)
-		w->autoindent = autoindent;
+	if(ival == IGlobal)
+		allwindows(fixindent, (void*)type);
+	else if(w != nil && ival >= 0)
+		w->indent[type] = ival;
 }
 
 void
blob - a7172b505f71d405da0d9ad6766e4540df54a887
blob + ce528330caa24eeb537bf76b88cf196eae3fd00e
--- src/cmd/acme/look.c
+++ src/cmd/acme/look.c
@@ -797,9 +797,11 @@ openfile(Text *t, Expand *e)
 				runemove(rp, ow->incl[i], n);
 				winaddincl(w, rp, n);
 			}
-			w->autoindent = ow->autoindent;
+			for(i=0; i < NINDENT; i++)
+				w->indent[i] = ow->indent[i];
 		}else
-			w->autoindent = globalautoindent;
+			for(i=0; i < NINDENT; i++)
+				w->indent[i] = globalindent[i];
 		xfidlog(w, "new");
 	}
 	if(e->a1 == e->a0)
blob - 09422dda077cfa755a87ba156da88fafa25cd7b1
blob + ff2da5b3e06a235c6976a582fd47ba9f6950c143
--- src/cmd/acme/text.c
+++ src/cmd/acme/text.c
@@ -531,7 +531,28 @@ textreadc(Text *t, uint q)
 		bufread(&t->file->b, q, &r, 1);
 	return r;
 }
+
+static int
+spacesindentbswidth(Text *t)
+{
+	uint q, col;
+	Rune r;
 
+	col = textbswidth(t, 0x15);
+	q = t->q0;
+	while(q > 0){
+		r = textreadc(t, q-1);
+		if(r != ' ')
+			break;
+		q--;
+		if(--col % t->tabstop == 0)
+			break;
+	}
+	if(t->q0 == q)
+		return 1;
+	return t->q0-q;
+}
+
 int
 textbswidth(Text *t, Rune c)
 {
@@ -540,8 +561,11 @@ textbswidth(Text *t, Rune c)
 	int skipping;
 
 	/* there is known to be at least one character to erase */
-	if(c == 0x08)	/* ^H: erase character */
+	if(c == 0x08){	/* ^H: erase character */
+		if(t->what == Body && t->w->indent[SPACESINDENT])
+			return spacesindentbswidth(t);
 		return 1;
+	}
 	q = t->q0;
 	skipping = TRUE;
 	while(q > 0){
@@ -887,8 +911,19 @@ texttype(Text *t, Rune r)
 			textfill(t->file->text[i]);
 		t->iq1 = t->q0;
 		return;
+	case '\t':
+		if(t->what == Body && t->w->indent[SPACESINDENT]){
+			nnb = textbswidth(t, 0x15);
+			if(nnb == 1 && textreadc(t, t->q0-1) == '\n')
+				nnb = 0;
+			nnb = t->tabstop - nnb % t->tabstop;
+			rp = runemalloc(nnb);
+			for(nr = 0; nr < nnb; nr++)
+				rp[nr] = ' ';
+		}
+		break;
 	case '\n':
-		if(t->w->autoindent){
+		if(t->what == Body && t->w->indent[AUTOINDENT]){
 			/* find beginning of previous line using backspace code */
 			nnb = textbswidth(t, 0x15); /* ^U case */
 			rp = runemalloc(nnb + 1);
blob - c153f8c180c0c2325d9b26c1b29e0f6257ba61b4
blob + ecd0450341809c99bcf3a55eb6a8aafd6d29164a
--- src/cmd/acme/util.c
+++ src/cmd/acme/util.c
@@ -107,7 +107,8 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
 		runemove(r, incl[i], n);
 		winaddincl(w, r, n);
 	}
-	w->autoindent = globalautoindent;
+	for(i=0; i<NINDENT; i++)
+		w->indent[i] = globalindent[i];
 	return w;
 }
 
blob - 9441bbb76077ff5aea945f3813efa501e32adf25
blob + 0cea1694a118c07fc8c98ee947c98895f55238cc
--- src/cmd/acme/wind.c
+++ src/cmd/acme/wind.c
@@ -21,7 +21,7 @@ wininit(Window *w, Window *clone, Rectangle r)
 	File *f;
 	Reffont *rf;
 	Rune *rp;
-	int nc;
+	int nc, i;
 
 	w->tag.w = w;
 	w->taglines = 1;
@@ -80,10 +80,12 @@ wininit(Window *w, Window *clone, Rectangle r)
 	draw(screen, br, button, nil, button->r.min);
 	w->filemenu = TRUE;
 	w->maxlines = w->body.fr.maxlines;
-	w->autoindent = globalautoindent;
+	for(i=0; i<NINDENT; i++)
+		w->indent[i] = globalindent[i];
 	if(clone){
 		w->dirty = clone->dirty;
-		w->autoindent = clone->autoindent;
+		for(i=0; i<NINDENT; i++)
+			w->indent[i] = clone->indent[i];
 		textsetselect(&w->body, clone->body.q0, clone->body.q1);
 		winsettag(w);
 	}