2 * Copyright (C) 2012-2013 Andy Spencer <andy753421@gmail.com>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #define _XOPEN_SOURCE_EXTENDED
28 #include <sys/signalfd.h>
37 #define KEY_CTRL_G '\7'
38 #define KEY_CTRL_L '\14'
39 #define KEY_RETURN '\12'
40 #define KEY_ESCAPE '\33'
43 static poll_t poll_in;
44 static poll_t poll_sig;
48 static char cmd_buf[512];
52 static char *channel = "#rhtest";
55 static void print_word(char **msg, int *row, int *col, int indent, int print)
58 while (*start && isspace(*start))
62 while (*end && !isspace(*end))
67 if ((*col != indent) && (*col + 1 + len > COLS)) {
72 if (*row < 1 || *row > LINES-2)
77 mvaddch(*row, *col, ' ');
81 mvaddnstr(*row, *col, start, len);
85 static void print_msg(log_t *log, int *row, int print)
90 int col = 0, indent = 0;
91 time_t timep = log->when;
92 struct tm *tm = localtime(&timep);
94 if (log->channel && log->from)
95 snprintf(buf, sizeof(buf), "%02d:%02d [%s] %s: ",
96 tm->tm_hour, tm->tm_min,
97 log->channel, log->from);
98 else if (log->channel)
99 snprintf(buf, sizeof(buf), "%02d:%02d [%s] *** ",
100 tm->tm_hour, tm->tm_min, log->channel);
102 snprintf(buf, sizeof(buf), "%02d:%02d *** %s: ",
103 tm->tm_hour, tm->tm_min, log->from);
105 snprintf(buf, sizeof(buf), "%02d:%02d *** ",
106 tm->tm_hour, tm->tm_min);
110 print_word(&hdr, row, &col, indent, print);
113 print_word(&msg, row, &col, indent, print);
118 /* Drawing functions */
119 void draw_header(void)
121 attron(COLOR_PAIR(COLOR_TITLE) | A_REVERSE);
124 printw("%-*s", COLS, "Header Bar");
125 attroff(COLOR_PAIR(COLOR_TITLE) | A_REVERSE);
132 int log = chat_len-1;
135 for (int i = 1; i < LINES-2; i++) {
141 while (row < space && log >= 0)
142 print_msg(&chat_log[log--], &row, 0);
144 /* Compute skip lines */
145 row = 1 + (space - row);
149 while (row <= space && log < chat_len)
150 print_msg(&chat_log[log++], &row, 1);
153 void draw_status(void)
155 attron(COLOR_PAIR(COLOR_TITLE) | A_REVERSE);
158 printw("%-*s", COLS, "Status Bar");
159 attroff(COLOR_PAIR(COLOR_TITLE) | A_REVERSE);
162 void draw_cmdline(void)
166 printw("[%s] %.*s", channel, cmd_len, cmd_buf);
167 move(LINES-1, 1 + strlen(channel) + 2 + cmd_pos);
173 /* Set default escape timeout */
174 if (!getenv("ESCDELAY"))
175 putenv("ESCDELAY=25");
178 setlocale(LC_ALL, "");
182 keypad(stdscr, TRUE);
185 use_default_colors();
186 mousemask(ALL_MOUSE_EVENTS, NULL);
188 init_pair(COLOR_TITLE, COLOR_BLUE, -1);
189 init_pair(COLOR_ERROR, COLOR_RED, -1);
191 /* Create signal FD */
194 sigaddset(&mask, SIGWINCH);
195 if ((sig_fd = signalfd(-1, &mask, SFD_CLOEXEC)) < 0)
196 error("creating signal fd");
198 /* Register callback */
199 poll_add(&poll_in, 0, (cb_t)view_sync, NULL);
200 poll_ctl(&poll_in, 1, 0, 1);
202 poll_add(&poll_sig, sig_fd, (cb_t)view_sync, NULL);
203 poll_ctl(&poll_sig, 1, 0, 1);
208 /* Draw initial view */
214 void view_config(const char *group, const char *name, const char *key, const char *value)
228 if (chr == KEY_MOUSE) {
229 if (getmouse(&btn) != OK)
233 /* Window management */
234 if (chr == KEY_RESIZE) {
238 else if (chr == KEY_CTRL_L) {
242 else if (chr == KEY_CTRL_G) {
247 else if (chr == KEY_RETURN) {
248 cmd_buf[cmd_len] = '\0';
251 chat_send(channel, cmd_buf);
255 else if (chr == KEY_ESCAPE) {
260 else if (chr == KEY_LEFT) {
265 else if (chr == KEY_RIGHT) {
266 if (cmd_pos < cmd_len)
270 else if (chr == KEY_BACKSPACE) {
272 memmove(&cmd_buf[cmd_pos-1],
274 (cmd_len-cmd_pos)+1);
280 else if (chr == KEY_DC) {
281 if (cmd_pos < cmd_len) {
282 memmove(&cmd_buf[cmd_pos],
284 (cmd_len-cmd_pos)+1);
289 else if (isprint(chr)) {
290 if (cmd_len+2 < sizeof(cmd_buf)) {
291 memmove(&cmd_buf[cmd_pos+1],
293 (cmd_len-cmd_pos)+1);
294 cmd_buf[cmd_pos] = chr;
299 debug("form: out of space");
303 /* Unknown control character */
305 debug("main: Unhandled key - Dec %3d, Hex %02x, Oct %03o, Chr <%c>",
309 /* Flush output to screen */