summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Carbonneaux2014-10-23 11:28:12 -0400
committerQuentin Carbonneaux2014-10-23 11:43:36 -0400
commit0fde8d24f4008126d8334ba98939bb268717de43 (patch)
treec4b83b1493a332a81bf8f8e486f00d50906f486b
parentba552a054ffcdd4a97e32e777f59386695465836 (diff)
improve visual feedback of cursor
-rw-r--r--cmd.h3
-rw-r--r--exec.c3
-rw-r--r--gui.h1
-rw-r--r--main.c31
-rw-r--r--vicmd.w28
-rw-r--r--win.c16
-rw-r--r--win.h6
-rw-r--r--x11.c22
8 files changed, 69 insertions, 41 deletions
diff --git a/cmd.h b/cmd.h
index 2da6acd..2f23ddc 100644
--- a/cmd.h
+++ b/cmd.h
@@ -1 +1,4 @@
+extern int mode;
+
void cmd_parse(Rune r);
+#define cmd_reset() cmd_parse(GKEsc);
diff --git a/exec.c b/exec.c
index 53a2623..293b49a 100644
--- a/exec.c
+++ b/exec.c
@@ -21,6 +21,7 @@
#include "evnt.h"
extern W *curwin;
+void repaint(void);
void die(char *);
typedef struct ecmd ECmd;
@@ -409,7 +410,7 @@ runev(int fd, int flag, void *data)
eb_setmark(t->eb, SelBeg, t->p);
eb_setmark(t->eb, SelEnd, t->p + t->ins);
eb_commit(t->eb);
- win_redraw_frame();
+ repaint();
}
if (flag & EWrite) {
assert(t->ob && t->wfd == fd);
diff --git a/gui.h b/gui.h
index ae8564c..e6c83da 100644
--- a/gui.h
+++ b/gui.h
@@ -100,6 +100,7 @@ struct gui {
void (*drawtext)(GRect *clip, Rune *str, int len,
int x, int y, GColor color);
void (*drawrect)(GRect *clip, int x, int y, int w, int h, GColor c);
+ void (*drawcursor)(GRect *clip, int insert, int x, int y, int w);
void (*setpointer)(GPointer pt);
int (*textwidth)(Rune *str, int len);
int (*nextevent)(GEvent *eret);
diff --git a/main.c b/main.c
index dd2cb3d..3cad2b9 100644
--- a/main.c
+++ b/main.c
@@ -17,9 +17,13 @@
W *curwin;
int scrolling;
+int needsredraw;
+enum {
+ RedrawDelay = 16, /* in milliseconds */
+ DoubleClick = 600,
+};
static struct gui *g;
-static int needsredraw;
static int clicks;
@@ -32,8 +36,13 @@ risword(Rune r)
static void
redraw()
{
+ static W *old;
+
assert(needsredraw);
- win_redraw_frame();
+ if (old != curwin && old)
+ old->dirty = 1;
+ win_redraw_frame(curwin, mode == 'i');
+ old = curwin;
needsredraw = 0;
}
@@ -43,13 +52,18 @@ resetclicks()
clicks = 0;
}
+void
+repaint()
+{
+ if (needsredraw)
+ return;
+ ev_alarm(RedrawDelay, redraw);
+ needsredraw = 1;
+}
+
static void
gev(int fd, int flag, void *unused)
{
- enum {
- RedrawDelay = 16, /* in milliseconds */
- DoubleClick = 200,
- };
static unsigned selbeg;
static W *mousewin;
static int resizing;
@@ -59,10 +73,7 @@ gev(int fd, int flag, void *unused)
(void)fd; (void)flag; (void)unused;
while (g->nextevent(&e)) {
- if (!needsredraw) {
- ev_alarm(RedrawDelay, redraw);
- needsredraw = 1;
- }
+ repaint();
switch (e.type) {
case GResize:
win_resize_frame(e.resize.width, e.resize.height);
diff --git a/vicmd.w b/vicmd.w
index 73706d9..5fdfac0 100644
--- a/vicmd.w
+++ b/vicmd.w
@@ -52,7 +52,7 @@ enum {
Command = 'c',
Insert = 'i'
};
-static int mode = Command;
+int mode = Command;
@** Parsing of commands. We structure the parsing function as a
@@ -159,6 +159,19 @@ if (!risbuf(r)) goto err;
buf = r;
state = CmdChar;
+@ When a double character command is expected we ensure that the
+second character received is the same as the first and resume
+the processing performed in |@<Input command count...@>|.
+
+@<Get the second char...@>=
+if (r != pcmd->chr)
+ goto err;
+goto gotdbl;
+
+@ @<Get the command arg...@>=
+pcmd->arg = r;
+goto gotarg;
+
@ The |CmdChar| state needs to handle both the count and the command
name. Depending on the command kind (double char, expecting an
argument, ...) we have to update the state differently. To get this
@@ -191,19 +204,6 @@ gotarg:
@<Reset parsing state@>;
}
-@ When a double character command is expected we ensure that the
-second character received is the same as the first and resume
-the processing performed in |@<Input command count...@>|.
-
-@<Get the second char...@>=
-if (r != pcmd->chr)
- goto err;
-goto gotdbl;
-
-@ @<Get the command arg...@>=
-pcmd->arg = r;
-goto gotarg;
-
@ The internal state is reset by zeroing the |count| field of the
commands, this is necessary since |@<Input command count...@>| relies
on it to determine if a received |'0'| is part of the count or is the
diff --git a/win.c b/win.c
index fc196e9..ee5bd66 100644
--- a/win.c
+++ b/win.c
@@ -19,7 +19,7 @@ struct lineinfo {
};
static int dirty(W *);
-static void draw(W *w, GColor bg);
+static void draw(W *w, GColor bg, W *focus, int insert);
static void move(W *pw, int x, int y, int w, int h);
static void lineinfo(W *w, unsigned off, unsigned lim, struct lineinfo *li);
static int runewidth(Rune r, int x);
@@ -239,7 +239,7 @@ win_resize_frame(int w1, int h1)
/* win_redraw_frame - Redraw the whole frame.
*/
void
-win_redraw_frame()
+win_redraw_frame(W *focus, int insert)
{
GRect b;
W *w;
@@ -253,7 +253,7 @@ win_redraw_frame()
b.x = w->rectx + w->rectw;
g->drawrect(&b, 0, 0, b.w, b.h, GGray);
}
- draw(w, GPaleYellow);
+ draw(w, GPaleYellow, focus, insert);
if (tag.owner == w)
tag.win.dirty = 1;
}
@@ -262,7 +262,7 @@ win_redraw_frame()
b = tag.win.rect;
b.y -= g->border;
g->drawrect(&b, 0, 0, b.w, g->border, GGray);
- draw(&tag.win, GPaleGreen);
+ draw(&tag.win, GPaleGreen, focus, insert);
}
g->sync();
}
@@ -442,7 +442,7 @@ flushfrag(struct frag *f, W *w, int x, int y, int sel)
}
static void
-draw(W *w, GColor bg)
+draw(W *w, GColor bg, W *focus, int insert)
{
struct frag f;
int x, y, cx, cy, cw, rw, sel;
@@ -496,8 +496,8 @@ draw(W *w, GColor bg)
pushfrag(&f, r, rw);
}
- if (cw != 0)
- g->drawrect(&w->rect, cx, cy, cw, font.height, GXBlack);
+ if (cw != 0 && w == focus)
+ g->drawcursor(&w->rect, insert, cx, cy, cw);
g->decorate(&w->rect, w->eb->path && w->eb->frev != eb_revision(w->eb), GGray);
w->dirty = 0;
}
@@ -642,7 +642,7 @@ int main()
do {
select(0, 0, 0, 0, &(struct timeval){ 0, 30000 });
- win_redraw_frame();
+ win_redraw_frame(w, 0);
if (!g->nextevent(&e))
continue;
if (e.type == GResize)
diff --git a/win.h b/win.h
index 98835f9..6ee9ea3 100644
--- a/win.h
+++ b/win.h
@@ -26,7 +26,9 @@ struct w {
unsigned cu; /* cursor offset */
EBuf *eb; /* underlying buffer object */
GRect rect; /* rectangle on the screen */
- int dirty; /* force redraw */
+ int dirty: 1; /* force redraw */
+ int insert: 1; /* inserting */
+ int focus: 1; /* focused window */
};
enum CursorLoc { CTop, CMid, CBot };
@@ -38,7 +40,7 @@ unsigned win_at(W *w, int x, int y);
W *win_which(int x, int y);
void win_move(W *, int x, int y);
void win_resize_frame(int w, int h);
-void win_redraw_frame(void);
+void win_redraw_frame(W *focus, int insert);
void win_scroll(W *, int);
void win_show_cursor(W *, enum CursorLoc);
W *win_tag_toggle(W *);
diff --git a/x11.c b/x11.c
index 1bf39f7..b358a05 100644
--- a/x11.c
+++ b/x11.c
@@ -160,6 +160,15 @@ drawrect(GRect *clip, int x, int y, int w, int h, GColor c)
}
static void
+drawcursor(GRect *clip, int insert, int x, int y, int w)
+{
+ if (insert)
+ drawrect(clip, x, y, 2, font->height, GXBlack);
+ else
+ drawrect(clip, x, y, w, font->height, GXBlack);
+}
+
+static void
decorate(GRect *clip, int dirty, GColor c)
{
int boxh;
@@ -335,15 +344,16 @@ struct gui gui_x11 = {
.init = init,
.fini = fini,
.sync = sync,
- .decorate = decorate,
+ .decorate = decorate,
.drawrect = drawrect,
+ .drawcursor = drawcursor,
.drawtext = drawtext,
.getfont = getfont,
.nextevent = nextevent,
- .setpointer = setpointer,
+ .setpointer = setpointer,
.textwidth = textwidth,
- .hmargin = HMargin,
- .vmargin = VMargin,
- .border = Border,
- .actionr = {0, 0, 0, 0},
+ .hmargin = HMargin,
+ .vmargin = VMargin,
+ .border = Border,
+ .actionr = {0, 0, 0, 0},
};