5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
21 * SILC client screen routines. These implement the user interface
22 * on ncurses routines. Most of these routines were taken from the
23 * old version of the SILC client dating back to 1997.
25 /* XXX: Input line handling is really buggy! */
29 * Revision 1.4 2000/07/10 05:38:08 priikone
30 * Fixed screen refresh.
32 * Revision 1.3 2000/07/07 06:52:10 priikone
33 * Fixed screen refresh routine.
35 * Revision 1.2 2000/07/05 06:12:05 priikone
36 * Global cosmetic changes.
38 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
39 * Imported from internal CVS/Added Log headers.
44 #include "clientincludes.h"
46 SilcScreen silc_screen_init()
50 new = silc_calloc(1, sizeof(*new));
58 silc_screen_create_output_window(new);
59 silc_screen_create_input_window(new);
64 /* Creates one (main) output window. Returns new created physical
67 WINDOW *silc_screen_create_output_window(SilcScreen screen)
69 assert(screen != NULL);
71 screen->output_win = silc_calloc(1, sizeof(*screen->output_win));
72 screen->output_win_count = 1;
73 screen->output_win[0] = newwin(LINES - 3, COLS, 1, 0);
74 scrollok(screen->output_win[0], TRUE);
75 idlok(screen->output_win[0], TRUE);
76 wrefresh(screen->output_win[0]);
78 return screen->output_win[0];
81 /* Adds new output window. Return new created physical window. */
83 WINDOW *silc_screen_add_output_window(SilcScreen screen)
87 assert(screen != NULL);
89 screen->output_win = silc_realloc(screen->output_win,
90 (screen->output_win_count + 1) *
91 sizeof(*screen->output_win));
92 i = screen->output_win_count;
93 screen->output_win[i] = newwin(LINES - 3, COLS, 1, 0);
94 scrollok(screen->output_win[i], TRUE);
95 idlok(screen->output_win[i], TRUE);
96 wrefresh(screen->output_win[i]);
97 screen->output_win_count++;
99 return screen->output_win[i];
102 void silc_screen_create_input_window(SilcScreen screen)
104 assert(screen != NULL);
106 screen->input_win = newwin(0, COLS, LINES - 1, 0);
107 scrollok(screen->input_win, TRUE);
108 keypad(screen->input_win, TRUE);
109 wrefresh(screen->input_win);
112 void silc_screen_init_upper_status_line(SilcScreen screen)
114 assert(screen != NULL);
116 /* Create upper status line */
117 screen->upper_stat_line = newwin(0, COLS, 0, 0);
118 scrollok(screen->upper_stat_line, FALSE);
119 wattrset(screen->upper_stat_line, A_REVERSE);
121 silc_screen_print_upper_stat_line(screen);
124 void silc_screen_print_upper_stat_line(SilcScreen screen)
129 /* Print empty line */
130 for (i = 0; i < COLS - 1; i++)
131 mvwprintw(screen->upper_stat_line, 0, i, " ");
133 /* Print stuff with justify */
135 mvwprintw(screen->upper_stat_line, 0, 1, "%s %s",
136 screen->u_stat_line.program_name,
137 screen->u_stat_line.program_version);
139 /* Prints clock on upper stat line */
140 silc_screen_print_clock(screen);
141 wrefresh(screen->upper_stat_line);
144 void silc_screen_init_output_status_line(SilcScreen screen)
148 assert(screen != NULL);
150 screen->output_stat_line = silc_calloc(1, sizeof(*screen->output_stat_line));
152 screen->output_stat_line[0] = newwin(1, COLS, LINES - 2, 0);
153 scrollok(screen->output_stat_line[0], FALSE);
154 wattrset(screen->output_stat_line[0], A_REVERSE);
156 /* print first just blank line */
157 for (i = 0; i < COLS - 1; i++)
158 mvwprintw(screen->output_stat_line[0], 0, i, " ");
160 /* Allocate bottom line */
161 screen->bottom_line = silc_calloc(1, sizeof(*screen->bottom_line));
163 wattrset(screen->output_stat_line[0], A_NORMAL);
164 wrefresh(screen->output_stat_line[0]);
167 void silc_screen_print_clock(SilcScreen screen)
173 tp = localtime(&curtime);
175 mvwprintw(screen->upper_stat_line, 0, COLS - 8, "[%02d:%02d] ",
176 tp->tm_hour, tp->tm_min);
177 wrefresh(screen->upper_stat_line);
180 /* Prints current cursor coordinates on some output stat line */
182 void silc_screen_print_coordinates(SilcScreen screen, int win_index)
184 wattrset(screen->output_stat_line[win_index], A_REVERSE);
185 mvwprintw(screen->output_stat_line[win_index], 0, COLS - 10,
186 "[%4d,%3d]", screen->input_pos, LINES);
187 wrefresh(screen->output_stat_line[win_index]);
188 wattrset(screen->output_stat_line[win_index], A_NORMAL);
191 /* Prints bottom line (the status line) of the screen. */
193 void silc_screen_print_bottom_line(SilcScreen screen, int win_index)
196 SilcScreenBottomLine line = screen->bottom_line;
199 memset(buf, 0, sizeof(buf));
202 len = strlen(line->mode);
203 strncat(buf, line->mode, len);
206 if (line->nickname) {
207 len = strlen(line->nickname);
208 strncat(buf, line->nickname, len > SILC_SCREEN_MAX_NICK_LEN ?
209 SILC_SCREEN_MAX_NICK_LEN : len);
212 if (line->connection) {
213 len = strlen(line->connection);
214 strncat(buf, " via ", 5);
215 strncat(buf, line->connection, len > SILC_SCREEN_MAX_CONN_LEN ?
216 SILC_SCREEN_MAX_CONN_LEN : len);
220 len = strlen(line->channel);
221 strncat(buf, " ", 1);
222 strncat(buf, line->channel, len > SILC_SCREEN_MAX_CHANNEL_LEN ?
223 SILC_SCREEN_MAX_CHANNEL_LEN : len);
226 wattrset(screen->output_stat_line[win_index], A_REVERSE);
228 for (i = 0; i < COLS - 10; i++)
229 mvwprintw(screen->output_stat_line[win_index], 0, i, " ");
231 mvwprintw(screen->output_stat_line[win_index], 0, 0, " %s", buf);
232 silc_screen_print_coordinates(screen, win_index);
233 wrefresh(screen->output_stat_line[win_index]);
234 wattrset(screen->output_stat_line[win_index], A_NORMAL);
237 /* Refresh all windows */
239 void silc_screen_refresh_all(SilcScreen screen)
243 assert(screen != NULL);
245 wclear(screen->upper_stat_line);
246 silc_screen_print_upper_stat_line(screen);
248 wclear(screen->output_stat_line[0]);
249 silc_screen_print_bottom_line(screen, 0);
250 silc_screen_print_coordinates(screen, 0);
252 for (i = 0; i < screen->output_win_count; i++) {
253 wclear(screen->output_win[i]);
254 wrefresh(screen->output_win[i]);
257 wclear(screen->input_win);
258 wrefresh(screen->input_win);
261 /* Refreshes a window */
263 void silc_screen_refresh_win(WINDOW *win)
271 /* Resets input window */
273 void silc_screen_input_reset(SilcScreen screen)
277 assert(screen != NULL);
278 for (i = 0; i < COLS - 1; i++)
279 mvwprintw(screen->input_win, 0, i, " ");
280 mvwprintw(screen->input_win, 0, 0, "");
281 wrefresh(screen->input_win);
282 screen->input_pos = 0;
283 screen->input_end = 0;
284 screen->cursor_pos = 0;
285 screen->virtual_window = 0;
288 /* Backspace. Removes one character from input windows. */
290 void silc_screen_input_backspace(SilcScreen screen)
295 assert(screen != NULL);
296 buffer = screen->input_buffer;
297 win = screen->input_win;
299 /* Return directly if at the start of input line */
300 if (screen->input_pos == 0)
303 if (screen->virtual_window) {
304 if (screen->cursor_pos <= 10) {
308 for (i = 0; i < COLS; i++)
309 mvwprintw(win, 0, i, " ");
310 mvwprintw(win, 0, 0, "");
312 screen->virtual_window--;
314 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
315 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
316 screen->input_end = ((screen->virtual_window + 1) * (COLS - 5));
317 screen->cursor_pos = (COLS - 5);
322 screen->cursor_pos--;
325 mvwdelch(win, 0, screen->cursor_pos);
327 if (screen->input_pos < screen->input_end)
328 /* Delete from inside the input line */
329 SILC_SCREEN_INPUT_DELETE(buffer, screen->input_pos, screen->input_end);
331 /* Delete from the end of the input line */
332 buffer[screen->input_pos] = 0;
337 /* Switches insert on input window on/off */
339 void silc_screen_input_insert(SilcScreen screen)
341 assert(screen != NULL);
343 screen->insert = screen->insert == TRUE ? FALSE : TRUE;
346 /* Moves cursor one character length to rightward */
348 void silc_screen_input_cursor_right(SilcScreen screen)
353 assert(screen != NULL);
354 buffer = screen->input_buffer;
355 win = screen->input_win;
357 /* Return directly if we are at the end of input line */
358 if (screen->cursor_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
361 /* Make sure cursor doesn't advance over the end of the line */
362 if (screen->input_pos >= screen->input_end)
365 /* When cursor advances enough we switch to new window and show
366 rest of the typed characters on the screen. */
367 if (screen->cursor_pos >= (COLS - 5)) {
371 for (i = 0; i < COLS; i++)
372 mvwprintw(win, 0, i, " ");
373 mvwprintw(win, 0, 0, "");
375 waddnstr(win, &buffer[screen->input_pos - 10],
376 ((screen->input_pos - 10) - screen->input_end >= COLS) ?
377 COLS : (screen->input_pos - 10) - screen->input_end);
378 screen->cursor_pos = 10;
381 screen->virtual_window++;
384 screen->cursor_pos++;
386 wmove(win, 0, screen->cursor_pos);
390 /* Moves cursor one character length to leftward */
392 void silc_screen_input_cursor_left(SilcScreen screen)
397 assert(screen != NULL);
398 buffer = screen->input_buffer;
399 win = screen->input_win;
401 /* Return directly if at the start of input line */
402 if (screen->input_pos == 0)
405 /* When cursor advances enough we switch to new window and show
406 rest of the typed characters on the screen. */
407 if (screen->virtual_window) {
408 if (screen->cursor_pos <= 10) {
412 for (i = 0; i < COLS; i++)
413 mvwprintw(win, 0, i, " ");
414 mvwprintw(win, 0, 0, "");
416 screen->virtual_window--;
418 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
419 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
420 screen->cursor_pos = (COLS - 5);
425 screen->cursor_pos--;
427 wmove(win, 0, screen->cursor_pos);
431 /* Moves cursor at the very start of the input line */
433 void silc_screen_input_cursor_home(SilcScreen screen)
438 assert(screen != NULL);
439 buffer = screen->input_buffer;
440 win = screen->input_win;
443 waddnstr(win, &buffer[0], COLS);
446 screen->input_pos = 0;
447 screen->cursor_pos = 0;
448 screen->virtual_window = 0;
451 /* Moves cursor at the very end of the input line */
453 void silc_screen_input_cursor_end(SilcScreen screen)
458 assert(screen != NULL);
459 buffer = screen->input_buffer;
460 win = screen->input_win;
463 waddnstr(win, &buffer[screen->input_end - 10], 10);
466 screen->input_pos = screen->input_end;
467 screen->cursor_pos = 10;
469 screen->virtual_window = 0;
472 /* Prints typed character into the input window for user to see. Character
473 attributes must be set separately outside this function. */
475 void silc_screen_input_print(SilcScreen screen, unsigned char c)
480 assert(screen != NULL);
481 buffer = screen->input_buffer;
482 win = screen->input_win;
484 /* Return directly if input window is full */
485 if (screen->input_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
488 /* The input window is COLS wide but one can type into it at most
489 SILC_SCREEN_INPUT_SIZE characters. When COLS - 5 characters is
490 typed the window is cleared and the cursor is moved at the tenth
491 character in the input window. Ten last typed character is then
492 showed at the start of the window. */
493 if (screen->cursor_pos >= (COLS - 5)) {
497 for (i = 0; i < COLS; i++)
498 mvwprintw(win, 0, i, " ");
499 mvwprintw(win, 0, 0, "");
501 /* Show ten last typed characters from the buffer on the screen */
502 waddnstr(win, &buffer[screen->input_pos - 10], 10);
503 screen->cursor_pos = 10;
506 screen->virtual_window++;
509 if (screen->input_pos < screen->input_end) {
510 /* User moved cursor into the typed line. We are not adding
511 character at the end of the line anymore */
513 if (screen->insert == FALSE) {
514 /* Add new character somewhere inside typed line. The input
515 line position is not advanced since a character was replaced
516 by the new character. */
518 buffer[screen->input_pos] = c;
519 screen->cursor_pos++;
521 screen->input_end = screen->input_pos;
523 /* Insert new character somewhere inside typed line. Other
524 characters are moved forward. We must advance the input line
527 wmove(win, 0, screen->cursor_pos + 1);
528 SILC_SCREEN_INPUT_INSERT(buffer, screen->input_pos,
529 c, screen->input_end);
530 screen->cursor_pos++;
535 /* Add new character at the end of input line */
537 buffer[screen->input_pos] = c;
539 screen->cursor_pos++;
540 screen->input_end = screen->input_pos;
543 /* Advance the cursor position. Cursor moves one to rightward always */
547 /* Prints prompt to the input window. Cursors position aftern printing
548 is length of the prompt. */
550 void silc_screen_input_print_prompt(SilcScreen screen, char *prompt)
554 assert(screen != NULL);
555 win = screen->input_win;
558 waddnstr(win, prompt, strlen(prompt));
561 screen->input_pos = strlen(prompt);
562 screen->cursor_pos = strlen(prompt);
563 screen->virtual_window = 0;