ClrTagsSel, ClrTagsCsr, ClrEditNor, ClrEditSel, ClrEditCsr, ClrEditRul,
ClrBorders,
- //BkgRuler, BkgGutter, BkgTags, BkgEdit, BkgScroll, BkgThumb, BkgBorder,
- //TxtCursor, TxtNormal, TxtSelected, TxtGutter, TxtCurrentLine,
-
SynNormal, SynComment, SynConstant, SynString, SynChar, SynNumber,
SynBoolean, SynFloat, SynVariable, SynFunction, SynKeyword, SynOperator,
SynPreProc, SynType, SynStatement, SynSpecial
bool win_getlinenums(void);
void win_setruler(size_t ruler);
Rune win_getkey(void);
-void win_setkeys(KeyBinding* bindings);
+void win_setkeys(KeyBinding* bindings, void (*inputfn)(Rune));
void win_setmouse(MouseConfig* mconfig);
void win_warpptr(WinRegion id);
View* win_view(WinRegion id);
void onmouseleft(WinRegion id, bool pressed, size_t row, size_t col);
void onmousemiddle(WinRegion id, bool pressed, size_t row, size_t col);
void onmouseright(WinRegion id, bool pressed, size_t row, size_t col);
+bool update_needed(void);
static void onmousebtn(int btn, bool pressed, int x, int y);
static void onwheelup(WinRegion id, bool pressed, size_t row, size_t col);
static void onwheeldn(WinRegion id, bool pressed, size_t row, size_t col);
+static bool update_focus(void);
static void draw_line_num(bool current, size_t x, size_t y, size_t gcols, size_t num);
static void draw_glyphs(size_t x, size_t y, UGlyph* glyphs, size_t rlen, size_t ncols);
static WinRegion getregion(size_t x, size_t y);
static Region Regions[NREGIONS] = {0};
static Rune LastKey;
static KeyBinding* Keys = NULL;
+static void (*InputFunc)(Rune);
static bool ShowLineNumbers = false;
static void win_init(void (*errfn)(char*)) {
x11_dialog(name, config_get_int(WinWidth), config_get_int(WinHeight));
}
-static bool update_focus(void) {
- static int prev_x = 0, prev_y = 0;
- int ptr_x, ptr_y;
- bool changed = false;
- /* dont change focus if any mouse buttons are pressed */
- if ((x11_keybtnstate() & 0x1f00) == 0) {
- x11_mouse_get(&ptr_x, &ptr_y);
- if (prev_x != ptr_x || prev_y != ptr_y)
- changed = win_setregion(getregion(ptr_x, ptr_y));
- prev_x = ptr_x, prev_y = ptr_y;
- }
- return changed;
-}
-
void win_loop(void) {
x11_show();
x11_flip();
while (x11_running()) {
bool pending = x11_events_await(config_get_int(EventTimeout));
int nevents = x11_events_queued();
- if (update_focus() || pending || nevents) {
+ if (update_focus() || pending || nevents || update_needed()) {
x11_events_take();
if (x11_running())
x11_flip();
return LastKey;
}
-void win_setkeys(KeyBinding* bindings) {
+void win_setkeys(KeyBinding* bindings, void (*inputfn)(Rune)) {
Keys = bindings;
+ InputFunc = inputfn;
}
bool win_btnpressed(int btn) {
/* fallback to just inserting the rune if it doesn't fall in the private use area.
* the private use area is used to encode special keys */
if (key < 0xE000 || key > 0xF8FF) {
- if (key == '\n' && win_view(FOCUSED)->buffer.crlf)
- key = RUNE_CRLF;
- view_insert(win_view(FOCUSED), true, key);
+ if (InputFunc) {
+ InputFunc(key);
+ } else {
+ if (key == '\n' && win_view(FOCUSED)->buffer.crlf)
+ key = RUNE_CRLF;
+ view_insert(win_view(FOCUSED), true, key);
+ }
}
}
view_scroll(win_view(id), +(config_get_int(ScrollLines)));
}
+static bool update_focus(void) {
+ static int prev_x = 0, prev_y = 0;
+ int ptr_x, ptr_y;
+ bool changed = false;
+ /* dont change focus if any mouse buttons are pressed */
+ if ((x11_keybtnstate() & 0x1f00) == 0) {
+ x11_mouse_get(&ptr_x, &ptr_y);
+ if (prev_x != ptr_x || prev_y != ptr_y)
+ changed = win_setregion(getregion(ptr_x, ptr_y));
+ prev_x = ptr_x, prev_y = ptr_y;
+ }
+ return changed;
+}
+
static void draw_line_num(bool current, size_t x, size_t y, size_t gcols, size_t num) {
int color = config_get_int(ClrGutterNor);
if (ShowLineNumbers) {
Colormap colormap;
unsigned depth;
int screen;
- /* assume a single window for now. these are it's attributes */
+ /* assume a single window for now. these are its attributes */
Window window;
XftDraw* xft;
Pixmap pixmap;
x11_deinit();
}
+bool update_needed(void) {
+ return false;
+}
+
/* Main Routine
*****************************************************************************/
static void onerror(char* msg) {
load_choices();
if (vec_size(&Choices) > 1) {
win_dialog("pick", onerror);
- win_setkeys(Bindings);
+ win_setkeys(Bindings, NULL);
win_settext(STATUS, (title ? title : "pick"));
if (argc >= 2) {
for (char* str = argv[1]; *str; str++)
+#define _XOPEN_SOURCE 700
#include <stdc.h>
+#include <unistd.h>
+#ifdef __MACH__
+ #include <util.h>
+#else
+ #include <pty.h>
+#endif
+#include <poll.h>
+#include <termios.h>
+#include <sys/select.h>
+#include <sys/types.h>
#include <x11.h>
#include <utf.h>
#include <edit.h>
#include <ctype.h>
#include <win.h>
-static int ShellFD;
+int CmdFD = -1;
+char* ShellCmd[] = { NULL, NULL };
-void onmouseleft(WinRegion id, bool pressed, size_t row, size_t col) {
-}
+bool fdready(int fd);
-void onmousemiddle(WinRegion id, bool pressed, size_t row, size_t col) {
-}
+/* unused functions */
+void onfocus(bool focused) {}
-void onmouseright(WinRegion id, bool pressed, size_t row, size_t col) {
+void onerror(char* msg) {
}
void onscroll(double percent) {
+ size_t bend = buf_end(win_buf(EDIT));
+ size_t off = (size_t)((double)bend * percent);
+ view_scrollto(win_view(EDIT), (off >= bend ? bend : off));
}
-void onfocus(bool focused) {
+void onlayout(void) {
+ /* calculate and update scroll region */
+ View* view = win_view(EDIT);
+ size_t bend = buf_end(win_buf(EDIT));
+ if (bend == 0) bend = 1;
+ if (!view->rows) return;
+ size_t vbeg = view->rows[0]->off;
+ size_t vend = view->rows[view->nrows-1]->off + view->rows[view->nrows-1]->rlen;
+ double scroll_vis = (double)(vend - vbeg) / (double)bend;
+ double scroll_off = ((double)vbeg / (double)bend);
+ win_setscroll(scroll_off, scroll_vis);
}
void onupdate(void) {
-}
-
-void onlayout(void) {
+ static char buf[8192];
+ long n;
+ if (!fdready(CmdFD)) return;
+ if ((n = read(CmdFD, buf, sizeof(buf))) < 0)
+ die("read() subprocess :");
+ for (long i = 0; i < n;) {
+ Rune rune = 0;
+ size_t length = 0;
+ while (!utf8decode(&rune, &length, buf[i++]));
+ view_insert(win_view(EDIT), false, rune);
+ }
}
void onshutdown(void) {
x11_deinit();
}
-void onerror(char* msg) {
+void onmouseleft(WinRegion id, bool pressed, size_t row, size_t col) {
}
-#ifndef TEST
-#include <unistd.h>
-#include <sys/ioctl.h>
-#ifdef __MACH__
-#include <util.h>
-#else
-#include <pty.h>
-#endif
+void onmousemiddle(WinRegion id, bool pressed, size_t row, size_t col) {
+}
-void spawn_shell(int master, int slave) {
- static char* shell[] = { "/bin/sh", "-l", NULL };
- dup2(slave, 0);
- dup2(slave, 1);
- dup2(slave, 2);
- if (ioctl(slave, TIOCSCTTY, NULL) < 0)
- die("ioctl(TIOSCTTY) failed");
- close(slave);
- close(master);
- execvp(shell[0], shell);
+void onmouseright(WinRegion id, bool pressed, size_t row, size_t col) {
}
-int main(int argc, char** argv) {
- int pid, m, s;
- if (openpty(&m, &s, NULL, NULL, NULL) < 0)
- die("openpty failed: %s\n", strerror(errno));
- if ((pid = fork()))
- die("fork failed");
-
- if (pid == 0) {
- spawn_shell(m, s);
- } else {
- close(s);
- ShellFD = m;
- //signal(SIGCHLD, sigchld);
+static void oninput(Rune rune) {
+ char c = (char)rune;
+ write(CmdFD, &c, 1);
+ view_insert(win_view(FOCUSED), false, rune);
+}
+
+bool update_needed(void) {
+ return fdready(CmdFD);
+}
+
+/******************************************************************************/
+
+bool fdready(int fd) {
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ struct timeval tv = { .tv_usec = 0 };
+ return (select(fd+1, &fds, NULL, NULL, &tv) > 0);
+}
+
+int pty_spawn(char** argv) {
+ int fd;
+ struct termios tio;
+ pid_t pid;
+ putenv("TERM=dumb");
+ switch ( (pid = forkpty(&fd, NULL, NULL, NULL)) ) {
+ case -1: // Failed
+ die("forkpty() :");
+ break;
+
+ case 0: // Child Process
+ if (execvp(argv[0], argv) < 0)
+ die("execvp('%s', ...) :", argv[0]);
+ exit(EXIT_FAILURE);
+ break;
+
+ default: // Parent Process
+ tcgetattr(fd, &tio);
+ tio.c_lflag &= ~(ECHO | ECHONL);
+ tio.c_cc[ VMIN ] = 1;
+ tio.c_cc[ VTIME ] = 0;
+ tcsetattr(fd, TCSANOW, &tio);
+ break;
}
+ return fd;
+}
+/******************************************************************************/
+
+#ifndef TEST
+int main(int argc, char** argv) {
+ if (!ShellCmd[0]) ShellCmd[0] = getenv("SHELL");
+ if (!ShellCmd[0]) ShellCmd[0] = "/bin/sh";
+ CmdFD = pty_spawn(argc > 1 ? argv+1 : ShellCmd);
win_window("term", onerror);
- //win_setkeys(&Bindings);
- //win_setmouse(&MouseHandlers);
+ win_setkeys(NULL, oninput);
+ win_buf(EDIT)->crlf = 1;
win_loop();
-
return 0;
}
#endif
ShellCmd[0] = "/bin/sh";
win_window("edit", ondiagmsg);
XDisplay = XOpenDisplay(NULL);
- win_setkeys(Bindings);
- //win_setmouse(&MouseHandlers);
+ win_setkeys(Bindings, NULL);
}
/* Helper Functions
quit();
}
+bool update_needed(void) {
+ return false;
+}
+
void edit_relative(char* path) {
char *currdir = NULL, *currpath = NULL, *relpath = NULL;
char* origdir = getcurrdir();
cmdrun(OpenCmd, NULL);
}
/* now create the window and start the event loop */
- win_setkeys(Bindings);
+ win_setkeys(Bindings, NULL);
win_loop();
return 0;
}