New 9term using rio sources more directly.

This commit is contained in:
rsc 2005-11-06 22:16:48 +00:00
parent a6c0ff35ee
commit e830a90849
10 changed files with 2963 additions and 1842 deletions

File diff suppressed because it is too large Load diff

243
src/cmd/9term/dat.h Normal file
View file

@ -0,0 +1,243 @@
#define STACK 32768
#undef Borderwidth
#define Borderwidth 0
typedef struct Consreadmesg Consreadmesg;
typedef struct Conswritemesg Conswritemesg;
typedef struct Stringpair Stringpair;
typedef struct Dirtab Dirtab;
typedef struct Mouseinfo Mouseinfo;
typedef struct Mousereadmesg Mousereadmesg;
typedef struct Mousestate Mousestate;
typedef struct Timer Timer;
typedef struct Wctlmesg Wctlmesg;
typedef struct Window Window;
enum
{
Selborder = 0, /* border of selected window */
Unselborder = 0, /* border of unselected window */
Scrollwid = 12, /* width of scroll bar */
Scrollgap = 4, /* gap right of scroll bar */
BIG = 3, /* factor by which window dimension can exceed screen */
TRUE = 1,
FALSE = 0,
};
enum
{
Kscrolloneup = KF|0x20,
Kscrollonedown = KF|0x21,
};
enum /* control messages */
{
Wakeup,
Reshaped,
Moved,
Refresh,
Movemouse,
Rawon,
Rawoff,
Holdon,
Holdoff,
Deleted,
Exited,
};
struct Wctlmesg
{
int type;
Rectangle r;
Image *image;
};
struct Conswritemesg
{
Channel *cw; /* chan(Stringpair) */
};
struct Consreadmesg
{
Channel *c1; /* chan(tuple(char*, int) == Stringpair) */
Channel *c2; /* chan(tuple(char*, int) == Stringpair) */
};
struct Mousereadmesg
{
Channel *cm; /* chan(Mouse) */
};
struct Stringpair /* rune and nrune or byte and nbyte */
{
void *s;
int ns;
};
struct Mousestate
{
Mouse m;
ulong counter; /* serial no. of mouse event */
};
struct Mouseinfo
{
Mousestate queue[16];
int ri; /* read index into queue */
int wi; /* write index */
ulong counter; /* serial no. of last mouse event we received */
ulong lastcounter; /* serial no. of last mouse event sent to client */
int lastb; /* last button state we received */
uchar qfull; /* filled the queue; no more recording until client comes back */
};
struct Window
{
Ref ref;
QLock lk;
Frame f;
Image *i;
Mousectl mc;
Mouseinfo mouse;
Channel *ck; /* chan(Rune[10]) */
Channel *cctl; /* chan(Wctlmesg)[20] */
Channel *conswrite; /* chan(Conswritemesg) */
Channel *consread; /* chan(Consreadmesg) */
Channel *mouseread; /* chan(Mousereadmesg) */
Channel *wctlread; /* chan(Consreadmesg) */
uint nr; /* number of runes in window */
uint maxr; /* number of runes allocated in r */
Rune *r;
uint nraw;
Rune *raw;
uint org;
uint q0;
uint q1;
uint qh;
int id;
char name[32];
uint namecount;
Rectangle scrollr;
/*
* Rio once used originwindow, so screenr could be different from i->r.
* Now they're always the same but the code doesn't assume so.
*/
Rectangle screenr; /* screen coordinates of window */
int resized;
int wctlready;
Rectangle lastsr;
int topped;
int notefd;
uchar scrolling;
Cursor cursor;
Cursor *cursorp;
uchar holding;
uchar rawing;
uchar ctlopen;
uchar wctlopen;
uchar deleted;
uchar mouseopen;
char *label;
int pid;
char *dir;
};
int winborder(Window*, Point);
void winctl(void*);
void winshell(void*);
Window* wlookid(int);
Window* wmk(Image*, Mousectl*, Channel*, Channel*, int);
Window* wpointto(Point);
Window* wtop(Point);
void wtopme(Window*);
void wbottomme(Window*);
char* wcontents(Window*, int*);
int wbswidth(Window*, Rune);
int wclickmatch(Window*, int, int, int, uint*);
int wclose(Window*);
int wctlmesg(Window*, int, Rectangle, Image*);
int wctlmesg(Window*, int, Rectangle, Image*);
uint wbacknl(Window*, uint, uint);
uint winsert(Window*, Rune*, int, uint);
void waddraw(Window*, Rune*, int);
void wborder(Window*, int);
void wclosewin(Window*);
void wcurrent(Window*);
void wcut(Window*);
void wdelete(Window*, uint, uint);
void wdoubleclick(Window*, uint*, uint*);
void wfill(Window*);
void wframescroll(Window*, int);
void wkeyctl(Window*, Rune);
void wmousectl(Window*);
void wmovemouse(Window*, Point);
void wpaste(Window*);
void wplumb(Window*);
void wrefresh(Window*, Rectangle);
void wrepaint(Window*);
void wresize(Window*, Image*, int);
void wscrdraw(Window*);
void wscroll(Window*, int);
void wselect(Window*);
void wsendctlmesg(Window*, int, Rectangle, Image*);
void wsetcursor(Window*, int);
void wsetname(Window*);
void wsetorigin(Window*, uint, int);
void wsetpid(Window*, int, int);
void wsetselect(Window*, uint, uint);
void wshow(Window*, uint);
void wsnarf(Window*);
void wscrsleep(Window*, uint);
void wsetcols(Window*);
void deletetimeoutproc(void*);
struct Timer
{
int dt;
int cancel;
Channel *c; /* chan(int) */
Timer *next;
};
#ifndef Extern
#define Extern extern
#endif
Extern Font *font;
Extern Mousectl *mousectl;
Extern Mouse *mouse;
Extern Keyboardctl *keyboardctl;
Extern Display *display;
Extern Image *view;
Extern Screen *wscreen;
Extern Cursor boxcursor;
Extern Cursor crosscursor;
Extern Cursor sightcursor;
Extern Cursor whitearrow;
Extern Cursor query;
Extern Cursor *corners[9];
Extern Image *background;
Extern Image *lightgrey;
Extern Image *red;
Extern Window **window;
Extern Window *wkeyboard; /* window of simulated keyboard */
Extern int nwindow;
Extern int snarffd;
Extern Window *input;
Extern QLock all; /* BUG */
Extern Window *hidden[100];
Extern int nhidden;
Extern int nsnarf;
Extern Rune* snarf;
Extern int scrolling;
Extern int maxtab;
Extern Channel* winclosechan;
Extern Channel* deletechan;
Extern char *startdir;
Extern int sweeping;
Extern int wctlfd;
Extern int errorshouldabort;
Extern int menuing; /* menu action is pending; waiting for window to be indicated */
Extern int snarfversion; /* updated each time it is written */
Extern int messagesize; /* negotiated in 9P version setup */

180
src/cmd/9term/data.c Normal file
View file

@ -0,0 +1,180 @@
#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 "dat.h"
#include "fns.h"
Cursor crosscursor = {
{-7, -7},
{0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0,
0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, },
{0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE,
0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, }
};
Cursor boxcursor = {
{-7, -7},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F,
0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
{0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,
0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, }
};
Cursor sightcursor = {
{-7, -7},
{0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,
0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,
0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, },
{0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,
0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,
0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,
0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00, }
};
Cursor whitearrow = {
{0, 0},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC,
0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },
{0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C,
0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C,
0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C,
0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }
};
Cursor query = {
{-7,-7},
{0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe,
0x7c, 0x7e, 0x78, 0x7e, 0x00, 0xfc, 0x01, 0xf8,
0x03, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x07, 0xc0,
0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, },
{0x00, 0x00, 0x0f, 0xf0, 0x1f, 0xf8, 0x3c, 0x3c,
0x38, 0x1c, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0,
0x01, 0xe0, 0x03, 0xc0, 0x03, 0x80, 0x03, 0x80,
0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
};
Cursor tl = {
{-4, -4},
{0xfe, 0x00, 0x82, 0x00, 0x8c, 0x00, 0x87, 0xff,
0xa0, 0x01, 0xb0, 0x01, 0xd0, 0x01, 0x11, 0xff,
0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,
0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x1f, 0x00, },
{0x00, 0x00, 0x7c, 0x00, 0x70, 0x00, 0x78, 0x00,
0x5f, 0xfe, 0x4f, 0xfe, 0x0f, 0xfe, 0x0e, 0x00,
0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00,
0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00, 0x00, }
};
Cursor t = {
{-7, -8},
{0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x06, 0xc0,
0x1c, 0x70, 0x10, 0x10, 0x0c, 0x60, 0xfc, 0x7f,
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x03, 0x80, 0x0f, 0xe0, 0x03, 0x80, 0x03, 0x80,
0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
};
Cursor tr = {
{-11, -4},
{0x00, 0x7f, 0x00, 0x41, 0x00, 0x31, 0xff, 0xe1,
0x80, 0x05, 0x80, 0x0d, 0x80, 0x0b, 0xff, 0x88,
0x00, 0x88, 0x0, 0x88, 0x00, 0x88, 0x00, 0x88,
0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xf8, },
{0x00, 0x00, 0x00, 0x3e, 0x00, 0x0e, 0x00, 0x1e,
0x7f, 0xfa, 0x7f, 0xf2, 0x7f, 0xf0, 0x00, 0x70,
0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, }
};
Cursor r = {
{-8, -7},
{0x07, 0xc0, 0x04, 0x40, 0x04, 0x40, 0x04, 0x58,
0x04, 0x68, 0x04, 0x6c, 0x04, 0x06, 0x04, 0x02,
0x04, 0x06, 0x04, 0x6c, 0x04, 0x68, 0x04, 0x58,
0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x07, 0xc0, },
{0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80,
0x03, 0x90, 0x03, 0x90, 0x03, 0xf8, 0x03, 0xfc,
0x03, 0xf8, 0x03, 0x90, 0x03, 0x90, 0x03, 0x80,
0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
};
Cursor br = {
{-11, -11},
{0x00, 0xf8, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88,
0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88,
0xff, 0x88, 0x80, 0x0b, 0x80, 0x0d, 0x80, 0x05,
0xff, 0xe1, 0x00, 0x31, 0x00, 0x41, 0x00, 0x7f, },
{0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
0x0, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
0x00, 0x70, 0x7f, 0xf0, 0x7f, 0xf2, 0x7f, 0xfa,
0x00, 0x1e, 0x00, 0x0e, 0x00, 0x3e, 0x00, 0x00, }
};
Cursor b = {
{-7, -7},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
0xfc, 0x7f, 0x0c, 0x60, 0x10, 0x10, 0x1c, 0x70,
0x06, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, },
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe,
0x03, 0x80, 0x03, 0x80, 0x0f, 0xe0, 0x03, 0x80,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
};
Cursor bl = {
{-4, -11},
{0x1f, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,
0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,
0x11, 0xff, 0xd0, 0x01, 0xb0, 0x01, 0xa0, 0x01,
0x87, 0xff, 0x8c, 0x00, 0x82, 0x00, 0xfe, 0x00, },
{0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00,
0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00,
0x0e, 0x00, 0x0f, 0xfe, 0x4f, 0xfe, 0x5f, 0xfe,
0x78, 0x00, 0x70, 0x00, 0x7c, 0x00, 0x00, 0x0, }
};
Cursor l = {
{-7, -7},
{0x03, 0xe0, 0x02, 0x20, 0x02, 0x20, 0x1a, 0x20,
0x16, 0x20, 0x36, 0x20, 0x60, 0x20, 0x40, 0x20,
0x60, 0x20, 0x36, 0x20, 0x16, 0x20, 0x1a, 0x20,
0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x03, 0xe0, },
{0x00, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0,
0x09, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x3f, 0xc0,
0x1f, 0xc0, 0x09, 0xc0, 0x09, 0xc0, 0x01, 0xc0,
0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, }
};
Cursor *corners[9] = {
&tl, &t, &tr,
&l, nil, &r,
&bl, &b, &br,
};
void
iconinit(void)
{
background = allocimage(display, Rect(0,0,1,1), RGB24, 1, 0x777777FF);
red = allocimage(display, Rect(0,0,1,1), RGB24, 1, 0xDD0000FF);
}

36
src/cmd/9term/fns.h Normal file
View file

@ -0,0 +1,36 @@
#undef isalnum
#define isalnum runeisalnum
void keyboardsend(char*, int);
int whide(Window*);
int wunhide(int);
void freescrtemps(void);
int parsewctl(char**, Rectangle, Rectangle*, int*, int*, int*, int*, char**, char*, char*);
Window *new(Image*, int, int, int, char*, char*, char**);
void riosetcursor(Cursor*, int);
int min(int, int);
int max(int, int);
Rune* strrune(Rune*, Rune);
int isalnum(Rune);
void timerstop(Timer*);
void timercancel(Timer*);
Timer* timerstart(int);
void error(char*);
void killprocs(void);
int shutdown(void*, char*);
void iconinit(void);
void *erealloc(void*, uint);
void *emalloc(uint);
char *estrdup(char*);
void button3menu(void);
void button2menu(Window*);
void cvttorunes(char*, int, Rune*, int*, int*, int*);
/* was (byte*,int) runetobyte(Rune*, int); */
char* runetobyte(Rune*, int, int*);
void timerinit(void);
int goodrect(Rectangle);
int rawon(void);
#define runemalloc(n) malloc((n)*sizeof(Rune))
#define runerealloc(a, n) realloc(a, (n)*sizeof(Rune))
#define runemove(a, b, n) memmove(a, b, (n)*sizeof(Rune))

63
src/cmd/9term/malloc.c Normal file
View file

@ -0,0 +1,63 @@
/*
* These are here mainly so that I can link against
* debugmalloc.c instead and not recompile the world.
*/
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
static Lock malloclock;
void*
p9malloc(ulong n)
{
void *v;
if(n == 0)
n++;
lock(&malloclock);
v = malloc(n);
unlock(&malloclock);
print("p9malloc %lud => %p; pc %lux\n", n, v, getcallerpc(&n));
return v;
}
void
p9free(void *v)
{
if(v == nil)
return;
lock(&malloclock);
print("p9free %p; pc %lux\n", v, getcallerpc(&v));
free(v);
unlock(&malloclock);
}
void*
p9calloc(ulong a, ulong b)
{
void *v;
if(a*b == 0)
a = b = 1;
lock(&malloclock);
v = calloc(a*b, 1);
unlock(&malloclock);
print("p9calloc %lud %lud => %p; pc %lux\n", a, b, v, getcallerpc(&a));
return v;
}
void*
p9realloc(void *v, ulong n)
{
void *vv;
lock(&malloclock);
vv = realloc(v, n);
unlock(&malloclock);
print("p9realloc %p %lud => %p; pc %lux\n", v, n, vv, getcallerpc(&v));
return vv;
}

View file

@ -6,7 +6,11 @@ OFILES=\
rcstart.$O\
$SYSNAME.$O\
HFILES=dat.h fns.h term.h
<$PLAN9/src/mkmany
Darwin.$O Linux.$O FreeBSD.$O: bsdpty.c
$O.9term: data.$O scrl.$O time.$O util.$O wind.$O

183
src/cmd/9term/scrl.c Normal file
View file

@ -0,0 +1,183 @@
#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 "dat.h"
#include "fns.h"
static Image *scrtmp;
static
void
scrtemps(void)
{
int h;
if(scrtmp)
return;
h = BIG*Dy(screen->r);
scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, DWhite);
if(scrtmp == nil)
error("scrtemps");
}
void
freescrtemps(void)
{
freeimage(scrtmp);
scrtmp = nil;
}
static
Rectangle
scrpos(Rectangle r, uint p0, uint p1, uint tot)
{
Rectangle q;
int h;
q = r;
h = q.max.y-q.min.y;
if(tot == 0)
return q;
if(tot > 1024*1024){
tot>>=10;
p0>>=10;
p1>>=10;
}
if(p0 > 0)
q.min.y += h*p0/tot;
if(p1 < tot)
q.max.y -= h*(tot-p1)/tot;
if(q.max.y < q.min.y+2){
if(q.min.y+2 <= r.max.y)
q.max.y = q.min.y+2;
else
q.min.y = q.max.y-2;
}
return q;
}
void
wscrdraw(Window *w)
{
Rectangle r, r1, r2;
Image *b;
scrtemps();
if(w->i == nil)
error("scrdraw");
r = w->scrollr;
b = scrtmp;
r1 = r;
r1.min.x = 0;
r1.max.x = Dx(r);
r2 = scrpos(r1, w->org, w->org+w->f.nchars, w->nr);
if(!eqrect(r2, w->lastsr)){
w->lastsr = r2;
/* move r1, r2 to (0,0) to avoid clipping */
r2 = rectsubpt(r2, r1.min);
r1 = rectsubpt(r1, r1.min);
draw(b, r1, w->f.cols[BORD], nil, ZP);
draw(b, r2, w->f.cols[BACK], nil, ZP);
r2.min.x = r2.max.x-1;
draw(b, r2, w->f.cols[BORD], nil, ZP);
draw(w->i, r, b, nil, Pt(0, r1.min.y));
}
}
void
wscrsleep(Window *w, uint dt)
{
Timer *timer;
int y, b;
static Alt alts[3];
timer = timerstart(dt);
y = w->mc.m.xy.y;
b = w->mc.m.buttons;
alts[0].c = timer->c;
alts[0].v = nil;
alts[0].op = CHANRCV;
alts[1].c = w->mc.c;
alts[1].v = &w->mc.m;
alts[1].op = CHANRCV;
alts[2].op = CHANEND;
for(;;)
switch(alt(alts)){
case 0:
timerstop(timer);
return;
case 1:
if(abs(w->mc.m.xy.y-y)>2 || w->mc.m.buttons!=b){
timercancel(timer);
return;
}
break;
}
}
void
wscroll(Window *w, int but)
{
uint p0, oldp0;
Rectangle s;
int x, y, my, h, first;
s = insetrect(w->scrollr, 1);
h = s.max.y-s.min.y;
x = (s.min.x+s.max.x)/2;
oldp0 = ~0;
first = TRUE;
do{
flushimage(display, 1);
if(w->mc.m.xy.x<s.min.x || s.max.x<=w->mc.m.xy.x){
readmouse(&w->mc);
}else{
my = w->mc.m.xy.y;
if(my < s.min.y)
my = s.min.y;
if(my >= s.max.y)
my = s.max.y;
if(!eqpt(w->mc.m.xy, Pt(x, my))){
wmovemouse(w, Pt(x, my));
readmouse(&w->mc); /* absorb event generated by moveto() */
}
if(but == 2){
y = my;
if(y > s.max.y-2)
y = s.max.y-2;
if(w->nr > 1024*1024)
p0 = ((w->nr>>10)*(y-s.min.y)/h)<<10;
else
p0 = w->nr*(y-s.min.y)/h;
if(oldp0 != p0)
wsetorigin(w, p0, FALSE);
oldp0 = p0;
readmouse(&w->mc);
continue;
}
if(but == 1)
p0 = wbacknl(w, w->org, (my-s.min.y)/w->f.font->height);
else
p0 = w->org+frcharofpt(&w->f, Pt(s.max.x, my));
if(oldp0 != p0)
wsetorigin(w, p0, TRUE);
oldp0 = p0;
/* debounce */
if(first){
flushimage(display, 1);
sleep(200);
nbrecv(w->mc.c, &w->mc.m);
first = FALSE;
}
wscrsleep(w, 100);
}
}while(w->mc.m.buttons & (1<<(but-1)));
while(w->mc.m.buttons)
readmouse(&w->mc);
}

125
src/cmd/9term/time.c Normal file
View file

@ -0,0 +1,125 @@
#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 "dat.h"
#include "fns.h"
static Channel* ctimer; /* chan(Timer*)[100] */
static Timer *timer;
static
uint
msec(void)
{
return nsec()/1000000;
}
void
timerstop(Timer *t)
{
t->next = timer;
timer = t;
}
void
timercancel(Timer *t)
{
t->cancel = TRUE;
}
static
void
timerproc(void *a)
{
int i, nt, na, dt, del;
Timer **t, *x;
uint old, new;
USED(a);
rfork(RFFDG);
threadsetname("TIMERPROC");
t = nil;
na = 0;
nt = 0;
old = msec();
for(;;){
sleep(1); /* will sleep minimum incr */
new = msec();
dt = new-old;
old = new;
if(dt < 0) /* timer wrapped; go around, losing a tick */
continue;
for(i=0; i<nt; i++){
x = t[i];
x->dt -= dt;
del = 0;
if(x->cancel){
timerstop(x);
del = 1;
}else if(x->dt <= 0){
/*
* avoid possible deadlock if client is
* now sending on ctimer
*/
if(nbsendul(x->c, 0) > 0)
del = 1;
}
if(del){
memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);
--nt;
--i;
}
}
if(nt == 0){
x = recvp(ctimer);
gotit:
if(nt == na){
na += 10;
t = realloc(t, na*sizeof(Timer*));
if(t == nil)
abort();
}
t[nt++] = x;
old = msec();
}
if(nbrecv(ctimer, &x) > 0)
goto gotit;
}
}
void
timerinit(void)
{
ctimer = chancreate(sizeof(Timer*), 100);
proccreate(timerproc, nil, STACK);
}
/*
* timeralloc() and timerfree() don't lock, so can only be
* called from the main proc.
*/
Timer*
timerstart(int dt)
{
Timer *t;
t = timer;
if(t)
timer = timer->next;
else{
t = emalloc(sizeof(Timer));
t->c = chancreate(sizeof(int), 0);
}
t->next = nil;
t->dt = dt;
t->cancel = FALSE;
sendp(ctimer, t);
return t;
}

149
src/cmd/9term/util.c Normal file
View file

@ -0,0 +1,149 @@
#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 "dat.h"
#include "fns.h"
void
cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
{
uchar *q;
Rune *s;
int j, w;
/*
* Always guaranteed that n bytes may be interpreted
* without worrying about partial runes. This may mean
* reading up to UTFmax-1 more bytes than n; the caller
* knows this. If n is a firm limit, the caller should
* set p[n] = 0.
*/
q = (uchar*)p;
s = r;
for(j=0; j<n; j+=w){
if(*q < Runeself){
w = 1;
*s = *q++;
}else{
w = chartorune(s, (char*)q);
q += w;
}
if(*s)
s++;
else if(nulls)
*nulls = TRUE;
}
*nb = (char*)q-p;
*nr = s-r;
}
void
error(char *s)
{
fprint(2, "rio: %s: %r\n", s);
if(errorshouldabort)
abort();
threadexitsall("error");
}
void*
erealloc(void *p, uint n)
{
p = realloc(p, n);
if(p == nil)
error("realloc failed");
return p;
}
void*
emalloc(uint n)
{
void *p;
p = malloc(n);
if(p == nil)
error("malloc failed");
memset(p, 0, n);
return p;
}
char*
estrdup(char *s)
{
char *p;
p = malloc(strlen(s)+1);
if(p == nil)
error("strdup failed");
strcpy(p, s);
return p;
}
int
isalnum(Rune c)
{
/*
* Hard to get absolutely right. Use what we know about ASCII
* and assume anything above the Latin control characters is
* potentially an alphanumeric.
*/
if(c <= ' ')
return FALSE;
if(0x7F<=c && c<=0xA0)
return FALSE;
if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
return FALSE;
return TRUE;
}
Rune*
strrune(Rune *s, Rune c)
{
Rune c1;
if(c == 0) {
while(*s++)
;
return s-1;
}
while(c1 = *s++)
if(c1 == c)
return s-1;
return nil;
}
int
min(int a, int b)
{
if(a < b)
return a;
return b;
}
int
max(int a, int b)
{
if(a > b)
return a;
return b;
}
char*
runetobyte(Rune *r, int n, int *ip)
{
char *s;
int m;
s = emalloc(n*UTFmax+1);
m = snprint(s, n*UTFmax+1, "%.*S", n, r);
*ip = m;
return s;
}

1628
src/cmd/9term/wind.c Normal file

File diff suppressed because it is too large Load diff