mirror of
https://hacklab.nilfm.cc/acme
synced 2024-10-22 14:31:48 +00:00
200 lines
3.9 KiB
C
200 lines
3.9 KiB
C
|
#include <u.h>
|
||
|
#include <libc.h>
|
||
|
#include <draw.h>
|
||
|
#include <thread.h>
|
||
|
#include <cursor.h>
|
||
|
#include <mouse.h>
|
||
|
#include <keyboard.h>
|
||
|
#include <frame.h>
|
||
|
#include <fcall.h>
|
||
|
#include <plumb.h>
|
||
|
#include <libsec.h>
|
||
|
#include "dat.h"
|
||
|
#include "fns.h"
|
||
|
|
||
|
// State for global log file.
|
||
|
typedef struct Log Log;
|
||
|
struct Log
|
||
|
{
|
||
|
QLock lk;
|
||
|
Rendez r;
|
||
|
|
||
|
vlong start; // msg[0] corresponds to 'start' in the global sequence of events
|
||
|
|
||
|
// queued events (nev=entries in ev, mev=capacity of p)
|
||
|
char **ev;
|
||
|
int nev;
|
||
|
int mev;
|
||
|
|
||
|
// open acme/put files that need to read events
|
||
|
Fid **f;
|
||
|
int nf;
|
||
|
int mf;
|
||
|
|
||
|
// active (blocked) reads waiting for events
|
||
|
Xfid **read;
|
||
|
int nread;
|
||
|
int mread;
|
||
|
};
|
||
|
|
||
|
static Log eventlog;
|
||
|
|
||
|
void
|
||
|
xfidlogopen(Xfid *x)
|
||
|
{
|
||
|
qlock(&eventlog.lk);
|
||
|
if(eventlog.nf >= eventlog.mf) {
|
||
|
eventlog.mf = eventlog.mf*2;
|
||
|
if(eventlog.mf == 0)
|
||
|
eventlog.mf = 8;
|
||
|
eventlog.f = erealloc(eventlog.f, eventlog.mf*sizeof eventlog.f[0]);
|
||
|
}
|
||
|
eventlog.f[eventlog.nf++] = x->f;
|
||
|
x->f->logoff = eventlog.start + eventlog.nev;
|
||
|
|
||
|
qunlock(&eventlog.lk);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
xfidlogclose(Xfid *x)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
qlock(&eventlog.lk);
|
||
|
for(i=0; i<eventlog.nf; i++) {
|
||
|
if(eventlog.f[i] == x->f) {
|
||
|
eventlog.f[i] = eventlog.f[--eventlog.nf];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
qunlock(&eventlog.lk);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
xfidlogread(Xfid *x)
|
||
|
{
|
||
|
char *p;
|
||
|
int i;
|
||
|
Fcall fc;
|
||
|
|
||
|
qlock(&eventlog.lk);
|
||
|
if(eventlog.nread >= eventlog.mread) {
|
||
|
eventlog.mread = eventlog.mread*2;
|
||
|
if(eventlog.mread == 0)
|
||
|
eventlog.mread = 8;
|
||
|
eventlog.read = erealloc(eventlog.read, eventlog.mread*sizeof eventlog.read[0]);
|
||
|
}
|
||
|
eventlog.read[eventlog.nread++] = x;
|
||
|
|
||
|
if(eventlog.r.l == nil)
|
||
|
eventlog.r.l = &eventlog.lk;
|
||
|
x->flushed = FALSE;
|
||
|
while(x->f->logoff >= eventlog.start+eventlog.nev && !x->flushed)
|
||
|
rsleep(&eventlog.r);
|
||
|
|
||
|
for(i=0; i<eventlog.nread; i++) {
|
||
|
if(eventlog.read[i] == x) {
|
||
|
eventlog.read[i] = eventlog.read[--eventlog.nread];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(x->flushed) {
|
||
|
qunlock(&eventlog.lk);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
i = x->f->logoff - eventlog.start;
|
||
|
p = estrdup(eventlog.ev[i]);
|
||
|
x->f->logoff++;
|
||
|
qunlock(&eventlog.lk);
|
||
|
|
||
|
fc.data = p;
|
||
|
fc.count = strlen(p);
|
||
|
respond(x, &fc, nil);
|
||
|
free(p);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
xfidlogflush(Xfid *x)
|
||
|
{
|
||
|
int i;
|
||
|
Xfid *rx;
|
||
|
|
||
|
qlock(&eventlog.lk);
|
||
|
for(i=0; i<eventlog.nread; i++) {
|
||
|
rx = eventlog.read[i];
|
||
|
if(rx->fcall.tag == x->fcall.oldtag) {
|
||
|
rx->flushed = TRUE;
|
||
|
rwakeupall(&eventlog.r);
|
||
|
}
|
||
|
}
|
||
|
qunlock(&eventlog.lk);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* add a log entry for op on w.
|
||
|
* expected calls:
|
||
|
*
|
||
|
* op == "new" for each new window
|
||
|
* - caller of coladd or makenewwindow responsible for calling
|
||
|
* xfidlog after setting window name
|
||
|
* - exception: zerox
|
||
|
*
|
||
|
* op == "zerox" for new window created via zerox
|
||
|
* - called from zeroxx
|
||
|
*
|
||
|
* op == "get" for Get executed on window
|
||
|
* - called from get
|
||
|
*
|
||
|
* op == "put" for Put executed on window
|
||
|
* - called from put
|
||
|
*
|
||
|
* op == "del" for deleted window
|
||
|
* - called from winclose
|
||
|
*/
|
||
|
void
|
||
|
xfidlog(Window *w, char *op)
|
||
|
{
|
||
|
int i, n;
|
||
|
vlong min;
|
||
|
File *f;
|
||
|
char *name;
|
||
|
|
||
|
qlock(&eventlog.lk);
|
||
|
if(eventlog.nev >= eventlog.mev) {
|
||
|
// Remove and free any entries that all readers have read.
|
||
|
min = eventlog.start + eventlog.nev;
|
||
|
for(i=0; i<eventlog.nf; i++) {
|
||
|
if(min > eventlog.f[i]->logoff)
|
||
|
min = eventlog.f[i]->logoff;
|
||
|
}
|
||
|
if(min > eventlog.start) {
|
||
|
n = min - eventlog.start;
|
||
|
for(i=0; i<n; i++)
|
||
|
free(eventlog.ev[i]);
|
||
|
eventlog.nev -= n;
|
||
|
eventlog.start += n;
|
||
|
memmove(eventlog.ev, eventlog.ev+n, eventlog.nev*sizeof eventlog.ev[0]);
|
||
|
}
|
||
|
|
||
|
// Otherwise grow.
|
||
|
if(eventlog.nev >= eventlog.mev) {
|
||
|
eventlog.mev = eventlog.mev*2;
|
||
|
if(eventlog.mev == 0)
|
||
|
eventlog.mev = 8;
|
||
|
eventlog.ev = erealloc(eventlog.ev, eventlog.mev*sizeof eventlog.ev[0]);
|
||
|
}
|
||
|
}
|
||
|
f = w->body.file;
|
||
|
name = runetobyte(f->name, f->nname);
|
||
|
if(name == nil)
|
||
|
name = estrdup("");
|
||
|
eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name);
|
||
|
free(name);
|
||
|
if(eventlog.r.l == nil)
|
||
|
eventlog.r.l = &eventlog.lk;
|
||
|
rwakeupall(&eventlog.r);
|
||
|
qunlock(&eventlog.lk);
|
||
|
}
|