]>
Commit | Line | Data |
---|---|---|
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 | ||
40 | static void sl_away(), sl_window(), sl_channel(), sl_time(); | |
41 | static void sl_query(), sl_chanmode(), sl_hold_lines(), sl_user(); | |
42 | static void sl_insert(), sl_overwrite(), sl_activity(); | |
43 | ||
44 | extern int log_level; | |
45 | extern server_ptr gsrv; | |
46 | extern win_ptr outwin, back_win; | |
47 | ||
48 | struct 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 | ||
55 | struct pasteboard { | |
56 | int id, maxrows, maxcols; | |
57 | } pb; | |
58 | ||
59 | struct replace{ | |
60 | char trigger[4]; | |
61 | void (*replace)(); | |
62 | }; | |
63 | ||
64 | win_ptr awins = NW; | |
65 | extern win_ptr gwin; | |
66 | ||
67 | static unsigned inwin = 0; | |
68 | static int pl; | |
69 | int max_win_num = 1; | |
70 | int DUMB = FALSE; | |
71 | static int start_row = 1; | |
72 | extern int INPUT_DEFINED; | |
73 | ||
74 | /* -------------------------------------------------------------------------*/ | |
75 | win_ptr get_curr_win(void) | |
76 | { | |
77 | return gwin; | |
78 | } | |
79 | ||
80 | /* -------------------------------------------------------------------------*/ | |
81 | win_mode win_getmode(win_ptr win) | |
82 | { | |
83 | return win?win->mode:NULL; | |
84 | } | |
85 | void win_setmode(win_ptr win, win_mode newmode) | |
86 | { | |
87 | if (win) win->mode = newmode; | |
88 | } | |
89 | /* -------------------------------------------------------------------------*/ | |
90 | win_ptr next_window(win_ptr win) | |
91 | { | |
92 | if (!win) return awins; | |
93 | return win->next; | |
94 | } | |
95 | head_ptr get_window_lastlog(win_ptr win) | |
96 | { | |
97 | if (!win) return NULL; | |
98 | return win->lastlog; | |
99 | } | |
100 | server_ptr get_window_server(win_ptr win) | |
101 | { | |
102 | if (!win) return NULL; | |
103 | return win->server; | |
104 | } | |
105 | void set_window_server(win_ptr win, server_ptr srv) | |
106 | { | |
107 | if (win) win->server = srv; | |
108 | } | |
109 | ||
110 | /* -------------------------------------------------------------------------*/ | |
111 | static void getx(int *r) | |
112 | { | |
113 | if (!inwin) *r = 0; | |
114 | else *r = smg$cursor_column(&inwin); | |
115 | } | |
116 | ||
117 | /* -------------------------------------------------------------------------*/ | |
118 | void 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 | /* -------------------------------------------------------------------------*/ | |
134 | static 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 | ||
157 | win_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 | ||
171 | void 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 | * ------------------------------------------------------------------------- */ | |
179 | static 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 | ||
188 | void 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 | /* ------------------------------------------------------------------------- */ | |
205 | void 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, ¤t, 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 | /* ------------------------------------------------------------------------- */ | |
226 | void 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 | /* ------------------------------------------------------------------------- */ | |
243 | static int w_s; | |
244 | static int curr_scroll = 0; | |
245 | void 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 | /* ------------------------------------------------------------------------- */ | |
268 | void 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 | /* ------------------------------------------------------------------------- */ | |
277 | static 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 | /* ------------------------------------------------------------------------- */ | |
286 | static 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 | /* ------------------------------------------------------------------------- */ | |
294 | static 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 | /* ------------------------------------------------------------------------- */ | |
310 | static 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 | /* ------------------------------------------------------------------------- */ | |
318 | static int off_counter = 0; | |
319 | ||
320 | void update_off(void) | |
321 | { | |
322 | if (off_counter++) return; | |
323 | smg$begin_pasteboard_update(&pb.id); | |
324 | } | |
325 | void 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 | /* ------------------------------------------------------------------------- */ | |
334 | win_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 | /* ------------------------------------------------------------------------- */ | |
343 | void 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 | /* ------------------------------------------------------------------------- */ | |
359 | static 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 | /* ------------------------------------------------------------------------- */ | |
369 | int hidden(win_ptr win) | |
370 | { | |
371 | return (win->hidden); | |
372 | } | |
373 | ||
374 | /* ------------------------------------------------------------------------- */ | |
375 | void 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 | /* ------------------------------------------------------------------------- */ | |
386 | int 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 | /* ------------------------------------------------------------------------- */ | |
424 | win_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 | * ------------------------------------------------------------------------- */ | |
442 | void 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 | ||
462 | win_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 | } | |
470 | win_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 | ||
477 | win_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 | ||
496 | static 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 | ||
504 | int 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 | /* ------------------------------------------------------------------------- */ | |
544 | win_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 | /* ------------------------------------------------------------------------- */ | |
553 | int 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 | /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ | |
595 | static 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 ------------------------------------------------------- */ | |
618 | static 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 | /* ------------------------------------------------------------------------- */ | |
630 | static 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 | /* ------------------------------------------------------------------------- */ | |
643 | static 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 | /* ------------------------------------------------------------------------- */ | |
652 | static 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 | /* ------------------------------------------------------------------------- */ | |
672 | static 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 | /* ------------------------------------------------------------------------- */ | |
682 | static 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 | /* ------------------------------------------------------------------------- */ | |
692 | void 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 | /* ------------------------------------------------------------------------- */ | |
698 | extern char curr_time[30]; | |
699 | static void sl_time(win_ptr win, char *str) | |
700 | { | |
701 | (void)strcpy(str, curr_time); | |
702 | } | |
703 | /* ------------------------------------------------------------------------- */ | |
704 | static void sl_user(win_ptr win, char *str) | |
705 | { | |
706 | get_username(str, 0); | |
707 | } | |
708 | /* ------------------------------------------------------------------------- */ | |
709 | static 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 | /* ------------------------------------------------------------------------- */ | |
720 | static 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 | /* ------------------------------------------------------------------------- */ | |
727 | static 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 | /* ------------------------------------------------------------------------- */ | |
734 | void sl_window2(win_ptr win, char *str) | |
735 | { | |
736 | if (win) sprintf(str, "%d", win->num); | |
737 | else strcpy(str, "-1"); | |
738 | } | |
739 | /* ------------------------------------------------------------------------- */ | |
740 | void 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 | * ------------------------------------------------------------------------ */ | |
798 | static 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 | * ------------------------------------------------------------------------ */ | |
816 | static 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 | * ------------------------------------------------------------------------ */ | |
884 | static 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 | * ------------------------------------------------------------------------- */ | |
901 | void 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 | /* ------------------------------------------------------------------------- */ | |
911 | void 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 | /* ------------------------------------------------------------------------- */ | |
920 | win_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 | /* ------------------------------------------------------------------------- */ | |
935 | char *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 | /* ------------------------------------------------------------------------- */ | |
949 | win_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 | ||
959 | int 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 | /* ------------------------------------------------------------------------- */ | |
976 | void 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 | /* ------------------------------------------------------------------------- */ | |
986 | char *getquery(void) | |
987 | { | |
988 | if (!gwin) return NULL; | |
989 | return gwin->query; | |
990 | } | |
991 | ||
992 | /* ------------------------------------------------------------------------- */ | |
993 | void 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 | /* ------------------------------------------------------------------------- */ | |
1021 | void 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 | /* ------------------------------------------------------------------------- */ | |
1030 | static 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 | /* ------------------------------------------------------------------------- */ | |
1043 | static 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 | /* ------------------------------------------------------------------ */ | |
1062 | void 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 | ||
1080 | void 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 | /* ------------------------------------------------------------------------- */ | |
1093 | void 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 | /* ------------------------------------------------------------------------- */ | |
1119 | static int echo = 1; | |
1120 | /* ------------------------------------------------------------------------- */ | |
1121 | int 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 | /* ------------------------------------------------------------------------- */ | |
1134 | int 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 | /* ------------------------------------------------------------------------- */ | |
1168 | void 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 | /* ------------------------------------------------------------------------- */ | |
1183 | static struct dsc$descriptor_s str_d = {1, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL}; | |
1184 | ||
1185 | void 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 | /* ------------------------------------------------------------------------- */ | |
1200 | void 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 | /* ------------------------------------------------------------------------- */ | |
1213 | void 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 | /* ------------------------------------------------------------------------- */ | |
1234 | static char format[1024], string[1024]; | |
1235 | static $DESCRIPTOR(for_d, format); | |
1236 | static $DESCRIPTOR(mvw_d, string); | |
1237 | ||
1238 | /* ------------------------------------------------------------------------- */ | |
1239 | /* | |
1240 | void 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 | /* ------------------------------------------------------------------------- */ | |
1252 | static 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 | /* ------------------------------------------------------------------------- */ | |
1271 | void 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 */ | |
1294 | static 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 | /* ------------------------------------------------------------------------- */ | |
1317 | static 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 | /* ------------------------------------------------------------------------- */ | |
1336 | void 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 | /* ------------------------------------------------------------------------- */ | |
1349 | extern int in_help; | |
1350 | static 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) \ | |
1369 | do { \ | |
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 | /* ------------------------------------------------------------------------- */ | |
1423 | void 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 | /* ------------------------------------------------------------------------- */ | |
1445 | static 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 | /* ------------------------------------------------------------------------- */ | |
1512 | static int in_redirect = FALSE; | |
1513 | static int inonw = FALSE; | |
1514 | ||
1515 | static 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 | /* ------------------------------------------------------------------------ */ | |
1541 | static 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 | /* ------------------------------------------------------------------------ */ | |
1556 | void 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 | /* ------------------------------------------------------------------------ */ | |
1571 | void 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 | /* ------------------------------------------------------------------------ */ | |
1587 | void 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 | /* ------------------------------------------------------------------------ */ | |
1603 | typedef struct { | |
1604 | server_ptr ss; | |
1605 | win_ptr ww; | |
1606 | int ll; | |
1607 | } levels_save; | |
1608 | ||
1609 | static stackptr levels_stack = NULL; | |
1610 | ||
1611 | void 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 | ||
1621 | void 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 | /* ------------------------------------------------------------------------ */ | |
1641 | win_ptr set_outwin(win_ptr win) | |
1642 | { | |
1643 | win_ptr temp; | |
1644 | temp = outwin; | |
1645 | outwin = win; | |
1646 | return temp; | |
1647 | } | |
1648 | ||
1649 | int set_loglevel(int new) | |
1650 | { | |
1651 | int old = log_level; | |
1652 | log_level = new; | |
1653 | return old; | |
1654 | } | |
1655 | /* ------------------------------------------------------------------------ */ | |
1656 | int 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 | /* ------------------------------------------------------------------------ */ |