#define INCLUDE_DEFS
#include "config.h"
-/* stub some functions for test so we don't interact with the outside world too much */
-#ifdef TEST
-#define job_start(cmd, data, ndata, dest) \
- ((void)(cmd), (void)(data), (void)(ndata), (void)(dest))
-#define job_run(cmd) \
- ((void)(cmd), 0)
-#define x11_sel_set(x, selid, str) \
- ((void)(x), (void)(selid), (void)(str))
-#define x11_sel_get(x, selid, cbfn) \
- ((void)(x), (void)(selid), (void)(cbfn), 1)
-#endif
-
/* predeclare some things */
static void exec(char* cmd, char* arg);
void cut(char* arg);
void paste(char* arg);
-typedef struct {
+typedef struct
+{
char* tag;
void (*action)(char*);
} Tag;
static int SearchDir = DOWN;
static char* SearchTerm = NULL;
-#define PRESSED(mods, btn) \
- ((mods & (1 << (btn + 7))) == (1 << (btn + 7)))
+static int PRESSED(int mods, int btn)
+{
+ return ((mods & (1 << (btn + 7))) == (1 << (btn + 7)));
+}
/* Crash Dump Handling
******************************************************************************/
-void dumpdata(FILE* f) {
+#ifndef NDEBUG
+static void dumpdata(FILE* f)
+{
fprintf(f, "Focused:\t%d\n", Focused);
fprintf(f, "Divider:\t%d\n", Divider);
fprintf(f, "FontSel:\t%d\n", FontSel);
fprintf(f, "SyncMouse:\t%d\n", SyncMouse);
fprintf(f, "SearchDir:\t%d\n", SearchDir);
fprintf(f, "SearchTerm:\t'%s'\n", SearchTerm);
- for (int i = 0; i < NREGIONS; i++) {
+ for (int i = 0; i < NREGIONS; i++)
+ {
fprintf(f, "Region[%d]:\n", i);
fprintf(f, "\t.sync_flags:\t%d\n", Regions[i].sync_flags);
fprintf(f, "\t.index:\t\t%zu\n", Regions[i].index);
fprintf(f, "\t\t.selcol:\t%zu\n", Regions[i].buffer.selection.col);
}
}
+#endif
/* X11 Window Code
******************************************************************************/
-static void font_load(char* name) {
+static void font_load(char* name)
+{
XftFont* font = x11_font_load(&X, name);
X.font = (font ? font : X.font); // Update if we found a new font
}
-static void get_position(WinRegion id, int x, int y, size_t* row, size_t* col) {
+static void get_position(WinRegion id, int x, int y, size_t* row, size_t* col)
+{
int starty = (id == EDIT ? Divider+3 : 0);
int startx = ScrollWidth+3;
int maxy = (id == EDIT
*col = (startx <= x ? x - startx : 0);
}
-static void tide_send(char* type) {
+static void tide_send(char* type)
+{
XEvent ev;
memset(&ev, 0, sizeof (ev));
Atom xa_registrar = XInternAtom(X.display, "TIDE_REGISTRAR", 0);
Window regwin = XGetSelectionOwner(X.display, xa_registrar);
- if (None != regwin) {
+ if (None != regwin)
+ {
ev.xclient.type = ClientMessage;
ev.xclient.window = X.self;
ev.xclient.message_type = xa_registrar;
}
}
-size_t glyph_width(View* view, int c) {
+size_t glyph_width(View* view, int c)
+{
size_t ret;
FcChar32 rune = (FcChar32)c;
XGlyphInfo extents;
return ret;
}
-static void xkeypress(XConf* x, XEvent* e) {
+static void xkeypress(XConf* x, XEvent* e)
+{
Focused = (e->xkey.y <= Divider ? TAGS : EDIT);
uint32_t key = x11_process_key(x, e, Bindings);
if (key != RUNE_ERR)
size_t row, col;
Focused = (e->xbutton.y <= Divider ? TAGS : EDIT);
get_position(Focused, e->xbutton.x, e->xbutton.y, &row, &col);
- switch (process_mouse(e->xbutton.button, (e->type == ButtonPress))) {
+ switch (process_mouse(e->xbutton.button, (e->type == ButtonPress)))
+ {
case MouseActNone:
break;
case MouseActSel:
case MouseActPaste:
paste(NULL);
break;
- case MouseActExec: {
+ case MouseActExec:
+ {
char* str = view_fetch(win_view(Focused), row, col, riscmd);
if (str) exec(str, NULL);
free(str);
break;
}
- case MouseActExecArg: {
+ case MouseActExecArg:
+ {
/* if we didnt get an arg, find one in the selection */
char* arg = NULL;
if (!arg || !*arg) arg = view_getstr(win_view(EDIT));
free(arg);
break;
}
- case MouseActFetch: {
+ case MouseActFetch:
+ {
FetchCmd[2] = view_fetch(win_view(Focused), row, col, risfile);
- if (job_run(FetchCmd) != 0) {
+ if (job_run(FetchCmd) != 0)
+ {
SearchDir *= (win_keymodsset(ModShift) ? -1 : +1);
free(SearchTerm);
SearchTerm = view_fetch(win_view(Focused), row, col, risfile);
}
}
-static void xbtnmotion(XConf* x, XEvent* e) {
+static void xbtnmotion(XConf* x, XEvent* e)
+{
while (XCheckTypedEvent(x->display, MotionNotify, e));
size_t row, col;
int xpos = e->xbutton.x, ypos = e->xbutton.y;
view_setcursor(win_view(Focused), row, col, true);
}
-static void xclientmsg(XConf* x, XEvent* e) {
+static void xclientmsg(XConf* x, XEvent* e)
+{
if ((Atom)(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))
win_setln(e->xclient.data.l[0]);
}
-void xresize(XConf* x, XEvent* e) {
+void xresize(XConf* x, XEvent* e)
+{
if (e->xconfigure.width != x->width || e->xconfigure.height != x->height)
view_sync(win_view(EDIT));
x11_resize(x, e);
}
-static void xredraw(XConf* x) {
+static void xredraw(XConf* x)
+{
/* force update the title */
win_title(NULL);
draw_scroll(x, &csr, win_view(EDIT), Divider);
XCopyArea(x->display, x->pixmap, x->self, x->gc, 0, 0, x->width, x->height, 0, 0);
SyncMouse = false;
- if (Divider < olddiv && Focused == TAGS) {
+ if (Divider < olddiv && Focused == TAGS)
+ {
int ptrx = 0, ptry = 0;
x11_getptr(x, &ptrx, &ptry);
XWarpPointer(X.display, X.self, X.self, 0, 0, X.width, X.height, ptrx, Divider-2);
XFlush(x->display);
}
-static void xupdate(Job* job) {
+static void xupdate(Job* job)
+{
/* redraw if we have changes or if we have input from a job */
x11_process_events(&X);
if (!job) xredraw(&X);
}
-void win_init(void) {
+void win_init(void)
+{
signal(SIGPIPE, SIG_IGN); // Ignore the SIGPIPE signal
setlocale(LC_CTYPE, "");
XSetLocaleModifiers("");
x11_init(&X);
font_load(Fonts[FontSel = 0]);
X.tagfont = X.font;
- if (!X.font) {
+ if (!X.font)
+ {
perror("unable to load base font");
exit(EXIT_FAILURE);
}
X.eventfns[ConfigureNotify] = xresize;
}
-void win_title(char* path) {
+void win_title(char* path)
+{
static char prevtitle[4096] = {0};
char title[4096] = {0};
if (!path) path = win_view(EDIT)->buffer.path;
memcpy(prevtitle, title, sizeof(title));
}
-void win_font(char* font) {
+void win_font(char* font)
+{
font_load(font ? font : Fonts[++FontSel % nelem(Fonts)]);
}
-void win_prop_set(char* xname, char* ename, char* value) {
+void win_prop_set(char* xname, char* ename, char* value)
+{
if (!value) return;
Atom propname = XInternAtom(X.display, xname, 0);
XChangeProperty(X.display, X.self, propname, XA_STRING, 8, PropModeReplace,
if (ename) setenv(ename, value, 1);
}
-void win_loop(void) {
+void win_loop(void)
+{
tide_send("ADD");
job_spawn(ConnectionNumber(X.display), xupdate, 0, 0);
XSync(X.display, False);
int maxcount = 1000 / Timeout;
int count = 0;
- while (X.running) {
+ while (X.running)
+ {
dbc_wdtkick();
bool ready = job_poll(Timeout);
count += (ready ? -count : 1);
}
}
-void win_quit(void) {
+void win_quit(void)
+{
static uint64_t before = 0;
- if ((win_buf(EDIT)->status != MODIFIED) || (X.now - before) <= (uint64_t)ClickTime) {
+ if ((win_buf(EDIT)->status != MODIFIED) || (X.now - before) <= (uint64_t)ClickTime)
+ {
tide_send("DEL");
X.eventfns[SelectionClear] = x11_sel_quit;
XUnmapWindow(X.display, X.self);
- if (!x11_sel_ready(&X)) {
+ if (!x11_sel_ready(&X))
+ {
X.running = False;
- } else {
+ }
+ else
+ {
if (fork()) exit(0); /* fork into background if we still have selection */
}
before = X.now;
}
-void win_togglefocus(void) {
+void win_togglefocus(void)
+{
int ypos = (Focused == EDIT ? Divider/2 : (X.height - ((X.height-Divider) / 2)));
XWarpPointer(X.display, X.self, X.self, 0, 0, X.width, X.height, X.width/2, ypos);
}
-View* win_view(WinRegion id) {
+View* win_view(WinRegion id)
+{
return &(Regions[id == FOCUSED ? Focused : id]);
}
-Buf* win_buf(WinRegion id) {
+Buf* win_buf(WinRegion id)
+{
return &(Regions[id == FOCUSED ? Focused : id].buffer);
}
-bool win_keymodsset(int mask) {
+bool win_keymodsset(int mask)
+{
return ((X.mods & mask) == mask);
}
-void win_setln(int line_num) {
+void win_setln(int line_num)
+{
view_setln(win_view(EDIT), line_num);
SyncMouse = true;
}
/* Tag/Cmd Execution
******************************************************************************/
-static Tag* tag_lookup(char* cmd) {
+static Tag* tag_lookup(char* cmd)
+{
size_t len = 0;
Tag* tags = Builtins;
return (tags->tag ? tags : NULL);
}
-static void cmd_exec(char* cmd) {
+static void cmd_exec(char* cmd)
+{
/* parse the command sigils */
char op = '\0', **execcmd = NULL;
if (rissigil(*cmd)) op = *(cmd++);
job_start(execcmd, input, len, (op != '<' ? curr : edit));
}
-static void exec(char* cmd, char* arg) {
+static void exec(char* cmd, char* arg)
+{
/* skip leading space */
for (; *cmd && isspace(*cmd); cmd++);
if (!*cmd) return;
/* see if it matches a builtin tag */
Tag* tag = tag_lookup(cmd);
- if (tag) {
+ if (tag)
+ {
for (; *cmd && !isspace(*cmd); cmd++); /* strip off tag name */
for (; *cmd && isspace(*cmd); cmd++); /* strip off leading space */
arg = (*cmd ? strdup(cmd) : arg);
tag->action(!arg || !*arg ? NULL : arg);
- } else if (arg) {
+ }
+ else if (arg)
+ {
cmd = (arg ? strmcat(cmd, " '", arg, "'", 0) : strmcat(cmd));
cmd_exec(cmd);
free(cmd);
- } else {
+ }
+ else
+ {
cmd_exec(cmd);
}
}
/* Keyboard and Tag Handlers
******************************************************************************/
-static void change_focus(char* arg) {
+static void change_focus(char* arg)
+{
(void)arg;
win_togglefocus();
}
-static void quit(char* arg) {
+static void quit(char* arg)
+{
(void)arg;
win_quit();
}
-static void put(char* arg) {
+static void put(char* arg)
+{
Buf* buf = win_buf(EDIT);
- if (buf_save(buf, arg) == NORMAL) {
+ if (buf_save(buf, arg) == NORMAL)
+ {
/* convert saved path to absolute path */
char* path = realpath(buf->path, NULL);
buf_setpath(buf, path);
win_prop_set("FILE", "file", path);
}
-static void get(char* arg) {
+static void get(char* arg)
+{
if (arg)
view_init(win_view(EDIT), arg);
else
view_reload(win_view(EDIT));
}
-static void tag_undo(char* arg) {
+static void tag_undo(char* arg)
+{
(void)arg;
view_undo(win_view(EDIT));
}
-static void tag_redo(char* arg) {
+static void tag_redo(char* arg)
+{
(void)arg;
view_redo(win_view(EDIT));
}
-static void search(char* arg) {
+static void search(char* arg)
+{
(void)arg;
char* str;
SearchDir *= (win_keymodsset(ModShift) ? UP : DOWN);
SearchTerm = str;
}
-static void execute(char* arg) {
+static void execute(char* arg)
+{
(void)arg;
char* str = view_getcmd(win_view(FOCUSED));
if (str) exec(str, NULL);
free(str);
}
-static void find(char* arg) {
+static void find(char* arg)
+{
SearchDir *= (win_keymodsset(ModShift) ? UP : DOWN);
view_findstr(win_view(EDIT), SearchDir, arg);
}
-static void open_file(char* arg) {
+static void open_file(char* arg)
+{
(void)arg;
cmd_exec(CMD_PICKFILE);
}
-static void pick_symbol(char* symbol) {
+static void pick_symbol(char* symbol)
+{
exec(CMD_GOTO_TAG, symbol);
}
-static void pick_ctag(char* arg) {
+static void pick_ctag(char* arg)
+{
(void)arg;
pick_symbol(NULL);
}
-static void complete(char* arg) {
+static void complete(char* arg)
+{
(void)arg;
View* view = win_view(FOCUSED);
view_selectobj(view, risword);
exec(CMD_COMPLETE, view_getstr(view));
}
-static void fcomplete(char* arg) {
+static void fcomplete(char* arg)
+{
(void)arg;
View* view = win_view(FOCUSED);
view_selectobj(view, risfile);
exec(CMD_FCOMPLETE, view_getstr(view));
}
-static void jump_to(char* arg) {
- if (arg) {
+static void jump_to(char* arg)
+{
+ if (arg)
+ {
size_t line = strtoul(arg, NULL, 0);
if (line)
win_setln(line);
}
}
-static void goto_ctag(char* arg) {
+static void goto_ctag(char* arg)
+{
(void)arg;
char* str = view_getctx(win_view(FOCUSED));
jump_to(str);
free(str);
}
-static void tabs(char* arg) {
+static void tabs(char* arg)
+{
(void)arg;
ExpandTabs = !ExpandTabs;
}
-static void indent(char* arg) {
+static void indent(char* arg)
+{
(void)arg;
CopyIndent = !CopyIndent;
}
-static void eol_mode(char* arg) {
+static void eol_mode(char* arg)
+{
(void)arg;
DosLineFeed = !DosLineFeed;
View* view = win_view(EDIT);
free(txt);
}
-static void new_win(char* arg) {
+static void new_win(char* arg)
+{
(void)arg;
cmd_exec(CMD_TIDE);
}
-static void lnexec(char* cmd) {
+static void lnexec(char* cmd)
+{
select_line(NULL);
exec(cmd, NULL);
}
-static void tag_kill(char* cmd) {
+static void tag_kill(char* cmd)
+{
(void)cmd;
Job* job = job_list();
if (job && job->fd != ConnectionNumber(X.display))
job_kill(job);
}
-static void tag_line(char* cmd) {
+static void tag_line(char* cmd)
+{
(void)cmd;
char buf[256] = {0};
size_t lnbeg = 1, lnend = 1;
};
#ifndef TEST
-static void usage(void) {
+static void usage(void)
+{
printf(
"Usage: %s [FLAGS] [FILE]\n"
"\n -I 0,1 Enable/disable automatic indenting"
exit(1);
}
-int main(int argc, char** argv) {
+int main(int argc, char** argv)
+{
long int line_num = 0;
#define BOOLARG() (EOPTARG(usage()), optarg_[0] == '0' ? 0 : 1)
#define STRARG() (EOPTARG(usage()))
#define NUMARG() (strtoul(EOPTARG(usage()),0,0))
- OPTBEGIN {
+ OPTBEGIN
+ {
case 'I': CopyIndent = BOOLARG(); break;
case 'W': TrimOnSave = BOOLARG(); break;
case 'E': ExpandTabs = BOOLARG(); break;
case 'C': ShellCmd[0] = STRARG(); break;
case 'l': line_num = NUMARG(); break;
default: usage(); break;
- } OPTEND;
+ }
+ OPTEND;
/* setup the shell */
if (!ShellCmd[0]) ShellCmd[0] = getenv("SHELL");
if (!ShellCmd[0]) ShellCmd[0] = "/bin/sh";
+ require(ShellCmd[0]);
/* Initialize the window and views */
win_init();
dbc_init(NULL, dumpdata);
/* if we still have args left we're going to open it in this instance */
- if (*argv) {
+ if (*argv)
+ {
char* path = realpath(*argv, NULL);
if (!path) path = strdup(*argv); /* if file doesnt exist, use the original name */
- if (!strcmp("-", path)) {
+ if (!strcmp("-", path))
+ {
job_readfd(STDIN_FILENO, win_view(EDIT));
- } else {
+ }
+ else
+ {
view_init(win_view(EDIT), path);
win_setln(line_num);
win_title(path);
/* check if we should embed in a parent */
char* winid = getenv("TIDE_PARENT");
- if (winid) {
+ if (winid)
+ {
XReparentWindow(X.display, X.self, strtoul(winid, 0, 0), 0, 0);
XFlush(X.display);
}