comparison ui.c @ 501:ca88945d8eda

Begin work on integrating the removal of ncurses "windowing" and transition to internally managing the screen as whole.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 01 Jun 2012 12:00:11 +0300
parents 012f106bf290
children bac3f9af112c
comparison
equal deleted inserted replaced
500:78447d70f9d3 501:ca88945d8eda
4 * (C) Copyright 2008-2012 Tecnic Software productions (TNSP) 4 * (C) Copyright 2008-2012 Tecnic Software productions (TNSP)
5 */ 5 */
6 #include "util.h" 6 #include "util.h"
7 #include "ui.h" 7 #include "ui.h"
8 8
9 #define STATUS_YPOS 0
10
9 nn_window_t *chatWindows[SET_MAX_WINDOWS], 11 nn_window_t *chatWindows[SET_MAX_WINDOWS],
10 *currWin = NULL; 12 *currWin = NULL;
11 13
12 BOOL cursesInit = FALSE; 14 BOOL cursesInit = FALSE;
13 int cursorVisible = ERR; 15 int cursorVisible = ERR,
14 WINDOW *mainWin = NULL, 16 scrWidth, scrHeight;
15 *statusWin = NULL,
16 *editWin = NULL;
17 17
18 18
19 static nn_window_t *nn_window_new(const char *id) 19 static nn_window_t *nn_window_new(const char *id)
20 { 20 {
21 nn_window_t *res = th_calloc(1, sizeof(nn_window_t)); 21 nn_window_t *res = th_calloc(1, sizeof(nn_window_t));
61 } 61 }
62 62
63 63
64 BOOL nnwin_init(int delay) 64 BOOL nnwin_init(int delay)
65 { 65 {
66 // Sanity check the terminal size
66 if (LINES < 0 || LINES > 1000) LINES = 24; 67 if (LINES < 0 || LINES > 1000) LINES = 24;
67 if (COLS < 0 || COLS > 1000) COLS = 80; 68 if (COLS < 0 || COLS > 1000) COLS = 80;
68 69
70 // Initialize (n)curses library and terminal settings
69 initscr(); 71 initscr();
70 raw(); 72 raw();
71 keypad(stdscr, TRUE); 73 keypad(stdscr, TRUE);
72 noecho(); 74 noecho();
73 meta(stdscr, TRUE); 75 meta(stdscr, TRUE);
74 timeout(delay); 76 timeout(delay);
75 cursorVisible = curs_set(0); 77 scrollok(stdscr, FALSE);
78 cursorVisible = curs_set(1);
76 79
77 if (has_colors()) 80 if (has_colors())
78 { 81 {
79 start_color(); 82 start_color();
80 83
95 init_pair(15, COLOR_MAGENTA, COLOR_RED); 98 init_pair(15, COLOR_MAGENTA, COLOR_RED);
96 init_pair(16, COLOR_CYAN, COLOR_RED); 99 init_pair(16, COLOR_CYAN, COLOR_RED);
97 } 100 }
98 101
99 cursesInit = TRUE; 102 cursesInit = TRUE;
100 103 nnwin_reset();
101 if (!nnwin_init_windows())
102 return FALSE;
103 104
104 #ifdef PDCURSES 105 #ifdef PDCURSES
105 PDC_set_title("NNChat v" NN_VERSION); 106 PDC_set_title("NNChat v" NN_VERSION);
106 #endif 107 #endif
107 108
123 if (cursesInit) 124 if (cursesInit)
124 { 125 {
125 if (cursorVisible != ERR) 126 if (cursorVisible != ERR)
126 curs_set(cursorVisible); 127 curs_set(cursorVisible);
127 128
128 nnwin_close_windows();
129
130 endwin(); 129 endwin();
131 THMSG(1, "NCurses deinitialized.\n"); 130 THMSG(1, "NCurses deinitialized.\n");
132 } 131 }
132 }
133
134
135 void nnwin_reset(void)
136 {
137 getmaxyx(stdscr, scrHeight, scrWidth);
133 } 138 }
134 139
135 140
136 nn_window_t *nnwin_find(const char *id) 141 nn_window_t *nnwin_find(const char *id)
137 { 142 {
177 { 182 {
178 int i; 183 int i;
179 if (win == NULL) return; 184 if (win == NULL) return;
180 185
181 for (i = 1; i < SET_MAX_WINDOWS; i++) 186 for (i = 1; i < SET_MAX_WINDOWS; i++)
187 {
182 if (chatWindows[i] == win) 188 if (chatWindows[i] == win)
183 { 189 {
184 chatWindows[i] = NULL; 190 chatWindows[i] = NULL;
185 nn_window_free(win); 191 nn_window_free(win);
186 return; 192 return;
187 } 193 }
188 } 194 }
189 195 }
190 196
191 void nnwin_update_statusline(char *optUserName, int optUserColor) 197
192 { 198 #define QPUTCH(ch) th_vputch(&(win->line->buf), &(win->line->bufsize), &(win->line->len), ch)
193 char tmpStr[128]; 199
194 int i; 200 int nnwin_print(nn_window_t *win, const char *fmt)
195
196 if (statusWin == NULL) return;
197
198 str_get_timestamp(tmpStr, sizeof(tmpStr), "%H:%M:%S");
199
200 wbkgdset(statusWin, COLOR_PAIR(10));
201 werase(statusWin);
202
203 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
204 mvwaddstr(statusWin, 0, 1, tmpStr);
205
206 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
207 waddstr(statusWin, " | ");
208 wattrset(statusWin, A_BOLD | COLOR_PAIR(16));
209 waddstr(statusWin, optUserName);
210 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
211
212 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
213 waddstr(statusWin, " | ");
214 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
215 snprintf(tmpStr, sizeof(tmpStr), "#%06x", optUserColor);
216 waddstr(statusWin, tmpStr);
217
218 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
219 waddstr(statusWin, " | WIN: ");
220 snprintf(tmpStr, sizeof(tmpStr), "%d: %s / %d",
221 currWin->num + 1,
222 currWin->id != NULL ? currWin->id : "MAIN",
223 currWin->pos);
224 waddstr(statusWin, tmpStr);
225
226 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
227 waddstr(statusWin, " | ");
228 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
229
230 for (i = 0; i < SET_MAX_WINDOWS; i++)
231 {
232 if (chatWindows[i] != NULL && chatWindows[i]->dirty)
233 {
234 snprintf(tmpStr, sizeof(tmpStr), "%d ", i + 1);
235 waddstr(statusWin, tmpStr);
236 }
237 }
238
239 wrefresh(statusWin);
240 }
241
242
243 void nnwin_update_editbuf(nn_editbuf_t *buf)
244 {
245 char *tmp;
246 if (editWin == NULL || buf == NULL || !buf->dirty)
247 return;
248
249 buf->dirty = FALSE;
250 buf->data[buf->len] = 0;
251 tmp = nn_username_decode(th_strdup(buf->data));
252
253 werase(editWin);
254
255 wattrset(editWin, A_NORMAL);
256
257 if (buf->pos < buf->len)
258 {
259 waddnstr(editWin, tmp, buf->pos);
260 wattrset(editWin, A_REVERSE);
261 waddch(editWin, tmp[buf->pos]);
262 wattrset(editWin, A_NORMAL);
263 waddnstr(editWin, tmp + buf->pos + 1, buf->len - buf->pos - 1);
264 }
265 else
266 {
267 waddnstr(editWin, tmp, buf->len);
268 wattrset(editWin, A_REVERSE);
269 waddch(editWin, ' ');
270 wattrset(editWin, A_NORMAL);
271 }
272 wrefresh(editWin);
273 th_free(tmp);
274 }
275
276
277 int nnwin_print(WINDOW *win, const char *fmt)
278 { 201 {
279 const char *s = fmt; 202 const char *s = fmt;
280 int col = 0; 203 int col = 0;
281 204
282 while (*s) 205 while (*s)
283 { 206 {
284 if (*s == '½') 207 if (win->line == NULL)
285 { 208 {
286 s++; 209 win->line = th_calloc(1, sizeof(nn_line_t));
287 if (*s == '½') 210 if (win->line == NULL)
288 { 211 return -15;
289 waddch(win, ((unsigned char) *s) | col); 212 }
290 s++; 213
291 }
292 else
293 {
294 memcpy(&col, s, sizeof(int));
295 s += sizeof(int);
296 }
297 }
298 else
299 {
300 waddch(win, ((unsigned char) *s) | col);
301 s++;
302 }
303 }
304 return 0;
305 }
306
307
308 #define QPUTCH(ch) th_vputch(&(win->buf), &(win->bufsize), &(win->len), ch)
309
310 int nnwin_print_buf(nn_window_t *win, const char *fmt)
311 {
312 const char *s = fmt;
313 int col = 0;
314 while (*s)
315 {
316 if (*s == '½') 214 if (*s == '½')
317 { 215 {
318 s++; 216 s++;
319 if (*s == '½') 217 if (*s == '½')
320 { 218 {
321 QPUTCH(*s); 219 QPUTCH(*s);
322 QPUTCH(*s); 220 QPUTCH(*s);
323 win->chlen++; 221 win->line->chlen++;
324 } 222 }
325 else 223 else
326 { 224 {
327 int val = 0; 225 int val = 0;
328 while (*s >= '0' && *s <= '9') 226 while (*s >= '0' && *s <= '9')
338 else if (val < 30) 236 else if (val < 30)
339 col = A_BOLD | COLOR_PAIR(val - 9); 237 col = A_BOLD | COLOR_PAIR(val - 9);
340 238
341 QPUTCH('½'); 239 QPUTCH('½');
342 240
343 if (!th_growbuf(&(win->buf), &(win->bufsize), &(win->len), sizeof(int))) 241 if (!th_growbuf(&(win->line->buf), &(win->line->bufsize), &(win->line->len), sizeof(int)))
344 return -2; 242 return -2;
345 243
346 memcpy(win->buf + win->len, &col, sizeof(int)); 244 memcpy(win->line->buf + win->line->len, &col, sizeof(int));
347 win->len += sizeof(int); 245 win->line->len += sizeof(int);
348 } 246 }
349 } 247 }
350 else if (*s == '\n') 248 else if (*s == '\n')
351 { 249 {
352 QPUTCH('\n');
353 QPUTCH(0); 250 QPUTCH(0);
354 th_ringbuf_add(win->data, win->buf); 251 th_ringbuf_add(win->data, win->line);
355 win->buf = NULL; 252 win->line = NULL;
356 win->chlen = 0;
357 win->dirty = TRUE; 253 win->dirty = TRUE;
358 } 254 }
359 else if (*s != '\r') 255 else if (*s != '\r')
360 { 256 {
361 QPUTCH((unsigned char) *s == 255 ? ' ' : *s); 257 QPUTCH((unsigned char) *s == 255 ? ' ' : *s);
362 win->chlen++; 258 win->line->chlen++;
363 } 259 }
364 260
365 s++; 261 s++;
366 } 262 }
367 263
368 return 0; 264 return 0;
369 } 265 }
370 266
371 267
372 char *nnwin_prompt_requester(WINDOW *win, const char *info, BOOL allowEmpty) 268 char *nnwin_prompt_requester(const char *info, BOOL allowEmpty)
373 { 269 {
374 char tmpBuf[512], *ptr; 270 char tmpBuf[512], *ptr;
375 size_t pos;
376 int curSave = curs_set(1); 271 int curSave = curs_set(1);
377 272
378 echo(); 273 echo();
379 waddstr(win, info); 274 waddstr(stdscr, info);
380 wgetnstr(win, tmpBuf, sizeof(tmpBuf) - 1); 275 wgetnstr(stdscr, tmpBuf, sizeof(tmpBuf) - 1);
381 noecho(); 276 noecho();
382 277
383 if (curSave != ERR) 278 if (curSave != ERR)
384 curs_set(curSave); 279 curs_set(curSave);
385 280
386 for (pos = strlen(tmpBuf) - 1; pos > 0 && th_isspace(tmpBuf[pos]); pos--) 281 str_trim_right(tmpBuf);
387 tmpBuf[pos] = 0;
388
389 ptr = str_trim_left(tmpBuf); 282 ptr = str_trim_left(tmpBuf);
390 283
391 if (allowEmpty || strlen(ptr) > 0) 284 if (allowEmpty || ptr[0])
392 return th_strdup(ptr); 285 return th_strdup(ptr);
393 else 286 else
394 return NULL; 287 return NULL;
395 } 288 }
396 289
397 290
398 BOOL nnwin_update_main(BOOL force) 291 void nnwin_update(BOOL force, nn_editbuf_t *ebuf, char *optUserName, int optUserColor)
399 { 292 {
400 int h, offs; 293 if (force)
401 qringbuf_t *buf; 294 {
402 295 wattrset(stdscr, A_NORMAL);
403 // Check pointers 296 wbkgdset(stdscr, COLOR_PAIR(0));
404 if (mainWin == NULL || currWin == NULL) 297 werase(stdscr);
405 return FALSE; 298 }
406 299
407 // Check if update is forced or if the window is dirty 300 // Check if update is forced or if the window is dirty
408 if (!force && !currWin->dirty) 301 if (currWin != NULL && (force || currWin->dirty))
409 return FALSE; 302 {
410 303 int h = scrHeight - 5, y, offs;
411 // Compute how many lines from backbuffer fit on the screen 304 qringbuf_t *buf = currWin->data;
412 buf = currWin->data; 305
413 h = getmaxy(mainWin); 306 wattrset(stdscr, A_NORMAL);
414 307 wbkgdset(stdscr, COLOR_PAIR(0));
415 // Clear and redraw window 308 wmove(stdscr, 0, 0);
416 werase(mainWin); 309
417 scrollok(mainWin, 1); 310 for (y = 0, offs = buf->size - h - currWin->pos; offs >= 0 && offs < buf->size - currWin->pos && offs < buf->size && y < h; offs++)
418 for (offs = buf->size - h - currWin->pos; offs >= 0 && offs < buf->size - currWin->pos && offs < buf->size; offs++) 311 {
419 { 312 int col = 0;
420 if (buf->data[offs] != NULL) 313 nn_line_t *line = buf->data[offs];
421 nnwin_print(mainWin, buf->data[offs]); 314 if (line == NULL)
422 } 315 continue;
423 316
424 currWin->dirty = FALSE; 317 while (*s && y < h)
425 wrefresh(mainWin); 318 {
426 return TRUE; 319 if (*s == '½')
427 } 320 {
428 321 s++;
429 322 if (*s == '½')
430 void nnwin_close_windows(void) 323 {
431 { 324 waddch(stdscr, ((unsigned char) *s) | col);
432 if (mainWin) delwin(mainWin); 325 s++;
433 if (statusWin) delwin(statusWin); 326 }
434 if (editWin) delwin(editWin); 327 else
435 } 328 {
436 329 memcpy(&col, s, sizeof(int));
437 330 s += sizeof(int);
438 BOOL nnwin_init_windows(void) 331 }
439 { 332 }
440 int w, h; 333 else
441 334 {
442 getmaxyx(stdscr, h, w); 335 waddch(stdscr, ((unsigned char) *s) | col);
443 336 s++;
444 nnwin_close_windows(); 337 }
445 338 y = getcury(stdscr);
446 mainWin = subwin(stdscr, h - 4, w, 0, 0); 339 }
447 statusWin = subwin(stdscr, 1, w, h - 4, 0); 340 }
448 editWin = subwin(stdscr, 3, w, h - 3, 0); 341
449 342 currWin->dirty = FALSE;
450 if (mainWin == NULL || statusWin == NULL || editWin == NULL) 343 }
451 return FALSE; 344
452 345 {
453 return TRUE; 346 // Statusline
454 } 347 char tmpStr[128];
348 int i;
349
350 str_get_timestamp(tmpStr, sizeof(tmpStr), "%H:%M:%S");
351
352 wmove(stdscr, scrHeight - 4, 0);
353 wbkgdset(stdscr, COLOR_PAIR(10));
354 wclrtoeol(stdscr);
355
356 wattrset(stdscr, A_BOLD | COLOR_PAIR(11));
357 mvwaddstr(stdscr, scrHeight - 4, 1, tmpStr);
358
359 wattrset(stdscr, A_BOLD | COLOR_PAIR(13));
360 waddstr(stdscr, " | ");
361 wattrset(stdscr, A_BOLD | COLOR_PAIR(16));
362 waddstr(stdscr, optUserName);
363 wattrset(stdscr, A_BOLD | COLOR_PAIR(13));
364
365 wattrset(stdscr, A_BOLD | COLOR_PAIR(13));
366 waddstr(stdscr, " | ");
367 wattrset(stdscr, A_BOLD | COLOR_PAIR(11));
368 snprintf(tmpStr, sizeof(tmpStr), "#%06x", optUserColor);
369 waddstr(stdscr, tmpStr);
370
371 wattrset(stdscr, A_BOLD | COLOR_PAIR(13));
372 waddstr(stdscr, " | WIN: ");
373 snprintf(tmpStr, sizeof(tmpStr), "%d: %s / %d",
374 currWin->num + 1,
375 currWin->id != NULL ? currWin->id : "MAIN",
376 currWin->pos);
377 waddstr(stdscr, tmpStr);
378
379 wattrset(stdscr, A_BOLD | COLOR_PAIR(13));
380 waddstr(stdscr, " | ");
381 wattrset(stdscr, A_BOLD | COLOR_PAIR(11));
382
383 for (i = 0; i < SET_MAX_WINDOWS; i++)
384 {
385 if (chatWindows[i] != NULL && chatWindows[i]->dirty)
386 {
387 snprintf(tmpStr, sizeof(tmpStr), "%d ", i + 1);
388 waddstr(stdscr, tmpStr);
389 }
390 }
391 }
392
393 if (ebuf != NULL)
394 // && (force || ebuf->dirty))
395 {
396 int yoffs = ebuf->pos / scrWidth,
397 xoffs = ebuf->pos % scrWidth;
398 char *tmp;
399
400 ebuf->dirty = FALSE;
401 ebuf->data[ebuf->len] = 0;
402 tmp = nn_username_decode(th_strdup(ebuf->data));
403
404 wmove(stdscr, scrHeight - 3, 0);
405 wattrset(stdscr, A_NORMAL);
406 wbkgdset(stdscr, COLOR_PAIR(0));
407 waddnstr(stdscr, tmp, ebuf->len);
408 wmove(stdscr, scrHeight - 3 + yoffs, xoffs);
409
410 th_free(tmp);
411 }
412
413 wrefresh(stdscr);
414 }