acme: fix crash in X |cat with multiple windows

Fixes #9.
Fixes #219.
Fixes #222.
Fixes #330.
This commit is contained in:
Russ Cox 2020-01-13 18:15:57 -05:00
parent 59b460f845
commit d2df5d6cbd

View file

@ -28,7 +28,7 @@ int append(File*, Cmd*, long);
int pdisplay(File*); int pdisplay(File*);
void pfilename(File*); void pfilename(File*);
void looper(File*, Cmd*, int); void looper(File*, Cmd*, int);
void filelooper(Cmd*, int); void filelooper(Text*, Cmd*, int);
void linelooper(File*, Cmd*); void linelooper(File*, Cmd*);
Address lineaddr(long, Address, int); Address lineaddr(long, Address, int);
int filematch(File*, String*); int filematch(File*, String*);
@ -584,7 +584,7 @@ X_cmd(Text *t, Cmd *cp)
{ {
USED(t); USED(t);
filelooper(cp, cp->cmdc=='X'); filelooper(t, cp, cp->cmdc=='X');
return TRUE; return TRUE;
} }
@ -978,9 +978,10 @@ alllocker(Window *w, void *v)
} }
void void
filelooper(Cmd *cp, int XY) filelooper(Text *t, Cmd *cp, int XY)
{ {
int i; int i;
Text *targ;
if(Glooping++) if(Glooping++)
editerror("can't nest %c command", "YX"[XY]); editerror("can't nest %c command", "YX"[XY]);
@ -1001,8 +1002,26 @@ filelooper(Cmd *cp, int XY)
*/ */
allwindows(alllocker, (void*)1); allwindows(alllocker, (void*)1);
globalincref = 1; globalincref = 1;
for(i=0; i<loopstruct.nw; i++)
cmdexec(&loopstruct.w[i]->body, cp->u.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->u.cmd);
if(targ && targ->w)
winunlock(targ->w);
}
if(t && t->w)
winlock(t->w, cp->cmdc);
allwindows(alllocker, (void*)0); allwindows(alllocker, (void*)0);
globalincref = 0; globalincref = 0;
free(loopstruct.w); free(loopstruct.w);