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.5 2000/07/19 09:19:05 priikone
30 * Enhancements to AWAY command.
32 * Revision 1.4 2000/07/10 05:38:08 priikone
33 * Fixed screen refresh.
35 * Revision 1.3 2000/07/07 06:52:10 priikone
36 * Fixed screen refresh routine.
38 * Revision 1.2 2000/07/05 06:12:05 priikone
39 * Global cosmetic changes.
41 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
42 * Imported from internal CVS/Added Log headers.
47 #include "clientincludes.h"
49 SilcScreen silc_screen_init()
53 new = silc_calloc(1, sizeof(*new));
61 silc_screen_create_output_window(new);
62 silc_screen_create_input_window(new);
67 /* Creates one (main) output window. Returns new created physical
70 WINDOW *silc_screen_create_output_window(SilcScreen screen)
72 assert(screen != NULL);
74 screen->output_win = silc_calloc(1, sizeof(*screen->output_win));
75 screen->output_win_count = 1;
76 screen->output_win[0] = newwin(LINES - 3, COLS, 1, 0);
77 scrollok(screen->output_win[0], TRUE);
78 idlok(screen->output_win[0], TRUE);
79 wrefresh(screen->output_win[0]);
81 return screen->output_win[0];
84 /* Adds new output window. Return new created physical window. */
86 WINDOW *silc_screen_add_output_window(SilcScreen screen)
90 assert(screen != NULL);
92 screen->output_win = silc_realloc(screen->output_win,
93 (screen->output_win_count + 1) *
94 sizeof(*screen->output_win));
95 i = screen->output_win_count;
96 screen->output_win[i] = newwin(LINES - 3, COLS, 1, 0);
97 scrollok(screen->output_win[i], TRUE);
98 idlok(screen->output_win[i], TRUE);
99 wrefresh(screen->output_win[i]);
100 screen->output_win_count++;
102 return screen->output_win[i];
105 void silc_screen_create_input_window(SilcScreen screen)
107 assert(screen != NULL);
109 screen->input_win = newwin(0, COLS, LINES - 1, 0);
110 scrollok(screen->input_win, TRUE);
111 keypad(screen->input_win, TRUE);
112 wrefresh(screen->input_win);
115 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 silc_screen_print_upper_stat_line(screen);
127 void silc_screen_print_upper_stat_line(SilcScreen screen)
132 /* Print empty line */
133 for (i = 0; i < COLS - 1; i++)
134 mvwprintw(screen->upper_stat_line, 0, i, " ");
136 /* Print stuff with justify */
138 mvwprintw(screen->upper_stat_line, 0, 1, "%s %s",
139 screen->u_stat_line.program_name,
140 screen->u_stat_line.program_version);
142 /* Prints clock on upper stat line */
143 silc_screen_print_clock(screen);
144 wrefresh(screen->upper_stat_line);
147 void silc_screen_init_output_status_line(SilcScreen screen)
151 assert(screen != NULL);
153 screen->output_stat_line = silc_calloc(1, sizeof(*screen->output_stat_line));
155 screen->output_stat_line[0] = newwin(1, COLS, LINES - 2, 0);
156 scrollok(screen->output_stat_line[0], FALSE);
157 wattrset(screen->output_stat_line[0], A_REVERSE);
159 /* print first just blank line */
160 for (i = 0; i < COLS - 1; i++)
161 mvwprintw(screen->output_stat_line[0], 0, i, " ");
163 /* Allocate bottom line */
164 screen->bottom_line = silc_calloc(1, sizeof(*screen->bottom_line));
166 wattrset(screen->output_stat_line[0], A_NORMAL);
167 wrefresh(screen->output_stat_line[0]);
170 void silc_screen_print_clock(SilcScreen screen)
176 tp = localtime(&curtime);
178 mvwprintw(screen->upper_stat_line, 0, COLS - 8, "[%02d:%02d] ",
179 tp->tm_hour, tp->tm_min);
180 wrefresh(screen->upper_stat_line);
183 /* Prints current cursor coordinates on some output stat line */
185 void silc_screen_print_coordinates(SilcScreen screen, int win_index)
187 wattrset(screen->output_stat_line[win_index], A_REVERSE);
188 mvwprintw(screen->output_stat_line[win_index], 0, COLS - 10,
189 "[%4d,%3d]", screen->input_pos, LINES);
190 wrefresh(screen->output_stat_line[win_index]);
191 wattrset(screen->output_stat_line[win_index], A_NORMAL);
194 /* Prints bottom line (the status line) of the screen. */
196 void silc_screen_print_bottom_line(SilcScreen screen, int win_index)
199 SilcScreenBottomLine line = screen->bottom_line;
202 memset(buf, 0, sizeof(buf));
205 len = strlen(line->mode);
206 strncat(buf, line->mode, len);
209 if (line->nickname) {
210 len = strlen(line->nickname);
211 strncat(buf, line->nickname, len > SILC_SCREEN_MAX_NICK_LEN ?
212 SILC_SCREEN_MAX_NICK_LEN : len);
215 if (line->connection) {
216 len = strlen(line->connection);
217 strncat(buf, " via ", 5);
218 strncat(buf, line->connection, len > SILC_SCREEN_MAX_CONN_LEN ?
219 SILC_SCREEN_MAX_CONN_LEN : len);
223 len = strlen(line->channel);
224 strncat(buf, " ", 1);
225 strncat(buf, line->channel, len > SILC_SCREEN_MAX_CHANNEL_LEN ?
226 SILC_SCREEN_MAX_CHANNEL_LEN : len);
230 strncat(buf, " (away)", 8);
232 wattrset(screen->output_stat_line[win_index], A_REVERSE);
234 for (i = 0; i < COLS - 10; i++)
235 mvwprintw(screen->output_stat_line[win_index], 0, i, " ");
237 mvwprintw(screen->output_stat_line[win_index], 0, 0, " %s", buf);
238 silc_screen_print_coordinates(screen, win_index);
239 wrefresh(screen->output_stat_line[win_index]);
240 wattrset(screen->output_stat_line[win_index], A_NORMAL);
243 /* Refresh all windows */
245 void silc_screen_refresh_all(SilcScreen screen)
249 assert(screen != NULL);
251 wclear(screen->upper_stat_line);
252 silc_screen_print_upper_stat_line(screen);
254 wclear(screen->output_stat_line[0]);
255 silc_screen_print_bottom_line(screen, 0);
256 silc_screen_print_coordinates(screen, 0);
258 for (i = 0; i < screen->output_win_count; i++) {
259 wclear(screen->output_win[i]);
260 wrefresh(screen->output_win[i]);
263 wclear(screen->input_win);
264 wrefresh(screen->input_win);
267 /* Refreshes a window */
269 void silc_screen_refresh_win(WINDOW *win)
277 /* Resets input window */
279 void silc_screen_input_reset(SilcScreen screen)
283 assert(screen != NULL);
284 for (i = 0; i < COLS - 1; i++)
285 mvwprintw(screen->input_win, 0, i, " ");
286 mvwprintw(screen->input_win, 0, 0, "");
287 wrefresh(screen->input_win);
288 screen->input_pos = 0;
289 screen->input_end = 0;
290 screen->cursor_pos = 0;
291 screen->virtual_window = 0;
294 /* Backspace. Removes one character from input windows. */
296 void silc_screen_input_backspace(SilcScreen screen)
301 assert(screen != NULL);
302 buffer = screen->input_buffer;
303 win = screen->input_win;
305 /* Return directly if at the start of input line */
306 if (screen->input_pos == 0)
309 if (screen->virtual_window) {
310 if (screen->cursor_pos <= 10) {
314 for (i = 0; i < COLS; i++)
315 mvwprintw(win, 0, i, " ");
316 mvwprintw(win, 0, 0, "");
318 screen->virtual_window--;
320 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
321 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
322 screen->input_end = ((screen->virtual_window + 1) * (COLS - 5));
323 screen->cursor_pos = (COLS - 5);
328 screen->cursor_pos--;
331 mvwdelch(win, 0, screen->cursor_pos);
333 if (screen->input_pos < screen->input_end)
334 /* Delete from inside the input line */
335 SILC_SCREEN_INPUT_DELETE(buffer, screen->input_pos, screen->input_end);
337 /* Delete from the end of the input line */
338 buffer[screen->input_pos] = 0;
343 /* Switches insert on input window on/off */
345 void silc_screen_input_insert(SilcScreen screen)
347 assert(screen != NULL);
349 screen->insert = screen->insert == TRUE ? FALSE : TRUE;
352 /* Moves cursor one character length to rightward */
354 void silc_screen_input_cursor_right(SilcScreen screen)
359 assert(screen != NULL);
360 buffer = screen->input_buffer;
361 win = screen->input_win;
363 /* Return directly if we are at the end of input line */
364 if (screen->cursor_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
367 /* Make sure cursor doesn't advance over the end of the line */
368 if (screen->input_pos >= screen->input_end)
371 /* When cursor advances enough we switch to new window and show
372 rest of the typed characters on the screen. */
373 if (screen->cursor_pos >= (COLS - 5)) {
377 for (i = 0; i < COLS; i++)
378 mvwprintw(win, 0, i, " ");
379 mvwprintw(win, 0, 0, "");
381 waddnstr(win, &buffer[screen->input_pos - 10],
382 ((screen->input_pos - 10) - screen->input_end >= COLS) ?
383 COLS : (screen->input_pos - 10) - screen->input_end);
384 screen->cursor_pos = 10;
387 screen->virtual_window++;
390 screen->cursor_pos++;
392 wmove(win, 0, screen->cursor_pos);
396 /* Moves cursor one character length to leftward */
398 void silc_screen_input_cursor_left(SilcScreen screen)
403 assert(screen != NULL);
404 buffer = screen->input_buffer;
405 win = screen->input_win;
407 /* Return directly if at the start of input line */
408 if (screen->input_pos == 0)
411 /* When cursor advances enough we switch to new window and show
412 rest of the typed characters on the screen. */
413 if (screen->virtual_window) {
414 if (screen->cursor_pos <= 10) {
418 for (i = 0; i < COLS; i++)
419 mvwprintw(win, 0, i, " ");
420 mvwprintw(win, 0, 0, "");
422 screen->virtual_window--;
424 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
425 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
426 screen->cursor_pos = (COLS - 5);
431 screen->cursor_pos--;
433 wmove(win, 0, screen->cursor_pos);
437 /* Moves cursor at the very start of the input line */
439 void silc_screen_input_cursor_home(SilcScreen screen)
444 assert(screen != NULL);
445 buffer = screen->input_buffer;
446 win = screen->input_win;
449 waddnstr(win, &buffer[0], COLS);
452 screen->input_pos = 0;
453 screen->cursor_pos = 0;
454 screen->virtual_window = 0;
457 /* Moves cursor at the very end of the input line */
459 void silc_screen_input_cursor_end(SilcScreen screen)
464 assert(screen != NULL);
465 buffer = screen->input_buffer;
466 win = screen->input_win;
469 waddnstr(win, &buffer[screen->input_end - 10], 10);
472 screen->input_pos = screen->input_end;
473 screen->cursor_pos = 10;
475 screen->virtual_window = 0;
478 /* Prints typed character into the input window for user to see. Character
479 attributes must be set separately outside this function. */
481 void silc_screen_input_print(SilcScreen screen, unsigned char c)
486 assert(screen != NULL);
487 buffer = screen->input_buffer;
488 win = screen->input_win;
490 /* Return directly if input window is full */
491 if (screen->input_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
494 /* The input window is COLS wide but one can type into it at most
495 SILC_SCREEN_INPUT_SIZE characters. When COLS - 5 characters is
496 typed the window is cleared and the cursor is moved at the tenth
497 character in the input window. Ten last typed character is then
498 showed at the start of the window. */
499 if (screen->cursor_pos >= (COLS - 5)) {
503 for (i = 0; i < COLS; i++)
504 mvwprintw(win, 0, i, " ");
505 mvwprintw(win, 0, 0, "");
507 /* Show ten last typed characters from the buffer on the screen */
508 waddnstr(win, &buffer[screen->input_pos - 10], 10);
509 screen->cursor_pos = 10;
512 screen->virtual_window++;
515 if (screen->input_pos < screen->input_end) {
516 /* User moved cursor into the typed line. We are not adding
517 character at the end of the line anymore */
519 if (screen->insert == FALSE) {
520 /* Add new character somewhere inside typed line. The input
521 line position is not advanced since a character was replaced
522 by the new character. */
524 buffer[screen->input_pos] = c;
525 screen->cursor_pos++;
527 screen->input_end = screen->input_pos;
529 /* Insert new character somewhere inside typed line. Other
530 characters are moved forward. We must advance the input line
533 wmove(win, 0, screen->cursor_pos + 1);
534 SILC_SCREEN_INPUT_INSERT(buffer, screen->input_pos,
535 c, screen->input_end);
536 screen->cursor_pos++;
541 /* Add new character at the end of input line */
543 buffer[screen->input_pos] = c;
545 screen->cursor_pos++;
546 screen->input_end = screen->input_pos;
549 /* Advance the cursor position. Cursor moves one to rightward always */
553 /* Prints prompt to the input window. Cursors position aftern printing
554 is length of the prompt. */
556 void silc_screen_input_print_prompt(SilcScreen screen, char *prompt)
560 assert(screen != NULL);
561 win = screen->input_win;
564 waddnstr(win, prompt, strlen(prompt));
567 screen->input_pos = strlen(prompt);
568 screen->cursor_pos = strlen(prompt);
569 screen->virtual_window = 0;