aboutsummaryrefslogtreecommitdiff
path: root/src/ui.c
diff options
context:
space:
mode:
authortoni <matzeton@googlemail.com>2016-07-04 15:36:07 +0200
committertoni <matzeton@googlemail.com>2016-07-04 15:36:07 +0200
commitcb6047b694a86f78723a613819677227f14e30c3 (patch)
tree4eb9c2f2339c5185fec81447bd832d4d4f0bd3d0 /src/ui.c
parent7248ec097b19828e047e83df89aa7bac4150c2cd (diff)
parentbc30ed7f5624f7d5ccc1e9937ed7bcb7faae9892 (diff)
Merge branch 'master' into jessie
Conflicts: main.c
Diffstat (limited to 'src/ui.c')
-rw-r--r--src/ui.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/src/ui.c b/src/ui.c
new file mode 100644
index 0000000..360f015
--- /dev/null
+++ b/src/ui.c
@@ -0,0 +1,325 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <string.h>
+#include <ncurses.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include "ui.h"
+#include "ui_ipc.h"
+#include "ui_elements.h"
+#include "ui_ani.h"
+#include "ui_input.h"
+#include "ui_statusbar.h"
+#include "ui_txtwindow.h"
+
+#include "status.h"
+#include "config.h"
+
+#define APP_TIMEOUT 60
+#define APP_TIMEOUT_FMT "%02d"
+#define PASSWD_WIDTH 35
+#define PASSWD_HEIGHT 5
+#define PASSWD_XRELPOS (unsigned int)(PASSWD_WIDTH / 2) - (PASSWD_WIDTH / 6)
+#define PASSWD_YRELPOS (unsigned int)(PASSWD_HEIGHT / 2) + 1
+#define INFOWND_WIDTH 25
+#define INFOWND_HEIGHT 3
+#define INFOWND_XRELPOS (unsigned int)(INFOWND_WIDTH / 2) - (INFOWND_WIDTH / 6)
+#define INFOWND_YRELPOS (unsigned int)(INFOWND_HEIGHT / 2) + 1
+
+#define STRLEN(s) (sizeof(s)/sizeof(s[0]))
+
+
+static unsigned int max_x, max_y;
+static unsigned int cur_x, cur_y;
+static WINDOW *wnd_main;
+static struct nask_ui /* simple linked list to all UI objects */ *nui = NULL,
+ /* current active input */ *active = NULL;
+static pthread_t thrd;
+static unsigned int atmout = APP_TIMEOUT;
+static pthread_cond_t cnd_update = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mtx_update = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t mtx_busy = PTHREAD_MUTEX_INITIALIZER;
+
+
+void
+register_ui_elt(struct ui_callbacks *cbs, void *data, WINDOW *wnd)
+{
+ struct nask_ui *tmp, *new;
+
+ new = calloc(1, sizeof(struct nask_ui));
+ new->cbs = *cbs;
+ new->wnd = wnd;
+ new->data = data;
+ new->next = NULL;
+ if (nui == NULL) {
+ nui = new;
+ nui->next = NULL;
+ } else {
+ tmp = nui;
+ while (tmp->next != NULL) {
+ tmp = tmp->next;
+ }
+ tmp->next = new;
+ }
+}
+
+void
+unregister_ui_elt(void *data)
+{
+ struct nask_ui *cur, *next, *before = NULL;
+
+ cur = nui;
+ while (cur != NULL) {
+ next = cur->next;
+ if (cur->data != NULL && cur->data == data) {
+ free(cur);
+ if (before != NULL) {
+ before->next = next;
+ } else {
+ nui = next;
+ }
+ }
+ before = cur;
+ cur = next;
+ }
+}
+
+unsigned int
+ui_get_maxx(void)
+{
+ return max_x;
+}
+
+unsigned int
+ui_get_maxy(void)
+{
+ return max_y;
+}
+
+void
+ui_set_cur(unsigned int x, unsigned int y)
+{
+ cur_x = x;
+ cur_y = y;
+}
+
+unsigned int
+ui_get_curx(void)
+{
+ return (cur_x);
+}
+
+unsigned int
+ui_get_cury(void)
+{
+ return (cur_y);
+}
+
+int
+activate_ui_input(void *data)
+{
+ int ret = DOUI_ERR;
+ struct nask_ui *cur = nui;
+
+ if (cur == NULL || data == NULL) return DOUI_NINIT;
+ while ( cur->data != NULL ) {
+ if ( cur->data == data ) {
+ if ( cur->cbs.ui_input != NULL && cur->cbs.ui_input(cur->wnd, data, UIKEY_ACTIVATE) == DOUI_OK ) {
+ active = cur;
+ ret = DOUI_OK;
+ break;
+ }
+ }
+ cur = cur->next;
+ }
+ return ret;
+}
+
+int
+deactivate_ui_input(void *data)
+{
+ int ret = DOUI_ERR;
+
+ if (active != NULL && data == active->data) {
+ active = NULL;
+ ret = DOUI_OK;
+ }
+ return ret;
+}
+
+static bool
+process_key(char key)
+{
+ bool ret = false;
+
+ if ( active != NULL ) {
+ ret = ( active->cbs.ui_input(active->wnd, active->data, key) == DOUI_OK ? true : false );
+ }
+ return ret;
+}
+
+static int
+do_ui_update(bool timed_out)
+{
+ int retval = UICB_OK;
+ struct nask_ui *cur = nui;
+
+ /* call all draw callback's */
+ erase();
+ if (timed_out == TRUE && atmout > 0) {
+ atmout--;
+ } else if (timed_out == TRUE && atmout == 0) {
+ ui_ipc_semwait(SEM_UI);
+ } else {
+ atmout = APP_TIMEOUT;
+ }
+ while (cur != NULL) {
+ if (cur->cbs.ui_element != NULL) {
+ cur->cbs.ui_element(cur->wnd, cur->data, timed_out);
+ doupdate();
+ } else {
+ retval = UICB_ERR_CB;
+ }
+ cur = cur->next;
+ }
+ /* TODO: Maybe export to an extra module? */
+ attron(COLOR_PAIR(1));
+ mvprintw(0, max_x - STRLEN(APP_TIMEOUT_FMT), "[" APP_TIMEOUT_FMT "]", atmout);
+ attroff(COLOR_PAIR(1));
+ /* EoT (End of Todo) */
+ wmove(wnd_main, cur_y, cur_x);
+ wrefresh(wnd_main);
+ return (retval);
+}
+
+static void *
+ui_thrd(void *arg)
+{
+ int cnd_ret;
+ struct timespec now;
+
+ do_ui_update(true);
+ ui_ipc_sempost(SEM_RD);
+ pthread_mutex_lock(&mtx_update);
+ clock_gettime(CLOCK_REALTIME, &now);
+ now.tv_sec += UILOOP_TIMEOUT;
+ while ( ui_ipc_getvalue(SEM_UI) > 0 ) {
+ cnd_ret = pthread_cond_timedwait(&cnd_update, &mtx_update, &now);
+ pthread_mutex_lock(&mtx_busy);
+ do_ui_update( (cnd_ret == ETIMEDOUT ? true : false) );
+ pthread_mutex_unlock(&mtx_busy);
+ if (cnd_ret == ETIMEDOUT) {
+ clock_gettime(CLOCK_REALTIME, &now);
+ now.tv_sec += UILOOP_TIMEOUT;
+ }
+ }
+ pthread_mutex_unlock(&mtx_update);
+ return (NULL);
+}
+
+void
+ui_thrd_force_update(void)
+{
+ pthread_mutex_lock(&mtx_busy);
+ pthread_cond_signal(&cnd_update);
+ pthread_mutex_unlock(&mtx_busy);
+}
+
+void
+ui_thrd_suspend(void)
+{
+ pthread_mutex_lock(&mtx_busy);
+}
+
+void
+ui_thrd_resume(void)
+{
+ pthread_mutex_unlock(&mtx_busy);
+}
+
+WINDOW *
+init_ui(void)
+{
+ wnd_main = initscr();
+ max_x = getmaxx(wnd_main);
+ max_y = getmaxy(wnd_main);
+ cur_x = getcurx(wnd_main);
+ cur_y = getcury(wnd_main);
+ start_color();
+ init_pair(1, COLOR_RED, COLOR_WHITE);
+ init_pair(2, COLOR_WHITE, COLOR_BLACK);
+ init_pair(3, COLOR_BLACK, COLOR_WHITE);
+ /* TXTwindow */
+ init_pair(4, COLOR_YELLOW, COLOR_RED);
+ init_pair(5, COLOR_WHITE, COLOR_CYAN);
+ /* EoF TXTwindow */
+ raw();
+ keypad(stdscr, TRUE);
+ noecho();
+ nodelay(stdscr, TRUE);
+ cbreak();
+ return (wnd_main);
+}
+
+void
+free_ui(void)
+{
+ delwin(wnd_main);
+ endwin();
+ clear();
+ printf(" \033[2J\n");
+}
+
+static int
+run_ui_thrd(void) {
+ return (pthread_create(&thrd, NULL, &ui_thrd, NULL));
+}
+
+static int
+stop_ui_thrd(void)
+{
+ return (pthread_join(thrd, NULL));
+}
+
+int
+do_ui(void)
+{
+ char key = '\0';
+ int ret = DOUI_ERR;
+
+ /* init TUI and UI Elements (input field, status bar, etc) */
+ init_ui();
+ init_ui_elements(wnd_main, max_x, max_y);
+
+ pthread_mutex_lock(&mtx_update);
+ if (run_ui_thrd() != 0) {
+ return ret;
+ }
+ ui_ipc_semwait(SEM_RD);
+ pthread_mutex_unlock(&mtx_update);
+ wtimeout(stdscr, 500);
+ while ( ui_ipc_getvalue(SEM_UI) > 0 ) {
+ if ((key = wgetch(wnd_main)) == ERR) {
+ continue;
+ }
+ if ( process_key(key) != true ) {
+ raise(SIGTERM);
+ }
+ ui_thrd_force_update();
+ }
+ stop_ui_thrd();
+ free_ui_elements();
+
+ return DOUI_OK;
+}
+