1 /*
2
3 screen.c
4
5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7 Copyright (C) 1997 - 2000 Pekka Riikonen
8
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.
13
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.
18
19 */
20 /*
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.
24 */
25 /* XXX: Input line handling is really buggy! */
26 /* $Id: screen.c,v 1.7 2001/03/19 17:54:34 priikone Exp $ */
27
28 #include "clientincludes.h"
29
30 SilcScreen silc_screen_init()
31 {
32 SilcScreen new;
33
34 new = silc_calloc(1, sizeof(*new));
35 new->insert = TRUE;
36
37 initscr();
38 cbreak();
39 nonl();
40 noecho();
41
42 silc_screen_create_output_window(new);
43 silc_screen_create_input_window(new);
44
45 return new;
46 }
47
48 /* Creates one (main) output window. Returns new created physical
49 window. */
50
51 WINDOW *silc_screen_create_output_window(SilcScreen screen)
52 {
53 assert(screen != NULL);
54
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]);
61
62 return screen->output_win[0];
63 }
64
65 /* Adds new output window. Return new created physical window. */
66
67 WINDOW *silc_screen_add_output_window(SilcScreen screen)
68 {
69 int i;
70
71 assert(screen != NULL);
72
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++;
82
83 return screen->output_win[i];
84 }
85
86 void silc_screen_create_input_window(SilcScreen screen)
87 {
88 assert(screen != NULL);
89
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);
94 }
95
96 void silc_screen_init_upper_status_line(SilcScreen screen)
97 {
98 assert(screen != NULL);
99
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);
104
105 silc_screen_print_upper_stat_line(screen);
106 }
107
108 void silc_screen_print_upper_stat_line(SilcScreen screen)
109 {
110 int i;
111 int justify;
112
113 /* Print empty line */
114 for (i = 0; i < COLS - 1; i++)
115 mvwprintw(screen->upper_stat_line, 0, i, " ");
116
117 /* Print stuff with justify */
118 justify = COLS / 5;
119 mvwprintw(screen->upper_stat_line, 0, 1, "%s %s",
120 screen->u_stat_line.program_name,
121 screen->u_stat_line.program_version);
122
123 /* Prints clock on upper stat line */
124 silc_screen_print_clock(screen);
125 wrefresh(screen->upper_stat_line);
126 }
127
128 void silc_screen_init_output_status_line(SilcScreen screen)
129 {
130 int i;
131
132 assert(screen != NULL);
133
134 screen->output_stat_line = silc_calloc(1, sizeof(*screen->output_stat_line));
135
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);
139
140 /* print first just blank line */
141 for (i = 0; i < COLS - 1; i++)
142 mvwprintw(screen->output_stat_line[0], 0, i, " ");
143
144 /* Allocate bottom line */
145 screen->bottom_line = silc_calloc(1, sizeof(*screen->bottom_line));
146
147 wattrset(screen->output_stat_line[0], A_NORMAL);
148 wrefresh(screen->output_stat_line[0]);
149 }
150
151 void silc_screen_print_clock(SilcScreen screen)
152 {
153 time_t curtime;
154 struct tm *tp;
155
156 curtime = time(0);
157 tp = localtime(&curtime);
158
159 mvwprintw(screen->upper_stat_line, 0, COLS - 8, "[%02d:%02d] ",
160 tp->tm_hour, tp->tm_min);
161 wrefresh(screen->upper_stat_line);
162 }
163
164 /* Prints current cursor coordinates on some output stat line */
165
166 void silc_screen_print_coordinates(SilcScreen screen, int win_index)
167 {
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);
173 }
174
175 /* Prints bottom line (the status line) of the screen. */
176
177 void silc_screen_print_bottom_line(SilcScreen screen, int win_index)
178 {
179 char buf[512];
180 SilcScreenBottomLine line = screen->bottom_line;
181 int i, len;
182
183 memset(buf, 0, sizeof(buf));
184
185 if (line->mode) {
186 len = strlen(line->mode);
187 strncat(buf, line->mode, len);
188 }
189
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);
194 }
195
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);
201 }
202
203 if (line->channel) {
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);
208 }
209
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);
216 }
217
218 if (line->umode) {
219 len = strlen(line->umode);
220 strncat(buf, " [", 2);
221 strncat(buf, line->umode, len > SILC_SCREEN_MAX_UMODE_LEN ?
222 SILC_SCREEN_MAX_UMODE_LEN : len);
223 strncat(buf, "]", 2);
224 }
225
226 if (line->away)
227 strncat(buf, " (away)", 8);
228
229 wattrset(screen->output_stat_line[win_index], A_REVERSE);
230
231 for (i = 0; i < COLS - 10; i++)
232 mvwprintw(screen->output_stat_line[win_index], 0, i, " ");
233
234 mvwprintw(screen->output_stat_line[win_index], 0, 0, " %s", buf);
235 silc_screen_print_coordinates(screen, win_index);
236 wrefresh(screen->output_stat_line[win_index]);
237 wattrset(screen->output_stat_line[win_index], A_NORMAL);
238 }
239
240 /* Refresh all windows */
241
242 void silc_screen_refresh_all(SilcScreen screen)
243 {
244 int i;
245
246 assert(screen != NULL);
247
248 wclear(screen->upper_stat_line);
249 silc_screen_print_upper_stat_line(screen);
250
251 wclear(screen->output_stat_line[0]);
252 silc_screen_print_bottom_line(screen, 0);
253 silc_screen_print_coordinates(screen, 0);
254
255 for (i = 0; i < screen->output_win_count; i++) {
256 wclear(screen->output_win[i]);
257 wrefresh(screen->output_win[i]);
258 }
259
260 wclear(screen->input_win);
261 wrefresh(screen->input_win);
262 }
263
264 /* Refreshes a window */
265
266 void silc_screen_refresh_win(WINDOW *win)
267 {
268 assert(win != NULL);
269
270 redrawwin(win);
271 wrefresh(win);
272 }
273
274 /* Resets input window */
275
276 void silc_screen_input_reset(SilcScreen screen)
277 {
278 int i;
279
280 assert(screen != NULL);
281 for (i = 0; i < COLS - 1; i++)
282 mvwprintw(screen->input_win, 0, i, " ");
283 mvwprintw(screen->input_win, 0, 0, "");
284 wrefresh(screen->input_win);
285 screen->input_pos = 0;
286 screen->input_end = 0;
287 screen->cursor_pos = 0;
288 screen->virtual_window = 0;
289 }
290
291 /* Backspace. Removes one character from input windows. */
292
293 void silc_screen_input_backspace(SilcScreen screen)
294 {
295 WINDOW *win;
296 char *buffer;
297
298 assert(screen != NULL);
299 buffer = screen->input_buffer;
300 win = screen->input_win;
301
302 /* Return directly if at the start of input line */
303 if (screen->input_pos == 0)
304 return;
305
306 if (screen->virtual_window) {
307 if (screen->cursor_pos <= 10) {
308 int i;
309
310 /* Clear line */
311 for (i = 0; i < COLS; i++)
312 mvwprintw(win, 0, i, " ");
313 mvwprintw(win, 0, 0, "");
314
315 screen->virtual_window--;
316
317 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
318 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
319 screen->input_end = ((screen->virtual_window + 1) * (COLS - 5));
320 screen->cursor_pos = (COLS - 5);
321 wrefresh(win);
322 }
323 }
324
325 screen->cursor_pos--;
326 screen->input_pos--;
327 screen->input_end--;
328 mvwdelch(win, 0, screen->cursor_pos);
329
330 if (screen->input_pos < screen->input_end)
331 /* Delete from inside the input line */
332 SILC_SCREEN_INPUT_DELETE(buffer, screen->input_pos, screen->input_end);
333 else
334 /* Delete from the end of the input line */
335 buffer[screen->input_pos] = 0;
336
337 wrefresh(win);
338 }
339
340 /* Switches insert on input window on/off */
341
342 void silc_screen_input_insert(SilcScreen screen)
343 {
344 assert(screen != NULL);
345
346 screen->insert = screen->insert == TRUE ? FALSE : TRUE;
347 }
348
349 /* Moves cursor one character length to rightward */
350
351 void silc_screen_input_cursor_right(SilcScreen screen)
352 {
353 WINDOW *win;
354 char *buffer;
355
356 assert(screen != NULL);
357 buffer = screen->input_buffer;
358 win = screen->input_win;
359
360 /* Return directly if we are at the end of input line */
361 if (screen->cursor_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
362 return;
363
364 /* Make sure cursor doesn't advance over the end of the line */
365 if (screen->input_pos >= screen->input_end)
366 return;
367
368 /* When cursor advances enough we switch to new window and show
369 rest of the typed characters on the screen. */
370 if (screen->cursor_pos >= (COLS - 5)) {
371 int i;
372
373 /* Clear line */
374 for (i = 0; i < COLS; i++)
375 mvwprintw(win, 0, i, " ");
376 mvwprintw(win, 0, 0, "");
377
378 waddnstr(win, &buffer[screen->input_pos - 10],
379 ((screen->input_pos - 10) - screen->input_end >= COLS) ?
380 COLS : (screen->input_pos - 10) - screen->input_end);
381 screen->cursor_pos = 10;
382 wrefresh(win);
383
384 screen->virtual_window++;
385 }
386
387 screen->cursor_pos++;
388 screen->input_pos++;
389 wmove(win, 0, screen->cursor_pos);
390 wrefresh(win);
391 }
392
393 /* Moves cursor one character length to leftward */
394
395 void silc_screen_input_cursor_left(SilcScreen screen)
396 {
397 WINDOW *win;
398 char *buffer;
399
400 assert(screen != NULL);
401 buffer = screen->input_buffer;
402 win = screen->input_win;
403
404 /* Return directly if at the start of input line */
405 if (screen->input_pos == 0)
406 return;
407
408 /* When cursor advances enough we switch to new window and show
409 rest of the typed characters on the screen. */
410 if (screen->virtual_window) {
411 if (screen->cursor_pos <= 10) {
412 int i;
413
414 /* Clear line */
415 for (i = 0; i < COLS; i++)
416 mvwprintw(win, 0, i, " ");
417 mvwprintw(win, 0, 0, "");
418
419 screen->virtual_window--;
420
421 waddnstr(win, &buffer[screen->virtual_window * (COLS - 5)], COLS);
422 screen->input_pos = ((screen->virtual_window + 1) * (COLS - 5));
423 screen->cursor_pos = (COLS - 5);
424 wrefresh(win);
425 }
426 }
427
428 screen->cursor_pos--;
429 screen->input_pos--;
430 wmove(win, 0, screen->cursor_pos);
431 wrefresh(win);
432 }
433
434 /* Moves cursor at the very start of the input line */
435
436 void silc_screen_input_cursor_home(SilcScreen screen)
437 {
438 WINDOW *win;
439 char *buffer;
440
441 assert(screen != NULL);
442 buffer = screen->input_buffer;
443 win = screen->input_win;
444
445 wclear(win);
446 waddnstr(win, &buffer[0], COLS);
447 wrefresh(win);
448
449 screen->input_pos = 0;
450 screen->cursor_pos = 0;
451 screen->virtual_window = 0;
452 }
453
454 /* Moves cursor at the very end of the input line */
455
456 void silc_screen_input_cursor_end(SilcScreen screen)
457 {
458 WINDOW *win;
459 char *buffer;
460
461 assert(screen != NULL);
462 buffer = screen->input_buffer;
463 win = screen->input_win;
464
465 wclear(win);
466 waddnstr(win, &buffer[screen->input_end - 10], 10);
467 wrefresh(win);
468
469 screen->input_pos = screen->input_end;
470 screen->cursor_pos = 10;
471 /* XXX */
472 screen->virtual_window = 0;
473 }
474
475 /* Prints typed character into the input window for user to see. Character
476 attributes must be set separately outside this function. */
477
478 void silc_screen_input_print(SilcScreen screen, unsigned char c)
479 {
480 WINDOW *win;
481 char *buffer;
482
483 assert(screen != NULL);
484 buffer = screen->input_buffer;
485 win = screen->input_win;
486
487 /* Return directly if input window is full */
488 if (screen->input_pos >= SILC_SCREEN_INPUT_WIN_SIZE)
489 return;
490
491 /* The input window is COLS wide but one can type into it at most
492 SILC_SCREEN_INPUT_SIZE characters. When COLS - 5 characters is
493 typed the window is cleared and the cursor is moved at the tenth
494 character in the input window. Ten last typed character is then
495 showed at the start of the window. */
496 if (screen->cursor_pos >= (COLS - 5)) {
497 int i;
498
499 /* Clear line */
500 for (i = 0; i < COLS; i++)
501 mvwprintw(win, 0, i, " ");
502 mvwprintw(win, 0, 0, "");
503
504 /* Show ten last typed characters from the buffer on the screen */
505 waddnstr(win, &buffer[screen->input_pos - 10], 10);
506 screen->cursor_pos = 10;
507 wrefresh(win);
508
509 screen->virtual_window++;
510 }
511
512 if (screen->input_pos < screen->input_end) {
513 /* User moved cursor into the typed line. We are not adding
514 character at the end of the line anymore */
515
516 if (screen->insert == FALSE) {
517 /* Add new character somewhere inside typed line. The input
518 line position is not advanced since a character was replaced
519 by the new character. */
520 waddch(win, c);
521 buffer[screen->input_pos] = c;
522 screen->cursor_pos++;
523 screen->input_pos++;
524 screen->input_end = screen->input_pos;
525 } else {
526 /* Insert new character somewhere inside typed line. Other
527 characters are moved forward. We must advance the input line
528 posititon. */
529 winsch(win, c);
530 wmove(win, 0, screen->cursor_pos + 1);
531 SILC_SCREEN_INPUT_INSERT(buffer, screen->input_pos,
532 c, screen->input_end);
533 screen->cursor_pos++;
534 screen->input_pos++;
535 screen->input_end++;
536 }
537 } else {
538 /* Add new character at the end of input line */
539 waddch(win, c);
540 buffer[screen->input_pos] = c;
541 screen->input_pos++;
542 screen->cursor_pos++;
543 screen->input_end = screen->input_pos;
544 }
545
546 /* Advance the cursor position. Cursor moves one to rightward always */
547 wrefresh(win);
548 }
549
550 /* Prints prompt to the input window. Cursors position aftern printing
551 is length of the prompt. */
552
553 void silc_screen_input_print_prompt(SilcScreen screen, char *prompt)
554 {
555 WINDOW *win;
556
557 assert(screen != NULL);
558 win = screen->input_win;
559
560 wclear(win);
561 waddnstr(win, prompt, strlen(prompt));
562 wrefresh(win);
563
564 screen->input_pos = strlen(prompt);
565 screen->cursor_pos = strlen(prompt);
566 screen->virtual_window = 0;
567 }
568
This page was automatically generated by the LXR engine.
Free-text search provided by Glimpse