From 700fbcf9daf42f028ff6bc1dd73be076f4de1acf Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Fri, 26 Oct 2018 23:46:28 -0400 Subject: [PATCH] added client message to jump open windows to specific line. --- src/edit.c | 21 ++++++++++++++++++--- src/lib/x11.c | 2 ++ src/registrar.c | 30 +++++++++++++++++++++--------- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/edit.c b/src/edit.c index 648087e..a4ed0c1 100644 --- a/src/edit.c +++ b/src/edit.c @@ -1,5 +1,6 @@ #include #include +#include Atom XA_REGISTRAR, XA_OPEN; @@ -19,6 +20,20 @@ Window start_registrar(XConf* x) { return XGetSelectionOwner(x->display, XA_REGISTRAR); } +void edit_file(XConf* x, Window registrar, char* path, size_t lnnum) { + char number[32] = {0}; + snprintf(number, 32, ":%lu", lnnum); + char* rpath = realpath(path, NULL); + if (rpath) + path = strmcat(rpath, number, 0); + else + path = strmcat(path, number, 0); + XChangeProperty( + x->display, registrar, XA_OPEN, XA_STRING, 8, PropModeAppend, + (const unsigned char *)path, strlen(path)+1); + free(path); +} + int main(int argc, char** argv) { XConf x = {0}; x11_init(&x); @@ -32,9 +47,9 @@ int main(int argc, char** argv) { } else { /* Loop over files and send and OPEN message for each one. */ for (int i = 1; i < argc; i++) { - XChangeProperty( - x.display, registrar, XA_OPEN, XA_STRING, 8, PropModeAppend, - (const unsigned char *)argv[i], strlen(argv[i])+1); + char* addr = strrchr(argv[i], ':'); + if (addr) *addr = '\0', addr++; + edit_file(&x, registrar, argv[i], strtoul((addr ? addr : ""), NULL, 0)); } } diff --git a/src/lib/x11.c b/src/lib/x11.c index 85d20a6..f3feac2 100644 --- a/src/lib/x11.c +++ b/src/lib/x11.c @@ -509,6 +509,8 @@ static void xselrequest(XEvent* e) { static void xclientmsg(XEvent* e) { if (e->xclient.data.l[0] == XInternAtom(X.display, "WM_DELETE_WINDOW", False)) win_quit(); + else if (e->xclient.message_type == XInternAtom(X.display, "GOTO", False)) + view_setln(win_view(EDIT), e->xclient.data.l[0]); } static void xresize(XEvent* e) { diff --git a/src/registrar.c b/src/registrar.c index 3aaf455..a8e9834 100644 --- a/src/registrar.c +++ b/src/registrar.c @@ -47,25 +47,37 @@ void win_del(Window id) { } } +void win_send(XConf* x, Window from, Window to, int mask, char* atom, size_t val) { + XEvent ev = {0}; + ev.xclient.type = ClientMessage; + ev.xclient.send_event = True; + ev.xclient.message_type = XInternAtom(x->display, atom, False); + ev.xclient.window = from; + ev.xclient.format = 32; + ev.xclient.data.l[0] = val; + XSendEvent(x->display, to, False, mask, &ev); +} + void win_open(XConf* x, char* path) { + /* parse out address for later */ + char* addr = strrchr(path, ':'); + if (addr) *addr = '\0', addr++; + if (!addr) addr = "0"; + /* search for an existing window */ for (TWindow* win = Windows; win; win = win->next) { if (!strcmp(win->path, path)) { - XEvent ev = {0}; - ev.xclient.type = ClientMessage; - ev.xclient.send_event = True; - ev.xclient.message_type = XInternAtom(x->display, "_NET_ACTIVE_WINDOW", False); - ev.xclient.window = win->win; - ev.xclient.format = 32; - XSendEvent(x->display, x->root, False, SubstructureRedirectMask|SubstructureNotifyMask, &ev); + win_send(x, win->win, x->root, SubstructureRedirectMask|SubstructureNotifyMask, "_NET_ACTIVE_WINDOW", 0); XMapRaised(x->display, win->win); + win_send(x, x->self, win->win, 0, "GOTO", strtoul(addr, NULL, 0)); XFlush(x->display); return; } } + /* if we don't find it, spawn a new one */ if (!fork()) - exit(execvp("tide", (char*[]){"tide", path, 0})); + exit(execvp("tide", (char*[]){"tide", "-l", addr, path, 0})); } void selclear(XConf* x, XEvent* e) { @@ -85,7 +97,7 @@ void propnotify(XConf* x, XEvent* e) { size_t length; char* paths = readprop(x, x->self, XA_OPEN, &length); char* path = paths; - while (length) { + while (length && *path) { size_t sz = strlen((char*)path)+1; win_open(x, (char*)path); path += sz, length -= sz; -- 2.51.0