Commit Diff


commit - 805d91d359d67676a89edc9789ee8267bb7da6e1
commit + 3d6e5cb56a6249e7f3001091fe81c171cd501319
blob - 861e5e01f0d7c4c13d31d1d89e565088179f155a
blob + 2ccae960a3cc7cf242f7bbb07c2eeb433f7fb3e3
--- src/cmd/acme/addr.c
+++ src/cmd/acme/addr.c
@@ -49,6 +49,27 @@ isregexc(int r)
 	return FALSE;
 }
 
+// nlcounttopos starts at q0 and advances nl lines,
+// being careful not to walk past the end of the text,
+// and then nr chars, being careful not to walk past
+// the end of the current line.
+// It returns the final position.
+long
+nlcounttopos(Text *t, long q0, long nl, long nr)
+{
+	while(nl > 0 && q0 < t->file->b.nc) {
+		if(textreadc(t, q0++) == '\n')
+			nl--;
+	}
+	if(nl > 0)
+		return q0;
+	while(nr > 0 && q0 < t->file->b.nc && textreadc(t, q0) != '\n') {
+		q0++;
+		nr--;
+	}
+	return q0;
+}
+
 Range
 number(uint showerr, Text *t, Range r, int line, int dir, int size, int *evalp)
 {
blob - 9bedae4ca39fa20069b7459fa576a3e573868192
blob + ef92e3395deca665f306c2f7059f35803ea96f16
--- src/cmd/acme/ecmd.c
+++ src/cmd/acme/ecmd.c
@@ -661,15 +661,16 @@ pipe_cmd(Text *t, Cmd *cp)
 }
 
 long
-nlcount(Text *t, long q0, long q1)
+nlcount(Text *t, long q0, long q1, long *pnr)
 {
-	long nl;
+	long nl, start;
 	Rune *buf;
 	int i, nbuf;
 
 	buf = fbufalloc();
 	nbuf = 0;
 	i = nl = 0;
+	start = q0;
 	while(q0 < q1){
 		if(i == nbuf){
 			nbuf = q1-q0;
@@ -678,24 +679,44 @@ nlcount(Text *t, long q0, long q1)
 			bufread(&t->file->b, q0, buf, nbuf);
 			i = 0;
 		}
-		if(buf[i++] == '\n')
+		if(buf[i++] == '\n') {
+			start = q0+1;
 			nl++;
+		}
 		q0++;
 	}
 	fbuffree(buf);
+	if(pnr != nil)
+		*pnr = q0 - start;
 	return nl;
 }
 
-void
-printposn(Text *t, int charsonly)
+enum {
+	PosnLine = 0,
+	PosnChars = 1,
+	PosnLineChars = 2,
+};
+
+void
+printposn(Text *t, int mode)
 {
-	long l1, l2;
+	long l1, l2, r1, r2;
 
 	if (t != nil && t->file != nil && t->file->name != nil)
 		warning(nil, "%.*S:", t->file->nname, t->file->name);
-	if(!charsonly){
-		l1 = 1+nlcount(t, 0, addr.r.q0);
-		l2 = l1+nlcount(t, addr.r.q0, addr.r.q1);
+	
+	switch(mode) {
+	case PosnChars:
+		warning(nil, "#%d", addr.r.q0);
+		if(addr.r.q1 != addr.r.q0)
+			warning(nil, ",#%d", addr.r.q1);
+		warning(nil, "\n");
+		return;
+	
+	default:
+	case PosnLine:
+		l1 = 1+nlcount(t, 0, addr.r.q0, nil);
+		l2 = l1+nlcount(t, addr.r.q0, addr.r.q1, nil);
 		/* check if addr ends with '\n' */
 		if(addr.r.q1>0 && addr.r.q1>addr.r.q0 && textreadc(t, addr.r.q1-1)=='\n')
 			--l2;
@@ -704,32 +725,43 @@ printposn(Text *t, int charsonly)
 			warning(nil, ",%lud", l2);
 		warning(nil, "\n");
 		return;
+
+	case PosnLineChars:
+		l1 = 1+nlcount(t, 0, addr.r.q0, &r1);
+		l2 = l1+nlcount(t, addr.r.q0, addr.r.q1, &r2);
+		if(l2 == l1)
+			r2 += r1;
+		warning(nil, "%lud+#%d", l1, r1);
+		if(l2 != l1)
+			warning(nil, ",%lud+#%d", l2, r2);
+		warning(nil, "\n");
+		return;
 	}
-	warning(nil, "#%d", addr.r.q0);
-	if(addr.r.q1 != addr.r.q0)
-		warning(nil, ",#%d", addr.r.q1);
-	warning(nil, "\n");
 }
 
 int
 eq_cmd(Text *t, Cmd *cp)
 {
-	int charsonly;
+	int mode;
 
 	switch(cp->u.text->n){
 	case 0:
-		charsonly = FALSE;
+		mode = PosnLine;
 		break;
 	case 1:
 		if(cp->u.text->r[0] == '#'){
-			charsonly = TRUE;
+			mode = PosnChars;
 			break;
 		}
+		if(cp->u.text->r[0] == '+'){
+			mode = PosnLineChars;
+			break;
+		}
 	default:
-		SET(charsonly);
+		SET(mode);
 		editerror("newline expected");
 	}
-	printposn(t, charsonly);
+	printposn(t, mode);
 	return TRUE;
 }
 
blob - 1df01c71647362aec240548e790dc3248c20f368
blob + deaef0cb18584ac8aa158a6f5c43c11471f47e10
--- src/cmd/acme/exec.c
+++ src/cmd/acme/exec.c
@@ -573,15 +573,27 @@ zeroxx(Text *et, Text *t, Text *_1, int _2, int _3, Ru
 		winunlock(t->w);
 }
 
+typedef struct TextAddr TextAddr;
+struct TextAddr {
+	long lorigin; // line+rune for origin
+	long rorigin;
+	long lq0; // line+rune for q0
+	long rq0;
+	long lq1; // line+rune for q1
+	long rq1;
+};
+
 void
 get(Text *et, Text *t, Text *argt, int flag1, int _0, Rune *arg, int narg)
 {
 	char *name;
 	Rune *r;
 	int i, n, dirty, samename, isdir;
+	TextAddr *addr, *a;
 	Window *w;
 	Text *u;
 	Dir *d;
+	long q0, q1;
 
 	USED(_0);
 
@@ -605,6 +617,14 @@ get(Text *et, Text *t, Text *argt, int flag1, int _0, 
 			warning(nil, "%s is a directory; can't read with multiple windows on it\n", name);
 			return;
 		}
+	}
+	addr = emalloc((t->file->ntext)*sizeof(TextAddr));
+	for(i=0; i<t->file->ntext; i++) {
+		a = &addr[i];
+		u = t->file->text[i];
+		a->lorigin = nlcount(u, 0, u->org, &a->rorigin);
+		a->lq0 = nlcount(u, 0, u->q0, &a->rq0);
+		a->lq1 = nlcount(u, u->q0, u->q1, &a->rq1);
 	}
 	r = bytetorune(name, &n);
 	for(i=0; i<t->file->ntext; i++){
@@ -631,8 +651,18 @@ get(Text *et, Text *t, Text *argt, int flag1, int _0, 
 	for(i=0; i<t->file->ntext; i++){
 		u = t->file->text[i];
 		textsetselect(&u->w->tag, u->w->tag.file->b.nc, u->w->tag.file->b.nc);
+		if(samename) {
+			a = &addr[i];
+			// warning(nil, "%d %d %d %d %d %d\n", a->lorigin, a->rorigin, a->lq0, a->rq0, a->lq1, a->rq1);
+			q0 = nlcounttopos(u, 0, a->lq0, a->rq0);
+			q1 = nlcounttopos(u, q0, a->lq1, a->rq1);
+			textsetselect(u, q0, q1);
+			q0 = nlcounttopos(u, 0, a->lorigin, a->rorigin);
+			textsetorigin(u, q0, FALSE);
+		}
 		textscrdraw(u);
 	}
+	free(addr);
 	xfidlog(w, "get");
 }
 
blob - 1cd352578f9646ff920f0a46e5306de89f75980a
blob + 8dc023781d70a5e42e4c5e671b674a586c0ae10e
--- src/cmd/acme/fns.h
+++ src/cmd/acme/fns.h
@@ -93,6 +93,8 @@ Rune*	findbl(Rune*, int, int*);
 char*	edittext(Window*, int, Rune*, int);
 void		flushwarnings(void);
 void		startplumbing(void);
+long	nlcount(Text*, long, long, long*);
+long	nlcounttopos(Text*, long, long, long);
 
 Runestr	runestr(Rune*, uint);
 Range range(int, int);
blob - 4832de8ecefd00aa99e5c29d49138b961ed32b87
blob + 8ff5884df8e3cc7aa1c8c3cbd1ef6e4792585304
--- src/cmd/acme/text.c
+++ src/cmd/acme/text.c
@@ -1615,7 +1615,7 @@ textsetorigin(Text *t, uint org, int exact)
 	Rune *r;
 	uint n;
 
-	if(org>0 && !exact){
+	if(org>0 && !exact && textreadc(t, org-1) != '\n'){
 		/* org is an estimate of the char posn; find a newline */
 		/* don't try harder than 256 chars */
 		for(i=0; i<256 && org<t->file->b.nc; i++){