commit 80df5b3f76c4f09fa540258924c6afdef4b13ff3
parent 6e4d4e1c68bdb032581973f3051799e1be6b5a50
Author: Pavel Renev <an2qzavok@gmail.com>
Date: Sun, 22 Aug 2021 23:02:28 +0000
selection probably works now
Diffstat:
M | TODO | | | 14 | +++++++++++++- |
M | richterm.c | | | 164 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
M | richterm.h | | | 2 | ++ |
3 files changed, 157 insertions(+), 23 deletions(-)
diff --git a/TODO b/TODO
@@ -1 +1,13 @@
-Retvrn selecting, object removal and screen clearing.
+# selecting
+
+activate menu elements
+
+# /ctl commands
+
+## object removal
+
+## screen clearing.
+
+# find and fix memory locks
+
+there's one related to spawning many new objects
diff --git a/richterm.c b/richterm.c
@@ -17,6 +17,8 @@ void send_interrupt(void);
void runcmd(void *);
void scroll(Point, Rich *);
void mouse(Mousectl *, Mouse, int *);
+Object * getobj(Point xy);
+long getsel(Point pt);
void mpaste(Rich *);
void msnarf(Rich *);
@@ -111,6 +113,9 @@ threadmain(int argc, char **argv)
rich.page.scroll = ZP;
+ rich.selmin = 0;
+ rich.selmax = 0;
+
qunlock(rich.l);
olast = newobject(&rich, nil, 0);
@@ -227,6 +232,7 @@ threadmain(int argc, char **argv)
void
mouse(Mousectl *mc, Mouse mv, int *mmode)
{
+ static long selstart, selend;
if (mv.buttons == 0) {
*mmode = MM_NONE;
return;
@@ -275,6 +281,10 @@ mouse(Mousectl *mc, Mouse mv, int *mmode)
break;
case MM_TEXT:
if (mv.buttons == 1) {
+ selstart = getsel(mv.xy);
+ selend = selstart;
+ rich.selmin = selstart;
+ rich.selmax = selstart;
redraw(0);
*mmode = MM_SELECT;
}
@@ -296,6 +306,14 @@ mouse(Mousectl *mc, Mouse mv, int *mmode)
/* paste */
break;
}
+ selend = getsel(mv.xy);
+ if (selstart < selend) {
+ rich.selmin = selstart;
+ rich.selmax = selend;
+ } else {
+ rich.selmin = selend;
+ rich.selmax = selstart;
+ }
redraw(0);
}
}
@@ -538,42 +556,69 @@ mplumb(Rich *)
{
}
+int
+objectisvisible(Object *obj)
+{
+ return (obj->nextlinept.y >= rich.page.scroll.y) &&
+ (obj->startpt.y <= rich.page.scroll.y + Dy(rich.page.r));
+}
+
void
-_drawchar(char *p, Point pt, Font *font, Image *fg, Image *bg)
+_drawchar(Rune r, Point pt, Font *font, Image *fg, Image *bg)
{
- Point ptact, ptnew;
- ptact = subpt(addpt(pt, rich.page.r.min), rich.page.scroll);
- ptnew = stringnbg(screen, ptact, fg, ZP, font, p, 1, bg, ZP);
+ runestringnbg(screen,
+ subpt(addpt(pt, rich.page.r.min), rich.page.scroll),
+ fg, ZP, font, &r, 1, bg, ZP);
}
void
-drawchar(Object *obj, long n, Point *cur)
+drawchar(Object *obj, long *n, Point *cur)
{
- int tab, cw;
+ int tabw, cw;
+ Image *bg;
+ Rune r;
char *p;
- p = arrayget(rich.text, n);
- cw = stringnwidth(obj->font, p, 1);
- if (cur->x + cw > Dx(rich.page.r)) {
+ bg = ((*n >= rich.selmin) && (*n < rich.selmax)) ?
+ Iselbg : Inormbg;
+
+ p = arrayget(rich.text, *n);
+
+ if (p == nil) return;
+
+ *n += chartorune(&r, p);
+ cw = runestringnwidth(obj->font, &r, 1);
+
+ if (cur->x + cw >= Dx(rich.page.r)) {
*cur = obj->nextlinept;
obj->nextlinept.y += obj->font->height;
}
switch (*p) {
case '\n':
- *cur = obj->nextlinept;
- obj->nextlinept.y += obj->font->height;
+ if (objectisvisible(obj))
+ draw(screen,
+ rectaddpt(
+ Rpt(*cur, Pt(Dx(rich.page.r), obj->nextlinept.y)),
+ subpt(rich.page.r.min, rich.page.scroll)),
+ bg, nil, ZP);
+
+ cur->x = Dx(rich.page.r);
break;
case '\t':
- tab = stringwidth(font, "0") * 4;
- cur->x = (cur->x / tab + 1) * tab;
+ tabw = stringwidth(font, "0") * 4;
+ if (objectisvisible(obj))
+ draw(screen,
+ rectaddpt(
+ Rpt(*cur, Pt(cur->x + tabw, obj->nextlinept.y)),
+ subpt(rich.page.r.min, rich.page.scroll)),
+ bg, nil, ZP);
+
+ cur->x = (cur->x / tabw + 1) * tabw;
break;
default:
- if ((cur->y >= rich.page.scroll.y) &&
- (obj->nextlinept.y <= rich.page.scroll.y + Dy(rich.page.r)))
- {
- _drawchar(p, *cur, obj->font, Itext, Inormbg);
- }
+ if (objectisvisible(obj))
+ _drawchar(r, *cur, obj->font, Itext, bg);
cur->x += cw;
}
}
@@ -587,6 +632,11 @@ drawobject(Object *obj, Point *cur)
obj->offset, rich.text->count);
return;
}
+
+ if ((cur->x >= Dx(rich.page.r)) && (obj->prev != nil)) {
+ *cur = obj->prev->nextlinept;
+ }
+
obj->startpt = *cur;
obj->nextlinept = Pt(0, cur->y + obj->font->height);
if ((obj->prev != nil) && (cur->x != 0)) {
@@ -595,8 +645,8 @@ drawobject(Object *obj, Point *cur)
}
if (obj->next == nil) n = rich.text->count;
else n = obj->next->offset;
- for (i = obj->offset; i < n; i++) {
- drawchar(obj, i, cur);
+ for (i = obj->offset; i < n;) {
+ drawchar(obj, &i, cur);
}
obj->endpt = *cur;
}
@@ -618,4 +668,75 @@ newdraw(void)
rich.page.max = cur;
qunlock(rich.text->l);
qunlock(rich.l);
-}
-\ No newline at end of file
+}
+
+Object *
+getobj(Point xy)
+{
+ long i;
+ Object **op, *obj;
+ Point prevlinept;
+ xy = subpt(xy, subpt(rich.page.r.min, rich.page.scroll));
+ for (i = 0; i < rich.objects->count; i++) {
+ op = arrayget(rich.objects, i);
+ obj = *op;
+ prevlinept = ( obj->prev == nil) ? ZP : obj->prev->nextlinept;
+
+ if (((obj->startpt.y == obj->endpt.y) &&
+ (xy.y >= obj->startpt.y) &&
+ (xy.y < obj->nextlinept.y) &&
+ (xy.x >= obj->startpt.x) &&
+ (xy.x < obj->endpt.x)) ||
+
+ ((xy.x >= obj->startpt.x) &&
+ (xy.y >= obj->startpt.y) &&
+ (xy.y < obj->endpt.y)) ||
+
+ ((obj->startpt.y < obj->endpt.y) &&
+ (xy.x < obj->endpt.x) &&
+ (xy.y >= obj->endpt.y) &&
+ (xy.y < obj->nextlinept.y)) ||
+
+ ((xy.y >= prevlinept.y) &&
+ (xy.y < obj->endpt.y))
+ )
+ return obj;
+ }
+ return nil;
+}
+
+long
+getsel(Point xy)
+{
+ Object *obj;
+ long n, i, li;
+ Point cur, oldcur;
+
+ obj = getobj(xy);
+
+ xy = subpt(xy, subpt(rich.page.r.min, rich.page.scroll));
+
+ if (obj == nil)
+ return (xy.y > rich.page.max.y) ? rich.text->count : 0;
+
+ n = (obj->next == nil) ? rich.text->count : obj->next->offset;
+ li = obj->offset;
+
+ cur = obj->startpt;
+ obj->nextlinept = Pt(0, cur.y + obj->font->height);
+ if ((obj->prev != nil) && (cur.x != 0)) {
+ if (obj->nextlinept.y < obj->prev->nextlinept.y)
+ obj->nextlinept.y = obj->prev->nextlinept.y;
+ }
+
+ for (i = obj->offset; i < n;) {
+ oldcur = cur;
+ li = i;
+ drawchar(obj, &i, &cur);
+
+ if (ptinrect(xy, Rpt(oldcur, Pt(cur.x, obj->nextlinept.y))) ||
+ (cur.y > xy.y))
+ break;
+ }
+ return li;
+}
diff --git a/richterm.h b/richterm.h
@@ -50,6 +50,8 @@ struct Rich {
Array *objects;
Array *text;
u64int idcount;
+ long selmin;
+ long selmax;
Page page;
};