The SILC Project

source navigation ]
identifier search ]
freetext search ]
file search ]

silc/silc/screen.c

  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