acme: import changes from plan9port (thanks jxy)
Import the following improvements and bugfixes from plan9port: 4650064a acme: scale window bodies on resize, not including tag space d28913a9 acme: save/restore multiline tags in Dump/Load d2df5d6c acme: fix crash in X |cat with multiple windows 3d6e5cb5 acme: preserve window position and selection during Get
This commit is contained in:
parent
c1c904776c
commit
313aebb964
9 changed files with 150 additions and 47 deletions
|
@ -513,8 +513,13 @@ mousethread(void *)
|
|||
but = 2;
|
||||
else if(m.buttons == 4)
|
||||
but = 3;
|
||||
else if(m.buttons == 8)
|
||||
but = 4;
|
||||
else if(m.buttons == 16)
|
||||
but = 5;
|
||||
barttext = t;
|
||||
if(t->what==Body && ptinrect(m.xy, t->scrollr)){
|
||||
if(t->what==Body && w != nil
|
||||
&& (ptinrect(m.xy, t->scrollr) || (m.buttons & (8|16)))){
|
||||
if(but){
|
||||
winlock(w, 'M');
|
||||
t->eq0 = ~0;
|
||||
|
@ -523,18 +528,6 @@ mousethread(void *)
|
|||
}
|
||||
goto Continue;
|
||||
}
|
||||
/* scroll buttons, wheels, etc. */
|
||||
if(t->what==Body && w != nil && (m.buttons & (8|16))){
|
||||
if(m.buttons & 8)
|
||||
but = Kscrolloneup;
|
||||
else
|
||||
but = Kscrollonedown;
|
||||
winlock(w, 'M');
|
||||
t->eq0 = ~0;
|
||||
texttype(t, but);
|
||||
winunlock(w);
|
||||
goto Continue;
|
||||
}
|
||||
if(ptinrect(m.xy, t->scrollr)){
|
||||
if(but){
|
||||
if(t->what == Columntag)
|
||||
|
|
|
@ -48,6 +48,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->nc) {
|
||||
if(textreadc(t, q0++) == '\n')
|
||||
nl--;
|
||||
}
|
||||
if(nl > 0)
|
||||
return q0;
|
||||
while(nr > 0 && q0 < t->file->nc && textreadc(t, q0) != '\n') {
|
||||
q0++;
|
||||
nr--;
|
||||
}
|
||||
return q0;
|
||||
}
|
||||
|
||||
Range
|
||||
number(Mntdir *md, Text *t, Range r, int line, int dir, int size, int *evalp)
|
||||
{
|
||||
|
|
|
@ -186,7 +186,7 @@ colmousebut(Column *c)
|
|||
void
|
||||
colresize(Column *c, Rectangle r)
|
||||
{
|
||||
int i;
|
||||
int i, old, new;
|
||||
Rectangle r1, r2;
|
||||
Window *w;
|
||||
|
||||
|
@ -199,6 +199,8 @@ colresize(Column *c, Rectangle r)
|
|||
r1.max.y += Border;
|
||||
draw(screen, r1, display->black, nil, ZP);
|
||||
r1.max.y = r.max.y;
|
||||
new = Dy(r) - c->nw*(Border + font->height);
|
||||
old = Dy(c->r) - c->nw*(Border + font->height);
|
||||
for(i=0; i<c->nw; i++){
|
||||
w = c->w[i];
|
||||
w->maxlines = 0;
|
||||
|
@ -206,8 +208,8 @@ colresize(Column *c, Rectangle r)
|
|||
r1.max.y = r.max.y;
|
||||
else {
|
||||
r1.max.y = r1.min.y;
|
||||
if(Dy(c->r) != 0)
|
||||
r1.max.y += (Dy(w->r)+Border)*Dy(r)/Dy(c->r);
|
||||
if(new > 0 && old > 0 && Dy(w->r) > Border+font->height)
|
||||
r1.max.y += (Dy(w->r)-Border-font->height)*new/old + Border + font->height;
|
||||
}
|
||||
r2 = r1;
|
||||
r2.max.y = r2.min.y+Border;
|
||||
|
|
|
@ -27,7 +27,7 @@ int append(File*, Cmd*, long);
|
|||
int pdisplay(File*);
|
||||
void pfilename(File*);
|
||||
void looper(File*, Cmd*, int);
|
||||
void filelooper(Cmd*, int);
|
||||
void filelooper(Text*, Cmd*, int);
|
||||
void linelooper(File*, Cmd*);
|
||||
Address lineaddr(long, Address, int);
|
||||
int filematch(File*, String*);
|
||||
|
@ -575,9 +575,9 @@ x_cmd(Text *t, Cmd *cp)
|
|||
}
|
||||
|
||||
int
|
||||
X_cmd(Text*, Cmd *cp)
|
||||
X_cmd(Text *t, Cmd *cp)
|
||||
{
|
||||
filelooper(cp, cp->cmdc=='X');
|
||||
filelooper(t, cp, cp->cmdc=='X');
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -636,15 +636,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;
|
||||
|
@ -653,24 +654,42 @@ nlcount(Text *t, long q0, long q1)
|
|||
bufread(t->file, 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;
|
||||
}
|
||||
|
||||
enum {
|
||||
PosnLine = 0,
|
||||
PosnChars = 1,
|
||||
PosnLineChars = 2,
|
||||
};
|
||||
|
||||
void
|
||||
printposn(Text *t, int charsonly)
|
||||
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;
|
||||
|
@ -679,32 +698,42 @@ 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+#%lud", l1, r1);
|
||||
if(l2 != l1)
|
||||
warning(nil, ",%lud+#%lud", 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->text->n){
|
||||
case 0:
|
||||
charsonly = FALSE;
|
||||
mode = PosnLine;
|
||||
break;
|
||||
case 1:
|
||||
if(cp->text->r[0] == '#'){
|
||||
charsonly = TRUE;
|
||||
mode = PosnChars;
|
||||
break;
|
||||
}
|
||||
if(cp->text->r[0] == '+'){
|
||||
mode = PosnLineChars;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SET(charsonly);
|
||||
SET(mode);
|
||||
editerror("newline expected");
|
||||
}
|
||||
printposn(t, charsonly);
|
||||
printposn(t, mode);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -921,9 +950,10 @@ alllocker(Window *w, void *v)
|
|||
}
|
||||
|
||||
void
|
||||
filelooper(Cmd *cp, int XY)
|
||||
filelooper(Text *t, Cmd *cp, int XY)
|
||||
{
|
||||
int i;
|
||||
Text *targ;
|
||||
|
||||
if(Glooping++)
|
||||
editerror("can't nest %c command", "YX"[XY]);
|
||||
|
@ -944,8 +974,22 @@ filelooper(Cmd *cp, int XY)
|
|||
*/
|
||||
allwindows(alllocker, (void*)1);
|
||||
globalincref = 1;
|
||||
for(i=0; i<loopstruct.nw; i++)
|
||||
cmdexec(&loopstruct.w[i]->body, cp->cmd);
|
||||
/*
|
||||
* Unlock the window running the X command.
|
||||
* We'll need to lock and unlock each target window in turn.
|
||||
*/
|
||||
if(t && t->w)
|
||||
winunlock(t->w);
|
||||
for(i=0; i<loopstruct.nw; i++){
|
||||
targ = &loopstruct.w[i]->body;
|
||||
if(targ && targ->w)
|
||||
winlock(targ->w, cp->cmdc);
|
||||
cmdexec(targ, cp->cmd);
|
||||
if(targ && targ->w)
|
||||
winunlock(targ->w);
|
||||
}
|
||||
if(t && t->w)
|
||||
winlock(t->w, cp->cmdc);
|
||||
allwindows(alllocker, (void*)0);
|
||||
globalincref = 0;
|
||||
free(loopstruct.w);
|
||||
|
|
|
@ -506,15 +506,27 @@ zeroxx(Text *et, Text *t, Text*, int, int, Rune*, int)
|
|||
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, 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;
|
||||
|
||||
if(flag1)
|
||||
if(et==nil || et->w==nil)
|
||||
|
@ -537,6 +549,14 @@ get(Text *et, Text *t, Text *argt, int flag1, int, Rune *arg, int narg)
|
|||
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++){
|
||||
u = t->file->text[i];
|
||||
|
@ -562,8 +582,18 @@ get(Text *et, Text *t, Text *argt, int flag1, int, Rune *arg, int narg)
|
|||
for(i=0; i<t->file->ntext; i++){
|
||||
u = t->file->text[i];
|
||||
textsetselect(&u->w->tag, u->w->tag.file->nc, u->w->tag.file->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");
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,8 @@ Rune* skipbl(Rune*, int, int*);
|
|||
Rune* findbl(Rune*, int, int*);
|
||||
char* edittext(Window*, int, Rune*, int);
|
||||
void flushwarnings(void);
|
||||
long nlcount(Text*, long, long, long*);
|
||||
long nlcounttopos(Text*, long, long, long);
|
||||
|
||||
#define runemalloc(a) (Rune*)emalloc((a)*sizeof(Rune))
|
||||
#define runerealloc(a, b) (Rune*)erealloc((a), (b)*sizeof(Rune))
|
||||
|
|
|
@ -293,7 +293,7 @@ rowclean(Row *row)
|
|||
void
|
||||
rowdump(Row *row, char *file)
|
||||
{
|
||||
int i, j, fd, m, n, dumped;
|
||||
int i, j, fd, m, n, start, dumped;
|
||||
uint q0, q1;
|
||||
Biobuf *b;
|
||||
char *buf, *a, *fontname;
|
||||
|
@ -396,10 +396,17 @@ rowdump(Row *row, char *file)
|
|||
m = min(RBUFSIZE, w->tag.file->nc);
|
||||
bufread(w->tag.file, 0, r, m);
|
||||
n = 0;
|
||||
while(n<m && r[n]!='\n')
|
||||
n++;
|
||||
r[n++] = '\n';
|
||||
Bprint(b, "%.*S", n, r);
|
||||
while(n<m) {
|
||||
start = n;
|
||||
while(n<m && r[n]!='\n')
|
||||
n++;
|
||||
Bprint(b, "%.*S", n-start, r+start);
|
||||
if(n<m) {
|
||||
Bputc(b, 0xff); // \n in tag becomes 0xff byte (invalid UTF)
|
||||
n++;
|
||||
}
|
||||
}
|
||||
Bprint(b, "\n");
|
||||
if(dumped){
|
||||
q0 = 0;
|
||||
q1 = t->file->nc;
|
||||
|
@ -639,6 +646,10 @@ rowload(Row *row, char *file, int initing)
|
|||
if(l == nil)
|
||||
goto Rescue2;
|
||||
l[Blinelen(b)-1] = 0;
|
||||
/* convert 0xff in multiline tag back to \n */
|
||||
for(i=0; l[i]!=0; i++)
|
||||
if((uchar)l[i] == 0xff)
|
||||
l[i] = '\n';
|
||||
r = bytetorune(l+5*12, &nr);
|
||||
ns = -1;
|
||||
for(n=0; n<nr; n++){
|
||||
|
|
|
@ -132,7 +132,7 @@ textscroll(Text *t, int but)
|
|||
readmouse(mousectl);
|
||||
continue;
|
||||
}
|
||||
if(but == 1)
|
||||
if(but == 1 || but == 4)
|
||||
p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height);
|
||||
else
|
||||
p0 = t->org+frcharofpt(t, Pt(s.max.x, my));
|
||||
|
@ -140,7 +140,7 @@ textscroll(Text *t, int but)
|
|||
textsetorigin(t, p0, TRUE);
|
||||
oldp0 = p0;
|
||||
/* debounce */
|
||||
if(first){
|
||||
if(first && but < 4){
|
||||
flushimage(display, 1);
|
||||
sleep(200);
|
||||
nbrecv(mousectl->c, &mousectl->Mouse);
|
||||
|
|
|
@ -1411,7 +1411,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->nc; i++){
|
||||
|
|
Loading…
Reference in a new issue