]> jfr.im git - irc.git/blame - software/ircd/www.irc.org/ftp/irc/clients/vms/ircII-for-vms/window.c
init
[irc.git] / software / ircd / www.irc.org / ftp / irc / clients / vms / ircII-for-vms / window.c
CommitLineData
3bd189cb
JR
1/* Tell any include files that we are in WINDOW */
2#define IN_WINDOW
3
4#include <stdio.h>
5#include <descrip.h>
6#ifdef __GNUC__
7#define SMG$M_ERASE_PBD 1
8#define SMG$M_ERASE_LINE 1
9#define SMG$M_ERASE_TO_EOL 2
10#define SMG$M_BOLD 1
11#define SMG$M_REVERSE 2
12#define SMG$M_UNDERLINE 8
13#define SMG$M_WRAP_CHAR 1
14#define SMG$M_UP 1
15#else
16#include <smgdef.h>
17#endif
18#include <ssdef.h>
19#include <string.h>
20#include <stdlib.h>
21#include <starlet.h>
22#include <smg$routines.h>
23#include <lib$routines.h>
24
25#include "base_includes.h"
26#include "list.h"
27#include <stdarg.h>
28#include "server_i.h"
29#include "chan.h"
30#include "alias.h"
31#include "window_i.h"
32#include "system.h"
33#include "sock.h"
34#include "winfunc.h"
35#include "inp.h"
36#include "queue.h"
37#include "on.h"
38#include "list.h"
39
40static void sl_away(), sl_window(), sl_channel(), sl_time();
41static void sl_query(), sl_chanmode(), sl_hold_lines(), sl_user();
42static void sl_insert(), sl_overwrite(), sl_activity();
43
44extern int log_level;
45extern server_ptr gsrv;
46extern win_ptr outwin, back_win;
47
48struct hold_list {
49 hold_ptr next; /* Next one in the list */
50 int len; /* How long is this string? */
51 char *str; /* This must be at the end of the structure */
52 char *att;
53};
54
55struct pasteboard {
56 int id, maxrows, maxcols;
57} pb;
58
59struct replace{
60 char trigger[4];
61 void (*replace)();
62};
63
64win_ptr awins = NW;
65extern win_ptr gwin;
66
67static unsigned inwin = 0;
68static int pl;
69int max_win_num = 1;
70int DUMB = FALSE;
71static int start_row = 1;
72extern int INPUT_DEFINED;
73
74/* -------------------------------------------------------------------------*/
75win_ptr get_curr_win(void)
76{
77 return gwin;
78}
79
80/* -------------------------------------------------------------------------*/
81win_mode win_getmode(win_ptr win)
82{
83 return win?win->mode:NULL;
84}
85void win_setmode(win_ptr win, win_mode newmode)
86{
87 if (win) win->mode = newmode;
88}
89/* -------------------------------------------------------------------------*/
90win_ptr next_window(win_ptr win)
91{
92 if (!win) return awins;
93 return win->next;
94}
95head_ptr get_window_lastlog(win_ptr win)
96{
97 if (!win) return NULL;
98 return win->lastlog;
99}
100server_ptr get_window_server(win_ptr win)
101{
102 if (!win) return NULL;
103 return win->server;
104}
105void set_window_server(win_ptr win, server_ptr srv)
106{
107 if (win) win->server = srv;
108}
109
110/* -------------------------------------------------------------------------*/
111static void getx(int *r)
112{
113 if (!inwin) *r = 0;
114 else *r = smg$cursor_column(&inwin);
115}
116
117/* -------------------------------------------------------------------------*/
118void win_serverset(server_ptr s)
119{
120 if (gwin) gwin->server = s;
121 gsrv = s;
122 reset_outwin();
123}
124
125/* -------------------------------------------------------------------------*/
126/* "%D", NULL, /* May contain %D (user) */
127/* "%H", NULL, /* Hold mode */
128/* "%M", NULL, /* May contain %M (number of mail) */
129/* "%S", NULL, /* May contain %S (servername) */
130/* "%@", NULL, /* chanop */
131/* "%*", NULL, /* Are you oper? */
132/* "%#", NULL, /* May contain %# (user mode) */
133/* -------------------------------------------------------------------------*/
134static struct replace status_list[] =
135{
136 { {"%+"}, sl_chanmode} , /* May contation %+ */
137 { {"%A"}, sl_away} ,
138 { {"%B"}, sl_hold_lines}, /* May contain %B (held lines) */
139 { {"%C"}, sl_channel} , /* May contain %C (channel) */
140 { {"%F"}, sl_activity} , /* May contain %F (activity) */
141 { {"%I"}, sl_insert} , /* insert mode */
142 { {"%N"}, sl_nick} , /* current nick */
143 { {"%O"}, sl_overwrite} , /* overwrite mode */
144 { {"%Q"}, sl_query} , /* May contain %Q (query user) */
145 { {"%R"}, sl_window2}, /* chanop */
146 { {"%T"}, sl_time} ,
147 { {"%U"}, sl_user} ,
148 { {"%W"}, sl_window} ,
149 { {""} , NULL}
150};
151
152/* -------------------------------------------------------------------------
153 * scan through the windows and look for the window that has it's window
154 * level set to type.
155 * ------------------------------------------------------------------------- */
156
157win_ptr type_winget(server, type)
158 server_ptr server;
159 int type;
160{
161 win_ptr walk, serv = NW;
162 for (walk=awins; walk; walk = walk->next)
163 if (walk->server == server)
164 if (walk->wlevel & type) return walk;
165 else serv = walk;
166 if (gwin && gwin->server == server) return gwin;
167 if (outwin && outwin->server == server) return outwin;
168 return serv;
169}
170
171void reset_outwin(void)
172{
173 outwin = type_winget(gsrv, CRAP);
174}
175
176/* -------------------------------------------------------------------------
177 * Delete all of the windows and the pasteboard that we have created
178 * ------------------------------------------------------------------------- */
179static void delete_a_window(win_ptr win)
180{
181 int status;
182 if (win->id) status = smg$unpaste_virtual_display(&win->id, &pb.id);
183 if (win->id) status = smg$delete_virtual_display(&win->id);
184 if (win->status) status = smg$unpaste_virtual_display(&win->status, &pb.id);
185 if (win->status) status = smg$delete_virtual_display(&win->status);
186}
187
188void delete_windows(void)
189{
190 win_ptr walk;
191 int flags = SMG$M_ERASE_PBD, status;
192
193 smg$unpaste_virtual_display(&inwin, &pb.id);
194 smg$delete_virtual_display(&inwin);
195 inwin = 0;
196 for (walk=awins; walk; walk = walk->next) delete_a_window(walk);
197 awins = NULL;
198 if (pb.id!=-1) status = smg$delete_pasteboard(&pb.id, &flags);
199}
200
201/* ------------------------------------------------------------------------- */
202/* This routine must never be called from ast level. It disables ast's */
203/* before calling a non-reetrant routine. */
204/* ------------------------------------------------------------------------- */
205void putcursor(x)
206 int x;
207{
208 unsigned long current;
209 int status, old, row = 1;
210 if (!inwin) return;
211 old = sys$setast(0);
212/*
213 status = smg$find_cursor_display(&pb.id, &current, 0, 0);
214 if (current != inwin) {
215 if (gwin) status = smg$set_cursor_abs(&gwin->id, &row, &row);
216*/
217 status = smg$set_cursor_abs(&inwin, &row, &x);
218/* } */
219 if (old == SS$_WASSET) (void)sys$setast(1);
220}
221
222/* ------------------------------------------------------------------------- */
223/* ------------------------------------------------------------------------- */
224/* Following are the functions that are called when a user uses /window */
225/* ------------------------------------------------------------------------- */
226void window_reorder(void)
227{
228 win_ptr top = NW, walk, f, b, temp;
229 for (walk = awins; walk; walk = temp) {
230 temp = walk->next;
231 if (walk->hidden)
232 for (b = NW, f = top; f ; b = f, f = f->next) ;
233 else
234 for (b = NW, f = top; f && (f->p_y < walk->p_y); b = f, f = f->next) ;
235 walk->next = f;
236 if (b) b->next = walk;
237 else top = walk;
238 }
239 awins = top;
240}
241
242/* ------------------------------------------------------------------------- */
243static int w_s;
244static int curr_scroll = 0;
245void scroll_with_recall(int lines)
246{
247 char *str;
248 unsigned long flag = SMG$M_UP, loop;
249 if ((curr_scroll + lines) > 0) lines = -curr_scroll;
250 if (lines < 0) { lines = -lines; flag = SMG$M_DOWN; }
251 w_s = smg$scroll_display_area(&gwin->id, 0, 0, 0, 0, &flag, &lines);
252 if (!(w_s & 1)) lib$signal(w_s);
253 if (flag == SMG$M_DOWN) {
254 for (loop=0;loop<lines;loop++)
255 {
256 str = get_prev_list(gwin->lastlog, TRUE, FALSE);
257 if (str) write_raw_to_screen(lines - loop, 1, TRUE, str);
258 else lines = loop - 1;
259 }
260 curr_scroll -= lines;
261 gwin->line += lines;
262 } else {
263 curr_scroll += lines;
264 gwin->line -= lines;
265 }
266}
267/* ------------------------------------------------------------------------- */
268void window_do_scroll(win_ptr win, int lines)
269{
270 unsigned long flag = SMG$M_UP;
271 if (lines < 0) { lines = -lines; flag = SMG$M_DOWN; }
272 win->line -= lines;
273 w_s = smg$scroll_display_area(&win->id, 0, 0, 0, 0, &flag, &lines);
274 if (!(w_s & 1)) lib$signal(w_s);
275}
276/* ------------------------------------------------------------------------- */
277static void window_change_size(win_ptr win, int lines, int columns)
278{
279 win->m_line = lines;
280 win->m_column = columns;
281 w_s = smg$change_virtual_display(&win->id, &win->m_line,
282 &win->m_column, 0, 0, 0);
283 if (!(w_s & 1)) lib$signal(w_s);
284}
285/* ------------------------------------------------------------------------- */
286static void window_move_window(win_ptr win, int x, int y)
287{
288 win->p_x = x;
289 win->p_y = y;
290 w_s = smg$move_virtual_display(&win->id, &pb.id, &win->p_y, &win->p_x, 0);
291 if (!(w_s & 1)) lib$signal(w_s);
292}
293/* ------------------------------------------------------------------------- */
294static void window_check_scroll(win_ptr win)
295{
296 int scroll;
297/* say("window check scroll %d %d", win->line, win->m_line); */
298 scroll = win->line - win->m_line;
299 if (scroll>0)
300 {
301 win->line = win->m_line;
302 w_s = smg$scroll_display_area(&win->id, 0, 0, 0, 0, 0, &scroll);
303 if (!(w_s & 1)) lib$signal(w_s);
304 w_s = smg$set_display_scroll_region(&win->id, &start_row,
305 &win->m_line);
306 if (!(w_s & 1)) lib$signal(w_s);
307 }
308}
309/* ------------------------------------------------------------------------- */
310static void window_move_status(win_ptr win)
311{
312 int dummy;
313 dummy = win->p_y + win->m_line - 1;
314 w_s = smg$move_virtual_display(&win->status, &pb.id, &dummy, &win->p_x, 0);
315 if (!(w_s & 1)) lib$signal(w_s);
316}
317/* ------------------------------------------------------------------------- */
318static int off_counter = 0;
319
320void update_off(void)
321{
322 if (off_counter++) return;
323 smg$begin_pasteboard_update(&pb.id);
324}
325void update_on(void)
326{
327 off_counter--;
328 if (off_counter>0) return;
329 off_counter = 0;
330 smg$end_pasteboard_update(&pb.id);
331}
332
333/* ------------------------------------------------------------------------- */
334win_ptr window_exists(int num)
335{
336 win_ptr loop;
337 for (loop=awins;loop;loop=loop->next)
338 if (loop->num == num) return loop;
339 return (win_ptr)NW;
340}
341
342/* ------------------------------------------------------------------------- */
343void window_rawshow(win_ptr win, int x, int y)
344{
345 int loop, count;
346 win->p_x = x;
347 win->p_y = y;
348 w_s = smg$paste_virtual_display(&win->id, &pb.id, &y, &x, 0);
349 if (!(w_s & 1)) lib$signal(w_s);
350 count = y + win->m_line - 1;
351 win->hidden = FALSE;
352 updatestatwin();
353 w_s = smg$paste_virtual_display(&win->status, &pb.id, &count, &x, 0);
354 if (!(w_s & 1)) lib$signal(w_s);
355 win->activity = win->notified = 0;
356}
357
358/* ------------------------------------------------------------------------- */
359static void window_rawhide(win_ptr win)
360{
361 w_s = smg$unpaste_virtual_display(&win->id, &pb.id);
362 if (!(w_s & 1)) lib$signal(w_s);
363 if (win->status) (void)smg$unpaste_virtual_display(&win->status, &pb.id);
364 win->hidden = TRUE;
365}
366
367/* ------------------------------------------------------------------------- */
368/* ------------------------------------------------------------------------- */
369int hidden(win_ptr win)
370{
371 return (win->hidden);
372}
373
374/* ------------------------------------------------------------------------- */
375void window_setsize(win_ptr win, int x, int y)
376{
377 int status, scroll, dummy, col = 1;
378 if (!is_window(win)) return;
379 update_off();
380 window_change_size(win, y, x);
381 window_move_status(win);
382 window_check_scroll(win);
383 update_on();
384}
385/* ------------------------------------------------------------------------- */
386int window_swap(win_ptr win)
387{
388 int old;
389 win_ptr walk, prev, pg = NW, pw = NW, sn;
390 if (!is_window(win)) return FALSE;
391 if (!win->hidden) {
392 if (gwin != win) back_win = gwin;
393 gwin = win;
394 return TRUE;
395 }
396 back_win = gwin;
397 update_off();
398 old = sys$setast(0);
399 window_rawhide(gwin);
400 window_setsize(win, gwin->m_column, gwin->m_line);
401 window_rawshow(win, gwin->p_x, gwin->p_y);
402
403 prev = NULL;
404 walk = awins;
405 for (walk = awins, prev = NULL; walk; prev = walk, walk = walk->next)
406 if (walk==gwin) pg = prev;
407 else if (walk==win) pw = prev;
408 sn = gwin->next;
409 gwin->next = win->next;
410 if (win==sn) win->next = gwin;
411 else {
412 pw->next = gwin;
413 win->next = sn;
414 }
415 if (is_window(pg)) pg->next = win;
416 else awins = win;
417 gwin = win;
418 if (old==SS$_WASSET) sys$setast(1);
419 update_on();
420 return TRUE;
421}
422
423/* ------------------------------------------------------------------------- */
424win_ptr window_num(ind)
425 int ind;
426{
427 win_ptr walk = awins;
428 int count = 1;
429 if (ind==0) return 0;
430 while ((walk) && (count<ind)) {
431 count++;
432 walk = walk->next;
433 }
434 if (walk && !walk->hidden) return walk;
435 return NULL;
436}
437
438/* -------------------------------------------------------------------------
439 * If change is < 0 then it means the change is to occur at the top of the
440 * window. Else the change is to occur at the bottom of the window
441 * ------------------------------------------------------------------------- */
442void window_resize(win_ptr win, int change, int shrink, int top)
443{
444 int new_y;
445 if (!(win && win->id)) return;
446
447 update_off();
448 win->m_line += shrink?-change:change;
449 if (top)
450 window_move_window(win, win->p_x, win->p_y + (shrink?change:-change));
451 if (shrink) window_check_scroll(win);
452 window_change_size(win, win->m_line, win->m_column);
453 window_move_status(win);
454 update_on();
455}
456
457/* Returns the next visible window. If there is no next window, then
458 * we try to get the window before the window.
459 * If we can't do either, we return NW
460 */
461
462win_ptr prev_visible(win_ptr win)
463{
464 win_ptr walk;
465 if (!is_window(win)) return NW;
466 for(walk=awins; walk && (walk->next != win); walk = walk->next)
467 if (walk->hidden) return NW;
468 return walk;
469}
470win_ptr next_visible(win_ptr win)
471{
472 if (!is_window(win)) return NW;
473 if (win->next && !win->next->hidden) return win->next;
474 return NW;
475}
476
477win_ptr previous_window(win_ptr win, int prev)
478{
479 int sl = -1, min;
480 win_ptr save = NW, walk;
481 if (!is_window(win)) return NW;
482 min = win->p_y;
483 for (walk = awins; walk; walk = walk->next)
484 {
485 if (( (prev && (walk->p_y > sl) && (walk->p_y < min)) ||
486 (!prev && (walk->p_y > min) && ((sl==-1) || (walk->p_y < sl))) ) &&
487 !walk->hidden)
488 {
489 sl = walk->p_y;
490 save = walk;
491 }
492 }
493 return save;
494}
495
496static int count_visible_windows(void)
497{
498 int count=0;
499 win_ptr win;
500 for (win=awins;win;win=win->next) if (!win->hidden) count++;
501 return count;
502}
503
504int window_hide(win_ptr win)
505{
506 unsigned status;
507 int count = 0, loop;
508 win_ptr p, n, temp, walk;
509
510 if (!(win && win->id)) {
511 say("Hiding nothing?!");
512 return FALSE;
513 }
514 for (walk=awins;walk;walk=walk->next)
515 if (!walk->hidden) count++;
516 if (count<=1) {
517 say("*** You can not hide your last window.");
518 return FALSE;
519 }
520 update_off();
521 back_win = win;
522 window_rawhide(win);
523 temp = previous_window(win, FALSE);
524 if (temp)
525 window_resize(temp, win->m_line, FALSE, TRUE);
526 else {
527 temp = previous_window(win, TRUE);
528 if (temp) window_resize(temp, win->m_line, FALSE, FALSE);
529 else say("Oh no!!! No window... after hiding one");
530 }
531 for(p = NW, n = awins; n != win; p = n, n = n->next);
532 if (!p) awins = win->next;
533 else p->next = win->next;
534 for(n = awins; n->next; n = n->next);
535 n->next = win;
536 win->next = NW;
537 gwin = temp;
538 updatestatwin();
539 update_on();
540 return TRUE;
541}
542
543/* ------------------------------------------------------------------------- */
544win_ptr last_invisible(void)
545{
546 win_ptr walk;
547 for (walk=awins;walk && walk->next; walk = walk->next);
548 if (!walk || !walk->hidden) return NW;
549 return walk;
550}
551
552/* ------------------------------------------------------------------------- */
553int window_delete(win)
554 win_ptr win;
555{
556 int count = 0, is_hidden;
557 win_ptr walk, p, n, w, temp = NW;
558 server_ptr serv;
559
560 if (!win) return FALSE;
561 serv = win->server;
562 is_hidden = win->hidden;
563 for (walk=awins;walk;walk=walk->next) if (!walk->hidden) count++;
564
565 if ((count+is_hidden) < 2) {
566 say("*** You can not delete your last visible window.");
567 return FALSE;
568 }
569 update_off();
570 if (gsrv) free_chan(gsrv->chan_list, win->channel);
571 delete_a_window(win);
572 if (!is_hidden)
573 {
574 temp = next_visible(win);
575 if (temp)
576 window_resize(temp, win->m_line, FALSE, TRUE);
577 else {
578 temp = prev_visible(win);
579 if (temp) window_resize(temp, win->m_line, FALSE, FALSE);
580 }
581 outwin = gwin = temp;
582 }
583 for (p=NW,n=awins; n && n!=win; p=n,n=n->next) ;
584 if (!n) yell("Really fucked up window list - deleteing noexistant node");
585 else if (p) p->next = n->next;
586 else awins = n->next;
587 if (!is_window(gwin)) gwin = awins;
588 update_on();
589 if (!server_has_window(serv)) remove_server(serv, 1);
590 return TRUE;
591}
592
593/* ------------------------------------------------------------------------- */
594/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
595static void replace_new(char *str, char it, char *insert)
596{
597 while (*str)
598 {
599 if (*str != '%') str++;
600 else
601 {
602 str++;
603 if (*str != it) str++;
604 else {
605 char save[MAXLEN];
606 strcpy(save, &str[1]);
607 str--; /* go back to the % sign */
608 strcpy(str, insert);
609 while (*str) str++;
610 strcpy(str, save);
611 return; /* only replace the first occurance */
612 }
613 }
614 }
615}
616
617/* Status hold_lines ------------------------------------------------------- */
618static void sl_hold_lines(win_ptr win, char *str)
619{
620 char dummy[MAXLEN];
621 *str = 0;
622 if (win->hold_curr)
623 {
624 sprintf(dummy, "%d", win->hold_curr);
625 strcpy(str, getvar(VAR_STATUS_HOLD_LINES));
626 replace_new(str, 'B', dummy);
627 }
628}
629/* ------------------------------------------------------------------------- */
630static void sl_chanmode(win, str)
631 win_ptr win;
632 char *str;
633{
634 char mode[MAXLEN];
635 (void)strcpy(str, getvar(VAR_STATUS_MODE));
636 if (win->channel && win->server && win->server->connected) {
637 recreate_chan_mode(win->server->chan_list, win->channel, mode);
638 if (*mode) replace_new(str, '+', mode);
639 else *str = 0;
640 } else *str = 0;
641}
642/* ------------------------------------------------------------------------- */
643static void sl_away(win, str)
644 win_ptr win;
645 char *str;
646{
647 if (win->server && win->server->connected && is_away(win->server))
648 (void)strcpy(str, getvar(VAR_STATUS_AWAY));
649 else str[0] = 0;
650}
651/* ------------------------------------------------------------------------- */
652static void sl_activity(win, str)
653 win_ptr win;
654 char *str;
655{
656 win_ptr wins;
657 int first = 1;
658 char repl[255], *end;
659 repl[0] = 0;
660 for (wins=awins;wins;wins=wins->next)
661 if (wins->activity) {
662 end = &(repl[strlen(repl)]);
663 sprintf(end, "%s%d", first?"":",", wins->num);
664 first = 0;
665 }
666 if (!first) {
667 strcpy(str, getvar(VAR_STATUS_ACTIVITY));
668 replace_new(str, 'F', repl);
669 } else str[0] = 0;
670}
671/* ------------------------------------------------------------------------- */
672static void sl_insert(win, str)
673 win_ptr win;
674 char *str;
675{
676 char *insert;
677 insert = getvar(VAR_STATUS_INSERT);
678 if (getbvar(VAR_INSERT_MODE) && insert) strcpy(str, insert);
679 else str[0] = 0;
680}
681/* ------------------------------------------------------------------------- */
682static void sl_overwrite(win, str)
683 win_ptr win;
684 char *str;
685{
686 char *overwrite;
687 overwrite = getvar(VAR_STATUS_OVERWRITE_MODE);
688 if (!getbvar(VAR_INSERT_MODE) && overwrite) strcpy(str, overwrite);
689 else str[0] = 0;
690}
691/* ------------------------------------------------------------------------- */
692void sl_nick(win_ptr win, char *str)
693{
694 if (win->server && win->server->nick) (void)strcpy(str, win->server->nick);
695 else (void)strcpy(str, "NONE");
696}
697/* ------------------------------------------------------------------------- */
698extern char curr_time[30];
699static void sl_time(win_ptr win, char *str)
700{
701 (void)strcpy(str, curr_time);
702}
703/* ------------------------------------------------------------------------- */
704static void sl_user(win_ptr win, char *str)
705{
706 get_username(str, 0);
707}
708/* ------------------------------------------------------------------------- */
709static void sl_channel(win_ptr win, char *str)
710{
711 char chan[MAXLEN];
712
713 (void)strcpy(str, getvar(VAR_STATUS_CHANNEL));
714 if (win->server && win->server->connected)
715 if (!get_chan_name(win->server->chan_list, win->channel, chan)) str[0] = 0;
716 else replace_new(str, 'C', chan);
717 else str[0] = 0;
718}
719/* ------------------------------------------------------------------------- */
720static void sl_query(win_ptr win, char *str)
721{
722 (void)strcpy(str, getvar(VAR_STATUS_QUERY));
723 if (win->query) replace_new(str, 'Q', win->query);
724 else str[0] = 0;
725}
726/* ------------------------------------------------------------------------- */
727static void sl_window(win_ptr win, char *str)
728{
729 if ((win==gwin) && (count_visible_windows() != 1))
730 (void)strcpy(str, getvar(VAR_STATUS_WINDOW));
731 else str[0] = 0;
732}
733/* ------------------------------------------------------------------------- */
734void sl_window2(win_ptr win, char *str)
735{
736 if (win) sprintf(str, "%d", win->num);
737 else strcpy(str, "-1");
738}
739/* ------------------------------------------------------------------------- */
740void updatestatwin(void)
741{
742 long int srow = 1, scol = 1, erase = SMG$M_ERASE_LINE, line_advance = 0;
743 long unsigned rendition_set = SMG$M_REVERSE | SMG$M_BOLD;
744 long unsigned status, wrap = 0; /* Do not wrap */
745 char str[MAXLEN], *temp, newfor[MAXLEN], *indx, *ts;
746 int loop, loc, col, row = 1;
747 win_ptr walk;
748 struct dsc$descriptor_s str_d;
749
750 str_d.dsc$b_dtype = DSC$K_DTYPE_T;
751 str_d.dsc$b_class = DSC$K_CLASS_S;
752
753 getx(&col);
754 for (walk=awins; walk ; walk=walk->next)
755 {
756 if (!walk->hidden)
757 {
758 ts = getvar(VAR_STATUS_FORMAT);
759 temp = str;
760 while (*ts)
761 {
762 if (*ts != '%')
763 *temp++ = *ts++;
764 else
765 {
766 ts++;
767 for (loop=0; status_list[loop].trigger[0]; loop++)
768 if (status_list[loop].trigger[1] == *ts) break;
769 if (status_list[loop].trigger[0])
770 {
771 (void)status_list[loop].replace(walk, temp);
772 while (*temp) temp++;
773 }
774 ts++;
775 }
776 }
777 *temp= 0;
778
779 for (loop=temp-str;loop<walk->m_column; loop++)
780 str[loop] = ' ';
781 str[loop] = '\0';
782 if (!(walk->status_line && (strcmp(str, walk->status_line) == 0))) {
783 myfree(walk->status_line);
784 walk->status_line = m_strcpy(str);
785 str_d.dsc$w_length = strlen(str);
786 str_d.dsc$a_pointer= str;
787 status = smg$put_chars(&walk->status, &str_d, &srow, &scol,
788 &erase, &rendition_set, 0, 0);
789 }
790 }
791 putcursor(col);
792 }
793}
794
795/* ------------------------------------------------------------------------
796 * Create a simple window (no status bar associated)
797 * ------------------------------------------------------------------------ */
798static unsigned simple_window(int lines, int columns, int x, int y, int flags)
799{
800 unsigned status, win, dummy = 0;
801 status = smg$create_virtual_display(&lines, &columns, &win,
802 &flags, &dummy, &dummy);
803 if (ODD(status))
804 {
805 (void)smg$erase_display(&win);
806 (void)smg$paste_virtual_display(&win, &pb.id, &y, &x, 0);
807 return win;
808 }
809 my_sig(status, "Simple window");
810 return 0;
811}
812
813/* ------------------------------------------------------------------------
814 * Create a window and initialize the window statistics.
815 * ------------------------------------------------------------------------ */
816static win_ptr create_window(lines, columns, x, y, flags)
817 int lines, columns, x, y, flags;
818{
819 unsigned status, id;
820 int loop, lev = NONE, dummy = 0, col = 1, num = 1;
821 win_ptr temp, f, p;
822
823 if (!DUMB) {
824 status = smg$create_virtual_display(&lines, &columns, &id,
825 &flags, &dummy, &dummy);
826 if (!ODD(status)) {
827 say("Error creating virtual display (%d)", status);
828 return NW;
829 }
830 } else id = 0;
831 temp = (win_ptr)mymalloc(sizeof(struct awin));
832 if (!temp) return NW;
833 temp->id = id;
834 temp->line = 1;
835 while (window_exists(num)) num++;
836 if (num>max_win_num) max_win_num = num;
837 temp->num = num;
838 temp->m_line = lines;
839 temp->m_column = columns;
840 temp->p_x = x;
841 temp->p_y = y;
842 temp->scroll = TRUE;
843 temp->name[0] = 0;
844 temp->query = NULL;
845 temp->channel = 0;
846 temp->hidden = FALSE;
847 (void)strcpy(temp->logfile, getvar(VAR_LOGFILE));
848 temp->file = NULL;
849 for (f=awins; f; f = f->next)
850 if (f->server == gsrv) lev |= f->wlevel;
851/* temp->wlevel = ALL - lev; */
852 temp->wlevel = NONE;
853 temp->activity = 0;
854 temp->notified = 0;
855 temp->notify_count = 0;
856 temp->lastloglevel = getivar(VAR_LASTLOG_LEVEL);
857 temp->notify_level = getivar(VAR_NOTIFY_LEVEL);
858 temp->status_line = NULL;
859 temp->lastlog = create_head(getivar(VAR_LASTLOG));
860 temp->server = NULL;
861 temp->hold_mode = getbvar(VAR_HOLD_MODE);
862 temp->hold_mode_max = getivar(VAR_HOLD_MODE_MAX);
863 temp->hold_curr = 0;
864 temp->is_holding = FALSE;
865 temp->hold_count = 0;
866 temp->hold_lines = NULL;
867 win_setmode(temp, win_getmode(gwin));
868
869 for (f = awins, p = NW; f && (f->p_y < y); p = f, f = f->next);
870 temp->next = f;
871 if (is_window(p)) p->next = temp;
872 else awins = temp;
873
874 if (temp->id) (void)smg$erase_display(&temp->id);
875 if (temp->id) (void)smg$set_display_scroll_region(&temp->id, &start_row, &y);
876 if ((temp->id) && (pb.id!=-1))
877 (void)smg$paste_virtual_display(&temp->id, &pb.id, &y, &x, 0);
878 return temp;
879}
880
881/* ------------------------------------------------------------------------
882 * Create an IRC window and a status bar
883 * ------------------------------------------------------------------------ */
884static win_ptr new_window(lines, columns, x, y)
885 int lines, columns, x, y;
886{
887 win_ptr tempwin = NW;
888
889 if (!DUMB || !gwin)
890 tempwin = create_window(lines, columns, x, y, 0);
891 if (!(DUMB && tempwin))
892 tempwin->status = simple_window(1, columns, x, y+lines-1, 0);
893 return tempwin;
894}
895
896/* -------------------------------------------------------------------------
897 * Following is a list of functions for manipulation joining and leaving of
898 * channels - these should be called only after the server has informed us
899 * of a channel change
900 * ------------------------------------------------------------------------- */
901void set_channel(indx)
902 int indx;
903{
904 if (!gsrv || !gsrv->connected) return;
905 free_chan(gsrv->chan_list, gwin->channel);
906 if (set_chan_used(gsrv->chan_list, indx, gwin) == TRUE)
907 gwin->channel = indx;
908}
909
910/* ------------------------------------------------------------------------- */
911void join_channel(server_ptr srv, char *chan, win_ptr towin)
912{
913 if (!(towin && srv && srv->connected)) return;
914 free_chan(srv->chan_list, towin->channel);
915 towin->channel = push_chan(&(srv->chan_list), chan, towin);
916 updatestatwin();
917}
918
919/* ------------------------------------------------------------------------- */
920win_ptr leave_channel(server, chan)
921 server_ptr server;
922 char *chan;
923{
924 win_ptr win;
925 if (!server || !server->connected) return NULL;
926 win = delete_channel(&server->chan_list, chan);
927 if (win) {
928 win->channel = find_chan_free(server->chan_list, win);
929 updatestatwin();
930 }
931 return win;
932}
933
934/* ------------------------------------------------------------------------- */
935char *get_channel(chan)
936 char *chan;
937{
938 if (!(gwin && gwin->channel)) {
939 if (chan) chan[0] = 0;
940 return NULL;
941 } else if (gwin->server && gwin->server->connected)
942 return get_chan_name(gwin->server->chan_list, gwin->channel, chan);
943 return NULL;
944}
945
946/* ------------------------------------------------------------------------- */
947/* Query functions. */
948/* ------------------------------------------------------------------------- */
949win_ptr isquery(server_ptr srv, char *str)
950{
951 win_ptr win = NW, walk;
952 for (walk=awins; walk; walk = walk->next)
953 if ((!srv || (walk->server == srv)) && (walk->query) &&
954 (strcasecmp(walk->query, str)==0))
955 win = walk;
956 return win;
957}
958
959int clearquery(query)
960 char *query;
961{
962 int isq;
963
964 if (!gwin) return FALSE;
965 if (gwin->query) {
966 (void)strcpy(query, gwin->query);
967 free(gwin->query);
968 gwin->query = NULL;
969 }
970 else *query = 0;
971 isq = (query[0] != 0);
972 return isq;
973}
974
975/* ------------------------------------------------------------------------- */
976void setquery(query)
977 char *query;
978{
979 if (gwin) {
980 if (gwin->query) free(gwin->query);
981 gwin->query = m_strcpy(query);
982 }
983}
984
985/* ------------------------------------------------------------------------- */
986char *getquery(void)
987{
988 if (!gwin) return NULL;
989 return gwin->query;
990}
991
992/* ------------------------------------------------------------------------- */
993void split_window(void)
994{
995 int half;
996 win_ptr newwin;
997
998 if (!gwin) return;
999 half = (int)(gwin->m_line/2);
1000 if (half < 4)
1001 {
1002 say("Not enough lines left to split window.");
1003 return;
1004 }
1005 if (getbvar(VAR_NOVICE))
1006 {
1007 yell("*** You can not create a new window with NOVICE mode on.");
1008 return;
1009 }
1010 if ((newwin = new_window(half, pb.maxcols, gwin->p_x, gwin->p_y)) != NW)
1011 {
1012 window_resize(gwin, half, TRUE, TRUE);
1013 newwin->server = gwin->server;
1014 back_win = gwin;
1015 gwin = newwin;
1016 updatestatwin();
1017 }
1018}
1019
1020/* ------------------------------------------------------------------------- */
1021void clear_window(void)
1022{
1023 unsigned status;
1024 gwin->line = 1;
1025 status = smg$erase_display(&gwin->id, &gwin->line, &gwin->line,
1026 &gwin->m_line, &gwin->m_column);
1027}
1028
1029/* ------------------------------------------------------------------------- */
1030static void clear_all_window(void)
1031{
1032 win_ptr loop;
1033 int start = 1;
1034 for (loop=awins;loop;loop=loop->next)
1035 {
1036 (void)smg$erase_display(&loop->id, &start, &start,
1037 &loop->m_line, &loop->m_column);
1038 loop->line = 1;
1039 }
1040}
1041
1042/* ------------------------------------------------------------------------- */
1043static void ast_rsend(void)
1044{
1045 unsigned status;
1046 char msg[200], send[200];
1047 unsigned short length, type=0;
1048 struct dsc$descriptor_s msg_d;
1049
1050 msg_d.dsc$a_pointer = msg;
1051 msg_d.dsc$b_dtype = DSC$K_DTYPE_T;
1052 msg_d.dsc$b_class = DSC$K_CLASS_S;
1053 msg_d.dsc$w_length = sizeof(msg);
1054
1055 status = smg$get_broadcast_message(&pb.id, &msg_d, &length, &type);
1056 msg[(int)length] = 0;
1057 (void)sprintf(send, "SEND: %s", msg);
1058 say("%s", send);
1059}
1060
1061/* ------------------------------------------------------------------ */
1062void trap(int on)
1063{
1064 unsigned status;
1065 if (!on)
1066 {
1067 stop_input();
1068 status = smg$disable_broadcast_trapping(&pb.id);
1069 smg$erase_pasteboard(&pb.id);
1070 }
1071 else
1072 {
1073 status = smg$set_broadcast_trapping(&pb.id, ast_rsend, 0);
1074 start_keybdio();
1075 }
1076 if (!(ODD(status)))
1077 say("Error in broadcast trapping: %d", status);
1078}
1079
1080void user_spawn(char *rest, int varpar, char *subparams)
1081{
1082 unsigned status;
1083 trap(FALSE);
1084 set_pasthru(TRUE);
1085 status = lib$spawn();
1086 set_pasthru(FALSE);
1087 if (!(ODD(status))) say("Error in spawn: %d", status);
1088 trap(TRUE);
1089 redraw();
1090}
1091
1092/* ------------------------------------------------------------------------- */
1093void init_window(void)
1094{
1095 int loop;
1096 unsigned status;
1097 unsigned long device_type;
1098 win_ptr temp;
1099 if (!DUMB) {
1100 status = smg$create_pasteboard(&pb.id, 0, &pb.maxrows, &pb.maxcols, 0,
1101 &device_type);
1102 if (!ODD(status)) (void)lib$signal(status);
1103 trap(TRUE);
1104 if (!ODD(status)) (void)lib$signal(status);
1105 } else {
1106 pb.maxrows = 23;
1107 pb.maxcols = 80;
1108 pb.id = -1;
1109 }
1110 if (INPUT_DEFINED) inwin = simple_window(1, pb.maxcols, 1, pb.maxrows, 0);
1111 else inwin = 0;
1112 gwin = new_window(pb.maxrows-1, pb.maxcols, 1, 1);
1113 set_outwin(gwin);
1114}
1115
1116/* ------------------------------------------------------------------------- */
1117/* This is the start of the routines user for handling user input */
1118/* ------------------------------------------------------------------------- */
1119static int echo = 1;
1120/* ------------------------------------------------------------------------- */
1121int set_echo(int on)
1122{
1123 int old;
1124 old = echo;
1125 if (on) echo = 1;
1126 else echo = 0;
1127 return old;
1128}
1129
1130/* ------------------------------------------------------------------------- */
1131/* This routine must never be called from ast level. It disables ast's */
1132/* before calling a non-reetrant routine. */
1133/* ------------------------------------------------------------------------- */
1134int print_at(char *str, int len, int pl)
1135{
1136 long int line = 1, col = 1;
1137 long unsigned flag = SMG$M_ERASE_LINE;
1138 int status, loop;
1139 char s[MAXLEN], f[MAXLEN];
1140 struct dsc$descriptor_s for_d, mvw_d;
1141
1142 if (len <= 0) return pb.maxcols;
1143 for_d.dsc$a_pointer = f;
1144 mvw_d.dsc$a_pointer = s;
1145 for_d.dsc$b_dtype = mvw_d.dsc$b_dtype = DSC$K_DTYPE_T;
1146 for_d.dsc$b_class = mvw_d.dsc$b_class = DSC$K_CLASS_S;
1147
1148 for (loop=0;loop<len;loop++) {
1149 if (str[loop] < 32) {s[loop] = str[loop] + 64; f[loop] = SMG$M_REVERSE;}
1150 else {s[loop] = str[loop]; f[loop] = 0;}
1151 }
1152 if (!echo && (len>pl)) len = pl;
1153 for_d.dsc$w_length = len;
1154 mvw_d.dsc$w_length = len;
1155 status = smg$put_chars_multi(&inwin, &mvw_d, &line, &col, &flag,
1156 &for_d, 0, 0);
1157 if (!ODD(status)) {
1158 say("PR len [%d]\n", len);
1159 my_sig(status, "MVADDSTR");
1160 }
1161 return pb.maxcols;
1162}
1163
1164/* ------------------------------------------------------------------------- */
1165/* This routine must never be called from ast level. It disables ast's */
1166/* before calling a non-reetrant routine. */
1167/* ------------------------------------------------------------------------- */
1168void del_char_from_input(x, num)
1169 int x;
1170 int num;
1171{
1172 int status, old, col = 1;
1173 if (!echo) return;
1174 old = sys$setast(0);
1175 status = smg$delete_chars(&inwin, &num, &col, &x);
1176 if (old == SS$_WASSET) (void)sys$setast(1);
1177}
1178
1179/* ------------------------------------------------------------------------- */
1180/* This routine must never be called from ast level. It disables ast's */
1181/* before calling a non-reetrant routine. */
1182/* ------------------------------------------------------------------------- */
1183static struct dsc$descriptor_s str_d = {1, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
1184
1185void rep_char_in_input(key, x)
1186 char key;
1187 int x;
1188{
1189 int status, old, col = 1, dummy = 0;
1190
1191 if (!echo) return;
1192 str_d.dsc$a_pointer = &key;
1193 old = sys$setast(0);
1194 status = smg$put_chars(&inwin, &str_d, &col, &x, &dummy, &dummy,
1195 &dummy, &dummy);
1196 if (old == SS$_WASSET) (void)sys$setast(1);
1197}
1198
1199/* ------------------------------------------------------------------------- */
1200void redraw(void)
1201{
1202 int x;
1203 getx(&x);
1204 (void)smg$repaint_screen(&pb.id);
1205 updatestatwin();
1206 putcursor(x);
1207}
1208
1209/* ------------------------------------------------------------------------- */
1210/* This routine must never be called from ast level. It disables ast's */
1211/* before calling a non-reetrant routine. */
1212/* ------------------------------------------------------------------------- */
1213void insert_char(key, x)
1214 char key;
1215 int x;
1216{
1217 int status, old, col = 1;
1218 unsigned form = 0;
1219
1220 if (!echo) return;
1221 if (key<32) {
1222 form = SMG$M_REVERSE;
1223 key += 64;
1224 }
1225 str_d.dsc$a_pointer = &key;
1226 old = sys$setast(0);
1227 status = smg$insert_chars(&inwin, &str_d, &col, &x, &form, 0, 0);
1228 if (old == SS$_WASSET) (void)sys$setast(1);
1229}
1230
1231/* ------------------------------------------------------------------------- */
1232/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1233/* ------------------------------------------------------------------------- */
1234static char format[1024], string[1024];
1235static $DESCRIPTOR(for_d, format);
1236static $DESCRIPTOR(mvw_d, string);
1237
1238/* ------------------------------------------------------------------------- */
1239/*
1240void put_line(win_ptr twin, char *str, int y, int x)
1241{
1242 int status, flag = SMG$M_ERASE_TO_EOL;
1243 mvw_d.dsc$a_pointer = str;
1244 for_d.dsc$a_pointer = att;
1245 for_d.dsc$w_length = mvw_d.dsc$w_length = len;
1246 status = smg$put_chars_multi(&twin->id, &mvw_d, &y, &x, &flag,
1247 &for_d, 0, 0);
1248}
1249*/
1250
1251/* ------------------------------------------------------------------------- */
1252static void display_line(win_ptr twin, char *str, char *att, int len)
1253{
1254 int status, col = 1, flag = SMG$M_ERASE_TO_EOL;
1255 mvw_d.dsc$a_pointer = str;
1256 for_d.dsc$a_pointer = att;
1257 for_d.dsc$w_length = mvw_d.dsc$w_length = len;
1258 status = smg$put_chars_multi(&twin->id, &mvw_d, &twin->line, &col, &flag,
1259 &for_d, 0, 0);
1260 if (++twin->line > twin->m_line)
1261 {
1262 if (twin->scroll == TRUE)
1263 window_do_scroll(twin, 1);
1264 else
1265 twin->line = 1;
1266 }
1267 if (!ODD(status)) my_sig(status, "MVADDSTR");
1268}
1269
1270/* ------------------------------------------------------------------------- */
1271void kill_hold(void)
1272{
1273 int old;
1274 hold_ptr temp, save;
1275
1276 if (!gwin) return;
1277 old = sys$setast(0);
1278 temp = gwin->hold_lines;
1279 while (temp)
1280 {
1281 save = temp;
1282 temp = temp->next;
1283 myfree(save->str);
1284 myfree(save->att);
1285 myfree(save);
1286 gwin->hold_curr--;
1287 }
1288 gwin->hold_lines = NULL;
1289 if (old == SS$_WASSET) sys$setast(1);
1290}
1291
1292/* ------------------------------------------------------------------------- */
1293/* Called when a user requests a flush */
1294static void flush_hold(int lines)
1295{
1296 int loop, old;
1297 hold_ptr temp, save;
1298 if (!gwin) return;
1299
1300 old = sys$setast(0);
1301 temp = gwin->hold_lines;
1302 for (loop=0; (loop!=lines) && temp; loop++)
1303 {
1304 display_line(gwin, temp->str, temp->att, temp->len);
1305 save = temp;
1306 temp = temp->next;
1307 myfree(save->str);
1308 myfree(save->att);
1309 myfree(save);
1310 gwin->hold_curr--;
1311 }
1312 gwin->hold_lines = temp;
1313 if (old == SS$_WASSET) sys$setast(1);
1314}
1315
1316/* ------------------------------------------------------------------------- */
1317static void add_to_hold_list(hold_ptr *list, char *str, char *att, int len)
1318{
1319 hold_ptr temp, walk, back;
1320 temp = (hold_ptr)mymalloc(sizeof(struct hold_list));
1321 if (!temp) return;
1322 temp->str = m_strcpy(str);
1323 temp->att = (char *)mymalloc(len); /* can't use m_strcpy -- not a string */
1324 if (temp->att) memcpy(temp->att, att, len);
1325 temp->len = len;
1326 temp->next = NULL;
1327 if (!*list) *list = temp;
1328 else {
1329 walk = *list;
1330 while (walk->next) walk = walk->next;
1331 walk->next = temp;
1332 }
1333}
1334
1335/* ------------------------------------------------------------------------- */
1336void free_hold(void)
1337{
1338 if (gwin) {
1339 if (gwin->just_held) gwin->just_held = 0;
1340 else {
1341 flush_hold(gwin->m_line-1); /* use -1 because of the statusbar */
1342 if (!gwin->hold_curr) gwin->is_holding = FALSE;
1343 }
1344 gwin->hold_count = 0;
1345 }
1346}
1347
1348/* ------------------------------------------------------------------------- */
1349extern int in_help;
1350static void write_to_screen(win_ptr twin, char *str, char *att, int len)
1351{
1352 if ((twin->is_holding) && !twin->hidden && !in_help)
1353 {
1354 str[len] = att[len] = 0;
1355 add_to_hold_list(&twin->hold_lines, str, att, len);
1356 twin->hold_curr++;
1357 if ((twin->hold_curr > twin->hold_mode_max) &&
1358 twin->hold_mode_max) flush_hold(-1);
1359 return;
1360 }
1361 if (twin->hold_mode)
1362 if (++twin->hold_count >= (twin->m_line-1))
1363 twin->just_held = twin->is_holding = TRUE;
1364 display_line(twin, str, att, len);
1365 return;
1366}
1367/* ------------------------------------------------------------------------- */
1368#define SINGLE_CHAR(__ochar, __oform, __ichar, __att, __beeps, __adv) \
1369do { \
1370 __adv = FALSE; \
1371 if (__ichar <= 32) \
1372 { \
1373 switch (__ichar) { \
1374 case 2: \
1375 __att = (SMG$M_BOLD & ~__att) | (~SMG$M_BOLD & __att); \
1376 break; \
1377 case 15: \
1378 __att = 0; \
1379 break; \
1380 case 22: \
1381 __att = (SMG$M_REVERSE & ~__att) | (~SMG$M_REVERSE & __att); \
1382 break; \
1383 case 31: \
1384 __att = (SMG$M_UNDERLINE & ~__att) | (~SMG$M_UNDERLINE & __att); \
1385 break; \
1386 case 7: \
1387 if (!getivar(VAR_BEEP) || (__beeps++>=getivar(VAR_BEEP_MAX))) { \
1388 __oform = SMG$M_REVERSE; \
1389 __ochar = __ichar + 64; \
1390 } else { \
1391 __oform = __att; \
1392 __ochar = __ichar; \
1393 } \
1394 __adv = TRUE; \
1395 break; \
1396 case 9: \
1397 __oform = __att; \
1398 __ochar = __ichar; \
1399 __adv = TRUE; \
1400 break; \
1401 default: \
1402 if (__ichar < 0) __ichar += 128; \
1403 if (__ichar < 32) { \
1404 __oform = SMG$M_REVERSE; \
1405 __ochar = (char)((int)__ichar + 64); \
1406 __adv = TRUE; \
1407 } else if (__ichar < 128) { \
1408 __oform = __att; \
1409 __ochar = __ichar; \
1410 __adv = TRUE; \
1411 } else { /* __ichar >= 128 */ \
1412 } \
1413 break; \
1414 } /* end of switch */ \
1415 } else { \
1416 __oform = __att; \
1417 __ochar = __ichar; \
1418 __adv = TRUE; \
1419 } \
1420} while (0) \
1421
1422/* ------------------------------------------------------------------------- */
1423void write_raw_to_screen(int row, int col, int clear, char *str)
1424{
1425 int status, flag = 0;
1426 int real, loop, att, beeps, adv;
1427 real = loop = att = beeps = 0;
1428
1429 if (clear) flag |= SMG$M_ERASE_TO_EOL;
1430
1431 while (str[loop] && (loop < sizeof(string)))
1432 {
1433 SINGLE_CHAR(string[real], format[real], str[loop], att, beeps, adv);
1434 if (adv) real++;
1435 loop++;
1436 }
1437 mvw_d.dsc$a_pointer = string;
1438 for_d.dsc$a_pointer = format;
1439 for_d.dsc$w_length = mvw_d.dsc$w_length = real;
1440 status = smg$put_chars_multi(&gwin->id, &mvw_d, &row, &col, &flag,
1441 &for_d, 0, 0);
1442}
1443
1444/* ------------------------------------------------------------------------- */
1445static void my_mvwaddstr(win_ptr win, char *str, int MAX, int indent_mode,
1446 int multi_row)
1447{
1448 int current, att, beeps, space, indent, loop, space_att, real, last, lines;
1449 int adv;
1450 lines = last = loop = space_att = space = indent = real =
1451 att = beeps = current = 0;
1452 while (str[loop]) {
1453/*
1454 adv = single_char(&string[real], &format[real], str[loop], &att,
1455 &beeps);
1456*/
1457 SINGLE_CHAR(string[real], format[real], str[loop], att, beeps, adv);
1458 if (string[real] == 32)
1459 {
1460 if ((indent == 0) || (indent == real)) indent = real + 1;
1461 space = real;
1462 space_att = format[real];
1463 }
1464 if (adv) real++;
1465 loop++;
1466 if (real >= MAX) { /* end of a line for the screen */
1467 int where;
1468 lines++;
1469 if (!indent || (indent >= (MAX/6))) indent = MAX/6;
1470 if (space && (space > indent)) where = space;
1471 else where = real;
1472 write_to_screen(win, string, format, where);
1473 if (!multi_row) return;
1474 if (space > indent) {
1475#if 0
1476 yell("indent %d space %d where %d real %d", indent, space, where,
1477 real);
1478#endif
1479 att = space_att;
1480 where = real-space-1;
1481 memcpy(&string[indent], &string[space+1], where);
1482 memcpy(&format[indent], &format[space+1], where);
1483 real = indent + where;
1484#if 0
1485 yell("indent %d space %d where %d real %d", indent, space, where,
1486 real);
1487#endif
1488 } else real = indent;
1489 memset(string, 32, indent);
1490 memset(format, 0, indent);
1491 space = 0;
1492 last = where;
1493 } /* If real >= MAX */
1494 } /* end of while */
1495#if 1
1496 if (!lines || ((last != loop) && (real != indent)))
1497 write_to_screen(win, string, format, real);
1498#else
1499 if (!lines || (last != loop)) write_to_screen(win, string, format, real);
1500#endif
1501#if 0
1502 if (lines && (last!=loop))
1503 yell("Wrap: indent %d real_len %d last %d loop %d", indent, real,
1504 last, loop);
1505#endif
1506}
1507
1508/* ------------------------------------------------------------------------- */
1509/* This is the routine that is called when a message needs to be printed to */
1510/* a particular window. It takes care of splitting the line up and scrolling */
1511/* ------------------------------------------------------------------------- */
1512static int in_redirect = FALSE;
1513static int inonw = FALSE;
1514
1515static void print_window(win_ptr twin, char *msg, int type)
1516{
1517 int col2 = 1, x, status;
1518
1519 if (!is_window(twin)) {
1520 (void)printf("%s\n", msg);
1521 return;
1522 }
1523 if (!in_redirect && twin->server && twin->server->redirect)
1524 new_send(twin->server, "PRIVMSG %s :%s\n", twin->server->redirect, msg+3);
1525 if (twin->file) (void)fprintf(twin->file, "%s\n", msg+3);
1526
1527 if (type==(LASTLOG*2)) type = log_level;
1528 if ((twin->lastloglevel & type) == type)
1529 (void)add_list(twin->lastlog, msg+3, type);
1530 inonw++;
1531 if ((inonw<=2) && !handle_on(o_window, msg, 0))
1532 {
1533 getx(&x);
1534 my_mvwaddstr(twin, msg+3, twin->m_column, TRUE, TRUE);
1535 putcursor(x);
1536 }
1537 inonw--;
1538}
1539
1540/* ------------------------------------------------------------------------ */
1541static void do_notify_window(win_ptr win)
1542{
1543 if (!win || !win->hidden) return;
1544 win->activity = 1;
1545 if ((win->notified < win->notify_count) &&
1546 (log_level & win->notify_level))
1547 {
1548 sprintf(string, "%2.2d *** Activity in window %d", gwin->num, win->num);
1549 win->notified++;
1550 print_window(gwin, string, LASTLOG*2);
1551 }
1552
1553}
1554
1555/* ------------------------------------------------------------------------ */
1556void yell(char *format, ...)
1557{
1558 char string[MAXLEN*100];
1559 int old;
1560 va_list arglist;
1561 va_start(arglist, format);
1562 old = sys$setast(0);
1563 sprintf(string, "%2.2d ", outwin?outwin->num:-1);
1564 (void)vsprintf(string+3, format, arglist);
1565 print_window(outwin, string, LASTLOG*2);
1566 do_notify_window(outwin);
1567 va_end(arglist);
1568 if (old == SS$_WASSET) (void)sys$setast(1);
1569}
1570/* ------------------------------------------------------------------------ */
1571void win_say(win_ptr win, char *format, ...)
1572{
1573 char string[MAXLEN*100];
1574 int old;
1575 va_list arglist;
1576 va_start(arglist, format);
1577 if (getivar(VAR_DISPLAY)<=0) return;
1578 old = sys$setast(0);
1579 sprintf(string, "%2.2d ", win?win->num:-1);
1580 (void)vsprintf(string+3, format, arglist);
1581 print_window(win, string, LASTLOG*2);
1582 do_notify_window(win);
1583 va_end(arglist);
1584 if (old == SS$_WASSET) (void)sys$setast(1);
1585}
1586/* ------------------------------------------------------------------------ */
1587void say(char *format, ...)
1588{
1589 char string[MAXLEN*100];
1590 int old;
1591 va_list arglist;
1592 va_start(arglist, format);
1593 if (getivar(VAR_DISPLAY)<=0) return;
1594 old = sys$setast(0);
1595 sprintf(string, "%2.2d ", outwin?outwin->num:-1);
1596 (void)vsprintf(string+3, format, arglist);
1597 print_window(outwin, string, LASTLOG*2);
1598 do_notify_window(outwin);
1599 va_end(arglist);
1600 if (old == SS$_WASSET) (void)sys$setast(1);
1601}
1602/* ------------------------------------------------------------------------ */
1603typedef struct {
1604 server_ptr ss;
1605 win_ptr ww;
1606 int ll;
1607} levels_save;
1608
1609static stackptr levels_stack = NULL;
1610
1611void unset_win_lvl_srv(void)
1612{
1613 levels_save *tmp;
1614 tmp = (levels_save *)pop_element(levels_stack, 0, NULL);
1615 if (!tmp) return;
1616 gsrv = tmp->ss;
1617 outwin = tmp->ww;
1618 log_level = tmp->ll;
1619}
1620
1621void set_win_lvl_srv(server_ptr srv, int level)
1622{
1623 win_ptr walk, tmpwin = NULL, tmpwin2 = NULL;
1624 levels_save tmp;
1625 tmp.ss = gsrv;
1626 tmp.ww = outwin;
1627 tmp.ll = log_level;
1628 if (!levels_stack) levels_stack = make_new_stack(TRUE, 0);
1629 push_element(levels_stack, NULL, (char *)&tmp, sizeof(tmp), TRUE);
1630 for (walk=awins; walk && !tmpwin; walk = walk->next)
1631 if (walk->server == srv)
1632 if (walk->wlevel & level) tmpwin = walk;
1633 else tmpwin2 = walk;
1634 if (!tmpwin) tmpwin = tmpwin2;
1635 gsrv = srv;
1636 outwin = tmpwin;
1637 log_level = level;
1638}
1639
1640/* ------------------------------------------------------------------------ */
1641win_ptr set_outwin(win_ptr win)
1642{
1643 win_ptr temp;
1644 temp = outwin;
1645 outwin = win;
1646 return temp;
1647}
1648
1649int set_loglevel(int new)
1650{
1651 int old = log_level;
1652 log_level = new;
1653 return old;
1654}
1655/* ------------------------------------------------------------------------ */
1656int get_menu_choice(int menu_count, char *menu_items[])
1657{
1658#if 1
1659 return;
1660#else
1661 unsigned winid, status;
1662 int lines, cols, col_width, orig_x, orig_y, loop;
1663 struct dsc$descriptor_a choice_list;
1664 char *fixed_choices;
1665 unsigned short menu_num;
1666 unsigned long kbid, max_width = 0, flag1, flag2;
1667
1668 lines = pb.maxrows;
1669 if (lines > 10) lines = 10;
1670 if (menu_count <= lines) lines = menu_count, cols = 1;
1671 else cols = menu_count / lines + 1;
1672 for (loop=0; loop<menu_count; loop++)
1673 {
1674/* yell("[%s]", menu_items[loop]); */
1675 if (strlen(menu_items[loop]) > max_width)
1676 max_width = strlen(menu_items[loop]);
1677 }
1678 col_width = (max_width + 2) * cols;
1679 orig_x = (col_width < pb.maxcols)?((pb.maxcols - col_width)/2):0;
1680 orig_y = (lines < pb.maxrows)?((pb.maxrows - lines)/2):0;
1681 winid = simple_window(lines, col_width, orig_x, orig_y, SMG$M_BORDER);
1682/* yell("max_width is %d, choice count is %d", max_width, menu_count); */
1683 max_width++;
1684 fixed_choices = (char *)mymalloc(menu_count * max_width);
1685 if (!fixed_choices) { say("malloc failed for menu"); return -1; }
1686 memset(fixed_choices, ' ', menu_count * max_width);
1687 for (loop=0;loop<menu_count;loop++)
1688 {
1689#if 1
1690 sprintf(&fixed_choices[loop * max_width], "%s", menu_items[loop]);
1691#else
1692 memcpy(&fixed_choices[loop * max_width], menu_items[loop],
1693 strlen(menu_items[loop]));
1694 fixed_choices[loop * max_width + max_width - 1] = 0;
1695#endif
1696 }
1697 choice_list.dsc$w_length = max_width;
1698 choice_list.dsc$b_dtype = DSC$K_DTYPE_T;
1699 choice_list.dsc$b_class = DSC$K_CLASS_A;
1700 choice_list.dsc$a_pointer = fixed_choices;
1701 choice_list.dsc$b_dimct = 1;
1702 choice_list.dsc$l_arsize = menu_count * max_width;
1703 stop_input();
1704 flag1 = SMG$K_VERTICAL;
1705 flag2 = SMG$M_WRAP_MENU;
1706 status = smg$create_menu(&winid, &choice_list, &flag1,
1707 &flag2, 0, 0, 0);
1708 if (!ODD(status)) my_sig(status, "create_menu");
1709 status = smg$create_virtual_keyboard(&kbid, 0, 0, 0, 0);
1710 if (!ODD(status)) my_sig(status, "create_keyboard");
1711 status = smg$select_from_menu(&kbid, &winid, &menu_num, 0, 0, 0, 0, 0, 0, 0, 0);
1712 if (!ODD(status)) my_sig(status, "select_menu");
1713 status = smg$delete_virtual_keyboard(&kbid);
1714 if (!ODD(status)) my_sig(status, "delete_keyboard");
1715 flag1 = SMG$M_ERASE_MENU;
1716 status = smg$delete_menu(&winid, &flag1);
1717 if (!ODD(status)) my_sig(status, "delete_menu");
1718 status = smg$unpaste_virtual_display(&winid, &pb.id);
1719 if (!ODD(status)) my_sig(status, "unpaste_display");
1720 status = smg$delete_virtual_display(&winid);
1721 if (!ODD(status)) my_sig(status, "delete_display");
1722 myfree(fixed_choices);
1723 start_keybdio();
1724 if (!ODD(status)) return -1;
1725 return menu_num - 1;
1726#endif
1727}
1728/* ------------------------------------------------------------------------ */