]> Pileus Git - lackey/blobdiff - src/view.c
Add option to show and hide weekends.
[lackey] / src / view.c
index 8341e97aa7433a428aefec70f5246b152937a837..a66fb853dcfe17ae59af7305744dab1f0754cb6d 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define _XOPEN_SOURCE
 #define _XOPEN_SOURCE_EXTENDED
 
+#include <stdlib.h>
 #include <string.h>
+#include <locale.h>
 #include <ncurses.h>
 
 #include "util.h"
@@ -82,15 +85,18 @@ view_t *menu[] = {
 };
 
 /* Config data */
-int COMPACT = 0;
+int COMPACT  = 0;
+int MORNING  = 8;
+int WEEKENDS = 0;
 
 /* Global data */
 edit_t EDIT = EDIT_NONE;
 
 /* Local data */
-view_t *view   = &day_view;
-view_t *active = &day_view;
-view_t *popup  = NULL;
+view_t *view    = &day_view;
+view_t *active  = &day_view;
+view_t *popup   = NULL;
+int     running = 0;
 
 /* Local functions */
 static void draw_header(void)
@@ -136,21 +142,102 @@ static int get_color(const char *cat)
               match(cat, "work")  ? COLOR_WORK  : COLOR_OTHER ;
 }
 
+static void update_sizes(void)
+{
+       int hdr = COMPACT ? 1 : 2;
+       for (int i = 0; i < N_ELEMENTS(views); i++) {
+               wresize(views[i]->win, LINES-hdr, COLS);
+               mvwin(views[i]->win, hdr, 0);
+               views[i]->size(LINES-hdr, COLS);
+       }
+}
+
+static void draw_view(void)
+{
+       draw_header();
+       werase(view->win);
+       view->draw();
+       wrefresh(view->win);
+}
+
 static int set_view(view_t *_active, view_t *_popup)
 {
        view = _popup ?: _active;
        if (active != _active) {
                active = _active;
                set_string("view", 0, "active", active->name);
-               view_draw();
+               draw_view();
        }
        if (popup != _popup) {
                popup = _popup;
-               view_draw();
+               draw_view();
        }
        return 1;
 }
 
+static int process(int key, mmask_t btn, int row, int col)
+{
+       /* Refresh timestamp */
+       draw_header();
+
+       /* Check for mouse events on the menu */
+       if (key == KEY_MOUSE && row == 0) {
+               int start = 1;
+               for (int i = 0; i < N_ELEMENTS(menu); i++) {
+                       int end = start + strlen(menu[i]->name) - 1;
+                       if (start <= col && col <= end && menu[i]->draw)
+                               return set_view(menu[i], NULL);
+                       start = end + 2;
+               }
+       }
+
+       /* Look though menu for hotkeys */
+       for (int i = 0; i < N_ELEMENTS(menu); i++) {
+               for (int j = 0; j < N_ELEMENTS(menu[i]->keys); j++)
+                       if (menu[i]->keys[j] == key)
+                               return set_view(menu[i], NULL);
+       }
+
+       /* Shift windows with left/right keys */
+       int shift = key == KEY_RIGHT ? +1 :
+                   key == KEY_LEFT  ? -1 : 0;
+       if (shift) {
+               int num = 0;
+               for (int i = 0; i < N_ELEMENTS(menu); i++)
+                       if (menu[i] == active)
+                               num = i;
+               do  {
+                       num += shift;
+                       num += N_ELEMENTS(menu);
+                       num %= N_ELEMENTS(menu);
+               } while (menu[num] == &spacer);
+               return set_view(menu[num], NULL);
+       }
+
+       /* Handle other keys */
+       switch (key) {
+               case KEY_RESIZE:
+                       endwin();
+                       refresh();
+                       update_sizes();
+                       draw_view();
+                       return 1;
+               case '\14': // Ctrl-L
+                       clear();
+               case '\7':  // Ctrl-G
+                       update_sizes();
+                       draw_view();
+                       return 1;
+               case '\033': // escape
+                       return set_view(active, NULL);
+               case '?':    // help
+                       return set_view(active, &help_view);
+       }
+
+       /* Pass key to active view */
+       return view->run(key, btn, row, col);
+}
+
 /* Curses functions */
 void wmvresize(WINDOW *win, int top, int left, int rows, int cols)
 {
@@ -177,7 +264,7 @@ void wshrink(WINDOW *win, int top)
 /* Helper functions */
 void event_box(WINDOW *win, event_t *event, int y, int x, int h, int w)
 {
-       int l = 0;
+       int i, l = 0;
        int s = y < 0 ? -y-1 : 0;
 
        int color = get_color(event->cat);
@@ -194,11 +281,18 @@ void event_box(WINDOW *win, event_t *event, int y, int x, int h, int w)
        if (h >= 2) mvwadd_wch(win,   y+h-1, x+w-1, WACS_T_LRCORNER);
        if (h >= 2) mvwhline_set(win, y+h-1, x+1,   WACS_T_HLINE, w-2);
 
+       for (i = 1; i < h-1; i++)
+               mvwhline(win, y+i, x+1, ' ', w-2);
+
        if (color) wattroff(win, COLOR_PAIR(color));
 
+       if (event == EVENT)     wattron(win, WA_BOLD | WA_REVERSE);
+       if (event == EVENT)     mvwhline(win, y+s, x, ' ', w);
        if (l<h && event->name) mvwprintw(win, y+l++, x+1, "%.*s",   w-2, event->name);
+       if (event == EVENT)     wattroff(win, WA_REVERSE);
        if (l<h && event->loc)  mvwprintw(win, y+l++, x+1, "@ %.*s", w-4, event->loc);
        if (l<h && event->desc) mvwprintw(win, y+l++, x+1, "%.*s",   w-2, event->desc);
+       if (event == EVENT)     wattroff(win, WA_BOLD);
 }
 
 void event_line(WINDOW *win, event_t *event, int y, int x, int w, int flags)
@@ -285,8 +379,39 @@ void todo_line(WINDOW *win, todo_t *todo, int y, int x, int w, int flags)
 /* View init */
 void view_init(void)
 {
-       int hdr = COMPACT ? 1 : 2;
+       /* Set default escape timeout */
+       if (!getenv("ESCDELAY"))
+               putenv("ESCDELAY=25");
+
+       /* Setup Curses */
+       setlocale(LC_ALL, "");
+       initscr();
+       cbreak();
+       noecho();
+       keypad(stdscr, TRUE);
+       start_color();
+       curs_set(false);
+       timeout(100);
+       use_default_colors();
+       mousemask(ALL_MOUSE_EVENTS, NULL);
+
+       init_pair(COLOR_TITLE, COLOR_GREEN,   -1);
+       init_pair(COLOR_ERROR, COLOR_RED,     -1);
+
+       init_pair(COLOR_NEW,   COLOR_RED,     -1);
+       init_pair(COLOR_WIP,   COLOR_YELLOW,  -1);
+       init_pair(COLOR_DONE,  COLOR_GREEN,   -1);
+
+       init_pair(COLOR_CLASS, COLOR_BLUE,    -1);
+       init_pair(COLOR_EC,    COLOR_GREEN,   -1);
+       init_pair(COLOR_WORK,  COLOR_MAGENTA, -1);
+       init_pair(COLOR_OTHER, COLOR_RED,     -1);
+
+       running = 1;
+
+       /* Setup windows */
        for (int i = 0; i < N_ELEMENTS(views); i++) {
+               int hdr = COMPACT ? 1 : 2;
                views[i]->win = newwin(LINES-hdr, COLS, hdr, 0);
                views[i]->init(views[i]->win);
                views[i]->size(LINES-hdr, COLS);
@@ -299,6 +424,10 @@ void view_config(const char *group, const char *name, const char *key, const cha
        if (match(group, "view")) {
                if (match(key, "compact")) {
                        COMPACT = get_bool(value);
+               } else if (match(key, "morning")) {
+                       MORNING = get_number(value);
+               } else if (match(key, "weekends")) {
+                       WEEKENDS = get_bool(value);
                } else if (match(key, "active")) {
                        for (int i = 0; i < N_ELEMENTS(views); i++) {
                                if (match(value, views[i]->name)) {
@@ -311,89 +440,58 @@ void view_config(const char *group, const char *name, const char *key, const cha
        }
 }
 
-/* View draw */
-void view_resize(void)
-{
-       int hdr = COMPACT ? 1 : 2;
-       for (int i = 0; i < N_ELEMENTS(views); i++) {
-               wresize(views[i]->win, LINES-hdr, COLS);
-               mvwin(views[i]->win, hdr, 0);
-               views[i]->size(LINES-hdr, COLS);
-       }
-}
-
-/* View draw */
-void view_draw(void)
+/* View event */
+void view_edit(edit_t mode)
 {
-       draw_header();
-       werase(view->win);
-       view->draw();
-       wrefresh(view->win);
+       EDIT = mode;
+       set_view(active, &edit_view);
 }
 
-/* View run */
-int view_run(int key, mmask_t btn, int row, int col)
+void view_main(void)
 {
-       /* Refresh timestamp */
-       draw_header();
-
-       /* Check for mouse events on the menu */
-       if (key == KEY_MOUSE && row == 0) {
-               int start = 1;
-               for (int i = 0; i < N_ELEMENTS(menu); i++) {
-                       int end = start + strlen(menu[i]->name) - 1;
-                       if (start <= col && col <= end && menu[i]->draw)
-                               return set_view(menu[i], NULL);
-                       start = end + 2;
-               }
+       /* Draw initial view */
+       draw_view();
+
+       /* Run */
+       while (1) {
+               MEVENT btn;
+               conf_sync();
+               int chr = getch();
+               date_sync();
+               if (chr == KEY_MOUSE)
+                       if (getmouse(&btn) != OK)
+                               continue;
+               if (process(chr, btn.bstate, btn.y, btn.x))
+                       continue;
+               if (chr == ERR) // timeout
+                       continue;
+               if (chr == 'q')
+                       break;
+               debug("main: Unhandled key - Dec %3d,  Hex %02x,  Oct %03o,  Chr <%c>",
+                               chr, chr, chr, chr);
        }
 
-       /* Look though menu for hotkeys */
-       for (int i = 0; i < N_ELEMENTS(menu); i++) {
-               for (int j = 0; j < N_ELEMENTS(menu[i]->keys); j++)
-                       if (menu[i]->keys[j] == key)
-                               return set_view(menu[i], NULL);
-       }
-
-       /* Shift windows with left/right keys */
-       int shift = key == KEY_RIGHT ? +1 :
-                   key == KEY_LEFT  ? -1 : 0;
-       if (shift) {
-               int num = 0;
-               for (int i = 0; i < N_ELEMENTS(menu); i++)
-                       if (menu[i] == active)
-                               num = i;
-               do  {
-                       num += shift;
-                       num += N_ELEMENTS(menu);
-                       num %= N_ELEMENTS(menu);
-               } while (menu[num] == &spacer);
-               return set_view(menu[num], NULL);
-       }
-
-       /* Handle other keys */
-       switch (key) {
-               case 'c':
-                       COMPACT ^= 1;
-                       set_bool("view", 0, "compact", COMPACT);
-                       view_resize();
-                       view_draw();
-                       return 1;
-               case '\033': // escape
-                       return set_view(active, NULL);
-               case '?':    // help
-                       return set_view(active, &help_view);
-               case 'e':    // edit
-                       return set_view(active, &edit_view);
-       }
+       /* Cleanup window */
+       view_exit();
+}
 
-       /* Pass key to active view */
-       return view->run(key, btn, row, col);
+void view_exit(void)
+{
+       if (running)
+               endwin();
 }
 
-/* View event */
-void view_edit(edit_t mode)
+void view_debug(const char *fmt, va_list ap)
 {
-       EDIT = mode;
-       set_view(active, &edit_view);
+       if (running) {
+               int rev = COMPACT ? A_BOLD : 0;
+               if (!COMPACT)
+                       mvhline(LINES-2, 0, ACS_HLINE, COLS);
+               move(LINES-1, 0);
+               attron(COLOR_PAIR(COLOR_ERROR) | rev);
+               vwprintw(stdscr, fmt, ap);
+               attroff(COLOR_PAIR(COLOR_ERROR) | rev);
+               if (!COMPACT)
+                       clrtoeol();
+       }
 }