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.3 2000/07/07 06:52:10 priikone
30 * Fixed screen refresh routine.
32 * Revision 1.2 2000/07/05 06:12:05 priikone
33 * Global cosmetic changes.
35 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
36 * Imported from internal CVS/Added Log headers.
41 #include "clientincludes.h"
43 SilcScreen silc_screen_init()
47 new = silc_malloc(sizeof(*new));
48 new->output_win_count = 0;
51 new->virtual_window = 0;
59 silc_screen_create_output_window(new);
60 silc_screen_create_input_window(new);
65 /* Creates one (main) output window. Returns new created physical
68 WINDOW *silc_screen_create_output_window(SilcScreen screen)
70 assert(screen != NULL);
72 screen->output_win = silc_malloc(sizeof(*screen->output_win) * 1);
73 screen->output_win_count = 1;
74 screen->output_win[0] = newwin(LINES - 3, COLS, 1, 0);
75 scrollok(screen->output_win[0], TRUE);
76 idlok(screen->output_win[0], TRUE);
77 wrefresh(screen->output_win[0]);
79 return screen->output_win[0];
82 /* Adds new output window. Return new created physical window. */
84 WINDOW *silc_screen_add_output_window(SilcScreen screen)
88 assert(screen != NULL);
90 screen->output_win = silc_realloc(screen->output_win,
91 (screen->output_win_count + 1) *
92 sizeof(*screen->output_win));
93 i = screen->output_win_count;
94 screen->output_win[i] = newwin(LINES - 3, COLS, 1, 0);
95 scrollok(screen->output_win[i], TRUE);
96 idlok(screen->output_win[i], TRUE);
97 wrefresh(screen->output_win[i]);
98 screen->output_win_count++;
100 return screen->output_win[i];
103 void silc_screen_create_input_window(SilcScreen screen)
105 assert(screen != NULL);
107 screen->input_win = newwin(0, COLS, LINES - 1, 0);
108 scrollok(screen->input_win, TRUE);
109 keypad(screen->input_win, TRUE);
110 wrefresh(screen->input_win);
113 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 silc_screen_print_upper_stat_line(screen);
125 void silc_screen_print_upper_stat_line(SilcScreen screen)
130 /* Print empty line */
131 for (i = 0; i < COLS - 1; i++)
132 mvwprintw(screen->upper_stat_line, 0, i, " ");
134 /* Print stuff with justify */
136 mvwprintw(screen->upper_stat_line, 0, 1, "%s %s",
137 screen->u_stat_line.program_name,
138 screen->u_stat_line.program_version);
140 /* Prints clock on upper stat line */
141 silc_screen_print_clock(screen);
142 wrefresh(screen->upper_stat_line);
145 void silc_screen_init_output_status_line(SilcScreen screen)
149 assert(screen != NULL);
151 screen->output_stat_line = silc_calloc(1, sizeof(*screen->output_stat_line));
153 screen->output_stat_line[0] = newwin(1, COLS, LINES - 2, 0);
154 scrollok(screen->output_stat_line[0], FALSE);
155 wattrset(screen->output_stat_line[0], A_REVERSE);
157 /* print first just blank line */
158 for (i = 0; i < COLS - 1; i++)
159 mvwprintw(screen->output_stat_line[0], 0, i, " ");
161 /* Allocate bottom line */
162 screen->bottom_line = silc_calloc(1, sizeof(*screen->bottom_line));
164 wattrset(screen->output_stat_line[0], A_NORMAL);
165 wrefresh(screen->output_stat_line[0]);
168 void silc_screen_print_clock(SilcScreen screen)
174 tp = localtime(&curtime);
176 mvwprintw(screen->upper_stat_line, 0, COLS - 8, "[%02d:%02d] ",
177 tp->tm_hour, tp->tm_min);
178 wrefresh(screen->upper_stat_line);
181 /* Prints current cursor coordinates on some output stat line */
183 void silc_screen_print_coordinates(SilcScreen screen, int win_index)
185 wattrset(screen->output_stat_line[win_index], A_REVERSE);
186 mvwprintw(screen->output_stat_line[win_index], 0, COLS - 10,
187 "[%4d,%3d]", screen->input_pos, LINES);
188 wrefresh(screen->output_stat_line[win_index]);
189 wattrset(screen->output_stat_line[win_index], A_NORMAL);
192 /* Prints bottom line (the status line) of the screen. */
194 void silc_screen_print_bottom_line(SilcScreen screen, int win_index)
197 SilcScreenBottomLine line = screen->bottom_line;
200 memset(buf, 0, sizeof(buf));
203 len = strlen(line->mode);
204 strncat(buf, line->mode, len);
207 if (line->nickname) {
208 len = strlen(line->nickname);
209 strncat(buf, line->nickname, len > SILC_SCREEN_MAX_NICK_LEN ?
210 SILC_SCREEN_MAX_NICK_LEN : len);
213 if (line->connection) {
214 len = strlen(line->connection);
215 strncat(buf, " via ", 5);
216 strncat(buf, line->connection, len > SILC_SCREEN_MAX_CONN_LEN ?
217 SILC_SCREEN_MAX_CONN_LEN : len);
221 len = strlen(line->channel);
222 strncat(buf, " ", 1);
223 strncat(buf, line->channel, len > SILC_SCREEN_MAX_CHANNEL_LEN ?
224 SILC_SCREEN_MAX_CHANNEL_LEN : len);
227 wattrset(screen->output_stat_line[win_index], A_REVERSE);
229 for (i = 0; i < COLS - 10; i++)
230 mvwprintw(screen->output_stat_line[win_index], 0, i, " ");
232 mvwprintw(screen->output_stat_line[win_index], 0, 0, " %s", buf);
233 silc_screen_print_coordinates(screen, win_index);
234 wrefresh(screen->output_stat_line[win_index]);
235 wattrset(screen->output_stat_line[win_index], A_NORMAL);
238 /* Refresh all windows */
240 void silc_screen_refresh_all(SilcScreen screen)
244 assert(screen != NULL);
246 wclear(screen->upper_stat_line);
247 silc_screen_print_upper_stat_line(screen);
249 wclear(screen->output_stat_line[0]);
250 silc_screen_print_bottom_line(screen, 0);
251 silc_screen_print_coordinates(screen, 0);
253 for (i = 0; i < screen->output_win_count; i++) {
254 wclear(screen->output_win[i]);
255 wrefresh(screen->output_win[i]);
258 wclear(screen->input_win);
259 wrefresh(screen->input_win);
262 /* Refreshes a window */
264 void silc_screen_refresh_win(WINDOW *win)
272 /* Resets input window */
274 void silc_screen_input_reset(SilcScreen screen)
278 assert(screen != NULL);
279 for (i = 0; i < COLS - 1; i++)
280 mvwprintw(screen->input_win, 0, i, " ");
281 mvwprintw(screen->input_win, 0, 0, "");
282 wrefresh(screen->input_win);
283 screen->input_pos = 0;
284 screen->input_end = 0;
285 screen->cursor_pos = 0;
286 screen->virtual_window = 0;
289 /* Backspace. Removes one character from input windows. */
291 void silc_screen_input_backspace(SilcScreen screen)
296 assert(screen != NULL);
297 buffer = screen->input_buffer;
298 win = screen->input_win;
300 /* Return directly if at the start of input line */
301 if (screen->input_pos == 0)
304 if (screen->virtual_window) {
305 if (screen->cursor_pos <= 10) {
309 for (i = 0; i < COLS; i++)
310 mvwprintw(win, 0, i, " ");
311 mvwprintw(win, 0, 0, "");
313 screen->virtual_window--;
315 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
316 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5)) + 1;
317 screen->input_end = ((screen->virtual_window + 1) * (COLS - 5)) + 1;
318 screen->cursor_pos = (COLS - 5) + 1;
323 screen->cursor_pos--;
326 mvwdelch(win, 0, screen->cursor_pos);
328 if (screen->input_pos < screen->input_end)
329 /* Delete from inside the input line */
330 SILC_SCREEN_INPUT_DELETE(buffer, screen->input_pos, screen->input_end);
332 /* Delete from the end of the input line */
333 buffer[screen->input_pos] = 0;
338 /* Switches insert on input window on/off */
340 void silc_screen_input_insert(SilcScreen screen)
342 assert(screen != NULL);
344 screen->insert = screen->insert == TRUE ? FALSE : TRUE;
347 /* Moves cursor one character length to rightward */
349 void silc_screen_input_cursor_right(SilcScreen screen)
354 assert(screen != NULL);
355 buffer = screen->input_buffer;
356 win = screen->input_win;
358 /* Return directly if we are at the end of input line */
359 if (screen->cursor_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
362 /* Make sure cursor doesn't advance over the end of the line */
363 if (screen->input_pos >= screen->input_end)
366 /* When cursor advances enough we switch to new window and show
367 rest of the typed characters on the screen. */
368 if (screen->cursor_pos >= (COLS - 5)) {
372 for (i = 0; i < COLS; i++)
373 mvwprintw(win, 0, i, " ");
374 mvwprintw(win, 0, 0, "");
376 waddnstr(win, &buffer[screen->input_pos - 10],
377 ((screen->input_pos - 10) - screen->input_end >= COLS) ?
378 COLS : (screen->input_pos - 10) - screen->input_end);
379 screen->cursor_pos = 10;
382 screen->virtual_window++;
385 screen->cursor_pos++;
387 wmove(win, 0, screen->cursor_pos);
391 /* Moves cursor one character length to leftward */
393 void silc_screen_input_cursor_left(SilcScreen screen)
398 assert(screen != NULL);
399 buffer = screen->input_buffer;
400 win = screen->input_win;
402 /* Return directly if at the start of input line */
403 if (screen->input_pos == 0)
406 /* When cursor advances enough we switch to new window and show
407 rest of the typed characters on the screen. */
408 if (screen->virtual_window) {
409 if (screen->cursor_pos <= 10) {
413 for (i = 0; i < COLS; i++)
414 mvwprintw(win, 0, i, " ");
415 mvwprintw(win, 0, 0, "");
417 screen->virtual_window--;
419 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
420 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5)) + 1;
421 screen->cursor_pos = (COLS - 5) + 1;
426 screen->cursor_pos--;
428 wmove(win, 0, screen->cursor_pos);
432 /* Moves cursor at the very start of the input line */
434 void silc_screen_input_cursor_home(SilcScreen screen)
439 assert(screen != NULL);
440 buffer = screen->input_buffer;
441 win = screen->input_win;
444 waddnstr(win, &buffer[0], COLS);
447 screen->input_pos = 0;
448 screen->cursor_pos = 0;
449 screen->virtual_window = 0;
452 /* Moves cursor at the very end of the input line */
454 void silc_screen_input_cursor_end(SilcScreen screen)
459 assert(screen != NULL);
460 buffer = screen->input_buffer;
461 win = screen->input_win;
464 waddnstr(win, &buffer[screen->input_end - 10], 10);
467 screen->input_pos = screen->input_end;
468 screen->cursor_pos = 10;
470 screen->virtual_window = 0;
473 /* Prints typed character into the input window for user to see. Character
474 attributes must be set separately outside this function. */
476 void silc_screen_input_print(SilcScreen screen, unsigned char c)
481 assert(screen != NULL);
482 buffer = screen->input_buffer;
483 win = screen->input_win;
485 /* Return directly if input window is full */
486 if (screen->input_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
489 /* The input window is COLS wide but one can type into it at most
490 SILC_SCREEN_INPUT_SIZE characters. When COLS - 5 characters is
491 typed the window is cleared and the cursor is moved at the tenth
492 character in the input window. Ten last typed character is then
493 showed at the start of the window. */
494 if (screen->cursor_pos >= (COLS - 5)) {
498 for (i = 0; i < COLS; i++)
499 mvwprintw(win, 0, i, " ");
500 mvwprintw(win, 0, 0, "");
502 /* Show ten last typed characters from the buffer on the screen */
503 waddnstr(win, &buffer[screen->input_pos - 10], 10);
504 screen->cursor_pos = 10;
507 screen->virtual_window++;
510 if (screen->input_pos < screen->input_end) {
511 /* User moved cursor into the typed line. We are not adding
512 character at the end of the line anymore */
514 if (screen->insert == FALSE) {
515 /* Add new character somewhere inside typed line. The input
516 line position is not advanced since a character was replaced
517 by the new character. */
519 buffer[screen->input_pos] = c;
520 screen->cursor_pos++;
522 screen->input_end = screen->input_pos;
524 /* Insert new character somewhere inside typed line. Other
525 characters are moved forward. We must advance the input line
528 wmove(win, 0, screen->cursor_pos + 1);
529 SILC_SCREEN_INPUT_INSERT(buffer, screen->input_pos,
530 c, screen->input_end);
531 screen->cursor_pos++;
536 /* Add new character at the end of input line */
538 buffer[screen->input_pos] = c;
540 screen->cursor_pos++;
541 screen->input_end = screen->input_pos;
544 /* Advance the cursor position. Cursor moves one to rightward always */
548 /* Prints prompt to the input window. Cursors position aftern printing
549 is length of the prompt. */
551 void silc_screen_input_print_prompt(SilcScreen screen, char *prompt)
555 assert(screen != NULL);
556 win = screen->input_win;
559 waddnstr(win, prompt, strlen(prompt));
562 screen->input_pos = strlen(prompt);
563 screen->cursor_pos = strlen(prompt);
564 screen->virtual_window = 0;