]> Pileus Git - lackey/blobdiff - src/view.c
Move main loop and curses init to view
[lackey] / src / view.c
index 7c62671f32d4631ae8957c27737d3bb18bf2baef..ceb9fec7328019bc154f067645e234fea3d68d80 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"
@@ -89,9 +92,10 @@ int MORNING = 8;
 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)
@@ -137,21 +141,110 @@ 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);
+               case 'c':
+                       COMPACT ^= 1;
+                       set_bool("view", 0, "compact", COMPACT);
+                       update_sizes();
+                       draw_view();
+                       return 1;
+               case 'e':    // edit
+                       return set_view(active, &edit_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)
 {
@@ -293,8 +386,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);
@@ -321,89 +445,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;
-               }
-       }
-
-       /* 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);
+       /* 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);
        }
 
-       /* 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();
+       }
 }