static int job_exec(char** cmd, int* p_pid)
{
- int pid, fds[2];
+ int pid, fds[2] = {-1,-1};
/* create the sockets */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0)
- return -1;
- /* create the process */
- if ((pid = fork()) < 0)
+ if (!socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
{
- close(fds[0]), close(fds[1]), fds[0] = -1;
- }
- else if (0 == pid)
- {
- /* redirect child process's io to the pipes */
- if ((dup2(fds[1], 0) < 0) || (dup2(fds[1], 1) < 0) || (dup2(fds[1], 2) < 0))
+ /* create the process */
+ if ((pid = fork()) < 0)
{
- perror("failed to pipe");
- exit(1);
+ close(fds[0]), close(fds[1]), fds[0] = -1;
}
- /* execute the process */
- close(fds[0]);
- exit(execvp(cmd[0], cmd));
- }
- else
- {
- close(fds[1]);
- fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL, 0) | O_NONBLOCK);
+ else if (0 == pid)
+ {
+ /* redirect child process's io to the pipes */
+ if ((dup2(fds[1], 0) < 0) || (dup2(fds[1], 1) < 0) || (dup2(fds[1], 2) < 0))
+ {
+ perror("failed to pipe");
+ exit(1);
+ }
+ /* execute the process */
+ close(fds[0]);
+ exit(execvp(cmd[0], cmd));
+ }
+ else
+ {
+ close(fds[1]);
+ fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL, 0) | O_NONBLOCK);
+ }
+ if (p_pid) *p_pid = pid;
}
- if (p_pid) *p_pid = pid;
return fds[0];
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
-void select_line(char* arg) {
+void select_line(char* arg)
+{
buf_selln(win_buf(FOCUSED));
}
-void join_lines(char* arg) {
+void join_lines(char* arg)
+{
View* view = win_view(FOCUSED);
buf_logstart(win_buf(FOCUSED));
view_eol(view, false);
view_delete(view, RIGHT, false);
Rune r = view_getrune(view);
for (; r == '\t' || r == ' '; r = view_getrune(view))
+ {
view_byrune(view, RIGHT, true);
+ }
if (r != '\n')
+ {
buf_putc(win_buf(FOCUSED), ' ');
+ }
buf_logstop(win_buf(FOCUSED));
}
-void delete(char* arg) {
+void delete(char* arg)
+{
bool byword = win_keymodsset(ModCtrl);
view_delete(win_view(FOCUSED), RIGHT, byword);
}
-static void onpaste(char* text) {
+static void onpaste(char* text)
+{
view_paste(win_view(FOCUSED), text);
}
-void cut(char* arg) {
+void cut(char* arg)
+{
View* view = win_view(FOCUSED);
/* select the current line if no selection */
if (!view_selsize(view))
+ {
select_line(arg);
+ }
/* now perform the cut */
char* str = view_getstr(view);
x11_sel_set(&X, CLIPBOARD, str);
- if (str && *str) delete(arg);
+ if (str && *str)
+ {
+ delete(arg);
+ }
}
-void paste(char* arg) {
+void paste(char* arg)
+{
int pasted = x11_sel_get(&X, CLIPBOARD, onpaste);
assert(pasted);
(void)pasted;
}
-void copy(char* arg) {
+void copy(char* arg)
+{
/* select the current line if no selection */
if (!view_selsize(win_view(FOCUSED)))
+ {
select_line(arg);
+ }
char* str = view_getstr(win_view(FOCUSED));
x11_sel_set(&X, CLIPBOARD, str);
}
-static void del_to(void (*tofn)(View*, bool)) {
+static void del_to(void (*tofn)(View*, bool))
+{
tofn(win_view(FOCUSED), true);
if (view_selsize(win_view(FOCUSED)) > 0)
+ {
delete(NULL);
+ }
}
-void del_to_bol(char* arg) {
+void del_to_bol(char* arg)
+{
del_to(view_bol);
}
-void del_to_eol(char* arg) {
+void del_to_eol(char* arg)
+{
del_to(view_eol);
}
-void del_to_bow(char* arg) {
+void del_to_bow(char* arg)
+{
view_byword(win_view(FOCUSED), LEFT, true);
if (view_selsize(win_view(FOCUSED)) > 0)
+ {
delete(arg);
+ }
}
-void backspace(char* arg) {
+void backspace(char* arg)
+{
view_delete(win_view(FOCUSED), LEFT, win_keymodsset(ModCtrl));
}
-void cursor_bol(char* arg) {
+void cursor_bol(char* arg)
+{
view_bol(win_view(FOCUSED), false);
}
-void cursor_eol(char* arg) {
+void cursor_eol(char* arg)
+{
view_eol(win_view(FOCUSED), false);
}
-void cursor_mvlr(int dir) {
+void cursor_mvlr(int dir)
+{
bool extsel = win_keymodsset(ModShift);
if (win_keymodsset(ModCtrl))
+ {
view_byword(win_view(FOCUSED), dir, extsel);
+ }
else
+ {
view_byrune(win_view(FOCUSED), dir, extsel);
+ }
}
-void cursor_mvupdn(int dir) {
+void cursor_mvupdn(int dir)
+{
bool extsel = win_keymodsset(ModShift);
view_byline(win_view(FOCUSED), dir, extsel);
}
static void cursor_home_end(
void (*docfn)(View*, bool),
void (*linefn)(View*, bool)
-) {
+)
+{
bool extsel = win_keymodsset(ModShift);
if (win_keymodsset(ModCtrl))
+ {
docfn(win_view(FOCUSED), extsel);
+ }
else
+ {
linefn(win_view(FOCUSED), extsel);
+ }
}
-void cursor_home(char* arg) {
+void cursor_home(char* arg)
+{
cursor_home_end(view_bof, view_bol);
}
-void cursor_end(char* arg) {
+void cursor_end(char* arg)
+{
cursor_home_end(view_eof, view_eol);
}
-void cursor_up(char* arg) {
+void cursor_up(char* arg)
+{
cursor_mvupdn(UP);
}
-void cursor_dn(char* arg) {
+void cursor_dn(char* arg)
+{
cursor_mvupdn(DOWN);
}
-void cursor_left(char* arg) {
+void cursor_left(char* arg)
+{
cursor_mvlr(LEFT);
}
-void cursor_right(char* arg) {
+void cursor_right(char* arg)
+{
cursor_mvlr(RIGHT);
}
-void page_up(char* arg) {
+void page_up(char* arg)
+{
view_scrollpage(win_view(FOCUSED), UP);
}
-void page_dn(char* arg) {
+void page_dn(char* arg)
+{
view_scrollpage(win_view(FOCUSED), DOWN);
}
-void select_prev(char* arg) {
+void select_prev(char* arg)
+{
view_selprev(win_view(FOCUSED));
}
-void undo(char* arg) {
+void undo(char* arg)
+{
view_undo(win_view(FOCUSED));
}
-void redo(char* arg) {
+void redo(char* arg)
+{
view_redo(win_view(FOCUSED));
}
-void newline(char* arg) {
+void newline(char* arg)
+{
(void)arg;
View* view = win_view(FOCUSED);
- if (win_keymodsset(ModShift)) {
+ if (win_keymodsset(ModShift))
+ {
view_byline(view, UP, false);
view_bol(view, false);
}
view_insert(view, '\n');
}
-void highlight(char* arg) {
+void highlight(char* arg)
+{
view_selctx(win_view(FOCUSED));
}
static Bool Has_Error = False;
static XErrorEvent Error = {0};
-static int onerror(Display* disp, XErrorEvent* ev) {
+static int onerror(Display* disp, XErrorEvent* ev)
+{
(void)disp;
Has_Error = True, Error = *ev;
return 0;
}
-int x11_init(XConf* x) {
+int x11_init(XConf* x)
+{
+ int ret = -1;
signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal
setlocale(LC_CTYPE, "");
XSetLocaleModifiers("");
/* open the X display and get basic attributes */
- if (!(x->display = XOpenDisplay(0)))
- return -1;
- x->root = DefaultRootWindow(x->display);
- XWindowAttributes wa;
- XGetWindowAttributes(x->display, x->root, &wa);
- x->visual = wa.visual;
- x->colormap = wa.colormap;
- x->screen = DefaultScreen(x->display);
- x->depth = DefaultDepth(x->display, x->screen);
- x->running = True;
- XSetErrorHandler(onerror);
- return 0;
+ if ( (x->display = XOpenDisplay(0)) )
+ {
+ x->root = DefaultRootWindow(x->display);
+ XWindowAttributes wa;
+ XGetWindowAttributes(x->display, x->root, &wa);
+ x->visual = wa.visual;
+ x->colormap = wa.colormap;
+ x->screen = DefaultScreen(x->display);
+ x->depth = DefaultDepth(x->display, x->screen);
+ x->running = True;
+ XSetErrorHandler(onerror);
+ ret = 0;
+ }
+ return ret;
}
-void x11_error_clear(void) {
+void x11_error_clear(void)
+{
Has_Error = False;
memset(&Error, 0, sizeof(Error));
}
-XErrorEvent* x11_error_get(void) {
+XErrorEvent* x11_error_get(void)
+{
return (Has_Error ? &Error : NULL);
}
-void x11_mkwin(XConf* x, int width, int height, int evmask) {
+void x11_mkwin(XConf* x, int width, int height, int evmask)
+{
/* create the main window */
x->width = width, x->height = height;
XSetWindowAttributes attr;
XSetWMProtocols(x->display, x->self, &wmDeleteMessage, 1);
}
-void x11_mkdialog(XConf* x, int width, int height, int evmask) {
+void x11_mkdialog(XConf* x, int width, int height, int evmask)
+{
x11_mkwin(x, width, height, evmask);
Atom WindowType = XInternAtom(x->display, "_NET_WM_WINDOW_TYPE", False);
Atom DialogType = XInternAtom(x->display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
XChangeProperty(x->display, x->self, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1);
}
-static void update_state(XConf* x, XEvent* e) {
- if (
- (e->type == KeyPress) || (e->type == ButtonPress) ||
- (e->type == ButtonRelease) || (e->type == MotionNotify)
- ) {
+static void update_state(XConf* x, XEvent* e)
+{
+ if ((e->type == KeyPress) || (e->type == ButtonPress) ||
+ (e->type == ButtonRelease) || (e->type == MotionNotify))
+ {
x->now = e->xkey.time;
x->mods = e->xkey.state;
}
}
-void x11_process_events(XConf* x) {
+void x11_process_events(XConf* x)
+{
int nevents;
/* reap zombie background processes */
for (int status; waitpid(-1, &status, WNOHANG) > 0;);
/* process the entire event queue */
- while (XEventsQueued(x->display, QueuedAfterFlush)) {
+ while (XEventsQueued(x->display, QueuedAfterFlush))
+ {
XGetMotionEvents(x->display, x->self, CurrentTime, CurrentTime, &nevents);
- for (XEvent e; XPending(x->display);) {
+ for (XEvent e; XPending(x->display);)
+ {
XNextEvent(x->display, &e);
update_state(x, &e);
if (!XFilterEvent(&e, None) && x->eventfns[e.type])
+ {
(x->eventfns[e.type])(x, &e);
+ }
}
}
}
-void x11_event_loop(XConf* x, void (*redraw)(XConf* x)) {
+void x11_event_loop(XConf* x, void (*redraw)(XConf* x))
+{
if (redraw) redraw(x);
- for (XEvent e; x->running;) {
+ for (XEvent e; x->running;)
+ {
XNextEvent(x->display, &e);
if (x->eventfns[e.type])
+ {
x->eventfns[e.type](x, &e);
+ }
for (int status; waitpid(-1, &status, WNOHANG) > 0;);
- if (redraw) redraw(x);
+ if (redraw)
+ {
+ redraw(x);
+ }
}
}
-int x11_getptr(XConf* x, int* ptrx, int* ptry) {
+int x11_getptr(XConf* x, int* ptrx, int* ptry)
+{
Window root = 0, child = 0;
int winx = 0, winy = 0, mask = 0;
return XQueryPointer(x->display, x->self, &root, &child, ptrx, ptry, &winx, &winy, (unsigned int*)&mask);
}
-static uint32_t special_keys(uint32_t key) {
+static uint32_t special_keys(uint32_t key)
+{
static uint32_t keymap[256] = {
/* Function keys */
[0xBE] = KEY_F1, [0xBF] = KEY_F2, [0xC0] = KEY_F3, [0xC1] = KEY_F4,
return (!key ? RUNE_ERR : key);
}
-uint32_t x11_getkey(XConf* x, XEvent* e) {
+uint32_t x11_getkey(XConf* x, XEvent* e)
+{
+ uint32_t ret;
char buf[8];
KeySym key;
Status status;
+
/* Read the key string */
if (x->xic)
+ {
Xutf8LookupString(x->xic, &(e->xkey), buf, sizeof(buf), &key, &status);
+ }
else
+ {
XLookupString(&(e->xkey), buf, sizeof(buf), &key, 0);
+ }
+
/* if it's ascii, just return it */
if (key >= 0x20 && key <= 0x7F)
- return (uint32_t)key;
- /* translate special key codes into unicode codepoints */
- return special_keys(key);
+ {
+ ret = (uint32_t)key;
+ }
+ else
+ {
+ ret = special_keys(key);
+ }
+ return ret;
}
-uint32_t x11_process_key(XConf* x, XEvent* e, KeyBinding* keys) {
+uint32_t x11_process_key(XConf* x, XEvent* e, KeyBinding* keys)
+{
uint32_t key = x11_getkey(x, e);
- if (key == RUNE_ERR) return key;
- int mods = e->xkey.state & (ModCtrl|ModShift|ModAlt);
- int32_t mkey = tolower(key);
- for (KeyBinding* bind = keys; bind && bind->key; bind++) {
- bool match = (mkey == (int32_t)bind->key);
- bool exact = (bind->mods == mods);
- bool any = (bind->mods == ModAny);
- bool oneplus = ((bind->mods == ModOneOrMore) && (mods & ModOneOrMore));
- if (match && (exact || oneplus || any)) {
- bind->fn(bind->arg);
- return RUNE_ERR;
+ if (key != RUNE_ERR)
+ {
+ int mods = e->xkey.state & (ModCtrl|ModShift|ModAlt);
+ int32_t mkey = tolower(key);
+ for (KeyBinding* bind = keys; bind && bind->key; bind++)
+ {
+ bool match = (mkey == (int32_t)bind->key);
+ bool exact = (bind->mods == mods);
+ bool any = (bind->mods == ModAny);
+ bool oneplus = ((bind->mods == ModOneOrMore) && (mods & ModOneOrMore));
+ if (match && (exact || oneplus || any))
+ {
+ bind->fn(bind->arg);
+ key = RUNE_ERR;
+ break;
+ }
}
}
/* fallback to just inserting the rune if it doesn't fall in the private use area.
#include <x11.h>
#include <X11/extensions/Xinerama.h>
-static void xfocus(XConf* x, XEvent* e) {
+static void xfocus(XConf* x, XEvent* e)
+{
if (x->xic)
+ {
(e->type == FocusIn ? XSetICFocus : XUnsetICFocus)(x->xic);
+ }
}
-void x11_resize(XConf* x, XEvent* e) {
- if (e->xconfigure.width != x->width || e->xconfigure.height != x->height) {
+void x11_resize(XConf* x, XEvent* e)
+{
+ if (e->xconfigure.width != x->width || e->xconfigure.height != x->height)
+ {
x->width = e->xconfigure.width;
x->height = e->xconfigure.height;
XFreePixmap(x->display, x->pixmap);
}
}
-void x11_mapnotify(XConf* x, XEvent* e) {
+void x11_mapnotify(XConf* x, XEvent* e)
+{
x11_resize(x, e);
XWarpPointer(x->display, None, x->self, 0, 0, x->width, x->height, x->width/2, x->height/2);
}
-void x11_init_gc(XConf* x) {
+void x11_init_gc(XConf* x)
+{
/* set input methods */
if ((x->xim = XOpenIM(x->display, 0, 0, 0)))
x->xic = XCreateIC(x->xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, x->self, XNFocusWindow, x->self, NULL);
x->eventfns[MappingNotify] = x11_mapnotify;
}
-void x11_centerwin(XConf* x) {
+void x11_centerwin(XConf* x)
+{
int ptrx = 0, ptry = 0;
(void)x11_getptr(x, &ptrx, &ptry);
int nscreens = 0;
XineramaScreenInfo* p_screens = XineramaQueryScreens(x->display, &nscreens);
- for (int i = 0; i < nscreens; i++) {
+ for (int i = 0; i < nscreens; i++)
+ {
int minx = p_screens[i].x_org,
maxx = p_screens[i].x_org + p_screens[i].width,
miny = p_screens[i].y_org,
maxy = p_screens[i].y_org + p_screens[i].height;
- if (minx <= ptrx && ptrx <= maxx && miny <= ptry && ptry <= maxy) {
+ if (minx <= ptrx && ptrx <= maxx && miny <= ptry && ptry <= maxy)
+ {
XMoveWindow(x->display, x->self,
minx + p_screens[i].width/2 - x->width/2,
miny + p_screens[i].height/2 - x->height/2);
break;
}
}
- if (p_screens) XFree(p_screens);
+ if (p_screens)
+ {
+ XFree(p_screens);
+ }
}
-void x11_show(XConf* x) {
+void x11_show(XConf* x)
+{
/* simulate an initial resize and map the window */
XConfigureEvent ce;
ce.type = ConfigureNotify;
/* Waiting for window mapping */
XEvent ev;
- do {
+ do
+ {
XNextEvent(x->display, &ev);
if (XFilterEvent(&ev, None))
+ {
continue;
+ }
if (ev.type == ConfigureNotify)
+ {
x11_resize(x, &ev);
- } while (ev.type != MapNotify);
+ }
+ }
+ while (ev.type != MapNotify);
XWarpPointer(x->display, None, x->self, 0, 0, x->width, x->height, x->width/2, x->height/2);
}
-XftFont* x11_font_load(XConf* x, char* name) {
+XftFont* x11_font_load(XConf* x, char* name)
+{
/* init the library and the base font pattern */
- if (!FcInit()) return NULL;
+ if (!FcInit())
+ {
+ return NULL;
+ }
FcPattern* pattern = FcNameParse((FcChar8 *)name);
- if (!pattern) return NULL;
+ if (!pattern)
+ {
+ return NULL;
+ }
/* load the base font */
FcResult result;
FcPattern* match = XftFontMatch(x->display, x->screen, pattern, &result);
XftFont* font = NULL;
if (match)
+ {
font = XftFontOpenPattern(x->display, match);
+ }
FcPatternDestroy(pattern);
FcPatternDestroy(match);
return font;
}
-void xftcolor(XConf* x, XftColor* xc, unsigned int c) {
+void xftcolor(XConf* x, XftColor* xc, unsigned int c)
+{
#define COLOR(c) ((c) | ((c) >> 8))
xc->color.alpha = 0xFFFF;
xc->color.red = COLOR((c & 0x00FF0000) >> 8);
XftColorAllocValue(x->display, x->visual, x->colormap, &(xc->color), xc);
}
-void x11_draw_rect(XConf* x, int color, int px, int py, int width, int height) {
+void x11_draw_rect(XConf* x, int color, int px, int py, int width, int height)
+{
XftColor clr;
xftcolor(x, &clr, color);
XftDrawRect(x->xft, &clr, px, py, width, height);
XftColorFree(x->display, x->visual, x->colormap, &clr);
}
-void x11_draw_glyphs(XConf* x, int color, XftFont* font, XftGlyphSpec* specs, long nspecs) {
+void x11_draw_glyphs(XConf* x, int color, XftFont* font, XftGlyphSpec* specs, long nspecs)
+{
XftColor clr;
xftcolor(x, &clr, color);
XftDrawGlyphSpec(x->xft, &clr, font, specs, nspecs);
XftColorFree(x->display, x->visual, x->colormap, &clr);
}
-void x11_flip(XConf* x) {
+void x11_flip(XConf* x)
+{
XCopyArea(x->display, x->pixmap, x->self, x->gc, 0, 0, x->width, x->height, 0, 0);
XFlush(x->display);
}
-void x11_draw_string(XConf* x, XftFont* font, int posx, int posy, int color, char* str) {
+void x11_draw_string(XConf* x, XftFont* font, int posx, int posy, int color, char* str)
+{
XftColor clr;
xftcolor(x, &clr, color);
XftDrawStringUtf8(x->xft, &clr, font, posx, posy, (const FcChar8*)str, strlen(str));