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.2 2000/07/05 06:12:05 priikone
30 * Global cosmetic changes.
32 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
33 * Imported from internal CVS/Added Log headers.
38 #include "clientincludes.h"
40 SilcScreen silc_screen_init()
44 new = silc_malloc(sizeof(*new));
45 new->output_win_count = 0;
48 new->virtual_window = 0;
56 silc_screen_create_output_window(new);
57 silc_screen_create_input_window(new);
62 /* Creates one (main) output window. Returns new created physical
65 WINDOW *silc_screen_create_output_window(SilcScreen screen)
67 assert(screen != NULL);
69 screen->output_win = silc_malloc(sizeof(*screen->output_win) * 1);
70 screen->output_win_count = 1;
71 screen->output_win[0] = newwin(LINES - 3, COLS, 1, 0);
72 scrollok(screen->output_win[0], TRUE);
73 idlok(screen->output_win[0], TRUE);
74 wrefresh(screen->output_win[0]);
76 return screen->output_win[0];
79 /* Adds new output window. Return new created physical window. */
81 WINDOW *silc_screen_add_output_window(SilcScreen screen)
85 assert(screen != NULL);
87 screen->output_win = silc_realloc(screen->output_win,
88 (screen->output_win_count + 1) *
89 sizeof(*screen->output_win));
90 i = screen->output_win_count;
91 screen->output_win[i] = newwin(LINES - 3, COLS, 1, 0);
92 scrollok(screen->output_win[i], TRUE);
93 idlok(screen->output_win[i], TRUE);
94 wrefresh(screen->output_win[i]);
95 screen->output_win_count++;
97 return screen->output_win[i];
100 void silc_screen_create_input_window(SilcScreen screen)
102 assert(screen != NULL);
104 screen->input_win = newwin(0, COLS, LINES - 1, 0);
105 scrollok(screen->input_win, TRUE);
106 keypad(screen->input_win, TRUE);
107 wrefresh(screen->input_win);
110 void silc_screen_init_upper_status_line(SilcScreen screen)
115 assert(screen != NULL);
117 /* Create upper status line */
118 screen->upper_stat_line = newwin(0, COLS, 0, 0);
119 scrollok(screen->upper_stat_line, FALSE);
120 wattrset(screen->upper_stat_line, A_REVERSE);
122 /* Print empty line */
123 for (i = 0; i < COLS - 1; i++)
124 mvwprintw(screen->upper_stat_line, 0, i, " ");
126 /* Print stuff with justify */
128 mvwprintw(screen->upper_stat_line, 0, 1, "%s %s",
129 screen->u_stat_line.program_name,
130 screen->u_stat_line.program_version);
132 mvwprintw(screen->upper_stat_line, 0, justify, "[Your Connection: %s]",
133 stat.uconnect_status[stat.uconnect]);
134 mvwprintw(screen->upper_stat_line, 0,
135 (justify + justify + justify), "[SILC: %s]",
136 stat.silc_status[stat.silc]);
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 redrawwin(screen->upper_stat_line);
247 for (i = 0; i < screen->output_win_count; i++) {
248 wrefresh(screen->output_win[i]);
249 redrawwin(screen->output_win[i]);
252 wrefresh(screen->input_win);
253 redrawwin(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)) + 1;
311 screen->input_end = ((screen->virtual_window + 1) * (COLS - 5)) + 1;
312 screen->cursor_pos = (COLS - 5) + 1;
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)) + 1;
415 screen->cursor_pos = (COLS - 5) + 1;
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;