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.1.1.1 2000/06/27 11:36:56 priikone
30 * Importet from internal CVS/Added Log headers.
35 #include "clientincludes.h"
37 SilcScreen silc_screen_init()
41 new = silc_malloc(sizeof(*new));
43 SILC_LOG_ERROR(("Could not create new screen object"));
47 new->output_win_count = 0;
50 new->virtual_window = 0;
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_malloc(sizeof(*screen->output_win) * 1);
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)
117 assert(screen != NULL);
119 /* Create upper status line */
120 screen->upper_stat_line = newwin(0, COLS, 0, 0);
121 scrollok(screen->upper_stat_line, FALSE);
122 wattrset(screen->upper_stat_line, A_REVERSE);
124 /* Print empty line */
125 for (i = 0; i < COLS - 1; i++)
126 mvwprintw(screen->upper_stat_line, 0, i, " ");
128 /* Print stuff with justify */
130 mvwprintw(screen->upper_stat_line, 0, 1, "%s %s",
131 screen->u_stat_line.program_name,
132 screen->u_stat_line.program_version);
134 mvwprintw(screen->upper_stat_line, 0, justify, "[Your Connection: %s]",
135 stat.uconnect_status[stat.uconnect]);
136 mvwprintw(screen->upper_stat_line, 0,
137 (justify + justify + justify), "[SILC: %s]",
138 stat.silc_status[stat.silc]);
141 /* Prints clock on upper stat line */
142 silc_screen_print_clock(screen);
143 wrefresh(screen->upper_stat_line);
146 void silc_screen_init_output_status_line(SilcScreen screen)
150 assert(screen != NULL);
152 screen->output_stat_line = silc_calloc(1, sizeof(*screen->output_stat_line));
154 screen->output_stat_line[0] = newwin(1, COLS, LINES - 2, 0);
155 scrollok(screen->output_stat_line[0], FALSE);
156 wattrset(screen->output_stat_line[0], A_REVERSE);
158 /* print first just blank line */
159 for (i = 0; i < COLS - 1; i++)
160 mvwprintw(screen->output_stat_line[0], 0, i, " ");
162 /* Allocate bottom line */
163 screen->bottom_line = silc_calloc(1, sizeof(*screen->bottom_line));
165 wattrset(screen->output_stat_line[0], A_NORMAL);
166 wrefresh(screen->output_stat_line[0]);
169 void silc_screen_print_clock(SilcScreen screen)
175 tp = localtime(&curtime);
177 mvwprintw(screen->upper_stat_line, 0, COLS - 8, "[%02d:%02d] ",
178 tp->tm_hour, tp->tm_min);
179 wrefresh(screen->upper_stat_line);
182 /* Prints current cursor coordinates on some output stat line */
184 void silc_screen_print_coordinates(SilcScreen screen, int win_index)
186 wattrset(screen->output_stat_line[win_index], A_REVERSE);
187 mvwprintw(screen->output_stat_line[win_index], 0, COLS - 10,
188 "[%4d,%3d]", screen->input_pos, LINES);
189 wrefresh(screen->output_stat_line[win_index]);
190 wattrset(screen->output_stat_line[win_index], A_NORMAL);
193 /* Prints bottom line (the status line) of the screen. */
195 void silc_screen_print_bottom_line(SilcScreen screen, int win_index)
198 SilcScreenBottomLine line = screen->bottom_line;
201 memset(buf, 0, sizeof(buf));
204 len = strlen(line->mode);
205 strncat(buf, line->mode, len);
208 if (line->nickname) {
209 len = strlen(line->nickname);
210 strncat(buf, line->nickname, len > SILC_SCREEN_MAX_NICK_LEN ?
211 SILC_SCREEN_MAX_NICK_LEN : len);
214 if (line->connection) {
215 len = strlen(line->connection);
216 strncat(buf, " via ", 5);
217 strncat(buf, line->connection, len > SILC_SCREEN_MAX_CONN_LEN ?
218 SILC_SCREEN_MAX_CONN_LEN : len);
222 len = strlen(line->channel);
223 strncat(buf, " ", 1);
224 strncat(buf, line->channel, len > SILC_SCREEN_MAX_CHANNEL_LEN ?
225 SILC_SCREEN_MAX_CHANNEL_LEN : len);
228 wattrset(screen->output_stat_line[win_index], A_REVERSE);
230 for (i = 0; i < COLS - 10; i++)
231 mvwprintw(screen->output_stat_line[win_index], 0, i, " ");
233 mvwprintw(screen->output_stat_line[win_index], 0, 0, " %s", buf);
234 silc_screen_print_coordinates(screen, win_index);
235 wrefresh(screen->output_stat_line[win_index]);
236 wattrset(screen->output_stat_line[win_index], A_NORMAL);
239 /* Refresh all windows */
241 void silc_screen_refresh_all(SilcScreen screen)
245 assert(screen != NULL);
247 redrawwin(screen->upper_stat_line);
249 for (i = 0; i < screen->output_win_count; i++) {
250 wrefresh(screen->output_win[i]);
251 redrawwin(screen->output_win[i]);
254 wrefresh(screen->input_win);
255 redrawwin(screen->input_win);
258 /* Refreshes a window */
260 void silc_screen_refresh_win(WINDOW *win)
268 /* Resets input window */
270 void silc_screen_input_reset(SilcScreen screen)
274 assert(screen != NULL);
275 for (i = 0; i < COLS - 1; i++)
276 mvwprintw(screen->input_win, 0, i, " ");
277 mvwprintw(screen->input_win, 0, 0, "");
278 wrefresh(screen->input_win);
279 screen->input_pos = 0;
280 screen->input_end = 0;
281 screen->cursor_pos = 0;
282 screen->virtual_window = 0;
285 /* Backspace. Removes one character from input windows. */
287 void silc_screen_input_backspace(SilcScreen screen)
292 assert(screen != NULL);
293 buffer = screen->input_buffer;
294 win = screen->input_win;
296 /* Return directly if at the start of input line */
297 if (screen->input_pos == 0)
300 if (screen->virtual_window) {
301 if (screen->cursor_pos <= 10) {
305 for (i = 0; i < COLS; i++)
306 mvwprintw(win, 0, i, " ");
307 mvwprintw(win, 0, 0, "");
309 screen->virtual_window--;
311 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
312 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5)) + 1;
313 screen->input_end = ((screen->virtual_window + 1) * (COLS - 5)) + 1;
314 screen->cursor_pos = (COLS - 5) + 1;
319 screen->cursor_pos--;
322 mvwdelch(win, 0, screen->cursor_pos);
324 if (screen->input_pos < screen->input_end)
325 /* Delete from inside the input line */
326 SILC_SCREEN_INPUT_DELETE(buffer, screen->input_pos, screen->input_end);
328 /* Delete from the end of the input line */
329 buffer[screen->input_pos] = 0;
334 /* Switches insert on input window on/off */
336 void silc_screen_input_insert(SilcScreen screen)
338 assert(screen != NULL);
340 screen->insert = screen->insert == TRUE ? FALSE : TRUE;
343 /* Moves cursor one character length to rightward */
345 void silc_screen_input_cursor_right(SilcScreen screen)
350 assert(screen != NULL);
351 buffer = screen->input_buffer;
352 win = screen->input_win;
354 /* Return directly if we are at the end of input line */
355 if (screen->cursor_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
358 /* Make sure cursor doesn't advance over the end of the line */
359 if (screen->input_pos >= screen->input_end)
362 /* When cursor advances enough we switch to new window and show
363 rest of the typed characters on the screen. */
364 if (screen->cursor_pos >= (COLS - 5)) {
368 for (i = 0; i < COLS; i++)
369 mvwprintw(win, 0, i, " ");
370 mvwprintw(win, 0, 0, "");
372 waddnstr(win, &buffer[screen->input_pos - 10],
373 ((screen->input_pos - 10) - screen->input_end >= COLS) ?
374 COLS : (screen->input_pos - 10) - screen->input_end);
375 screen->cursor_pos = 10;
378 screen->virtual_window++;
381 screen->cursor_pos++;
383 wmove(win, 0, screen->cursor_pos);
387 /* Moves cursor one character length to leftward */
389 void silc_screen_input_cursor_left(SilcScreen screen)
394 assert(screen != NULL);
395 buffer = screen->input_buffer;
396 win = screen->input_win;
398 /* Return directly if at the start of input line */
399 if (screen->input_pos == 0)
402 /* When cursor advances enough we switch to new window and show
403 rest of the typed characters on the screen. */
404 if (screen->virtual_window) {
405 if (screen->cursor_pos <= 10) {
409 for (i = 0; i < COLS; i++)
410 mvwprintw(win, 0, i, " ");
411 mvwprintw(win, 0, 0, "");
413 screen->virtual_window--;
415 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
416 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5)) + 1;
417 screen->cursor_pos = (COLS - 5) + 1;
422 screen->cursor_pos--;
424 wmove(win, 0, screen->cursor_pos);
428 /* Moves cursor at the very start of the input line */
430 void silc_screen_input_cursor_home(SilcScreen screen)
435 assert(screen != NULL);
436 buffer = screen->input_buffer;
437 win = screen->input_win;
440 waddnstr(win, &buffer[0], COLS);
443 screen->input_pos = 0;
444 screen->cursor_pos = 0;
445 screen->virtual_window = 0;
448 /* Moves cursor at the very end of the input line */
450 void silc_screen_input_cursor_end(SilcScreen screen)
455 assert(screen != NULL);
456 buffer = screen->input_buffer;
457 win = screen->input_win;
460 waddnstr(win, &buffer[screen->input_end - 10], 10);
463 screen->input_pos = screen->input_end;
464 screen->cursor_pos = 10;
466 screen->virtual_window = 0;
469 /* Prints typed character into the input window for user to see. Character
470 attributes must be set separately outside this function. */
472 void silc_screen_input_print(SilcScreen screen, unsigned char c)
477 assert(screen != NULL);
478 buffer = screen->input_buffer;
479 win = screen->input_win;
481 /* Return directly if input window is full */
482 if (screen->input_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
485 /* The input window is COLS wide but one can type into it at most
486 SILC_SCREEN_INPUT_SIZE characters. When COLS - 5 characters is
487 typed the window is cleared and the cursor is moved at the tenth
488 character in the input window. Ten last typed character is then
489 showed at the start of the window. */
490 if (screen->cursor_pos >= (COLS - 5)) {
494 for (i = 0; i < COLS; i++)
495 mvwprintw(win, 0, i, " ");
496 mvwprintw(win, 0, 0, "");
498 /* Show ten last typed characters from the buffer on the screen */
499 waddnstr(win, &buffer[screen->input_pos - 10], 10);
500 screen->cursor_pos = 10;
503 screen->virtual_window++;
506 if (screen->input_pos < screen->input_end) {
507 /* User moved cursor into the typed line. We are not adding
508 character at the end of the line anymore */
510 if (screen->insert == FALSE) {
511 /* Add new character somewhere inside typed line. The input
512 line position is not advanced since a character was replaced
513 by the new character. */
515 buffer[screen->input_pos] = c;
516 screen->cursor_pos++;
518 screen->input_end = screen->input_pos;
520 /* Insert new character somewhere inside typed line. Other
521 characters are moved forward. We must advance the input line
524 wmove(win, 0, screen->cursor_pos + 1);
525 SILC_SCREEN_INPUT_INSERT(buffer, screen->input_pos,
526 c, screen->input_end);
527 screen->cursor_pos++;
532 /* Add new character at the end of input line */
534 buffer[screen->input_pos] = c;
536 screen->cursor_pos++;
537 screen->input_end = screen->input_pos;
540 /* Advance the cursor position. Cursor moves one to rightward always */
544 /* Prints prompt to the input window. Cursors position aftern printing
545 is length of the prompt. */
547 void silc_screen_input_print_prompt(SilcScreen screen, char *prompt)
551 assert(screen != NULL);
552 win = screen->input_win;
555 waddnstr(win, prompt, strlen(prompt));
558 screen->input_pos = strlen(prompt);
559 screen->cursor_pos = strlen(prompt);
560 screen->virtual_window = 0;