commit c7293470b622b891a59b84a10584c21817de44dc
parent ad4c82fcbc74324a9c3121e0b62d93eb53813f87
Author: Pavel Renev <an2qzavok@gmail.com>
Date: Fri, 25 Mar 2022 22:46:14 +0000
use single-rune text elements
Diffstat:
M | richterm.c | | | 143 | +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
M | richterm.h | | | 84 | +++++++++++++++++++++++++++++++++++-------------------------------------------- |
2 files changed, 133 insertions(+), 94 deletions(-)
diff --git a/richterm.c b/richterm.c
@@ -31,6 +31,10 @@ Image *Iscrollbar, *Ilink, *Inormbg, *Iselbg, *Itext;
char *srvname;
+Array *elems;
+Array *richdata;
+Elem *euser;
+
void mpaste(Rich *);
void msnarf(Rich *);
void mplumb(Rich *);
@@ -132,8 +136,6 @@ threadmain(int argc, char **argv)
qlock(rich.l);
- rich.page.scroll = ZP;
-
rich.selmin = 0;
rich.selmax = 0;
@@ -294,21 +296,21 @@ mouse(Mousectl *mc, Mouse mv, int *mmode)
}
if (mv.buttons == 8) {
scroll(
- Pt(0, rich.scroll - (mv.xy.y - rich.page.r.min.y)),
+ Pt(0, rich.scroll - (mv.xy.y - rich.r.min.y)),
&rich);
return;
}
if (mv.buttons == 16) {
scroll(
- Pt(0, rich.scroll + (mv.xy.y - rich.page.r.min.y)),
+ Pt(0, rich.scroll + (mv.xy.y - rich.r.min.y)),
&rich);
return;
}
if (*mmode == MM_NONE) {
- if (ptinrect(mv.xy, rich.page.rs) != 0)
+ if (ptinrect(mv.xy, rich.rs) != 0)
*mmode = MM_SCROLLBAR;
- if (ptinrect(mv.xy, rich.page.r) != 0)
+ if (ptinrect(mv.xy, rich.r) != 0)
*mmode = MM_TEXT;
}
@@ -317,18 +319,18 @@ mouse(Mousectl *mc, Mouse mv, int *mmode)
if (mv.buttons == 1) {
scroll(
subpt(Pt(0, rich.scroll),
- Pt(0, mv.xy.y - rich.page.r.min.y)),
+ Pt(0, mv.xy.y - rich.r.min.y)),
&rich);
} else if (mv.buttons == 2) {
scroll(
Pt(0,
- (mv.xy.y - rich.page.r.min.y) *
- ((double)rich.page.max.y / Dy(rich.page.r))),
+ (mv.xy.y - rich.r.min.y) *
+ ((double)rich.max / Dy(rich.r))),
&rich);
} else if (mv.buttons == 4) {
scroll(
addpt(Pt(0, rich.scroll),
- Pt(0, mv.xy.y - rich.page.r.min.y)),
+ Pt(0, mv.xy.y - rich.r.min.y)),
&rich);
}
break;
@@ -429,18 +431,18 @@ drawscrollbar(void)
{
double D;
Rectangle rs;
- D = (double)rich.max / (double)Dy(rich.page.r);
+ D = (double)rich.max / (double)Dy(rich.r);
if (D != 0) {
rs = rectaddpt(Rect(
0, rich.scroll / D,
- 11, (rich.scroll + Dy(rich.page.r)) / D
- ), rich.page.rs.min);
+ 11, (rich.scroll + Dy(rich.r)) / D
+ ), rich.rs.min);
} else {
- rs = rich.page.rs;
+ rs = rich.rs;
rs.max.x--;
};
- draw(screen, rich.page.rs, Iscrollbar, nil, ZP);
+ draw(screen, rich.rs, Iscrollbar, nil, ZP);
draw(screen, rs, Inormbg, nil, ZP);
}
@@ -499,11 +501,11 @@ send_interrupt(void)
void
resize(void)
{
- rich.page.rs = Rpt(
+ rich.rs = Rpt(
addpt(Pt(1,1), screen->r.min),
Pt(screen->r.min.x + 13, screen->r.max.y - 1)
);
- rich.page.r = Rpt(
+ rich.r = Rpt(
addpt(screen->r.min, Pt(17, 1)),
subpt(screen->r.max, Pt(1,1))
);
@@ -517,7 +519,7 @@ mpaste(Rich *)
char buf[4096];
if ((fd = open("/dev/snarf", OREAD)) > 0) {
while((n = read(fd, buf, sizeof(buf))) > 0) {
- arraygrow(rich.text, n, buf);
+ arraygrow(richdata, n, buf);
}
if (n < 0) fprint(2, "mpaste: %r\n");
close(fd);
@@ -532,7 +534,7 @@ msnarf(Rich *)
long n;
if ((rich.selmin < rich.selmax) &&
((fd = open("/dev/snarf", OWRITE)) > 0)) {
- n = write(fd, arrayget(rich.text, rich.selmin, nil),
+ n = write(fd, arrayget(richdata, rich.selmin, nil),
rich.selmax - rich.selmin);
if (n < rich.selmax - rich.selmin) fprint(2, "msnarf: %r\n");
close(fd);
@@ -553,7 +555,7 @@ mplumb(Rich *)
"text",
nil,
rich.selmax - rich.selmin,
- arrayget(rich.text, rich.selmin, nil)
+ arrayget(richdata, rich.selmin, nil)
};
plumbsend(pd, &m);
close(pd);
@@ -663,14 +665,6 @@ rusergen(int f)
return genbuf;
}
-/* **** New Code Beyond This Point **** */
-
-Array *elems;
-Array *richdata;
-Elem *euser;
-
-char *sampledata = "";
-
char *
elemparse(Elem *e, char *str, long n)
{
@@ -682,10 +676,22 @@ elemparse(Elem *e, char *str, long n)
if (n <= 1) return nil;
ep = memchr(sp, '\n', n - 1);
if (ep == nil) return nil;
-
+
+
e->type = type;
e->count = ep - sp;
+/*
+ switch(e->type) {
+ case E_NL:
+ case E_TAB:
+ case E_SPACE:
+ e->type = E_TEXT;
+ e->count = 1;
+ sp = str;
+ }
+*/
+
if (e->count > 0) {
e->str = malloc(e->count + 1);
memcpy(e->str, sp, e->count);
@@ -696,6 +702,23 @@ elemparse(Elem *e, char *str, long n)
}
void
+text2runes(Elem *E, Array *elems)
+{
+ if (E->str == nil) return;
+ Rune *r = runesmprint("%s", E->str);
+ Rune *rp;
+ for (rp =r; *rp != L'\0'; rp++) {
+ Elem *e = mallocz(sizeof(Elem), 1);
+ e->type = E_TEXT;
+ e->str = smprint("%C", *rp);
+ e->count = strlen(e->str);
+ e->r = *rp;
+ arraygrow(elems, 1, &e);
+ }
+ free(r);
+}
+
+void
parsedata(Array *data, Array *elems)
{
Elem *e;
@@ -709,7 +732,10 @@ parsedata(Array *data, Array *elems)
e = mallocz(sizeof(Elem), 1);
dp = elemparse(e, dp, data->p + data->count - dp);
if (dp == nil) break;
- arraygrow(elems, 1, &e);
+ if (e->type == E_TEXT) {
+ text2runes(e, elems);
+ freeelem(e);
+ } else arraygrow(elems, 1, &e);
}
qunlock(data->l);
@@ -768,16 +794,8 @@ elemsupdatecache(Array *elems)
void
generatesampleelems(void)
{
- long count;
-
elems = arraycreate(sizeof(Elem *), 128, nil);
-
- count = strlen(sampledata);
-
- richdata = arraycreate(sizeof(char), count, nil);
- arraygrow(richdata, count, (void *)sampledata);
-
- parsedata(richdata, elems);
+ richdata = arraycreate(sizeof(char), 1024, nil);
euser = mallocz(sizeof(Elem), 1);
euser->type = E_TEXT;
@@ -797,7 +815,7 @@ drawelems(void)
Point pos;
Elem *e;
e = nil;
- pos = rich.page.r.min;
+ pos = rich.r.min;
pos.y -= rich.scroll;
for (i = 0; i < elems->count; i++) {
if (arrayget(elems, i, &e) == nil)
@@ -805,7 +823,7 @@ drawelems(void)
e->pos = pos;
pos = drawelem(e);
}
- if (e != nil) rich.max = e->nlpos.y + rich.scroll - rich.page.r.min.y;
+ if (e != nil) rich.max = e->nlpos.y + rich.scroll - rich.r.min.y;
else rich.max = 0;
}
@@ -816,7 +834,7 @@ drawelem(Elem *e)
static const Point (*dtable[256])(Elem *) = {
[E_NOOP] drawnoop,
- [E_TEXT] drawtext,
+ [E_TEXT] drawrune,
[E_FONT] drawnoop,
[E_LINK] drawnoop,
[E_IMAGE] drawnoop,
@@ -829,7 +847,7 @@ drawelem(Elem *e)
e->nlpos = (e->prev != nil) ?
e->prev->nlpos :
- Pt(rich.page.r.min.x, rich.page.r.min.y + e->font->height - rich.scroll);
+ Pt(rich.r.min.x, rich.r.min.y + e->font->height - rich.scroll);
drawp = dtable[e->type];
@@ -843,6 +861,37 @@ drawelem(Elem *e)
}
Point
+drawrune(Elem *e)
+{
+ if (e->r == L'\t') return drawtab(e);
+ if (e->r == L'\n') return drawnl(e);
+
+ Point pos;
+ Image *fg;
+ int w;
+
+ if (e->font == nil) sysfatal("drawtext: e->font is nil!");
+
+ fg = (e->link != nil) ? Ilink : Itext;
+
+ if (e->nlpos.y < e->pos.y + e->font->height)
+ e->nlpos.y = e->pos.y + e->font->height;
+
+ pos = e->pos;
+ w = runestringnwidth(e->font, &e->r, 1);
+ if (pos.x + w > rich.r.max.x) {
+ pos = e->nlpos;
+ e->nlpos.y = pos.y + e->font->height;
+ }
+
+ if ((pos.y >= rich.r.min.y) && (pos.y <= rich.r.max.y)) {
+ runestringn(screen, pos, fg, ZP, e->font, &e->r, 1);
+ }
+ pos.x += w;
+ return pos;
+}
+
+Point
drawtext(Elem *e)
{
Point pos;
@@ -875,7 +924,7 @@ drawtext(Elem *e)
for (i = 0; i < n - s; i++) {
/* if (selection start) break; */
/* if (selection end) break; */
- if (pos.x + runestringnwidth(e->font, &R[s], i) > rich.page.r.max.x) {
+ if (pos.x + runestringnwidth(e->font, &R[s], i) > rich.r.max.x) {
i --;
nl = 1;
break;
@@ -937,10 +986,10 @@ drawtab(Elem *e)
{
int x, tabw;
tabw = stringwidth(font, "0") * 4;
- x = (e->pos.x - rich.page.r.min.x) / tabw;
+ x = (e->pos.x - rich.r.min.x) / tabw;
Point pos;
pos = e->pos;
- pos.x = rich.page.r.min.x + (x + 1) * tabw;
+ pos.x = rich.r.min.x + (x + 1) * tabw;
return pos;
}
@@ -1019,7 +1068,7 @@ getelem(Point xy)
arrayget(elems, i, &e);
sp = e->pos;
np = e->nlpos;
- ep = (e->next != nil) ? e->next->pos : Pt(rich.page.r.max.x, sp.y);
+ ep = (e->next != nil) ? e->next->pos : Pt(rich.r.max.x, sp.y);
if (
(xy.y >= sp.y) &&
(xy.y < np.y) &&
diff --git a/richterm.h b/richterm.h
@@ -1,22 +1,16 @@
-typedef struct Page Page;
typedef struct Rich Rich;
typedef struct Faux Faux;
-
-struct Page {
- Point scroll;
- Point max;
- Rectangle r;
- Rectangle rs;
-};
+typedef struct Token Token;
+typedef struct Elem Elem;
struct Rich {
QLock *l;
Array *objects;
- Array *text;
u64int idcount;
long selmin;
long selmax;
- Page page;
+ Rectangle r;
+ Rectangle rs;
int scroll;
int max;
};
@@ -30,24 +24,6 @@ struct Faux {
void (*destroyfid)(Fid *);
};
-Faux * fauxalloc(Array *, void (*)(Req *), void (*)(Req *), void (*)(Req *), void (*)(Req *), void (*)(Fid *));
-Font* getfont(Array *, char *);
-int initfs(char *);
-void drawpage(Image *, Rich *);
-void drawscrollbar(void);
-void generatepage(Rich *, long);
-
-extern Channel *redrawc;
-extern Channel *insertc;
-extern Channel *consc;
-extern Channel *ctlc;
-extern File *fsroot;
-extern Array *menubuf;
-extern Array *fonts;
-extern Rich rich;
-
-/* **** New Code Beyond This Point **** */
-
enum {
E_NOOP = '\0',
E_TEXT = '.',
@@ -56,46 +32,60 @@ enum {
E_IMAGE = 'I',
E_NL = 'n',
E_TAB = 't',
- E_SPACE = 's'
+ E_SPACE = 's',
};
-typedef struct Token Token;
-typedef struct Elem Elem;
+enum {TRune, TFont, TLink, TImage};
+
+struct Elem {
+ char type;
-struct Token {
- int type;
char *str;
long count;
-};
-struct Elem {
- Token;
+ // union {
+ Rune r;
+ char *link;
+ Font *font;
+ Image *image;
+ // };
Elem *next;
Elem *prev;
- char *link;
- Image *image;
- Font *font;
-
Point pos;
Point nlpos;
};
-void drawelems(void);
+extern Channel *redrawc;
+extern Channel *insertc;
+extern Channel *consc;
+extern Channel *ctlc;
+extern File *fsroot;
+extern Array *menubuf;
+extern Array *fonts;
+extern Rich rich;
+extern Array *elems;
+extern Array *richdata;
+extern Elem *euser;
+
+
+Faux * fauxalloc(Array *, void (*)(Req *), void (*)(Req *), void (*)(Req *), void (*)(Req *), void (*)(Fid *));
+Font* getfont(Array *, char *);
Point drawelem(Elem *);
-Point drawtext(Elem *);
Point drawnl(Elem *);
+Point drawnoop(Elem *);
Point drawspace(Elem *);
Point drawtab(Elem *);
-Point drawnoop(Elem *);
+// Point drawtext(Elem *);
+Point drawrune(Elem *);
char * elemparse(Elem *, char *, long);
+int initfs(char *);
+void drawelems(void);
+void drawpage(Image *, Rich *);
+void drawscrollbar(void);
void elemslinklist(Array *);
void elemsupdatecache(Array *);
void freeelem(Elem *);
void generatesampleelems(void);
void parsedata(Array *, Array *);
-
-extern Array *elems;
-extern Array *richdata;
-extern Elem *euser;