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 strncat(buf, " (away)", 8);
221 wattrset(screen->output_stat_line[win_index], A_REVERSE);
223 for (i = 0; i < COLS - 10; i++)
224 mvwprintw(screen->output_stat_line[win_index], 0, i, " ");
226 mvwprintw(screen->output_stat_line[win_index], 0, 0, " %s", buf);
227 silc_screen_print_coordinates(screen, win_index);
228 wrefresh(screen->output_stat_line[win_index]);
229 wattrset(screen->output_stat_line[win_index], A_NORMAL);
232 /* Refresh all windows */
234 void silc_screen_refresh_all(SilcScreen screen)
238 assert(screen != NULL);
240 wclear(screen->upper_stat_line);
241 silc_screen_print_upper_stat_line(screen);
243 wclear(screen->output_stat_line[0]);
244 silc_screen_print_bottom_line(screen, 0);
245 silc_screen_print_coordinates(screen, 0);
247 for (i = 0; i < screen->output_win_count; i++) {
248 wclear(screen->output_win[i]);
249 wrefresh(screen->output_win[i]);
252 wclear(screen->input_win);
253 wrefresh(screen->input_win);
256 /* Refreshes a window */
258 void silc_screen_refresh_win(WINDOW *win)
266 /* Resets input window */
268 void silc_screen_input_reset(SilcScreen screen)
272 assert(screen != NULL);
273 for (i = 0; i < COLS - 1; i++)
274 mvwprintw(screen->input_win, 0, i, " ");
275 mvwprintw(screen->input_win, 0, 0, "");
276 wrefresh(screen->input_win);
277 screen->input_pos = 0;
278 screen->input_end = 0;
279 screen->cursor_pos = 0;
280 screen->virtual_window = 0;
283 /* Backspace. Removes one character from input windows. */
285 void silc_screen_input_backspace(SilcScreen screen)
290 assert(screen != NULL);
291 buffer = screen->input_buffer;
292 win = screen->input_win;
294 /* Return directly if at the start of input line */
295 if (screen->input_pos == 0)
298 if (screen->virtual_window) {
299 if (screen->cursor_pos <= 10) {
303 for (i = 0; i < COLS; i++)
304 mvwprintw(win, 0, i, " ");
305 mvwprintw(win, 0, 0, "");
307 screen->virtual_window--;
309 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
310 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
311 screen->input_end = ((screen->virtual_window + 1) * (COLS - 5));
312 screen->cursor_pos = (COLS - 5);
317 screen->cursor_pos--;
320 mvwdelch(win, 0, screen->cursor_pos);
322 if (screen->input_pos < screen->input_end)
323 /* Delete from inside the input line */
324 SILC_SCREEN_INPUT_DELETE(buffer, screen->input_pos, screen->input_end);
326 /* Delete from the end of the input line */
327 buffer[screen->input_pos] = 0;
332 /* Switches insert on input window on/off */
334 void silc_screen_input_insert(SilcScreen screen)
336 assert(screen != NULL);
338 screen->insert = screen->insert == TRUE ? FALSE : TRUE;
341 /* Moves cursor one character length to rightward */
343 void silc_screen_input_cursor_right(SilcScreen screen)
348 assert(screen != NULL);
349 buffer = screen->input_buffer;
350 win = screen->input_win;
352 /* Return directly if we are at the end of input line */
353 if (screen->cursor_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
356 /* Make sure cursor doesn't advance over the end of the line */
357 if (screen->input_pos >= screen->input_end)
360 /* When cursor advances enough we switch to new window and show
361 rest of the typed characters on the screen. */
362 if (screen->cursor_pos >= (COLS - 5)) {
366 for (i = 0; i < COLS; i++)
367 mvwprintw(win, 0, i, " ");
368 mvwprintw(win, 0, 0, "");
370 waddnstr(win, &buffer[screen->input_pos - 10],
371 ((screen->input_pos - 10) - screen->input_end >= COLS) ?
372 COLS : (screen->input_pos - 10) - screen->input_end);
373 screen->cursor_pos = 10;
376 screen->virtual_window++;
379 screen->cursor_pos++;
381 wmove(win, 0, screen->cursor_pos);
385 /* Moves cursor one character length to leftward */
387 void silc_screen_input_cursor_left(SilcScreen screen)
392 assert(screen != NULL);
393 buffer = screen->input_buffer;
394 win = screen->input_win;
396 /* Return directly if at the start of input line */
397 if (screen->input_pos == 0)
400 /* When cursor advances enough we switch to new window and show
401 rest of the typed characters on the screen. */
402 if (screen->virtual_window) {
403 if (screen->cursor_pos <= 10) {
407 for (i = 0; i < COLS; i++)
408 mvwprintw(win, 0, i, " ");
409 mvwprintw(win, 0, 0, "");
411 screen->virtual_window--;
413 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
414 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
415 screen->cursor_pos = (COLS - 5);
420 screen->cursor_pos--;
422 wmove(win, 0, screen->cursor_pos);
426 /* Moves cursor at the very start of the input line */
428 void silc_screen_input_cursor_home(SilcScreen screen)
433 assert(screen != NULL);
434 buffer = screen->input_buffer;
435 win = screen->input_win;
438 waddnstr(win, &buffer[0], COLS);
441 screen->input_pos = 0;
442 screen->cursor_pos = 0;
443 screen->virtual_window = 0;
446 /* Moves cursor at the very end of the input line */
448 void silc_screen_input_cursor_end(SilcScreen screen)
453 assert(screen != NULL);
454 buffer = screen->input_buffer;
455 win = screen->input_win;
458 waddnstr(win, &buffer[screen->input_end - 10], 10);
461 screen->input_pos = screen->input_end;
462 screen->cursor_pos = 10;
464 screen->virtual_window = 0;
467 /* Prints typed character into the input window for user to see. Character
468 attributes must be set separately outside this function. */
470 void silc_screen_input_print(SilcScreen screen, unsigned char c)
475 assert(screen != NULL);
476 buffer = screen->input_buffer;
477 win = screen->input_win;
479 /* Return directly if input window is full */
480 if (screen->input_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
483 /* The input window is COLS wide but one can type into it at most
484 SILC_SCREEN_INPUT_SIZE characters. When COLS - 5 characters is
485 typed the window is cleared and the cursor is moved at the tenth
486 character in the input window. Ten last typed character is then
487 showed at the start of the window. */
488 if (screen->cursor_pos >= (COLS - 5)) {
492 for (i = 0; i < COLS; i++)
493 mvwprintw(win, 0, i, " ");
494 mvwprintw(win, 0, 0, "");
496 /* Show ten last typed characters from the buffer on the screen */
497 waddnstr(win, &buffer[screen->input_pos - 10], 10);
498 screen->cursor_pos = 10;
501 screen->virtual_window++;
504 if (screen->input_pos < screen->input_end) {
505 /* User moved cursor into the typed line. We are not adding
506 character at the end of the line anymore */
508 if (screen->insert == FALSE) {
509 /* Add new character somewhere inside typed line. The input
510 line position is not advanced since a character was replaced
511 by the new character. */
513 buffer[screen->input_pos] = c;
514 screen->cursor_pos++;
516 screen->input_end = screen->input_pos;
518 /* Insert new character somewhere inside typed line. Other
519 characters are moved forward. We must advance the input line
522 wmove(win, 0, screen->cursor_pos + 1);
523 SILC_SCREEN_INPUT_INSERT(buffer, screen->input_pos,
524 c, screen->input_end);
525 screen->cursor_pos++;
530 /* Add new character at the end of input line */
532 buffer[screen->input_pos] = c;
534 screen->cursor_pos++;
535 screen->input_end = screen->input_pos;
538 /* Advance the cursor position. Cursor moves one to rightward always */
542 /* Prints prompt to the input window. Cursors position aftern printing
543 is length of the prompt. */
545 void silc_screen_input_print_prompt(SilcScreen screen, char *prompt)
549 assert(screen != NULL);
550 win = screen->input_win;
553 waddnstr(win, prompt, strlen(prompt));
556 screen->input_pos = strlen(prompt);
557 screen->cursor_pos = strlen(prompt);
558 screen->virtual_window = 0;