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! */
28 #include "clientincludes.h"
30 SilcScreen silc_screen_init()
34 new = silc_calloc(1, sizeof(*new));
42 silc_screen_create_output_window(new);
43 silc_screen_create_input_window(new);
48 /* Creates one (main) output window. Returns new created physical
51 WINDOW *silc_screen_create_output_window(SilcScreen screen)
53 assert(screen != NULL);
55 screen->output_win = silc_calloc(1, sizeof(*screen->output_win));
56 screen->output_win_count = 1;
57 screen->output_win[0] = newwin(LINES - 3, COLS, 1, 0);
58 scrollok(screen->output_win[0], TRUE);
59 idlok(screen->output_win[0], TRUE);
60 wrefresh(screen->output_win[0]);
62 return screen->output_win[0];
65 /* Adds new output window. Return new created physical window. */
67 WINDOW *silc_screen_add_output_window(SilcScreen screen)
71 assert(screen != NULL);
73 screen->output_win = silc_realloc(screen->output_win,
74 (screen->output_win_count + 1) *
75 sizeof(*screen->output_win));
76 i = screen->output_win_count;
77 screen->output_win[i] = newwin(LINES - 3, COLS, 1, 0);
78 scrollok(screen->output_win[i], TRUE);
79 idlok(screen->output_win[i], TRUE);
80 wrefresh(screen->output_win[i]);
81 screen->output_win_count++;
83 return screen->output_win[i];
86 void silc_screen_create_input_window(SilcScreen screen)
88 assert(screen != NULL);
90 screen->input_win = newwin(0, COLS, LINES - 1, 0);
91 scrollok(screen->input_win, TRUE);
92 keypad(screen->input_win, TRUE);
93 wrefresh(screen->input_win);
96 void silc_screen_init_upper_status_line(SilcScreen screen)
98 assert(screen != NULL);
100 /* Create upper status line */
101 screen->upper_stat_line = newwin(0, COLS, 0, 0);
102 scrollok(screen->upper_stat_line, FALSE);
103 wattrset(screen->upper_stat_line, A_REVERSE);
105 silc_screen_print_upper_stat_line(screen);
108 void silc_screen_print_upper_stat_line(SilcScreen screen)
113 /* Print empty line */
114 for (i = 0; i < COLS - 1; i++)
115 mvwprintw(screen->upper_stat_line, 0, i, " ");
117 /* Print stuff with justify */
119 mvwprintw(screen->upper_stat_line, 0, 1, "%s %s",
120 screen->u_stat_line.program_name,
121 screen->u_stat_line.program_version);
123 /* Prints clock on upper stat line */
124 silc_screen_print_clock(screen);
125 wrefresh(screen->upper_stat_line);
128 void silc_screen_init_output_status_line(SilcScreen screen)
132 assert(screen != NULL);
134 screen->output_stat_line = silc_calloc(1, sizeof(*screen->output_stat_line));
136 screen->output_stat_line[0] = newwin(1, COLS, LINES - 2, 0);
137 scrollok(screen->output_stat_line[0], FALSE);
138 wattrset(screen->output_stat_line[0], A_REVERSE);
140 /* print first just blank line */
141 for (i = 0; i < COLS - 1; i++)
142 mvwprintw(screen->output_stat_line[0], 0, i, " ");
144 /* Allocate bottom line */
145 screen->bottom_line = silc_calloc(1, sizeof(*screen->bottom_line));
147 wattrset(screen->output_stat_line[0], A_NORMAL);
148 wrefresh(screen->output_stat_line[0]);
151 void silc_screen_print_clock(SilcScreen screen)
157 tp = localtime(&curtime);
159 mvwprintw(screen->upper_stat_line, 0, COLS - 8, "[%02d:%02d] ",
160 tp->tm_hour, tp->tm_min);
161 wrefresh(screen->upper_stat_line);
164 /* Prints current cursor coordinates on some output stat line */
166 void silc_screen_print_coordinates(SilcScreen screen, int win_index)
168 wattrset(screen->output_stat_line[win_index], A_REVERSE);
169 mvwprintw(screen->output_stat_line[win_index], 0, COLS - 10,
170 "[%4d,%3d]", screen->input_pos, LINES);
171 wrefresh(screen->output_stat_line[win_index]);
172 wattrset(screen->output_stat_line[win_index], A_NORMAL);
175 /* Prints bottom line (the status line) of the screen. */
177 void silc_screen_print_bottom_line(SilcScreen screen, int win_index)
180 SilcScreenBottomLine line = screen->bottom_line;
183 memset(buf, 0, sizeof(buf));
186 len = strlen(line->mode);
187 strncat(buf, line->mode, len);
190 if (line->nickname) {
191 len = strlen(line->nickname);
192 strncat(buf, line->nickname, len > SILC_SCREEN_MAX_NICK_LEN ?
193 SILC_SCREEN_MAX_NICK_LEN : len);
196 if (line->connection) {
197 len = strlen(line->connection);
198 strncat(buf, " via ", 5);
199 strncat(buf, line->connection, len > SILC_SCREEN_MAX_CONN_LEN ?
200 SILC_SCREEN_MAX_CONN_LEN : len);
204 len = strlen(line->channel);
205 strncat(buf, " ", 1);
206 strncat(buf, line->channel, len > SILC_SCREEN_MAX_CHANNEL_LEN ?
207 SILC_SCREEN_MAX_CHANNEL_LEN : len);
210 if (line->channel_mode) {
211 len = strlen(line->channel_mode);
212 strncat(buf, " (+", 3);
213 strncat(buf, line->channel_mode, len > SILC_SCREEN_MAX_CHANNEL_LEN ?
214 SILC_SCREEN_MAX_CHANNEL_LEN : len);
215 strncat(buf, ")", 2);
219 len = strlen(line->umode);
220 strncat(buf, " [", 2);
221 strncat(buf, line->umode, len > SILC_SCREEN_MAX_UMODE_LEN ?
222 SILC_SCREEN_MAX_UMODE_LEN : len);
223 strncat(buf, "]", 2);
227 strncat(buf, " (away)", 8);
229 wattrset(screen->output_stat_line[win_index], A_REVERSE);
231 for (i = 0; i < COLS - 10; i++)
232 mvwprintw(screen->output_stat_line[win_index], 0, i, " ");
234 mvwprintw(screen->output_stat_line[win_index], 0, 0, " %s", buf);
235 silc_screen_print_coordinates(screen, win_index);
236 wrefresh(screen->output_stat_line[win_index]);
237 wattrset(screen->output_stat_line[win_index], A_NORMAL);
240 /* Refresh all windows */
242 void silc_screen_refresh_all(SilcScreen screen)
246 assert(screen != NULL);
248 wclear(screen->upper_stat_line);
249 silc_screen_print_upper_stat_line(screen);
251 wclear(screen->output_stat_line[0]);
252 silc_screen_print_bottom_line(screen, 0);
253 silc_screen_print_coordinates(screen, 0);
255 for (i = 0; i < screen->output_win_count; i++) {
256 wclear(screen->output_win[i]);
257 wrefresh(screen->output_win[i]);
260 wclear(screen->input_win);
261 wrefresh(screen->input_win);
264 /* Refreshes a window */
266 void silc_screen_refresh_win(WINDOW *win)
274 /* Resets input window */
276 void silc_screen_input_reset(SilcScreen screen)
280 assert(screen != NULL);
281 for (i = 0; i < COLS - 1; i++)
282 mvwprintw(screen->input_win, 0, i, " ");
283 mvwprintw(screen->input_win, 0, 0, "");
284 wrefresh(screen->input_win);
285 screen->input_pos = 0;
286 screen->input_end = 0;
287 screen->cursor_pos = 0;
288 screen->virtual_window = 0;
291 /* Backspace. Removes one character from input windows. */
293 void silc_screen_input_backspace(SilcScreen screen)
298 assert(screen != NULL);
299 buffer = screen->input_buffer;
300 win = screen->input_win;
302 /* Return directly if at the start of input line */
303 if (screen->input_pos == 0)
306 if (screen->virtual_window) {
307 if (screen->cursor_pos <= 10) {
311 for (i = 0; i < COLS; i++)
312 mvwprintw(win, 0, i, " ");
313 mvwprintw(win, 0, 0, "");
315 screen->virtual_window--;
317 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
318 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
319 screen->input_end = ((screen->virtual_window + 1) * (COLS - 5));
320 screen->cursor_pos = (COLS - 5);
325 screen->cursor_pos--;
328 mvwdelch(win, 0, screen->cursor_pos);
330 if (screen->input_pos < screen->input_end)
331 /* Delete from inside the input line */
332 SILC_SCREEN_INPUT_DELETE(buffer, screen->input_pos, screen->input_end);
334 /* Delete from the end of the input line */
335 buffer[screen->input_pos] = 0;
340 /* Switches insert on input window on/off */
342 void silc_screen_input_insert(SilcScreen screen)
344 assert(screen != NULL);
346 screen->insert = screen->insert == TRUE ? FALSE : TRUE;
349 /* Moves cursor one character length to rightward */
351 void silc_screen_input_cursor_right(SilcScreen screen)
356 assert(screen != NULL);
357 buffer = screen->input_buffer;
358 win = screen->input_win;
360 /* Return directly if we are at the end of input line */
361 if (screen->cursor_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
364 /* Make sure cursor doesn't advance over the end of the line */
365 if (screen->input_pos >= screen->input_end)
368 /* When cursor advances enough we switch to new window and show
369 rest of the typed characters on the screen. */
370 if (screen->cursor_pos >= (COLS - 5)) {
374 for (i = 0; i < COLS; i++)
375 mvwprintw(win, 0, i, " ");
376 mvwprintw(win, 0, 0, "");
378 waddnstr(win, &buffer[screen->input_pos - 10],
379 ((screen->input_pos - 10) - screen->input_end >= COLS) ?
380 COLS : (screen->input_pos - 10) - screen->input_end);
381 screen->cursor_pos = 10;
384 screen->virtual_window++;
387 screen->cursor_pos++;
389 wmove(win, 0, screen->cursor_pos);
393 /* Moves cursor one character length to leftward */
395 void silc_screen_input_cursor_left(SilcScreen screen)
400 assert(screen != NULL);
401 buffer = screen->input_buffer;
402 win = screen->input_win;
404 /* Return directly if at the start of input line */
405 if (screen->input_pos == 0)
408 /* When cursor advances enough we switch to new window and show
409 rest of the typed characters on the screen. */
410 if (screen->virtual_window) {
411 if (screen->cursor_pos <= 10) {
415 for (i = 0; i < COLS; i++)
416 mvwprintw(win, 0, i, " ");
417 mvwprintw(win, 0, 0, "");
419 screen->virtual_window--;
421 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
422 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
423 screen->cursor_pos = (COLS - 5);
428 screen->cursor_pos--;
430 wmove(win, 0, screen->cursor_pos);
434 /* Moves cursor at the very start of the input line */
436 void silc_screen_input_cursor_home(SilcScreen screen)
441 assert(screen != NULL);
442 buffer = screen->input_buffer;
443 win = screen->input_win;
446 waddnstr(win, &buffer[0], COLS);
449 screen->input_pos = 0;
450 screen->cursor_pos = 0;
451 screen->virtual_window = 0;
454 /* Moves cursor at the very end of the input line */
456 void silc_screen_input_cursor_end(SilcScreen screen)
461 assert(screen != NULL);
462 buffer = screen->input_buffer;
463 win = screen->input_win;
466 waddnstr(win, &buffer[screen->input_end - 10], 10);
469 screen->input_pos = screen->input_end;
470 screen->cursor_pos = 10;
472 screen->virtual_window = 0;
475 /* Prints typed character into the input window for user to see. Character
476 attributes must be set separately outside this function. */
478 void silc_screen_input_print(SilcScreen screen, unsigned char c)
483 assert(screen != NULL);
484 buffer = screen->input_buffer;
485 win = screen->input_win;
487 /* Return directly if input window is full */
488 if (screen->input_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
491 /* The input window is COLS wide but one can type into it at most
492 SILC_SCREEN_INPUT_SIZE characters. When COLS - 5 characters is
493 typed the window is cleared and the cursor is moved at the tenth
494 character in the input window. Ten last typed character is then
495 showed at the start of the window. */
496 if (screen->cursor_pos >= (COLS - 5)) {
500 for (i = 0; i < COLS; i++)
501 mvwprintw(win, 0, i, " ");
502 mvwprintw(win, 0, 0, "");
504 /* Show ten last typed characters from the buffer on the screen */
505 waddnstr(win, &buffer[screen->input_pos - 10], 10);
506 screen->cursor_pos = 10;
509 screen->virtual_window++;
512 if (screen->input_pos < screen->input_end) {
513 /* User moved cursor into the typed line. We are not adding
514 character at the end of the line anymore */
516 if (screen->insert == FALSE) {
517 /* Add new character somewhere inside typed line. The input
518 line position is not advanced since a character was replaced
519 by the new character. */
521 buffer[screen->input_pos] = c;
522 screen->cursor_pos++;
524 screen->input_end = screen->input_pos;
526 /* Insert new character somewhere inside typed line. Other
527 characters are moved forward. We must advance the input line
530 wmove(win, 0, screen->cursor_pos + 1);
531 SILC_SCREEN_INPUT_INSERT(buffer, screen->input_pos,
532 c, screen->input_end);
533 screen->cursor_pos++;
538 /* Add new character at the end of input line */
540 buffer[screen->input_pos] = c;
542 screen->cursor_pos++;
543 screen->input_end = screen->input_pos;
546 /* Advance the cursor position. Cursor moves one to rightward always */
550 /* Prints prompt to the input window. Cursors position aftern printing
551 is length of the prompt. */
553 void silc_screen_input_print_prompt(SilcScreen screen, char *prompt)
557 assert(screen != NULL);
558 win = screen->input_win;
561 waddnstr(win, prompt, strlen(prompt));
564 screen->input_pos = strlen(prompt);
565 screen->cursor_pos = strlen(prompt);
566 screen->virtual_window = 0;